lawspec 0.6.0 → 0.8.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/REFINEMENTS.md ADDED
@@ -0,0 +1,158 @@
1
+ # Refinements and abstract integers (0.8.0)
2
+
3
+ A refinement restricts a scalar domain with a pure Boolean expression. LawSpec
4
+ checks concrete examples, generates satisfying input tuples, and checks adapter
5
+ contracts during testing. It does not prove that an adapter is correct.
6
+
7
+ ## Exact integers without a storage width
8
+
9
+ `Integer` is the mathematical integer domain. Integer literals default to it;
10
+ integer addition, subtraction, multiplication, negation, quotient, and remainder
11
+ produce it. Calculations use arbitrary precision internally. `BigInt` remains
12
+ available when a concrete arbitrary-precision adapter representation is wanted.
13
+
14
+ ```lawspec
15
+ unit example.increment
16
+ successor :: (x :: Int8) -> (result :: Integer where result == x + 1)
17
+ ```
18
+
19
+ This signature generates contract tests without a separate law. The maximum
20
+ input, `127`, requires the value `128`. Returning a wrapped `-128` fails.
21
+ `Integer` does not assert which storage width the implementation used.
22
+
23
+ Abstract integer results accept Python `int` (excluding `bool`), JavaScript or
24
+ TypeScript `bigint` and safe integral `number` values, Java/Kotlin standard signed
25
+ integral wrappers and `BigInteger` through `Number`, and Go signed/unsigned integer
26
+ values or `big.Int` values/pointers through `any`. Floating representations are
27
+ rejected even when their current value is integral. Haskell uses `IntegerValue`:
28
+
29
+ ```haskell
30
+ successor :: Int8 -> IntegerValue
31
+ successor x = integerValue (toInteger x + 1)
32
+ ```
33
+
34
+ `integerValue :: Integral a => a -> IntegerValue` erases the width losslessly.
35
+ Abstract integer arguments use the target's arbitrary-precision integer type.
36
+ Concrete signatures keep their existing checked native mappings.
37
+
38
+ ## Inline and named refinements
39
+
40
+ Use `where` on a quantified input, function argument, or function result:
41
+
42
+ ```lawspec
43
+ `for all` (x :: Int8) (y :: Int8 where y > Int8.max - x) .
44
+ add x y = x + y
45
+ ```
46
+
47
+ A predicate can reference its own value and earlier inputs. A function result
48
+ predicate can also reference the function's named arguments. Forward value
49
+ references are errors. `Int8.min` and `Int8.max` denote representation bounds;
50
+ machine-sized bounds use the requested `machineBits` profile.
51
+
52
+ Named refinements distinguish type parameters from value parameters:
53
+
54
+ ```lawspec
55
+ refinement Between
56
+ (T :: Type) (minimum :: T) (maximum :: T)
57
+ requires Ordered T is
58
+ (value :: T where minimum <= value && value <= maximum)
59
+ end
60
+
61
+ refinement AdditionOverflows
62
+ (T :: Type) (left :: T)
63
+ requires Integer T Bounded T is
64
+ (right :: T where left + right > T.max)
65
+ end
66
+
67
+ add :: (x :: Int8)
68
+ -> (y :: AdditionOverflows Int8 x)
69
+ -> (result :: Integer where result == x + y)
70
+ ```
71
+
72
+ `(x :: Between Int8 1 10)` applies a refinement. Parenthesize compound arguments,
73
+ for example `Between Int8 (-10) (5 + 5)`. Later value-parameter types can use
74
+ earlier parameters. Value arguments must satisfy their declared domains,
75
+ including refinements. Substitution avoids capturing names from the call site.
76
+ Declarations can appear in any order within a unit; recursive aliases are errors.
77
+ Fixed refinements are the zero-parameter form:
78
+
79
+ ```lawspec
80
+ refinement PositiveInt8 is (value :: Int8 where value > 0) end
81
+ ```
82
+
83
+ Aliases preserve their underlying native representation. They can be nested in
84
+ `Nullable` and `Optional`; inner predicates are checked only for present values.
85
+ Type parameters range over the supported scalar types, including presence types.
86
+
87
+ `requires Integer T` describes integer capabilities in a generic declaration.
88
+ `Integer` entails `Eq` and `Ordered`. `Ordered` currently covers exact real numbers
89
+ and floats, with the existing IEEE comparisons (including NaN behavior).
90
+ `Bounded` covers fixed and machine-sized integers. Bounds refer to the underlying
91
+ integer representation, rather than a tighter interval inferred from a predicate.
92
+ Capabilities are checked on generic declarations and their specializations.
93
+
94
+ ## Predicate expressions and contracts
95
+
96
+ Predicates support existing pure arithmetic, comparisons, scalar constructors,
97
+ conversions, and built-in helpers. `&&`, `||`, and `!` short-circuit; comparisons
98
+ bind more tightly than `&&`, which binds more tightly than `||`. Assertion `and`
99
+ continues to combine law conclusions. Exact/inexact mixing still needs an explicit
100
+ conversion, and floating expressions retain their declared precision.
101
+
102
+ `prelude.length` counts Unicode scalars for Text, code points for CodePointText,
103
+ UTF-16 units for Utf16Text, and octets for Bytes. `prelude.isPresent` and
104
+ `prelude.presentValue` inspect tagged presence values; guard extraction with
105
+ `isPresent` before accessing a possibly absent value.
106
+
107
+ Adapter calls are forbidden in refinements. Predicate errors such as division by
108
+ zero are reported as failures when evaluated; they are not ordinary rejection of
109
+ an input. Short-circuited branches are not evaluated by generation optimizations.
110
+
111
+ Every refined function signature creates a standalone property. Calls from other
112
+ laws also check argument preconditions, invoke the adapter once, snapshot its
113
+ result, and check postconditions. Calling a function outside its precondition is
114
+ a test failure, not a discarded example. Ordinary `implies` guards retain their
115
+ existing conditional behavior.
116
+
117
+ ## Dependent generation and shrinking
118
+
119
+ A quantified law ranges over satisfying tuples. For `AdditionOverflows Int8 x`,
120
+ `x = 0` has no admissible `y`. The generator backtracks to choose another `x`;
121
+ it does not count that dead end as a passing test. Valid pairs satisfy:
122
+
123
+ ```text
124
+ 1 <= x <= 127
125
+ 128 - x <= y <= 127
126
+ ```
127
+
128
+ The generator derives integer bounds from affine comparisons and conjunctions,
129
+ seeds direct comparison values and boundaries, and checks the complete predicate.
130
+ Predicates outside that analysis use bounded sampling. Small finite base-domain
131
+ products are enumerated exhaustively, retaining only satisfying tuples.
132
+
133
+ Shrinking checks refinements again and repairs dependent later inputs when an
134
+ earlier value changes. An overflowing counterexample can shrink to `(1, 127)`;
135
+ it cannot shrink to `(0, 127)` because that pair is outside the domain.
136
+
137
+ Compiler requests and `lawspec.json` accept:
138
+
139
+ ```json
140
+ {
141
+ "generation": {
142
+ "cases": 100,
143
+ "maxAttempts": 10000,
144
+ "maxShrinks": 1000,
145
+ "exhaustiveLimit": 4096
146
+ }
147
+ }
148
+ ```
149
+
150
+ All limits are positive integers. These are the defaults for refinement properties.
151
+ `cases` counts accepted property inputs; explicit examples and boundary fixtures
152
+ are additional checks. Exhausted searches report an error with reproduction
153
+ information. Exhaustion does not prove that the mathematical domain is empty.
154
+ Statically established empty executable domains and invalid examples are rejected.
155
+
156
+ See [the bundled examples](examples/specs/refinements.lawspec) for overflow,
157
+ abstract integer arguments/results, dependent bounds, optional refinements,
158
+ floating classification, and raw-byte lengths.
package/RUST.md ADDED
@@ -0,0 +1,97 @@
1
+ # Rust backend (0.8)
2
+
3
+ Rust is the first backend built on LawSpec's typed core and testing plan. The
4
+ compiler remains implemented in Haskell. Rust generation does not parse source
5
+ expressions, infer their types, or expand refinement declarations.
6
+
7
+ ## Project setup
8
+
9
+ Use Rust 1.85 or later, edition 2024, and Cargo. The generated project pins
10
+ Proptest 1.11.0, num-bigint 0.4.8, num-rational 0.4.2, num-complex 0.4.6, and
11
+ num-traits 0.2.19.
12
+
13
+ ```sh
14
+ lawspec init --target rust
15
+ lawspec doctor
16
+ lawspec generate
17
+ cargo test
18
+ cargo test --release
19
+ ```
20
+
21
+ Adapters are user-owned files under `src/`. LawSpec maintains
22
+ `lawspec_runtime.rs`, module declarations in `lawspec_modules.rs`, and tests
23
+ under `tests/`. The scaffolded `src/lib.rs` includes the generated declarations;
24
+ an existing library can include those declarations explicitly. Generation
25
+ preserves edited adapters and reports required signature updates.
26
+
27
+ The numeric runtime has no Proptest dependency. Framework support lives in a
28
+ separate generated file, `tests/support/lawspec_strategies.rs`.
29
+
30
+ ## Owned adapter values
31
+
32
+ Arguments and results are owned Rust values. LawSpec does not add borrowing,
33
+ lifetimes, or pointer operations to its language. Tests clone values where an
34
+ expression needs to use an input more than once.
35
+
36
+ | LawSpec domain | Rust adapter representation |
37
+ | --- | --- |
38
+ | `Bool` | `bool` |
39
+ | Fixed signed/unsigned integers | `i8`…`i64`, `u8`…`u64` |
40
+ | `IntSize`, `UIntSize`, `UIntPtr` | `isize`, `usize`, `usize` |
41
+ | `BigInt`, `BigUInt` | `BigInt`, `BigUint` |
42
+ | `Integer` input | `BigInt` |
43
+ | `Integer` result | `Integer`, with lossless `From` implementations |
44
+ | `Decimal`, `Rational` | Generated `Decimal`, `BigRational` |
45
+ | `Float32`, `Float64` | `f32`, `f64` |
46
+ | `Complex64`, `Complex128` | `Complex32`, `Complex64` from num-complex |
47
+ | `Char`, `Text` | `char`, `String` |
48
+ | `CodePoint`, `CodePointText` | Generated checked wrappers |
49
+ | `CodeUnit16`, `Utf16Text`, `Bytes` | `u16`, generated UTF-16 wrapper, `Vec<u8>` |
50
+ | `Symbol` | Generated identity type; cloning preserves identity |
51
+ | `Unit`, `Null`, `Undefined` | `()`, distinct generated absence types |
52
+ | `Nullable a`, `Optional a` | Distinct generated enums, including nested presence |
53
+
54
+ Names such as `Integer` and `Decimal` above are exported by the generated
55
+ `lawspec_runtime` module. Machine-sized native bindings check the requested
56
+ `machineBits` against the executing architecture.
57
+
58
+ For a declaration such as `successor :: Int8 -> Integer`, an implementation can
59
+ return a wider native integer through the logical result wrapper:
60
+
61
+ ```rust
62
+ use crate::lawspec_runtime as ls;
63
+
64
+ pub fn successor(value: i8) -> ls::Integer {
65
+ (i16::from(value) + 1).into()
66
+ }
67
+ ```
68
+
69
+ Exact arithmetic in laws uses arbitrary precision. Passing its result to an
70
+ `i8` adapter parameter performs a checked conversion. A fractional or
71
+ out-of-range value fails with the adapter's context.
72
+
73
+ `Decimal` stores an arbitrary integer coefficient and exponent. Decimal
74
+ arithmetic is exact; explicit rounding uses the requested scale and ties to
75
+ even. Exact-to-float conversion rounds directly to the requested IEEE precision,
76
+ including subnormal and halfway cases.
77
+
78
+ ## Refinements and generation
79
+
80
+ Small finite domains are enumerated. Larger domains use native Proptest
81
+ strategies. Integer bounds over earlier inputs become dependent strategies;
82
+ when a prefix has no possible continuation, generation retries the prefix.
83
+ Shrinking recomputes those dependent bounds and retains only valid tuples.
84
+ Refinement evaluation errors fail the test rather than being counted as rejected
85
+ samples. Generation limits prevent an empty or unreachable domain from passing
86
+ vacuously.
87
+
88
+ Contracts check preconditions, evaluate the adapter once, validate its native
89
+ result, and then check postconditions on that result.
90
+
91
+ ## Custom layouts
92
+
93
+ `sourceDir` and `testDir` move generated sources and imports together. Set Cargo's
94
+ `[lib] path` to the library entry point under the selected source directory. For
95
+ test directories other than `tests`, register generated test files using Cargo
96
+ `[[test]]` entries. Doctor checks the selected Cargo package, edition, resolved
97
+ dependencies, library directory, and custom test registration.
package/api.mjs CHANGED
@@ -2,5 +2,5 @@
2
2
  import { loadCore } from './launcher.mjs';
