lawspec 0.9.0 → 0.11.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 +78 -2
- package/HASKELL.md +1 -0
- package/KOTLIN.md +5 -0
- package/LANGUAGE.md +70 -11
- package/NATIVE-BINDINGS.md +1049 -0
- package/PRIMITIVES.md +1 -1
- package/README.md +86 -23
- package/REFINEMENTS.md +6 -1
- package/RELEASE-0.10.md +60 -0
- package/RELEASE-0.11.md +62 -0
- package/api.mjs +23 -3
- package/bin/lawspec.mjs +17 -4
- package/build.json +60 -38
- package/core.wasm +0 -0
- package/examples/native-payments/go/example/payments/domain.go +38 -0
- package/examples/native-payments/go/example/payments/native_generators_test.go +13 -0
- package/examples/native-payments/go/lawspec.json +136 -0
- package/examples/native-payments/haskell/lawspec.json +149 -0
- package/examples/native-payments/haskell/src/PaymentsDomain.hs +21 -0
- package/examples/native-payments/haskell/test/PaymentGenerators.hs +12 -0
- package/examples/native-payments/java/lawspec.json +165 -0
- package/examples/native-payments/java/src/main/java/domain/PaymentsDomain.java +32 -0
- package/examples/native-payments/java/src/test/java/domain/PaymentGenerators.java +16 -0
- package/examples/native-payments/javascript/lawspec.json +149 -0
- package/examples/native-payments/javascript/src/payments_domain.mjs +44 -0
- package/examples/native-payments/javascript/test/lawspec_generators.mjs +6 -0
- package/examples/native-payments/kotlin/lawspec.json +165 -0
- package/examples/native-payments/kotlin/src/main/kotlin/domain/PaymentsDomain.kt +17 -0
- package/examples/native-payments/kotlin/src/test/kotlin/domain/PaymentGenerators.kt +12 -0
- package/examples/native-payments/python/lawspec.json +149 -0
- package/examples/native-payments/python/src/payments_domain.py +60 -0
- package/examples/native-payments/python/tests/lawspec_generators.py +15 -0
- package/examples/native-payments/rust/lawspec.json +167 -0
- package/examples/native-payments/rust/src/domain.rs +37 -0
- package/examples/native-payments/rust/src/lib.rs +2 -0
- package/examples/native-payments/rust/tests/support/lawspec_generators.rs +11 -0
- package/examples/native-payments/typescript/lawspec.json +149 -0
- package/examples/native-payments/typescript/src/payments_domain.ts +42 -0
- package/examples/native-payments/typescript/test/lawspec_generators.ts +8 -0
- package/examples/specs/indexed_families.lawspec +59 -0
- package/examples/specs/payments.lawspec +76 -0
- package/examples-command.mjs +5 -0
- package/files.mjs +6 -6
- package/index.d.ts +53 -2
- package/native-examples.mjs +81 -0
- package/package.json +2 -2
package/API-MIGRATION.md
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
# Compiler API migration
|
|
1
|
+
# Compiler API migration
|
|
2
|
+
|
|
3
|
+
This document covers the published schema-3 interface and the schema-4 native
|
|
4
|
+
binding interface introduced in 0.10. See
|
|
5
|
+
[schema 4 native bindings](#schema-4-native-bindings) when adding
|
|
6
|
+
application types or generators to an existing project.
|
|
7
|
+
|
|
8
|
+
## Schema 2 → schema 3
|
|
2
9
|
|
|
3
10
|
LawSpec 0.8 introduced API schema version **3**, which 0.9 continues to use.
|
|
4
11
|
Requests may omit `schemaVersion` or
|
|
5
|
-
send `3`. An explicit `2`
|
|
12
|
+
send `3`. An explicit `2` receives a request diagnostic;
|
|
6
13
|
it is never silently reinterpreted. LawSpec specification syntax remains compatible.
|
|
7
14
|
The generated `index.d.ts` describes the public protocol. Internal Haskell
|
|
8
15
|
constructors and record fields are no longer the wire format.
|
|
@@ -202,3 +209,72 @@ definition and constructor contracts support recursive payload proof facts. Cons
|
|
|
202
209
|
matches/constructions participate in the constructor dependency-cycle check.
|
|
203
210
|
The TypeScript declarations now include both
|
|
204
211
|
`allElements` and `allPayloads`; exhaustive visitors should handle both.
|
|
212
|
+
|
|
213
|
+
## Schema 4 native bindings
|
|
214
|
+
|
|
215
|
+
Binding requests use `schemaVersion: 4`. Schema-3 requests remain supported for
|
|
216
|
+
existing specifications without bindings. This negotiation is deliberate: an
|
|
217
|
+
older compiler must reject a binding request rather than silently use generated
|
|
218
|
+
types in place of application types.
|
|
219
|
+
|
|
220
|
+
The JavaScript API selects schema 4 when `nativeBindings` is provided, unless an
|
|
221
|
+
explicit `schemaVersion` overrides it. A nonempty binding configuration with
|
|
222
|
+
schema 3 is rejected. Results and diagnostics report the negotiated schema.
|
|
223
|
+
|
|
224
|
+
`nativeBindings` contains optional `types`, `functions`, `generators`,
|
|
225
|
+
`rustCrate` and `goImports` fields. Native symbols use arrays of identifier segments; unknown
|
|
226
|
+
configuration fields are rejected. See [the native-binding scope and current
|
|
227
|
+
implementation status](NATIVE-BINDINGS.md). Rust, Python, JavaScript, TypeScript,
|
|
228
|
+
Java and Kotlin support application type bridges and native generator factories.
|
|
229
|
+
Go supports package-local and imported application types with native Rapid
|
|
230
|
+
factories. Haskell supports application types and native Hedgehog factories.
|
|
231
|
+
Custom codec hooks are available on all eight targets; see the native-binding
|
|
232
|
+
reference for target-specific signatures and current integration limitations.
|
|
233
|
+
|
|
234
|
+
### Go imports in schema 4 binding requests
|
|
235
|
+
|
|
236
|
+
`nativeBindings.goImports` is an optional array of `{alias, path}` entries.
|
|
237
|
+
References such as `["domain", "Price"]` select exported names from that alias's
|
|
238
|
+
Go import path. One-component references continue to select package-local names.
|
|
239
|
+
Types, constructors, functions and generator factories share the import table;
|
|
240
|
+
only imports used by each generated file are emitted. Other targets reject this
|
|
241
|
+
option. Paths must be module import paths without empty or traversal segments.
|
|
242
|
+
|
|
243
|
+
Go reserves local application symbols before generating canonical data names.
|
|
244
|
+
Colliding generated families receive a fresh `Canonical` prefix (and a numeric
|
|
245
|
+
suffix in that prefix if necessary). Logical type and constructor IDs do not
|
|
246
|
+
change. Hooks that name generated data types should use the emitted canonical
|
|
247
|
+
names; imported application types keep their original names.
|
|
248
|
+
|
|
249
|
+
### Codec hooks in schema 4 type bindings
|
|
250
|
+
|
|
251
|
+
`NativeTypeBinding` now accepts either `constructors` or
|
|
252
|
+
`codec: {toNative: NativeReference, fromNative: NativeReference}`. Both hook
|
|
253
|
+
references are required and constructor mappings cannot be combined with hooks.
|
|
254
|
+
The canonical side uses generated LawSpec data types, while the native side uses
|
|
255
|
+
`native`; generic hooks receive one directional child converter per type argument.
|
|
256
|
+
All eight targets implement emission. Go hooks return `(value, error)` and the
|
|
257
|
+
verified fixture places them beside the generated canonical types to avoid package
|
|
258
|
+
import cycles. See `NATIVE-BINDINGS.md` for signatures and
|
|
259
|
+
validation behavior.
|
|
260
|
+
|
|
261
|
+
### Native-binding ownership transitions
|
|
262
|
+
|
|
263
|
+
Existing user adapters are protected when their paths become generated bridges.
|
|
264
|
+
Move application implementations into the configured native modules and save the
|
|
265
|
+
old adapters elsewhere before adopting bindings. Removing bindings preserves the
|
|
266
|
+
old bridge as user-owned content and reports a required adapter update; it does
|
|
267
|
+
not silently replace that content with a stub. Generated layout changes do not
|
|
268
|
+
move application-owned model, hook or factory files. See `NATIVE-BINDINGS.md` for
|
|
269
|
+
the migration sequence and all-target filesystem acceptance checks.
|
|
270
|
+
|
|
271
|
+
### Optional generator scaffolds in schema 4
|
|
272
|
+
|
|
273
|
+
`NativeGeneratorBinding` accepts `stub?: boolean`, defaulting to false. Python,
|
|
274
|
+
Rust, JavaScript, TypeScript, Java, Kotlin, Go and Haskell support `stub: true` to
|
|
275
|
+
create a user-owned factory in the test directory. Go
|
|
276
|
+
requires a package-local factory and a quantified use to determine placement.
|
|
277
|
+
Existing factory files remain untouched. Factory signature changes
|
|
278
|
+
use the existing `adapterUpdates` reporting channel. See `NATIVE-BINDINGS.md`
|
|
279
|
+
for grouping, module collision checks, and layout
|
|
280
|
+
migration behavior.
|
package/HASKELL.md
CHANGED
|
@@ -41,6 +41,7 @@ have no constructors. They can appear in inhabited containers such as
|
|
|
41
41
|
| `Nullable a` | `LS.Nullable a`, with `NullValue` and `NullableValue` |
|
|
42
42
|
| `Optional a` | `LS.Optional a`, with `UndefinedValue` and `OptionalValue` |
|
|
43
43
|
| `BigInt`, `BigUInt`, `Integer` | `Integer`, with domain checks |
|
|
44
|
+
| `Integer` adapter result | `LS.IntegerValue`, built from any `Integral` with `LS.integerValue` |
|
|
44
45
|
| `Decimal` | `LS.Decimal`, wrapping an exact finite base-ten `Rational` |
|
|
45
46
|
| `Rational` | `Rational` |
|
|
46
47
|
| `Complex64`, `Complex128` | `Complex Float`, `Complex Double` |
|
package/KOTLIN.md
CHANGED
|
@@ -61,6 +61,11 @@ arbitrary integers, and machine-profile integers use `BigInteger` with explicit
|
|
|
61
61
|
domain checks. These portable machine-profile representations do not bind a
|
|
62
62
|
host machine-sized primitive.
|
|
63
63
|
|
|
64
|
+
An adapter whose result is the abstract `Integer` returns Kotlin `Number`.
|
|
65
|
+
`Integer` is the top of the integral tower, so an implementation may return
|
|
66
|
+
`Int`, `Long` or `BigInteger`; the result bridge rejects non-integral values
|
|
67
|
+
such as `Double` and checks the logical domain. Arguments remain `BigInteger`.
|
|
68
|
+
|
|
64
69
|
Decimal uses exact `BigDecimal`; Rational uses the normalized
|
|
65
70
|
`LawSpecRuntime.Ratio`. Complex components use `LawSpecRuntime.Complex`, with
|
|
66
71
|
Float32 precision validated for Complex64. Raw code-point text uses `IntArray`,
|
package/LANGUAGE.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# LawSpec language and compiler boundary (0.
|
|
1
|
+
# LawSpec language and compiler boundary (0.11)
|
|
2
2
|
|
|
3
3
|
LawSpec describes portable laws, concrete examples, and adapter contracts. The
|
|
4
4
|
compiler is written in Haskell. Rust is an output backend alongside Java, Python,
|
|
@@ -102,7 +102,8 @@ scrutinee once; each branch binds that constructor's fields in the same order.
|
|
|
102
102
|
Bindings are scoped to the branch. Matching must be exhaustive and cannot repeat
|
|
103
103
|
a constructor. Lists match with `Nil` and `Cons head tail`; Maybe and Either use
|
|
104
104
|
their constructors above. Recursive declarations must be strictly positive.
|
|
105
|
-
|
|
105
|
+
Constructors may refine natural indices; see [indexed families](#natural-indexed-families).
|
|
106
|
+
GADT result signatures that refine type arguments are not supported.
|
|
106
107
|
|
|
107
108
|
Equality is structural and type-directed, including named fields and nested
|
|
108
109
|
containers. Native public declarations retain their names and type parameters;
|
|
@@ -129,6 +130,58 @@ of recursive and nonrecursive named type constructors are supported; see
|
|
|
129
130
|
constructor fields use checked constructor contracts. Recursive payload predicates
|
|
130
131
|
follow stored type arguments and preserve outer dependent inputs.
|
|
131
132
|
|
|
133
|
+
## Natural-indexed families
|
|
134
|
+
|
|
135
|
+
A data declaration may take `Natural` parameters. Each constructor states how it
|
|
136
|
+
determines them with `where <index> = <expression>`:
|
|
137
|
+
|
|
138
|
+
```lawspec
|
|
139
|
+
type Vec (n :: Natural) (a :: Type) is
|
|
140
|
+
| VNil where n = 0
|
|
141
|
+
| VCons head :: a tail :: Vec m a where n = m + 1
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
type Tree (n :: Natural) (a :: Type) is
|
|
145
|
+
| Tip where n = 0
|
|
146
|
+
| Bin left :: Tree l a value :: a right :: Tree r a where n = l + r + 1
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
append :: (xs :: Vec n Int8) -> (ys :: Vec m Int8) -> (r :: Vec (n + m) Int8)
|
|
150
|
+
zip :: (xs :: Vec n Int8) -> (ys :: Vec n Bool) -> (r :: Vec n Bool)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Index expressions are sums of natural literals and index variables. A variable
|
|
154
|
+
such as `m` is bound by the field whose type mentions it, and every index needs
|
|
155
|
+
exactly one equation in every constructor. `Natural` is also an ordinary value
|
|
156
|
+
type: an unbounded integer that is at least zero.
|
|
157
|
+
|
|
158
|
+
Indices are evidence, not a second type system. The compiler elaborates a family
|
|
159
|
+
before inference into three ordinary declarations:
|
|
160
|
+
|
|
161
|
+
- erased data `Vec a` with the same constructors, which is the native
|
|
162
|
+
representation on every target;
|
|
163
|
+
- a checked structural measure for each index, named `<index>Of<Type>` (here
|
|
164
|
+
`nOfVec` and `nOfTree`), recomputed from the constructor equations;
|
|
165
|
+
- a refinement, so `Vec e a` in any signature or quantifier means
|
|
166
|
+
`(v :: Vec a where nOfVec v == e)`.
|
|
167
|
+
|
|
168
|
+
`append` above is therefore an adapter contract: its result must have length
|
|
169
|
+
`nOfVec xs + nOfVec ys`, and a native implementation that drops an element
|
|
170
|
+
fails with the postcondition. An index variable that is otherwise unbound, like
|
|
171
|
+
`n` and `m` in `append`, is implicit. It is determined by the first binder whose
|
|
172
|
+
family type mentions it alone, and later occurrences read that binder's measure.
|
|
173
|
+
Implicit indices must not first appear inside an expression, and a result cannot
|
|
174
|
+
introduce one.
|
|
175
|
+
|
|
176
|
+
Generation follows the index. For a free index, as in `append`, values come from
|
|
177
|
+
the erased type and the index is their measure. For a fixed index (`Vec 3 Int8`)
|
|
178
|
+
or a shared one (`zip`'s `ys`), the target is solved backwards through the
|
|
179
|
+
constructor equations: `VCons` for `n = 3` needs a tail with index 2, and `Bin`
|
|
180
|
+
splits `n - 1` between its subtrees. Samples are constructed, not filtered, and
|
|
181
|
+
shrinking stays within the index on every target. The same planning applies to
|
|
182
|
+
any user-written measure over declared data whose branches are a constant plus
|
|
183
|
+
the same measure of that branch's fields.
|
|
184
|
+
|
|
132
185
|
## Total definitions
|
|
133
186
|
|
|
134
187
|
A unit can supply an implementation as a checked total definition:
|
|
@@ -332,14 +385,20 @@ API schema v3 uses separately defined wire views, with lossless tagged scalar
|
|
|
332
385
|
values. It does not serialize internal AST constructors. See the
|
|
333
386
|
[API migration guide](API-MIGRATION.md).
|
|
334
387
|
|
|
335
|
-
## Beyond 0.
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
type
|
|
342
|
-
|
|
388
|
+
## Beyond 0.11
|
|
389
|
+
|
|
390
|
+
Natural-indexed families are implemented in 0.11 by elaboration to erased data,
|
|
391
|
+
measures and refinements. GADTs that refine type arguments, non-linear or
|
|
392
|
+
non-natural indices, index equalities between sibling fields (such as perfect
|
|
393
|
+
trees whose subtrees share one index), and general dependent types remain future
|
|
394
|
+
work. The Core type model distinguishes type arguments from index arguments, but
|
|
395
|
+
that representation is not a claim that arbitrary dependent programs are
|
|
396
|
+
accepted.
|
|
397
|
+
External type bindings and custom generator bindings are implemented in the
|
|
398
|
+
0.10 release; see [the binding reference](NATIVE-BINDINGS.md) for their
|
|
399
|
+
interface and acceptance status. They configure native representations alongside
|
|
400
|
+
the typed testing plan and do not change source-language typing or equality.
|
|
401
|
+
Cross-unit packages remain future work.
|
|
343
402
|
|
|
344
403
|
## Generated project formatting
|
|
345
404
|
|
|
@@ -357,5 +416,5 @@ code, and 72-column prose. Other targets follow Google language guidance where
|
|
|
357
416
|
applicable, with standard Rust formatting. Formatting is deterministic in the
|
|
358
417
|
native and WASM compilers; generation does not download or invoke a formatter.
|
|
359
418
|
|
|
360
|
-
See [the release notes](RELEASE-0.
|
|
419
|
+
See [the release notes](RELEASE-0.10.md) for compatibility and scope, and the target
|
|
361
420
|
guides for formatting verification and native representation details.
|