lawspec 0.8.0 → 0.10.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 +180 -3
- package/GO.md +144 -0
- package/HASKELL.md +171 -0
- package/JAVA.md +113 -0
- package/KOTLIN.md +214 -0
- package/LANGUAGE.md +240 -12
- package/NATIVE-BINDINGS.md +1046 -0
- package/PRIMITIVES.md +1 -1
- package/PYTHON.md +152 -0
- package/README.md +86 -23
- package/REFINEMENTS.md +289 -3
- package/RELEASE-0.10.md +60 -0
- package/RELEASE-0.9.md +61 -0
- package/RUST.md +115 -1
- package/WEB.md +144 -0
- package/api.mjs +28 -2
- package/bin/lawspec.mjs +23 -7
- package/build.json +199 -37
- 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/collections.lawspec +67 -0
- 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/payments.lawspec +76 -0
- package/examples/specs/recursive_refinements.lawspec +41 -0
- package/examples/specs/refined_definitions.lawspec +44 -0
- package/examples/specs/sum_refinements.lawspec +49 -0
- package/examples/specs/total_functions.lawspec +101 -0
- package/examples-command.mjs +11 -1
- package/files.mjs +16 -7
- package/index.d.ts +297 -27
- package/native-examples.mjs +81 -0
- package/package.json +2 -2
- package/templates.mjs +107 -17
package/PRIMITIVES.md
CHANGED
package/PYTHON.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Python backend
|
|
2
|
+
|
|
3
|
+
Python output follows [PEP 8](https://peps.python.org/pep-0008/): four-space
|
|
4
|
+
indentation, a 79-column code target, 72-column prose comments/docstrings, and
|
|
5
|
+
two blank lines between top-level definitions. Explicit `--minify` permits
|
|
6
|
+
compact layout while preserving Python indentation and semantics.
|
|
7
|
+
`tools/python-formatting-integration.mjs` checks generated runtime, adapter,
|
|
8
|
+
definition, and test files with pycodestyle 2.14.0 at both machine widths. It
|
|
9
|
+
also compares readable and compact syntax trees, including literal contents.
|
|
10
|
+
|
|
11
|
+
Use Python 3.13 or later. Generated tests use Hypothesis; generated data classes,
|
|
12
|
+
scalar operations, and schema validation do not depend on a test framework.
|
|
13
|
+
|
|
14
|
+
## Native structural values
|
|
15
|
+
|
|
16
|
+
| LawSpec type | Adapter representation |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| `List a` | `list[A]` |
|
|
19
|
+
| `Maybe a` | `lawspec_schema.Maybe[A]`, with `Nothing` and `Just` variants |
|
|
20
|
+
| `Either a b` | `lawspec_schema.Either[A, B]`, with `Left` and `Right` variants |
|
|
21
|
+
| User-defined products and sums | Named generic dataclasses in `lawspec_data` |
|
|
22
|
+
| `Nullable a`, `Optional a` | Tagged `lawspec_runtime.Presence` values |
|
|
23
|
+
|
|
24
|
+
`Nothing()` differs from `Just(Nothing())`. `Left(value)` differs from
|
|
25
|
+
`Right(value)`. These algebraic variants are separate from the interoperability
|
|
26
|
+
states represented by `Nullable`, `Optional`, `Null`, and `Undefined`.
|
|
27
|
+
|
|
28
|
+
For example, this declaration:
|
|
29
|
+
|
|
30
|
+
```lawspec
|
|
31
|
+
type Tree (a :: Type) is
|
|
32
|
+
Leaf value :: a
|
|
33
|
+
Branch children :: List (Tree a)
|
|
34
|
+
end
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
produces a generic `Tree` base and `TreeLeaf` and `TreeBranch` dataclasses. A
|
|
38
|
+
product has one variant: `Pair` with constructor `Pair` produces `PairPair`.
|
|
39
|
+
When names conflict across units or between types and variants, the compiler
|
|
40
|
+
plans distinct names using their Core identities. Use the emitted declarations
|
|
41
|
+
and adapter annotations as the authoritative names.
|
|
42
|
+
|
|
43
|
+
Native pattern matching works on the generated variants:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import lawspec_data as data
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def count_leaves(tree: data.Tree[int]) -> int:
|
|
50
|
+
match tree:
|
|
51
|
+
case data.TreeLeaf():
|
|
52
|
+
return 1
|
|
53
|
+
case data.TreeBranch(children=children):
|
|
54
|
+
return sum(count_leaves(child) for child in children)
|
|
55
|
+
raise TypeError("unknown Tree variant")
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Classes are frozen and use slots. Container payloads are copied when crossing
|
|
59
|
+
adapter boundaries, so modifying a native list does not change another use of
|
|
60
|
+
the logical test input. An abstract base cannot be directly constructed; empty
|
|
61
|
+
types acquire no artificial variant.
|
|
62
|
+
|
|
63
|
+
LawSpec equality uses schema-directed comparisons, including IEEE NaN and
|
|
64
|
+
signed-zero rules and Symbol identity. Generated dataclasses do not derive
|
|
65
|
+
Python field equality, whose container shortcuts can change those rules.
|
|
66
|
+
|
|
67
|
+
## Checked boundaries
|
|
68
|
+
|
|
69
|
+
Generated calls validate input values, convert them to native classes, call the
|
|
70
|
+
adapter, and validate its result. A field extracted from a native product can
|
|
71
|
+
be returned directly from an adapter with the corresponding LawSpec result
|
|
72
|
+
type. The same representation is used for nested and standalone containers.
|
|
73
|
+
|
|
74
|
+
Diagnostics identify constructor fields and list indices. Checks distinguish
|
|
75
|
+
Bool from integers, enforce primitive ranges under the selected `machineBits`,
|
|
76
|
+
reject invalid scalar text, and preserve raw code units, code points, and bytes.
|
|
77
|
+
Preconditions and postconditions operate on validated logical values.
|
|
78
|
+
|
|
79
|
+
## Total definitions
|
|
80
|
+
|
|
81
|
+
Checked total definitions emit reusable Python functions separately from adapters:
|
|
82
|
+
|
|
83
|
+
```lawspec
|
|
84
|
+
unit example.total
|
|
85
|
+
|
|
86
|
+
definition increment (x :: Int8) :: BigInt is x + 1 end
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from lawspec_definitions.example import total
|
|
91
|
+
|
|
92
|
+
symbols = {}
|
|
93
|
+
assert total.increment(symbols, 127) == 128
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The first argument is the Symbol fixture context shared within an example.
|
|
97
|
+
Public signatures preserve native container and variant annotations; checked
|
|
98
|
+
conversion enforces element types, ranges, machine profiles, and nested presence
|
|
99
|
+
states at runtime. Errors include the resolved definition name. Source functions
|
|
100
|
+
and implementation bodies have no Hypothesis or pytest dependency.
|
|
101
|
+
|
|
102
|
+
`lawspec_definition_bodies.py` holds checked logical implementations. Public
|
|
103
|
+
modules under `lawspec_definitions/` provide native entry points grouped by unit.
|
|
104
|
+
Both belong in source directories and are generated-owned. Properties invoke
|
|
105
|
+
those checked bodies directly; definitions do not create adapter stubs. Unit
|
|
106
|
+
modules cannot shadow support modules or another unit's package. Native function
|
|
107
|
+
names such as `str` do not shadow built-ins used by generated validation.
|
|
108
|
+
|
|
109
|
+
Definition bodies and Python properties share typed expression rendering. Match
|
|
110
|
+
inputs are evaluated once, branches remain lazy, guards short-circuit, and exact
|
|
111
|
+
Decimal arithmetic is independent of Python's ambient rounding context.
|
|
112
|
+
Definitions must pass structural termination and definedness checks. Generic
|
|
113
|
+
definitions specialize to concrete uses. Refined signatures become checked
|
|
114
|
+
contracts, and refinement predicates may call checked definitions.
|
|
115
|
+
|
|
116
|
+
`tools/python-definitions-integration.mjs` checks standalone source calls,
|
|
117
|
+
properties, incorrect adapters, both machine profiles, custom layouts, compact
|
|
118
|
+
execution, and regeneration protection. The bundled Python corpus passes PEP 8 checks at 79 code columns and 72 prose
|
|
119
|
+
columns. The style audit includes the standalone total-definition fixture.
|
|
120
|
+
|
|
121
|
+
## Generation and layouts
|
|
122
|
+
|
|
123
|
+
Hypothesis composes tuples, alternatives, lists, and dependent strategies.
|
|
124
|
+
Recursive generation reserves each field's minimum node budget before sharing
|
|
125
|
+
the remainder. List length and element budgets vary together. Shrinking remains
|
|
126
|
+
native to Hypothesis and preserves the schema and structural size bound.
|
|
127
|
+
Small finite domains are enumerated; empty domains do not pass vacuously.
|
|
128
|
+
|
|
129
|
+
`lawspec_data.py` and `lawspec_schema.py` belong in the configured source
|
|
130
|
+
directory. `lawspec_data_strategies.py` belongs in the test directory. Configure
|
|
131
|
+
Python's import paths for those directories when using a custom layout.
|
|
132
|
+
Adapters remain user-owned. Unit names cannot shadow generated support modules.
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
Internal checked Core definition contracts now run at native and logical entry
|
|
136
|
+
points. Emission proves the obligations first; argument validation precedes
|
|
137
|
+
ordered preconditions, and result validation precedes postconditions. Contract
|
|
138
|
+
binders map explicitly to body inputs and the checked result. Refined source
|
|
139
|
+
signatures now produce these contracts through template proof and specialization.
|
|
140
|
+
|
|
141
|
+
`tools/portable-definition-contract-integration.mjs` exercises Python, JavaScript
|
|
142
|
+
and strict TypeScript with both machine profiles and layouts, without property
|
|
143
|
+
frameworks. It also verifies that deliberately corrupted results are rejected.
|
|
144
|
+
The fixture in `test/DefinitionContractFixture.hs` is shared with the JVM checks.
|
|
145
|
+
|
|
146
|
+
## Checking Python style
|
|
147
|
+
|
|
148
|
+
Set `LAWSPEC_CORE` to the native compiler, `LAWSPEC_PYTHON` to Python 3.13 or
|
|
149
|
+
later, and `LAWSPEC_PYCODESTYLE` to the `pycodestyle.py` source from version
|
|
150
|
+
2.14.0. Then run `node tools/python-formatting-integration.mjs`. The checker is
|
|
151
|
+
a development dependency; generating and executing runtime code does not
|
|
152
|
+
require it. Optional positional arguments select individual specification files.
|
package/README.md
CHANGED
|
@@ -2,10 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
**State the law once. Check it everywhere.**
|
|
4
4
|
|
|
5
|
-
LawSpec 0.
|
|
5
|
+
LawSpec 0.10 compiles reusable laws into native property tests, executable examples,
|
|
6
6
|
and implementation adapters. The compiler is Haskell, distributed as prebuilt
|
|
7
7
|
WebAssembly with a Node CLI and an asynchronous, typed JavaScript API.
|
|
8
8
|
|
|
9
|
+
## Structural data and total definitions in 0.9.0
|
|
10
|
+
|
|
11
|
+
LawSpec 0.9 adds `List`, algebraic `Maybe` and `Either`, named
|
|
12
|
+
parameterized products and sums, and checked total definitions on all eight
|
|
13
|
+
backends. See the [language reference](LANGUAGE.md),
|
|
14
|
+
[collections](examples/specs/collections.lawspec),
|
|
15
|
+
[data types](examples/specs/data_types.lawspec), and
|
|
16
|
+
[total functions](examples/specs/total_functions.lawspec).
|
|
17
|
+
|
|
18
|
+
Generated code is readable by default; `--minify` explicitly selects compact
|
|
19
|
+
output. Python follows PEP 8. See the [0.9 release notes](RELEASE-0.9.md)
|
|
20
|
+
and [API migration guide](API-MIGRATION.md).
|
|
21
|
+
|
|
9
22
|
## Rust and the typed front end in 0.8.0
|
|
10
23
|
|
|
11
24
|
Rust joins Java, Python, JavaScript, TypeScript, Go, Haskell, and Kotlin. All
|
|
@@ -23,12 +36,27 @@ Compiler API consumers should read the [schema v3 migration guide](API-MIGRATION
|
|
|
23
36
|
Scalar values use tagged, lossless encodings; generated runtime placement is
|
|
24
37
|
separate from artifact ownership. Java 25+ and Python 3.13+ baselines are unchanged.
|
|
25
38
|
|
|
39
|
+
## Native domain bindings in 0.10
|
|
40
|
+
|
|
41
|
+
LawSpec 0.10 adds configuration for existing application products and sums,
|
|
42
|
+
function bindings, checked conversion hooks, and native property-generator
|
|
43
|
+
factories on all eight targets. Generators retain their framework's shrinkers;
|
|
44
|
+
explicit examples, boundaries, and finite-domain checks remain independent.
|
|
45
|
+
See the [native-binding reference and acceptance status](NATIVE-BINDINGS.md),
|
|
46
|
+
the [release notes](RELEASE-0.10.md), and
|
|
47
|
+
[schema 4 migration notes](API-MIGRATION.md#schema-4-native-bindings).
|
|
48
|
+
Existing specifications without bindings retain their behavior.
|
|
49
|
+
|
|
26
50
|
## Install and try it
|
|
27
51
|
|
|
52
|
+
LawSpec has its own [syntax-highlighting grammar and VS Code extension](editors/vscode/README.md)
|
|
53
|
+
for keywords, types, refinements, literals, and law names. GitHub needs upstream Linguist
|
|
54
|
+
support to use it; GitHub currently uses the Haskell fallback.
|
|
55
|
+
|
|
28
56
|
Install [LawSpec from npm](https://www.npmjs.com/package/lawspec):
|
|
29
57
|
|
|
30
58
|
```sh
|
|
31
|
-
npm install --save-dev lawspec@0.
|
|
59
|
+
npm install --save-dev lawspec@0.10.0
|
|
32
60
|
npx lawspec --version
|
|
33
61
|
```
|
|
34
62
|
|
|
@@ -42,8 +70,8 @@ local dependencies so LawSpec can create its `package.json` and test script:
|
|
|
42
70
|
```sh
|
|
43
71
|
mkdir lawspec-example
|
|
44
72
|
cd lawspec-example
|
|
45
|
-
npm exec --package=lawspec@0.
|
|
46
|
-
npm install --save-dev lawspec@0.
|
|
73
|
+
npm exec --package=lawspec@0.10.0 -- lawspec init --target javascript
|
|
74
|
+
npm install --save-dev lawspec@0.10.0
|
|
47
75
|
npx lawspec check
|
|
48
76
|
npx lawspec explain 'example.atoi_codec::itoa and then atoi yields a'
|
|
49
77
|
npx lawspec doctor
|
|
@@ -179,11 +207,13 @@ Reusable laws can declare typed unary function parameters and `requires Eq a`, n
|
|
|
179
207
|
[parameterized refinements and executable contracts](REFINEMENTS.md).
|
|
180
208
|
Definitions support law application, function application/composition, universal
|
|
181
209
|
quantification, `implies`, Boolean predicates, scalar literals, and equality.
|
|
182
|
-
Function signatures and quantified inputs support the [scalar catalog](PRIMITIVES.md)
|
|
183
|
-
including mixed and multiple inputs.
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
210
|
+
Function signatures and quantified inputs support the [scalar catalog](PRIMITIVES.md)
|
|
211
|
+
and [structural types](LANGUAGE.md), including mixed and multiple inputs.
|
|
212
|
+
Generic variables are supported in reusable laws. Scalar and structural values
|
|
213
|
+
can also be intermediate or compared results. Functions are synchronous and
|
|
214
|
+
support curried signatures with any positive number of arguments. Text literals
|
|
215
|
+
are double-quoted, with escapes such as `\"`, `\\`, `\n`, and `\t`; examples must
|
|
216
|
+
bind each input to a concrete value of its declared type.
|
|
187
217
|
Text values contain Unicode scalar values; surrogate code points are rejected.
|
|
188
218
|
|
|
189
219
|
Examples refer to the expanded input names, including names inherited from the
|
|
@@ -193,9 +223,10 @@ produce literal braces. Law blocks use this order:
|
|
|
193
223
|
definition, optional description, optional rationale, examples, optional references.
|
|
194
224
|
`--` starts a line comment. Names that cannot be emitted portably are diagnosed.
|
|
195
225
|
|
|
196
|
-
|
|
197
|
-
prelude, async functions
|
|
198
|
-
|
|
226
|
+
Collections beyond `List`, external law packages, cross-unit imports beyond the
|
|
227
|
+
prelude, async functions and browser hosting remain outside the language.
|
|
228
|
+
Direct existing-symbol bindings are part of LawSpec 0.10 described
|
|
229
|
+
above; the published 0.9 release uses implementation adapters.
|
|
199
230
|
|
|
200
231
|
## Algebra and currying (0.6)
|
|
201
232
|
|
|
@@ -250,7 +281,7 @@ reusable laws accept these curried functions, their partial applications, and
|
|
|
250
281
|
scalar parameters. Quantified test inputs remain scalar.
|
|
251
282
|
|
|
252
283
|
The prelude defines the following laws. Every row has an executable example in
|
|
253
|
-
[algebra.lawspec](https://github.com/brain-fuel/lawspec/blob/v0.
|
|
284
|
+
[algebra.lawspec](https://github.com/brain-fuel/lawspec/blob/v0.10.0/examples/specs/algebra.lawspec), including both sides of every
|
|
254
285
|
combined law. `f` and `g` are binary operations, `inverse` is unary, and `e` and
|
|
255
286
|
`zero` are scalar parameters. All these laws require equality of the element type.
|
|
256
287
|
|
|
@@ -318,7 +349,7 @@ their entire consequence. Every conjunct is type-checked and emitted. As with
|
|
|
318
349
|
existing assertions, the first failure stops that individual test. `and` is now
|
|
319
350
|
a reserved word.
|
|
320
351
|
|
|
321
|
-
[Currying examples](https://github.com/brain-fuel/lawspec/blob/v0.
|
|
352
|
+
[Currying examples](https://github.com/brain-fuel/lawspec/blob/v0.10.0/examples/specs/currying.lawspec) demonstrate a four-argument
|
|
322
353
|
function partially applied twice, a formatter with four heterogeneous arguments,
|
|
323
354
|
and composition after partial application. Each example states its exact outputs.
|
|
324
355
|
Run `node npm/bin/lawspec.mjs examples` after rebuilding to inspect all nine units
|
|
@@ -370,7 +401,7 @@ law `valid ports round trip` is
|
|
|
370
401
|
end
|
|
371
402
|
```
|
|
372
403
|
|
|
373
|
-
The [complete port example](https://github.com/brain-fuel/lawspec/blob/v0.
|
|
404
|
+
The [complete port example](https://github.com/brain-fuel/lawspec/blob/v0.10.0/examples/specs/parse_port.lawspec)
|
|
374
405
|
defines valid ports as 1–65535, and covers both endpoints, ordinary ports, zero,
|
|
375
406
|
negative values, and 65536. All explicit `expect` assertions run regardless of
|
|
376
407
|
the law's condition. A false condition skips only the consequence: invalid ports
|
|
@@ -388,7 +419,7 @@ The prelude includes `satisfies predicate` (the predicate holds for every input)
|
|
|
388
419
|
and `left inverse when predicate parse render` (the guarded round trip above).
|
|
389
420
|
These reusable laws preserve the condition and its lexical bindings when expanded.
|
|
390
421
|
`equivalent` can also compare two predicates, since `Bool` supports equality.
|
|
391
|
-
The [Boolean flags example](https://github.com/brain-fuel/lawspec/blob/v0.
|
|
422
|
+
The [Boolean flags example](https://github.com/brain-fuel/lawspec/blob/v0.10.0/examples/specs/boolean_flags.lawspec)
|
|
392
423
|
checks that flipping twice restores both `false` and `true`; all targets generate
|
|
393
424
|
Boolean property inputs and explicit tests for both Boolean boundary values. Java caps Boolean-only JetCheck runs at the number of
|
|
394
425
|
possible input combinations (up to 100), avoiding generator exhaustion.
|
|
@@ -467,7 +498,7 @@ This expands to `for all (x :: Int32) . render (x) = referenceRender (x)`.
|
|
|
467
498
|
The example inherits the input name `x` from the prelude. Both functions are
|
|
468
499
|
user-owned adapter functions; either may delegate to your existing code.
|
|
469
500
|
|
|
470
|
-
[The complete example](https://github.com/brain-fuel/lawspec/blob/v0.
|
|
501
|
+
[The complete example](https://github.com/brain-fuel/lawspec/blob/v0.10.0/examples/specs/equivalent.lawspec) compares decimal
|
|
471
502
|
renderers and two implementations that clamp negative integers to zero. For
|
|
472
503
|
JavaScript, their adapters can be:
|
|
473
504
|
|
|
@@ -504,7 +535,7 @@ law `normalizers agree` is
|
|
|
504
535
|
end
|
|
505
536
|
```
|
|
506
537
|
|
|
507
|
-
The [slug example](https://github.com/brain-fuel/lawspec/blob/v0.
|
|
538
|
+
The [slug example](https://github.com/brain-fuel/lawspec/blob/v0.10.0/examples/specs/slug.lawspec)
|
|
508
539
|
compares two implementations of ASCII-space replacement. It includes empty,
|
|
509
540
|
Unicode and escaped text. Each target uses its native string generator:
|
|
510
541
|
JetCheck `Generator.stringsOf(Generator.asciiPrintableChars())`, Hypothesis `st.text()`, fast-check `fc.string()`,
|
|
@@ -531,7 +562,7 @@ law `canonicalization reaches a fixed point` is
|
|
|
531
562
|
end
|
|
532
563
|
```
|
|
533
564
|
|
|
534
|
-
The [canonical URL example](https://github.com/brain-fuel/lawspec/blob/v0.
|
|
565
|
+
The [canonical URL example](https://github.com/brain-fuel/lawspec/blob/v0.10.0/examples/specs/canonical_url.lawspec)
|
|
535
566
|
uses removal of **all trailing slashes** as a small fixed-point demonstration,
|
|
536
567
|
not a complete URL canonicalization algorithm. For JavaScript:
|
|
537
568
|
|
|
@@ -540,13 +571,31 @@ export const canonicalize = value => value.replace(/\/+$/, "");
|
|
|
540
571
|
```
|
|
541
572
|
|
|
542
573
|
Removing just one trailing slash fails the supplied repeated-slash example.
|
|
543
|
-
The [mixed-input example](https://github.com/brain-fuel/lawspec/blob/v0.
|
|
574
|
+
The [mixed-input example](https://github.com/brain-fuel/lawspec/blob/v0.10.0/examples/specs/mixed_inputs.lawspec)
|
|
544
575
|
shows `Text` and `Int32` in the same quantified property and executable example.
|
|
545
|
-
The JavaScript API represents
|
|
546
|
-
|
|
576
|
+
The JavaScript API represents example bindings as typed records whose values use
|
|
577
|
+
`DataValue`: lossless tagged scalar payloads or structural constructors. Expected results are
|
|
578
|
+
typed expressions inside `Assertion` trees, not untyped JavaScript primitives.
|
|
579
|
+
See the [API migration guide](API-MIGRATION.md) for their wire representation.
|
|
547
580
|
|
|
548
581
|
## Generate all example artifacts
|
|
549
582
|
|
|
583
|
+
To use native domain bindings, export the runnable payment
|
|
584
|
+
example (omit `--target` to export all eight languages):
|
|
585
|
+
|
|
586
|
+
```sh
|
|
587
|
+
lawspec examples --example payments --target rust --output native_payments
|
|
588
|
+
cd native_payments/rust
|
|
589
|
+
# Install the dependencies listed in README.md, then:
|
|
590
|
+
lawspec check
|
|
591
|
+
lawspec generate
|
|
592
|
+
cargo test
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
These projects include application-owned types, native generators, binding
|
|
596
|
+
configuration, and build files. Re-exporting preserves edits and leaves the
|
|
597
|
+
compiler's generation manifest separate from the example export manifest.
|
|
598
|
+
|
|
550
599
|
```sh
|
|
551
600
|
npx lawspec examples
|
|
552
601
|
# Or select a target and a relative output directory:
|
|
@@ -605,7 +654,7 @@ by the JS shim.
|
|
|
605
654
|
## Build and verify
|
|
606
655
|
|
|
607
656
|
For contributors working from a repository checkout, build a local archive with
|
|
608
|
-
`npm pack ./npm` and install it with `npm install --save-dev ./lawspec-0.
|
|
657
|
+
`npm pack ./npm` and install it with `npm install --save-dev ./lawspec-0.10.0.tgz`.
|
|
609
658
|
The package payload lives in `npm/`.
|
|
610
659
|
|
|
611
660
|
```sh
|
|
@@ -644,6 +693,20 @@ unchanged. Arguments select individual targets. `LAWSPEC_PYTHON=3.14` selects th
|
|
|
644
693
|
additional Python reference environment. CI also exercises Node 22/24/26 and packs
|
|
645
694
|
and installs the npm archive. Registry publication is a separate release action.
|
|
646
695
|
|
|
696
|
+
The native-binding acceptance command uses the installed npm archive, public CLI,
|
|
697
|
+
and the selected target's normal test command:
|
|
698
|
+
|
|
699
|
+
```sh
|
|
700
|
+
node tools/native-example-integration.mjs rust
|
|
701
|
+
LAWSPEC_MACHINE_BITS=32 LAWSPEC_MINIFY=1 node tools/native-example-integration.mjs rust
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
Replace `rust` with any supported target. It exports the payment project, verifies
|
|
705
|
+
correct behavior, rejects an incorrect fee, and checks regeneration. Per-command
|
|
706
|
+
logs live in `.artifacts/native-example-integration/`. See the
|
|
707
|
+
[acceptance reference](NATIVE-BINDINGS.md) for dependency overrides and remaining
|
|
708
|
+
verification gates.
|
|
709
|
+
|
|
647
710
|
|
|
648
711
|
Refinement predicates can depend on earlier inputs. Generated tests backtrack from
|
|
649
712
|
impossible prefixes, preserve the domain during shrinking, and validate function
|