3
3
  export async function createCompiler() {
4
4
  const call = await loadCore();
5
- return { check: (input) => call({ ...input, method: 'check' }), expand: (input) => call({ ...input, method: 'expand' }), planGeneration: (input) => call({ ...input, method: 'planGeneration' }) };
5
+ return { check: (input) => call({ schemaVersion: 3, ...input, method: 'check' }), expand: (input) => call({ schemaVersion: 3, ...input, method: 'expand' }), planGeneration: (input) => call({ schemaVersion: 3, ...input, method: 'planGeneration' }) };
6
6
  }
package/bin/lawspec.mjs CHANGED
@@ -4,6 +4,7 @@ import path from "node:path";
4
4
  import { createCompiler } from "../api.mjs";
5
5
  import { targets, templates, commands, setup } from "../templates.mjs";
6
6
  import { generateExamples } from "../examples-command.mjs";
7
+ import { showScalar } from "../scalars.mjs";
7
8
  import { doctor } from "../doctor.mjs";
8
9
  import {
9
10
  readOptional,
@@ -18,7 +19,7 @@ const options = {};
18
19
  const positional = [];
19
20
  for (let i = 0; i < args.length; i++) {
20
21
  const arg = args[i];
21
- if (["--target", "--project", "--config", "--output"].includes(arg)) {
22
+ if (["--target", "--project", "--config", "--output", "--machine-bits"].includes(arg)) {
22
23
  if (!args[i + 1] || args[i + 1].startsWith("--"))
23
24
  throw new Error(`Missing value for ${arg}`);
24
25
  options[arg.slice(2)] = args[++i];
@@ -103,6 +104,7 @@ async function init() {
103
104
  throw new Error("Target is already configured");
104
105
  await mkdir(root, { recursive: true });
105
106
  const buildFiles = [
107
+ "Cargo.toml",
106
108
  "pom.xml",
107
109
  "pyproject.toml",
108
110
  "package.json",
@@ -138,6 +140,7 @@ async function init() {
138
140
  await readFile(new URL("../starter.lawspec", import.meta.url), "utf8"),
139
141
  true,
140
142
  );
143
+ if (options.machineBits !== undefined) config.machineBits = options.machineBits;
141
144
  config.targets.push({
142
145
  language,
143
146
  root: path.relative(configRoot, root) || ".",
@@ -151,47 +154,32 @@ async function init() {
151
154
  `Configured ${language}. ${hasBuild ? "Existing build files preserved." : "Created missing project build files."}\n${setup[language]}\nNext: lawspec doctor, then lawspec generate.`,
152
155
  );
153
156
  }
154
- function showExpression(expr) {
155
- const value = expr.contents;
156
- if (expr.tag === "Var") return value;
157
- if (
158
- expr.tag === "Number" ||
159
- expr.tag === "StringLit" ||
160
- expr.tag === "BoolLit"
161
- )
162
- return JSON.stringify(value);
163
- if (expr.tag === "Apply")
164
- return `${showExpression(value[0])} (${showExpression(value[1])})`;
165
- return `(${showExpression(value[0])} . ${showExpression(value[1])})`;
157
+ function showAssertion(assertion) {
158
+ if (assertion.kind === "equal") return `${assertion.left.text} = ${assertion.right.text}`;
159
+ if (assertion.kind === "implies") return `${assertion.guard.text} implies ${showAssertion(assertion.body)}`;
160
+ return assertion.items.map(showAssertion).join(" and ");
166
161
  }
167
162
  function explainExamples(law) {
168
- return law.original.examples
169
- .map(
170
- (ex) =>
171
- `\nexample ${JSON.stringify(ex.exampleName)}\n` +
172
- ex.bindings
173
- .map(([n, v]) => ` ${n} = ${JSON.stringify(v)}`)
174
- .join("\n") +
175
- "\n" +
176
- ex.expectations
177
- .map(
178
- (e) =>
179
- ` expect ${showExpression(e.actual)} = ${JSON.stringify(e.expected)}`,
180
- )
181
- .join("\n"),
182
- )
183
- .join("\n");
163
+ return law.examples.map(ex =>
164
+ `\nexample ${JSON.stringify(ex.name)}\n` +
165
+ ex.bindings.map(b => ` ${b.name} = ${showScalar(b.value)}`).join("\n") + "\n" +
166
+ ex.expectations.map(e => ` expect ${showAssertion(e)}`).join("\n")
167
+ ).join("\n");
184
168
  }
185
169
  async function main() {
170
+ if (options['machine-bits'] !== undefined) {
171
+ options.machineBits = Number(options['machine-bits']);
172
+ if (![32,64].includes(options.machineBits)) throw new Error('machineBits must be 32 or 64');
173
+ }
186
174
  if (!verb || ["help", "--help", "-h"].includes(verb)) {
187
175
  output(
188
- "LawSpec 0.6.0\nUsage: lawspec init --target <language> [--project <directory>]\n lawspec check | doctor | explain <unit>::<law> | generate\n lawspec examples [--target <language>] [--output example_artifacts]\nOptions: --config <path>, --target <language>, --json\nGeneration: --dry-run, --check\nTargets: " +
176
+ "LawSpec 0.8.0\nUsage: lawspec init --target <language> [--project <directory>]\n lawspec check | doctor | explain <unit>::<law> | generate\n lawspec examples [--target <language>] [--output example_artifacts]\nOptions: --config <path>, --target <language>, --machine-bits <32|64>, --json\nGeneration: --dry-run, --check\nTargets: " +
189
177
  targets.join(", "),
190
178
  );
191
179
  return;
192
180
  }
193
181
  if (verb === "--version") {
194
- output("0.6.0");
182
+ output("0.8.0");
195
183
  return;
196
184
  }
197
185
  if (positional.length > (verb === "explain" ? 1 : 0))
@@ -256,14 +244,15 @@ async function main() {
256
244
  if (reports.some((r) => !r.ok)) process.exitCode = 1;
257
245
  return;
258
246
  }
259
- const input = { sources: await sources(config) };
247
+ if (config.machineBits !== undefined && ![32, 64].includes(config.machineBits)) throw new Error("machineBits must be 32 or 64");
248
+ const input = { sources: await sources(config), generation: config.generation, machineBits: options.machineBits ?? config.machineBits ?? 64 };
260
249
  const compiler = await createCompiler();
261
250
  if (verb === "check") {
262
251
  const result = diagnostics(await compiler.check(input));
263
252
  output(
264
253
  options.json
265
254
  ? result
266
- : `Checked ${result.laws.length} executable law(s).`,
255
+ : `Checked ${result.laws.length} law(s).`,
267
256
  );
268
257
  return;
269
258
  }
@@ -274,7 +263,7 @@ async function main() {
274
263
  .filter(
275
264
  ({ e }) => !positional[0] || `${e.owner}::${e.name}` === positional[0],
276
265
  );
277
- if (!indices.length) throw new Error("No matching executable law");
266
+ if (!indices.length) throw new Error("No matching law");
278
267
  output(
279
268
  options.json
280
269
  ? indices.map(({ e, i }) => ({ ...e, expansion: result.expansions[i] }))
@@ -302,7 +291,7 @@ async function main() {
302
291
  ).files,
303
292
  );
304
293
  const reports = await Promise.all(
305
- selected.map((t, i) => doctor(t, roots[i])),
294
+ selected.map((t, i) => doctor(t, roots[i], artifacts[i])),
306
295
  );
307
296
  const failed = reports.filter((r) => !r.ok);
308
297
  if (failed.length)
package/build.json CHANGED
@@ -2,38 +2,94 @@
2
2
  "version": 1,
3
3
  "compilerSources": [
4
4
  "package.yaml",
5
+ "runtime/LawSpecRuntime.hs",
6
+ "runtime/LawSpecRuntime.java",
7
+ "runtime/lawspec_runtime.go",
8
+ "runtime/lawspec_runtime.mjs",
9
+ "runtime/lawspec_runtime.py",
10
+ "runtime/lawspec_runtime.rs",
11
+ "runtime/lawspec_strategies.rs",
12
+ "runtime/rust/Cargo.lock",
13
+ "runtime/rust/Cargo.toml",
5
14
  "src/LawSpec/Api.hs",
15
+ "src/LawSpec/Backend.hs",
16
+ "src/LawSpec/Common.hs",
6
17
  "src/LawSpec/Compile.hs",
18
+ "src/LawSpec/Core.hs",
19
+ "src/LawSpec/Core/Eval.hs",
20
+ "src/LawSpec/Core/Semantics.hs",
21
+ "src/LawSpec/Core/Validate.hs",
22
+ "src/LawSpec/CoreEmit.hs",
23
+ "src/LawSpec/CoreNativeScalarEmit.hs",
24
+ "src/LawSpec/CoreScalarEmit.hs",
25
+ "src/LawSpec/Domain.hs",
7
26
  "src/LawSpec/Emit.hs",
27
+ "src/LawSpec/Eval.hs",
28
+ "src/LawSpec/Frontend.hs",
8
29
  "src/LawSpec/Gen.hs",
9
30
  "src/LawSpec/Model.hs",
10
31
  "src/LawSpec/Parser.hs",
11
32
  "src/LawSpec/Prelude.hs",
33
+ "src/LawSpec/Public.hs",
34
+ "src/LawSpec/Refinement.hs",
35
+ "src/LawSpec/RuntimeSources.hs",
36
+ "src/LawSpec/RustEmit.hs",
37
+ "src/LawSpec/Scalar.hs",
38
+ "src/LawSpec/Testing.hs",
12
39
  "stack.yaml",
13
40
  "stack.yaml.lock",
41
+ "tools/embed-runtimes.py",
14
42
  "wasm/app/Exports.hs",
15
43
  "wasm/cabal.project",
16
44
  "wasm/cabal.project.freeze",
17
45
  "wasm/lawspec-wasm.cabal"
18
46
  ],
19
47
  "digests": {
20
- "package.yaml": "25d79d741039fe21e1164d789fdf4f698f135df7e4c96c82560e4f7efe8fbdf9",
21
- "src/LawSpec/Api.hs": "00b1e4bc81231ebd387f10652463904084ebf9c3c4486fd2c2217a6d4dbfc157",
22
- "src/LawSpec/Compile.hs": "64aa042ce2f0f460d691ea43fa27bf75576a49a6e852a068f62a2cf5a28e81b7",
23
- "src/LawSpec/Emit.hs": "85ab85d789c4e2c98703e2768075cb1c0bed42b987c45b5060b9a9df56e8d291",
24
- "src/LawSpec/Gen.hs": "c596e411790a47cb15b2945d391b9909cbec1972bf6e502ed8c069db2c67e991",
25
- "src/LawSpec/Model.hs": "549f553d1cc5d65c804a5acfac0cc06e63ff10eb80674893e32fcd3c0a71a5b3",
26
- "src/LawSpec/Parser.hs": "ae7c5ad29871b99441db2dae10548afafb2ae4931dd1a62208ca0f5e3545002c",
48
+ "package.yaml": "90923d07cf41977f62a201faf26667ae4fd76de84c6f25ce47917ac92a6a1f4b",
49
+ "runtime/LawSpecRuntime.hs": "1c3ca22232c64227717d836a57d375d906f748ecde6b79705944a2319ce5064d",
50
+ "runtime/LawSpecRuntime.java": "5637914bd491f75ad0c75fb19d1bec798164295b7bcf9d23e1549e8ebf780d01",
51
+ "runtime/lawspec_runtime.go": "62d2041c33760b67db619e0a803501768a505c4dfd9837bca85e158fff81fda9",
52
+ "runtime/lawspec_runtime.mjs": "7d0abd53fa45dd9828c10ff2ffa7876162e965e7bb4913f4c460af13e06142fa",
53
+ "runtime/lawspec_runtime.py": "7541353effebd133e50cd00a3f4d8999651c93ba751a6d951164b1f390ce0c15",
54
+ "runtime/lawspec_runtime.rs": "bf9cf5fa546346a59c85248936395fe11946974ce0bad053aeeaf4e26b6a829d",
55
+ "runtime/lawspec_strategies.rs": "a5dcee400574a69a5d2aa066bb8959e366728b3f21a578de84f50feadadf6641",
56
+ "runtime/rust/Cargo.lock": "91533e20939436e117c0f09ded695a8a05a86e79efc29fe4b4b93ad8ef1771c8",
57
+ "runtime/rust/Cargo.toml": "7ec66cf82dcc73a4a0b4a44d6048b6c3a340897c488aaaace9e8d4bac90b5e0a",
58
+ "src/LawSpec/Api.hs": "4810c05d53e370daf7520b9116c34997b7b4ba9c8d3f1a349e2afdb7b1424552",
59
+ "src/LawSpec/Backend.hs": "15ba04b69739e3891f73757d9cdc0a29acca6b7f7e067fd11d83d718474d0f20",
60
+ "src/LawSpec/Common.hs": "baa849dad0cc6227af334fdc7488389df50c0fe3a74a2ba1d84eb60c6b6edd6e",
61
+ "src/LawSpec/Compile.hs": "6c8bcea938f2ec3f83afb348c5ca932d96ce070f4e916fc9233a3a02ffcc89f2",
62
+ "src/LawSpec/Core.hs": "27ce2bb1274485cc190e10f8520118d5b381c90ac4ab6343223c46fb3cd10869",
63
+ "src/LawSpec/Core/Eval.hs": "87bf2acfdfff1431f1358947044c0474df40b5bc601076f5e5051e089f1d2fa4",
64
+ "src/LawSpec/Core/Semantics.hs": "a9d019433e3b9731f8cd0f65ec0ccc53179824bea58247b72df26760b878c2b6",
65
+ "src/LawSpec/Core/Validate.hs": "bd67926c872e190279f3758ad57b45c0f80d5be8381cedc8ac56a5b88b115201",
66
+ "src/LawSpec/CoreEmit.hs": "7ba225a262372f61edd6fe2ba0f2dbade44dfa2f767cdbcdd3f4c323eb5e9e7b",
67
+ "src/LawSpec/CoreNativeScalarEmit.hs": "f20382952f5854605ae617609c1ff9f5627e5acb134417cf3a67b97054844acb",
68
+ "src/LawSpec/CoreScalarEmit.hs": "db564e0cb07c69dee63b7dcb9cd524c30d4e7d658264d72f834adcc9fa05899d",
69
+ "src/LawSpec/Domain.hs": "8ad50ad3a37aacb3a429c2d7924279e2a3b973204ce3c5c04c634c1b9ada0151",
70
+ "src/LawSpec/Emit.hs": "9f34f5765915a2a12a66a6dca647ddaef9289372956802c6d99cf0cfec447c7a",
71
+ "src/LawSpec/Eval.hs": "bbaa50d3febee690c3b09ceb3f2592964cdb458dd1b4c38b6ec68a80f3e077ea",
72
+ "src/LawSpec/Frontend.hs": "b483732416f23960f0f03c30079a6db3ba630cf013b38fd6beede08b186585b8",
73
+ "src/LawSpec/Gen.hs": "f0a153e05fb0599a7cb2303dd62a269b2561738466c7211efc1927af2d5604b0",
74
+ "src/LawSpec/Model.hs": "75cedd730b8e8f7bff2dd39cfe3c1ed8f64e74471f6231248474957df446328f",
75
+ "src/LawSpec/Parser.hs": "e64356888d78f02572ff8c0a39b782248dd6a4bb9f0b1e30900f9dc12c3cd946",
27
76
  "src/LawSpec/Prelude.hs": "b1e155c12f58e7c346551a0c65c5d5af76d045b3f1625977ca2a5d1c97cb8c46",
77
+ "src/LawSpec/Public.hs": "eec6c9684b3c5cb42fa882f89460104856cb02f963822b66d9b9583dc011dfeb",
78
+ "src/LawSpec/Refinement.hs": "9902897edc0a803c2d440cf6d5a1d44e524f94b7384ea55a6f9dcd16dbfa8957",
79
+ "src/LawSpec/RuntimeSources.hs": "69dadd138bb784eaebd74869d03e30079e6d73e1724179794d8ec32be178e171",
80
+ "src/LawSpec/RustEmit.hs": "702652cc590c5db148f35d2e591d90e45270eee47e78c31772749943509aafe7",
81
+ "src/LawSpec/Scalar.hs": "2907d94b72e66584b762b5ab33da64adb26f9bf84b885151ef408dc3de1a440d",
82
+ "src/LawSpec/Testing.hs": "a5dc1c15a45539bb72d1c7cb24cbd04888bbb8ef2f066c829654c3bdbf32c609",
28
83
  "stack.yaml": "20ccf4d599e355e60b7aa4f814a7cd4299fe2048616cc2e6dbdc22a7bd8cec73",
29
84
  "stack.yaml.lock": "ae222b9c81af920c56e50fa4596fa57786e7fa5a7b461390362b2b2ff63818c7",
85
+ "tools/embed-runtimes.py": "26dda6ecf944ac065d10165d84ecdf44f134945fabbd48492a67d2495b5faba4",
30
86
  "wasm/app/Exports.hs": "4ecbdac8faa2449e6fc61b93c82e6278fa14374154f29b4dacf0eef433f06a47",
31
87
  "wasm/cabal.project": "021e560afdc5eb4cb7169e7119ecb8f92c9ee170245af909c94b612941bff5cc",
32
88
  "wasm/cabal.project.freeze": "733dbed3d2ecccb26e874fd58f136296dad772184deb1658c196b5d54a0814dc",
33
- "wasm/lawspec-wasm.cabal": "d0d9c395b96de75264d5dc62f7995f02b285aebc696a2cf603a62b4e280f9132",
34
- "npm/core.wasm": "e90e71610ca9f58a1b1e88d65f593c74d2a5b09347a4b47802bd771c954b7e42",
89
+ "wasm/lawspec-wasm.cabal": "22590b2a6fcd384ef8957bd179e04a055e90535f7eaaa2b5ac3d314fd0b686ed",
90
+ "npm/core.wasm": "09efa9e767c3d33e718a8a0909cdf23b24d158813570cc610f56e72d37a59fa3",
35
91
  "npm/core_jsffi.js": "88d136efe92f7cff5758c8fec8d9b6bbc9707fe37741cebeeb415fe34ce3d72b",
36
- "npm/api.mjs": "d6df654600172131ac66a55b86876fc29cde2a76a0a63bbefff3183488a4837b",
37
- "npm/index.d.ts": "628016928dc71dc735d59d15ccde45500d9a4133e3b20c8d3c21cb9c65ccb604"
92
+ "npm/api.mjs": "7415fc057ea5f4da68f9d255ce862152d6bc45d6b0053d44f61f9110911ac64b",
93
+ "npm/index.d.ts": "d19ecaea0be4ca01c8667a76e1bcfe758fd200d728ef67a44ad14e1b1dd15b72"
38
94
  }
39
95
  }
@@ -2,37 +2,120 @@
2
2
  "version": 1,
3
3
  "targets": {
4
4
  "java": {
5
- "java": ["25", "26"],
6
- "jetCheck": ["0.3.0", "0.3.1"],
7
- "junit-jupiter": ["5.14.0", "5.15.0"]
5
+ "java": [
6
+ "25",
7
+ "26"
8
+ ],
9
+ "jetCheck": [
10
+ "0.3.0",
11
+ "0.3.1"
12
+ ],
13
+ "junit-jupiter": [
14
+ "5.14.0",
15
+ "5.15.0"
16
+ ]
8
17
  },
9
18
  "python": {
10
- "python": ["3.13", "3.15"],
11
- "pytest": ["8.4.0", "8.5.0"],
12
- "hypothesis": ["6.135.26", "7"]
19
+ "python": [
20
+ "3.13",
21
+ "3.15"
22
+ ],
23
+ "pytest": [
24
+ "8.4.0",
25
+ "8.5.0"
26
+ ],
27
+ "hypothesis": [
28
+ "6.135.26",
29
+ "7"
30
+ ]
13
31
  },
14
32
  "javascript": {
15
- "fast-check": ["4", "5"]
33
+ "fast-check": [
34
+ "4",
35
+ "5"
36
+ ]
16
37
  },
17
38
  "typescript": {
18
- "fast-check": ["4", "5"],
19
- "typescript": ["5.9", "5.10"],
20
- "@types/node": ["22", "23"]
39
+ "fast-check": [
40
+ "4",
41
+ "5"
42
+ ],
43
+ "typescript": [
44
+ "5.9",
45
+ "5.10"
46
+ ],
47
+ "@types/node": [
48
+ "22",
49
+ "23"
50
+ ]
21
51
  },
22
52
  "go": {
23
- "go": ["1.22", "1.27"],
24
- "rapid": ["1.2.0", "1.2.1"]
53
+ "go": [
54
+ "1.22",
55
+ "1.27"
56
+ ],
57
+ "rapid": [
58
+ "1.2.0",
59
+ "1.2.1"
60
+ ]
25
61
  },
26
62
  "haskell": {
27
- "hspec": ["2.11", "2.12"],
28
- "hedgehog": ["1.5", "1.6"],
29
- "hspec-hedgehog": ["0.3.0.0", "0.3.0.1"],
30
- "ghc": ["9.10", "9.11"]
63
+ "hspec": [
64
+ "2.11",
65
+ "2.12"
66
+ ],
67
+ "hedgehog": [
68
+ "1.5",
69
+ "1.6"
70
+ ],
71
+ "hspec-hedgehog": [
72
+ "0.3.0.0",
73
+ "0.3.0.1"
74
+ ],
75
+ "ghc": [
76
+ "9.10",
77
+ "9.11"
78
+ ]
31
79
  },
32
80
  "kotlin": {
33
- "java": ["25", "26"],
34
- "gradle": ["9.1", "9.4"],
35
- "kotlin": ["2.3.21", "2.3.22"]
81
+ "java": [
82
+ "25",
83
+ "26"
84
+ ],
85
+ "gradle": [
86
+ "9.1",
87
+ "9.4"
88
+ ],
89
+ "kotlin": [
90
+ "2.3.21",
91
+ "2.3.22"
92
+ ]
93
+ },
94
+ "rust": {
95
+ "rust": [
96
+ "1.85",
97
+ "2"
98
+ ],
99
+ "proptest": [
100
+ "1.11.0",
101
+ "1.11.1"
102
+ ],
103
+ "num-bigint": [
104
+ "0.4.8",
105
+ "0.4.9"
106
+ ],
107
+ "num-rational": [
108
+ "0.4.2",
109
+ "0.4.3"
110
+ ],
111
+ "num-complex": [
112
+ "0.4.6",
113
+ "0.4.7"
114
+ ],
115
+ "num-traits": [
116
+ "0.2.19",
117
+ "0.2.20"
118
+ ]
36
119
  }
37
120
  }
38
121
  }
package/core.wasm CHANGED
Binary file