lawspec 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API-MIGRATION.md +186 -67
- package/GO.md +144 -0
- package/HASKELL.md +171 -0
- package/JAVA.md +113 -0
- package/KOTLIN.md +214 -0
- package/LANGUAGE.md +361 -0
- package/PRIMITIVES.md +2 -2
- package/PYTHON.md +152 -0
- package/README.md +45 -26
- package/REFINEMENTS.md +289 -3
- package/RELEASE-0.9.md +61 -0
- package/RUST.md +211 -0
- package/WEB.md +144 -0
- package/api.mjs +8 -2
- package/bin/lawspec.mjs +22 -47
- package/build.json +198 -26
- package/compatibility.json +102 -19
- package/core.wasm +0 -0
- package/doctor.mjs +31 -2
- package/examples/specs/algebra.lawspec +36 -8
- package/examples/specs/collections.lawspec +67 -0
- package/examples/specs/currying.lawspec +1 -1
- package/examples/specs/data_types.lawspec +66 -0
- package/examples/specs/finite_data.lawspec +37 -0
- package/examples/specs/list_contracts.lawspec +136 -0
- package/examples/specs/list_refinements.lawspec +51 -0
- package/examples/specs/matching.lawspec +49 -0
- package/examples/specs/recursive_refinements.lawspec +41 -0
- package/examples/specs/refined_definitions.lawspec +44 -0
- package/examples/specs/refinements.lawspec +11 -0
- package/examples/specs/sum_refinements.lawspec +49 -0
- package/examples/specs/total_functions.lawspec +101 -0
- package/examples-command.mjs +7 -2
- package/files.mjs +10 -1
- package/index.d.ts +246 -27
- package/package.json +2 -2
- package/templates.mjs +130 -16
package/JAVA.md
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Java backend (0.9)
|
|
2
|
+
|
|
3
|
+
Java targets Java 25+, JUnit, and JetCheck. The compiler emits native named
|
|
4
|
+
products and sums, checked scalar/data codecs, reusable runtime sources, and
|
|
5
|
+
separate property-test helpers. Native type parameters remain visible in public
|
|
6
|
+
data declarations and adapter signatures.
|
|
7
|
+
|
|
8
|
+
## Total definitions
|
|
9
|
+
|
|
10
|
+
A unit-level definition supplies its implementation together with its signature:
|
|
11
|
+
|
|
12
|
+
```lawspec
|
|
13
|
+
unit example.total
|
|
14
|
+
|
|
15
|
+
definition size (xs :: List Int8) :: BigInt is
|
|
16
|
+
match xs with
|
|
17
|
+
| Nil -> 0
|
|
18
|
+
| Cons head tail -> 1 + size tail
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The compiler checks the body even when no law uses it. It requires exhaustive
|
|
24
|
+
matching, established structural descent for recursion, and proof that partial
|
|
25
|
+
operations are defined. Calls may target other checked definitions, including
|
|
26
|
+
forward declarations; definitions cannot call external adapters. Generic definitions specialize to concrete uses. Refined signatures become
|
|
27
|
+
checked contracts, and refinement predicates may call checked definitions.
|
|
28
|
+
|
|
29
|
+
Java writes native entry points beneath `lawspec.definitions`, preserving the
|
|
30
|
+
unit's package and class mapping. The example above provides
|
|
31
|
+
`lawspec.definitions.example.Total.size`:
|
|
32
|
+
|
|
33
|
+
```java
|
|
34
|
+
var symbols = new java.util.HashMap<String, Object>();
|
|
35
|
+
var count = lawspec.definitions.example.Total.size(symbols, java.util.List.of((byte) 1, (byte) 2));
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Arguments and results use the same checked native representations as generated
|
|
39
|
+
data codecs: `List<Byte>` and `BigInteger` in this example. Domains without a
|
|
40
|
+
faithful Java representation retain their tagged runtime support values,
|
|
41
|
+
including nested Nullable/Optional states and machine-profile integers. Share
|
|
42
|
+
the Symbol map when fixture IDs should refer to the same identity.
|
|
43
|
+
|
|
44
|
+
`LawSpecDefinitionBodies.java` contains generated checked implementation helpers.
|
|
45
|
+
Generated properties call those same bodies. The native entry points validate
|
|
46
|
+
and copy values through codecs, and invalid native values report the definition
|
|
47
|
+
identity in an `IllegalArgumentException`. Logical machine integers enforce the
|
|
48
|
+
selected 32- or 64-bit range independently of the JVM architecture.
|
|
49
|
+
|
|
50
|
+
These files belong to source directories and have no JUnit or JetCheck dependency.
|
|
51
|
+
Definitions never receive user-owned adapter stubs. External declarations still
|
|
52
|
+
receive stubs, and regeneration preserves edited adapters. Edits to generated
|
|
53
|
+
definition files are protected by the generation manifest.
|
|
54
|
+
|
|
55
|
+
## Verification and layout
|
|
56
|
+
|
|
57
|
+
`tools/java-definitions-integration.mjs` executes recursive list/tree definitions,
|
|
58
|
+
forward calls, scalars, sums, raw code units, Symbol identity, and nested absence
|
|
59
|
+
under both profiles. It checks custom source/test roots, typed native misuse,
|
|
60
|
+
incorrect adapters, framework-independent compilation, and ownership.
|
|
61
|
+
|
|
62
|
+
Readable generated sources and tests use structured formatting that matches
|
|
63
|
+
Google Java Format. `tools/java-formatting-integration.mjs` checks all bundled
|
|
64
|
+
examples and the total-definition fixture under both machine profiles. The
|
|
65
|
+
compiler emits this layout directly; generation does not invoke a formatter.
|
|
66
|
+
JetCheck combinators retain native shrinking and the existing scalar domains.
|
|
67
|
+
|
|
68
|
+
The CLI/API accept explicit minify. Native integration checks run
|
|
69
|
+
both readable and fully minified generation plans, including properties and
|
|
70
|
+
contracts. Independent Java execution checks preserve long diagnostics,
|
|
71
|
+
supplementary Unicode, escaping and arbitrary integers when literals wrap.
|
|
72
|
+
The bundled WASM package is checked against the native compiler.
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
For internal checked Core definitions, shared JVM implementation bodies now
|
|
76
|
+
prove attached contracts before emission and enforce ordered preconditions and
|
|
77
|
+
validated-result postconditions at runtime. Native wrappers and direct logical
|
|
78
|
+
entry points both use those checks. `tools/jvm-definition-contract-integration.mjs`
|
|
79
|
+
verifies both JVM languages, profiles and layouts without a test-framework
|
|
80
|
+
dependency, including corrupted-result rejection. Refined source signatures
|
|
81
|
+
now produce these contracts through template proof and specialization.
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
## Constructor contracts
|
|
85
|
+
|
|
86
|
+
Public Java generation supports typed constructor callbacks, context-aware codecs
|
|
87
|
+
and definition boundaries. Property emission supplies validated witnesses and one
|
|
88
|
+
Symbol context shared by generation, adapter conversions and assertions.
|
|
89
|
+
Required conjunctive Symbol equalities can use fixture/prior-input values;
|
|
90
|
+
equalities beneath disjunctions contribute candidates without restricting the
|
|
91
|
+
whole domain to one alternative.
|
|
92
|
+
|
|
93
|
+
The test helper's `checkedGenerator` composes JetCheck generators with native
|
|
94
|
+
`suchThat` filtering at nested and outer value boundaries. False predicates reject
|
|
95
|
+
candidates; predicate evaluation errors are retained for the property to report.
|
|
96
|
+
Each filter respects the smaller of `maxAttempts` and JetCheck 0.3's native
|
|
97
|
+
100-attempt limit. The counter for smaller budgets is recreated on replay, so
|
|
98
|
+
native filtering still discards invalid shrinks. Validated witnesses contribute typed nested seeds. Sampled seeds
|
|
99
|
+
can limit payload shrinking; native list and constructor generation remains an
|
|
100
|
+
alternative, and shrinking does not promise a globally minimal counterexample.
|
|
101
|
+
|
|
102
|
+
`tools/java-checked-strategies.mjs` verifies valid generation/shrinking, nested
|
|
103
|
+
witness use, exhaustion, error classification and shared Symbol identity at both
|
|
104
|
+
machine widths, with compiled behavioral mutants. These helpers depend on
|
|
105
|
+
JetCheck; the value/schema/codec runtime remains framework-independent.
|
|
106
|
+
|
|
107
|
+
Constructor-contract properties run the requested case count as one-iteration
|
|
108
|
+
JetCheck sessions with increasing size hints. This preserves native shrinking and
|
|
109
|
+
avoids session-wide draw-uniqueness exhaustion for fixture-identity domains. It
|
|
110
|
+
does not claim those domains are finite; domains proven finite by Core retain
|
|
111
|
+
exhaustive cases. `tools/java-field-properties.mjs` executes public generation at
|
|
112
|
+
both widths and layouts, including custom placement, adapter mutants, disjunctive
|
|
113
|
+
Symbol candidates and generation-time evaluator errors.
|
package/KOTLIN.md
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Native Kotlin data
|
|
2
|
+
|
|
3
|
+
LawSpec 0.9 emits Kotlin sealed interfaces and named generic variant classes from
|
|
4
|
+
checked Core declarations. Generated schemas and codecs share the JVM scalar
|
|
5
|
+
runtime, independently of Kotest.
|
|
6
|
+
|
|
7
|
+
```lawspec
|
|
8
|
+
unit example.trees
|
|
9
|
+
|
|
10
|
+
type Tree (a :: Type) is
|
|
11
|
+
Leaf value :: a
|
|
12
|
+
Branch children :: List (Tree a)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
echo :: Tree Int8 -> Tree Int8
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The public type is `lawspec.data.Tree<Byte>`. Its variants are
|
|
19
|
+
`Tree.LeafCase<Byte>`, with a typed `value` property, and
|
|
20
|
+
`Tree.BranchCase<Byte>`, with `children: List<Tree<Byte>>`. Recursive and mutually
|
|
21
|
+
recursive fields retain native types. Generic parameters also remain on nullary
|
|
22
|
+
variants. Empty types have a private constructor and cannot supply generated
|
|
23
|
+
arguments, but can occur inside inhabited types such as `Maybe Empty`.
|
|
24
|
+
|
|
25
|
+
A correct adapter is:
|
|
26
|
+
|
|
27
|
+
```kotlin
|
|
28
|
+
fun echo(value: lawspec.data.Tree<Byte>): lawspec.data.Tree<Byte> = value
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Adapter files remain user-owned. Duplicate type names across units receive
|
|
32
|
+
qualified generated names. Kotlin built-ins are qualified in generated signatures
|
|
33
|
+
to avoid shadowing by domain types. Adapters that collide with generated JVM
|
|
34
|
+
runtime classes are rejected before output.
|
|
35
|
+
|
|
36
|
+
## Containers and absence
|
|
37
|
+
|
|
38
|
+
`List a` uses Kotlin `List<T>`. `Maybe a` uses `LawSpecRuntime.Maybe<T>` with
|
|
39
|
+
`Nothing<T>` and `Just<T>`. `Either a b` uses `LawSpecRuntime.Either<L, R>` with
|
|
40
|
+
`Left<L, R>` and `Right<L, R>`.
|
|
41
|
+
|
|
42
|
+
Interoperability absence remains separate:
|
|
43
|
+
|
|
44
|
+
- `Nullable a`: `LawSpecKotlin.Nullable<T>`, with `Null<T>` and `Present<T>`.
|
|
45
|
+
- `Optional a`: `LawSpecKotlin.Optional<T>`, with `Undefined<T>` and `Present<T>`.
|
|
46
|
+
- `Null` and `Undefined`: distinct singleton support values.
|
|
47
|
+
- `Unit`: Kotlin `Unit`, including adapter operations without a meaningful result.
|
|
48
|
+
|
|
49
|
+
These representations preserve every state of `Nullable (Optional a)` and other
|
|
50
|
+
nested combinations. Checked codecs validate both native adapter arguments and
|
|
51
|
+
results. Containers and raw arrays are copied across the logical/native boundary.
|
|
52
|
+
LawSpec equality is schema-directed, including IEEE component equality and
|
|
53
|
+
Symbol identity; generated variant classes do not substitute Kotlin data-class
|
|
54
|
+
equality for those rules.
|
|
55
|
+
|
|
56
|
+
## Scalars
|
|
57
|
+
|
|
58
|
+
Fixed signed integers use Kotlin `Byte`, `Short`, `Int`, and `Long`. UInt8,
|
|
59
|
+
UInt16, and UInt32 use the next sufficiently wide signed JVM type. UInt64,
|
|
60
|
+
arbitrary integers, and machine-profile integers use `BigInteger` with explicit
|
|
61
|
+
domain checks. These portable machine-profile representations do not bind a
|
|
62
|
+
host machine-sized primitive.
|
|
63
|
+
|
|
64
|
+
Decimal uses exact `BigDecimal`; Rational uses the normalized
|
|
65
|
+
`LawSpecRuntime.Ratio`. Complex components use `LawSpecRuntime.Complex`, with
|
|
66
|
+
Float32 precision validated for Complex64. Raw code-point text uses `IntArray`,
|
|
67
|
+
raw UTF-16 uses `String`, and bytes use `ByteArray`. `Char` uses a one-scalar
|
|
68
|
+
`String`, allowing supplementary characters; `CodePoint` uses `Int` and
|
|
69
|
+
`CodeUnit16` uses Kotlin `Char`.
|
|
70
|
+
|
|
71
|
+
`LawSpecKotlin.Symbol` preserves the underlying fixture identity through checked
|
|
72
|
+
round trips. Its native equality compares that identity, so two Symbols with the
|
|
73
|
+
same description remain distinct.
|
|
74
|
+
|
|
75
|
+
## Total definitions
|
|
76
|
+
|
|
77
|
+
Checked source definitions produce native Kotlin entry points and shared Java
|
|
78
|
+
implementation bodies in source directories. Neither requires Kotest. For example:
|
|
79
|
+
|
|
80
|
+
```lawspec
|
|
81
|
+
unit example.total
|
|
82
|
+
|
|
83
|
+
definition increment (value :: Int8) :: BigInt is
|
|
84
|
+
value + 1
|
|
85
|
+
end
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The native call is `lawspec.definitions.example.Total.increment(symbols, value)`;
|
|
89
|
+
`value` is a Kotlin `Byte`, the result is `BigInteger`, and `symbols` is a
|
|
90
|
+
`MutableMap<String, Any>` shared by calls in one example. An input of 127 returns
|
|
91
|
+
128. Native signatures retain typed lists, custom variants, and nested presence
|
|
92
|
+
payloads. Checked codecs validate inputs and results; failures include the
|
|
93
|
+
resolved definition name.
|
|
94
|
+
|
|
95
|
+
Properties call the generated implementation directly. Definitions never become
|
|
96
|
+
user-owned adapter stubs. Recursive definitions must pass the frontend's
|
|
97
|
+
structural termination and definedness checks. Generic definitions specialize to concrete uses. Refined signatures become
|
|
98
|
+
checked contracts, and refinement predicates may call checked definitions.
|
|
99
|
+
|
|
100
|
+
`tools/kotlin-definitions-integration.mjs` checks both machine profiles, standalone
|
|
101
|
+
source calls, native type errors, recursive properties, incorrect adapters,
|
|
102
|
+
compact source and complete minified generation plans, custom layouts, and
|
|
103
|
+
regeneration protection. Java implementation
|
|
104
|
+
bodies are checked against Google Java Format; Kotlin uses structured document
|
|
105
|
+
layout checked by the independent compiler-parser audit described below.
|
|
106
|
+
|
|
107
|
+
## Generated tests
|
|
108
|
+
|
|
109
|
+
Native declarations, schema metadata, and codecs belong in source directories.
|
|
110
|
+
`LawSpecStrategies` and `LawSpecKotlinStrategies` belong in test directories and
|
|
111
|
+
compose Kotest arbitraries and shrink trees. Bounded recursive generation reserves
|
|
112
|
+
each product field's minimum cost before distributing remaining nodes. Dependent
|
|
113
|
+
generation retains source shrink trees, including list lengths and constructor
|
|
114
|
+
choices, which Kotest 5.9's flatMap otherwise discards.
|
|
115
|
+
|
|
116
|
+
`tools/kotlin-data-integration.mjs` checks native declarations, codecs, and
|
|
117
|
+
shrinking in readable/compact layouts. `tools/kotlin-data-properties.mjs` compiles
|
|
118
|
+
and runs actual compiler output through Kotest with correct and incorrect
|
|
119
|
+
adapters, both profiles, and custom source/test roots. It accepts
|
|
120
|
+
`LAWSPEC_MINIFY=1` and includes the shared arithmetic conformance vectors in its
|
|
121
|
+
scalar scenario. The refinements scenario checks dependent domains, guarded
|
|
122
|
+
arithmetic, standalone contracts and four faulty adapters. It uses cached
|
|
123
|
+
compiler/library dependencies directly.
|
|
124
|
+
|
|
125
|
+
Generated property files now use structured documents throughout: imports,
|
|
126
|
+
helpers, examples, boundaries, native Kotest strategies, dependent refinement
|
|
127
|
+
domains, guarded assertions and contract wrappers. Blocks use two-space
|
|
128
|
+
indentation and continuation arguments use four spaces. Checked native codecs,
|
|
129
|
+
short-circuiting, Symbol context, single-evaluation matches and framework
|
|
130
|
+
generation/shrinking remain intact. The corpus audit below covers both machine
|
|
131
|
+
profiles and readable/compact syntax equivalence.
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
For internal checked Core definitions, shared JVM implementation bodies now
|
|
135
|
+
prove attached contracts before emission and enforce ordered preconditions and
|
|
136
|
+
validated-result postconditions at runtime. Native wrappers and direct logical
|
|
137
|
+
entry points both use those checks. `tools/jvm-definition-contract-integration.mjs`
|
|
138
|
+
verifies both JVM languages, profiles and layouts without a test-framework
|
|
139
|
+
dependency, including corrupted-result rejection. Refined source signatures
|
|
140
|
+
now produce these contracts through template proof and specialization.
|
|
141
|
+
|
|
142
|
+
## Source formatting and independent parsing
|
|
143
|
+
|
|
144
|
+
Kotlin output follows the published [Google Android Kotlin style guide](https://developer.android.com/kotlin/style-guide):
|
|
145
|
+
four-space blocks and wrapped arguments/parameters, with a 100-column code limit.
|
|
146
|
+
This corrects the earlier two-space Kotlin layout. Java support files continue to
|
|
147
|
+
use Google Java Format conventions. Python independently follows PEP 8.
|
|
148
|
+
|
|
149
|
+
`tools/kotlin-formatting-integration.mjs` generates the bundled corpus and the
|
|
150
|
+
total-definition fixture in both machine profiles and formatting modes, plus both
|
|
151
|
+
Gradle Kotlin scaffold files. An
|
|
152
|
+
independently installed Kotlin compiler parses both outputs. The checker compares
|
|
153
|
+
syntax trees, retaining operators, declaration modifiers, type arguments, and
|
|
154
|
+
string-template contents; it ignores whitespace, comments, semicolons and optional
|
|
155
|
+
trailing commas. Negative fixtures distinguish changed signs, val/var, string
|
|
156
|
+
contents and escaped dollars from template interpolation.
|
|
157
|
+
|
|
158
|
+
The audit also checks block/argument indentation, line lengths, tabs, trailing
|
|
159
|
+
whitespace, explicit ASCII-sorted imports, breaks after binary operators,
|
|
160
|
+
multiline conditional/when braces, and loop braces. Set `LAWSPEC_CORE` to the native compiler and optionally set
|
|
161
|
+
`LAWSPEC_KOTLIN_HOME` to a Kotlin installation containing `lib/kotlin-compiler.jar`.
|
|
162
|
+
The tool detects ordinary and Homebrew installations of `kotlinc`. Positional
|
|
163
|
+
arguments select specification files. All parser and formatting tooling remains
|
|
164
|
+
development-only; generated projects do not download it.
|
|
165
|
+
|
|
166
|
+
The audit checks the rules listed above. It does not compare byte-for-byte with
|
|
167
|
+
an external Kotlin formatter. No formatter is required to generate projects.
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
## Constructor contracts
|
|
171
|
+
|
|
172
|
+
Kotlin data emission uses profile-aware typed JVM schema callbacks.
|
|
173
|
+
Generated named codecs and native definition arguments/results preserve a caller's
|
|
174
|
+
Symbol context through nested List, Maybe, Either, Nullable and Optional values.
|
|
175
|
+
Kotlin-specific construct/match helpers also accept an explicit context; existing
|
|
176
|
+
Kotlin calls retain overloads or default arguments. Scalar-only bridges remain
|
|
177
|
+
framework-independent.
|
|
178
|
+
|
|
179
|
+
`tools/kotlin-constructor-native-integration.mjs` compiles and executes dependent
|
|
180
|
+
fields, generic/refined lists, sums, guarded arithmetic, machine ranges, nested
|
|
181
|
+
absence, fixture Symbols and raw UTF-16 units at both widths and layouts. It also
|
|
182
|
+
checks context-reset mutants, Google-formatted Java companions and independent
|
|
183
|
+
Kotlin parsing/layout/compact syntax parity.
|
|
184
|
+
|
|
185
|
+
Public Kotlin constructor-contract properties use the checked strategies and
|
|
186
|
+
share one Symbol context across witnesses, input generation, definitions, adapter
|
|
187
|
+
bridges and structural assertions. A context is allocated once per sampled case
|
|
188
|
+
and remains stable when the framework reads its shrink tree. Required conjunctive
|
|
189
|
+
Symbol equalities can draw fixture/prior-input values; disjunctions preserve both
|
|
190
|
+
alternatives and retain their predicate check.
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
The internal `LawSpecKotlinStrategies.checkedGenerator` validates supplied witnesses
|
|
194
|
+
and indexes their typed nested values. Native Kotest list/product/choice trees
|
|
195
|
+
remain the source of candidates and shrinks. A bounded sampling wrapper retries
|
|
196
|
+
false predicates up to `maxAttempts` at each value boundary; Kotest's `RTree.filter`
|
|
197
|
+
removes invalid shrink nodes. This avoids Kotest 5.9's unbounded arbitrary-filter
|
|
198
|
+
sampling without changing global framework settings. Evaluator errors are retained
|
|
199
|
+
as checked errors, including errors discovered during shrinking. Sampled witness
|
|
200
|
+
branches can limit payload shrinking; a globally minimal result is not promised.
|
|
201
|
+
|
|
202
|
+
`tools/kotlin-checked-strategies.mjs` checks both profiles, bounded exhaustion,
|
|
203
|
+
valid shrinking, nested witnesses, error classification and Symbol identity, with
|
|
204
|
+
compiled behavioral mutants. The legacy unchecked generator rejects schemas with
|
|
205
|
+
constructor contracts rather than bypassing their checks.
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
Generated dependent-input chains retain evaluator errors as case state, skip
|
|
209
|
+
subsequent draws after an error, and report the original failure before reading
|
|
210
|
+
input bindings. Input filtering accepts failed cases for reporting instead of
|
|
211
|
+
silently discarding them. Core-proven finite domains still emit exhaustive cases.
|
|
212
|
+
`tools/kotlin-field-properties.mjs` runs public generation at both widths and
|
|
213
|
+
layouts, with custom placement, finite domains, typed native adapters, nested
|
|
214
|
+
presence and lists, disjunctive fixtures, evaluator errors and incorrect adapters.
|