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.
Files changed (61) hide show
  1. package/API-MIGRATION.md +180 -3
  2. package/GO.md +144 -0
  3. package/HASKELL.md +171 -0
  4. package/JAVA.md +113 -0
  5. package/KOTLIN.md +214 -0
  6. package/LANGUAGE.md +240 -12
  7. package/NATIVE-BINDINGS.md +1046 -0
  8. package/PRIMITIVES.md +1 -1
  9. package/PYTHON.md +152 -0
  10. package/README.md +86 -23
  11. package/REFINEMENTS.md +289 -3
  12. package/RELEASE-0.10.md +60 -0
  13. package/RELEASE-0.9.md +61 -0
  14. package/RUST.md +115 -1
  15. package/WEB.md +144 -0
  16. package/api.mjs +28 -2
  17. package/bin/lawspec.mjs +23 -7
  18. package/build.json +199 -37
  19. package/core.wasm +0 -0
  20. package/examples/native-payments/go/example/payments/domain.go +38 -0
  21. package/examples/native-payments/go/example/payments/native_generators_test.go +13 -0
  22. package/examples/native-payments/go/lawspec.json +136 -0
  23. package/examples/native-payments/haskell/lawspec.json +149 -0
  24. package/examples/native-payments/haskell/src/PaymentsDomain.hs +21 -0
  25. package/examples/native-payments/haskell/test/PaymentGenerators.hs +12 -0
  26. package/examples/native-payments/java/lawspec.json +165 -0
  27. package/examples/native-payments/java/src/main/java/domain/PaymentsDomain.java +32 -0
  28. package/examples/native-payments/java/src/test/java/domain/PaymentGenerators.java +16 -0
  29. package/examples/native-payments/javascript/lawspec.json +149 -0
  30. package/examples/native-payments/javascript/src/payments_domain.mjs +44 -0
  31. package/examples/native-payments/javascript/test/lawspec_generators.mjs +6 -0
  32. package/examples/native-payments/kotlin/lawspec.json +165 -0
  33. package/examples/native-payments/kotlin/src/main/kotlin/domain/PaymentsDomain.kt +17 -0
  34. package/examples/native-payments/kotlin/src/test/kotlin/domain/PaymentGenerators.kt +12 -0
  35. package/examples/native-payments/python/lawspec.json +149 -0
  36. package/examples/native-payments/python/src/payments_domain.py +60 -0
  37. package/examples/native-payments/python/tests/lawspec_generators.py +15 -0
  38. package/examples/native-payments/rust/lawspec.json +167 -0
  39. package/examples/native-payments/rust/src/domain.rs +37 -0
  40. package/examples/native-payments/rust/src/lib.rs +2 -0
  41. package/examples/native-payments/rust/tests/support/lawspec_generators.rs +11 -0
  42. package/examples/native-payments/typescript/lawspec.json +149 -0
  43. package/examples/native-payments/typescript/src/payments_domain.ts +42 -0
  44. package/examples/native-payments/typescript/test/lawspec_generators.ts +8 -0
  45. package/examples/specs/collections.lawspec +67 -0
  46. package/examples/specs/data_types.lawspec +66 -0
  47. package/examples/specs/finite_data.lawspec +37 -0
  48. package/examples/specs/list_contracts.lawspec +136 -0
  49. package/examples/specs/list_refinements.lawspec +51 -0
  50. package/examples/specs/matching.lawspec +49 -0
  51. package/examples/specs/payments.lawspec +76 -0
  52. package/examples/specs/recursive_refinements.lawspec +41 -0
  53. package/examples/specs/refined_definitions.lawspec +44 -0
  54. package/examples/specs/sum_refinements.lawspec +49 -0
  55. package/examples/specs/total_functions.lawspec +101 -0
  56. package/examples-command.mjs +11 -1
  57. package/files.mjs +16 -7
  58. package/index.d.ts +297 -27
  59. package/native-examples.mjs +81 -0
  60. package/package.json +2 -2
  61. package/templates.mjs +107 -17
@@ -0,0 +1,41 @@
1
+ unit example.recursive_refinements
2
+
3
+ -- Refining a type argument follows its stored occurrences through recursion.
4
+ -- The fixed Int8 field remains independent of the refined argument.
5
+ type Tree (a :: Type) is
6
+ Leaf value :: a fixed :: Int8
7
+ Fork left :: Tree a right :: Tree a
8
+ end
9
+
10
+ refinement Positive is (value :: Int8 where value > 0) end
11
+
12
+ -- The payload guarantee is available when proving recursive definitions.
13
+ definition positiveSum (tree :: Tree Positive) :: (total :: BigInt where total > 0) is
14
+ match tree with
15
+ | Leaf value fixed -> value + 0
16
+ | Fork left right -> positiveSum left + positiveSum right
17
+ end
18
+ end
19
+
20
+ law `positive leaves have a positive total` is
21
+ definition is
22
+ `for all` (tree :: Tree Positive) . positiveSum tree > 0
23
+ end
24
+ example `fixed fields may be negative` is
25
+ tree = Fork (Leaf 1 -128) (Fork (Leaf 2 0) (Leaf 3 -1))
26
+ expect positiveSum tree = 6
27
+ end
28
+ end
29
+
30
+ -- Dependent predicates retain the enclosing input, even below several forks.
31
+ law `every stored argument exceeds the threshold` is
32
+ definition is
33
+ `for all` (threshold :: Int8 where threshold < 127)
34
+ (tree :: Tree (value :: Int8 where value > threshold)) . tree = tree
35
+ end
36
+ example `nested threshold` is
37
+ threshold = 4
38
+ tree = Fork (Leaf 5 -128) (Leaf 6 0)
39
+ expect tree = Fork (Leaf 5 -128) (Leaf 6 0)
40
+ end
41
+ end
@@ -0,0 +1,44 @@
1
+ unit example.refined_definitions
2
+
3
+ refinement Nonzero (T :: Type) requires Integer T is
4
+ (value :: T where value != 0)
5
+ end
6
+
7
+ -- The compiler proves division is defined under the input contract.
8
+ -- Native callers are checked before the body runs.
9
+ definition reciprocal (x :: Nonzero a) :: Rational
10
+ requires Integer a
11
+ is
12
+ 1 / x
13
+ end
14
+
15
+ -- Arithmetic promotes before this explicit, proved narrowing conversion.
16
+ definition increment (x :: Int8 where x < 127)
17
+ :: (result :: Int8 where result > x)
18
+ is
19
+ prelude.Int8 (x + 1)
20
+ end
21
+
22
+ -- Later argument refinements can depend on earlier arguments.
23
+ definition inverseGap (x :: Int8) (y :: Int8 where y > x) :: Rational is
24
+ 1 / (y - x)
25
+ end
26
+
27
+ law `exact reciprocal` is
28
+ definition is `for all` (x :: Nonzero Int8) . reciprocal x = 1 / x end
29
+ example `one half` is x = 2 expect reciprocal x = rational(1, 2) end
30
+ end
31
+
32
+ law `checked increment` is
33
+ definition is `for all` (x :: Int8 where x < 127) . increment x = x + 1 end
34
+ example `largest admitted input` is x = 126 expect increment x = 127 end
35
+ end
36
+
37
+ law `dependent gap` is
38
+ definition is `for all` (x :: Int8) (y :: Int8 where y > x) .
39
+ inverseGap x y = 1 / (y - x)
40
+ end
41
+ example `difference exceeds Int8` is
42
+ x = -128 y = 127 expect inverseGap x y = rational(1, 255)
43
+ end
44
+ end
@@ -0,0 +1,49 @@
1
+ unit example.sum_refinements
2
+
3
+ law `positive Maybe payloads` is
4
+ definition is `for all` (x :: Maybe (value :: Int8 where value > 0)) .
5
+ (match x with | Nothing -> true | Just payload -> payload >= 1 end) = true
6
+ end
7
+ example `absent` is x = Nothing expect x = Nothing end
8
+ example `present` is x = Just 1 expect x = Just 1 end
9
+ end
10
+
11
+ law `selected Either payload` is
12
+ definition is `for all`
13
+ (x :: Either (value :: Int8 where value > 0) (value :: Int8 where value < 0)) .
14
+ (match x with | Left payload -> payload >= 1 | Right payload -> payload <= -1 end) = true
15
+ end
16
+ example `left` is x = Left 1 expect x = Left 1 end
17
+ example `right` is x = Right -1 expect x = Right -1 end
18
+ end
19
+
20
+ law `nested Maybe states` is
21
+ definition is `for all` (x :: Maybe (Maybe (value :: Bool where value))) .
22
+ (match x with | Nothing -> true | Just inner ->
23
+ match inner with | Nothing -> true | Just payload -> payload end
24
+ end) = true
25
+ end
26
+ example `outer absent` is x = Nothing expect x = Nothing end
27
+ example `inner absent` is x = Just Nothing expect x = Just Nothing end
28
+ example `present` is x = Just (Just true) expect x = Just (Just true) end
29
+ end
30
+
31
+ law `finite Either variants` is
32
+ definition is `for all`
33
+ (x :: Either (value :: Bool where value) (value :: Bool where !value)) .
34
+ (match x with | Left payload -> payload | Right payload -> !payload end) = true
35
+ end
36
+ end
37
+
38
+ law `dependent payload keeps outer binding` is
39
+ definition is `for all` (lawspecElement :: Int8)
40
+ (x :: Maybe (value :: Int8 where value > lawspecElement)) .
41
+ (match x with | Nothing -> true | Just payload -> payload - lawspecElement >= 1 end) = true
42
+ end
43
+ example `maximum prefix has absent continuation` is
44
+ lawspecElement = 127 x = Nothing expect x = Nothing
45
+ end
46
+ example `present continuation` is
47
+ lawspecElement = 0 x = Just 1 expect x = Just 1
48
+ end
49
+ end
@@ -0,0 +1,101 @@
1
+ unit example.total_functions
2
+
3
+ -- These functions are implemented in the specification. LawSpec checks their
4
+ -- bodies and emits reusable source; they do not need adapter implementations.
5
+ definition increment (x :: a) :: BigInt
6
+ requires Integer a
7
+ is
8
+ x + 1
9
+ end
10
+
11
+ definition count (xs :: List a) :: BigInt is
12
+ match xs with
13
+ | Nil -> 0
14
+ | Cons head tail -> 1 + count tail
15
+ end
16
+ end
17
+
18
+ definition nonempty (xs :: List a) :: Bool is
19
+ match xs with
20
+ | Nil -> false
21
+ | Cons head tail -> true
22
+ end
23
+ end
24
+
25
+ law `nonempty lists have positive length` is
26
+ definition is
27
+ `for all` (xs :: List Int8 where nonempty xs) . count xs > 0
28
+ end
29
+ example `singleton` is xs = [0] expect count xs = 1 end
30
+ end
31
+
32
+ -- The exact guard proves that the promoted denominator cannot be zero.
33
+ definition positiveReciprocal (x :: a) :: Bool
34
+ requires Integer a
35
+ is
36
+ x >= 0 && 1 / (x + 1) > 0
37
+ end
38
+
39
+ law `guarded exact arithmetic` is
40
+ definition is
41
+ `for all` (x :: Int8) . positiveReciprocal x = (x >= 0)
42
+ end
43
+ example `skip zero denominator` is
44
+ x = -1 expect positiveReciprocal x = false
45
+ end
46
+ example `promote before division` is
47
+ x = 127 expect positiveReciprocal x = true
48
+ end
49
+ end
50
+
51
+ definition guardedNarrow (x :: Int8) :: Bool is
52
+ x < 127 && prelude.Int8 (x + 1) > x
53
+ end
54
+
55
+ law `narrow only after proving the range` is
56
+ definition is
57
+ `for all` (x :: Int8) . guardedNarrow x = (x < 127)
58
+ end
59
+ example `largest valid conversion` is x = 126 expect guardedNarrow x = true end
60
+ example `overflow branch is skipped` is x = 127 expect guardedNarrow x = false end
61
+ end
62
+
63
+ definition same (xs :: List a) (ys :: List a) :: Bool
64
+ requires Eq a
65
+ is
66
+ xs == ys
67
+ end
68
+
69
+ -- The same checked template produces independent concrete instances.
70
+ law `count also accepts text` is
71
+ definition is
72
+ `for all` (xs :: List Text) . count xs = prelude.length xs
73
+ end
74
+ example `two words` is xs = ["hello", "world"] expect count xs = 2 end
75
+ end
76
+
77
+ law `increment preserves the mathematical result` is
78
+ definition is
79
+ `for all` (x :: Int8) . increment x = x + 1
80
+ end
81
+ example `maximum input` is
82
+ x = 127 expect increment x = 128
83
+ end
84
+ end
85
+
86
+ law `recursive count agrees with length` is
87
+ definition is
88
+ `for all` (xs :: List Int8) . count xs = prelude.length xs
89
+ end
90
+ example `empty` is xs = [] expect count xs = 0 end
91
+ example `duplicates still count` is xs = [7, 7, 7] expect count xs = 3 end
92
+ end
93
+
94
+ law `list equality preserves duplicates and order` is
95
+ definition is
96
+ `for all` (xs :: List Int8) (ys :: List Int8) . same xs ys = (xs == ys)
97
+ end
98
+ example `different order` is
99
+ xs = [1, 2] ys = [2, 1] expect same xs ys = false
100
+ end
101
+ end
@@ -3,11 +3,16 @@ import path from "node:path";
3
3
  import { createCompiler } from "./api.mjs";
4
4
  import { targets } from "./templates.mjs";
5
5
  import { safePath, planWrites, applyWrites } from "./files.mjs";
6
+ import { exportNativePayments } from "./native-examples.mjs";
6
7
 
7
8
  export async function generateExamples(options) {
8
9
  const selected = options.target ? [options.target] : targets;
9
10
  if (selected.some((t) => !targets.includes(t)))
10
11
  throw new Error(`Unknown target: ${options.target}`);
12
+ if (options.example !== undefined) {
13
+ if (options.example !== "payments") throw new Error(`Unknown example: ${options.example}`);
14
+ return exportNativePayments(options, selected);
15
+ }
11
16
  const directory = new URL("./examples/specs/", import.meta.url);
12
17
  const sources = await Promise.all(
13
18
  (await readdir(directory))
@@ -21,7 +26,12 @@ export async function generateExamples(options) {
21
26
  const compiler = await createCompiler();
22
27
  const artifacts = [];
23
28
  for (const target of selected) {
24
- const result = await compiler.planGeneration({ sources, target, machineBits: options.machineBits ?? 64 });
29
+ const result = await compiler.planGeneration({
30
+ sources,
31
+ target,
32
+ machineBits: options.machineBits ?? 64,
33
+ minify: options.minify === true,
34
+ });
25
35
  if (result.diagnostics.length)
26
36
  throw Object.assign(new Error("Bundled examples failed to compile"), {
27
37
  diagnostics: result.diagnostics,
package/files.mjs CHANGED
@@ -63,8 +63,8 @@ export async function atomicWrite(file, content, exclusive = false) {
63
63
  }
64
64
  }
65
65
  }
66
- export async function planWrites(root, artifacts) {
67
- const manifestPath = await safePath(root, ".lawspec/generated.json");
66
+ export async function planWrites(root, artifacts, {manifest = ".lawspec/generated.json"} = {}) {
67
+ const manifestPath = await safePath(root, manifest);
68
68
  const previousText = await readOptional(manifestPath);
69
69
  const previous =
70
70
  previousText === null
@@ -89,7 +89,16 @@ export async function planWrites(root, artifacts) {
89
89
  const file = await safePath(root, artifact.path);
90
90
  const old = await readOptional(file);
91
91
  if (artifact.ownership === "user") {
92
- adapterHashes[artifact.path] = digest(artifact.content);
92
+ if (
93
+ artifact.adapterReference !== undefined &&
94
+ typeof artifact.adapterReference !== "string"
95
+ )
96
+ throw new Error(`Invalid adapter reference: ${artifact.path}`);
97
+ // Compare compiler-owned canonical scaffolds, never normalized user code.
98
+ // Older compilers and manifests used readable content as this reference.
99
+ adapterHashes[artifact.path] = digest(
100
+ artifact.adapterReference ?? artifact.content,
101
+ );
93
102
  if (
94
103
  old !== null &&
95
104
  previous.adapters?.[artifact.path] !== adapterHashes[artifact.path]
@@ -135,18 +144,18 @@ export async function planWrites(root, artifacts) {
135
144
  throw new Error(`Refusing to remove edited generated file: ${relative}`);
136
145
  changes.push({ action: "remove", file, relative, expected: old });
137
146
  }
138
- const manifest =
147
+ const manifestContent =
139
148
  JSON.stringify(
140
149
  { version: 1, files: next, adapters: adapterHashes },
141
150
  null,
142
151
  2,
143
152
  ) + "\n";
144
- if (manifest !== previousText)
153
+ if (manifestContent !== previousText)
145
154
  changes.push({
146
155
  action: previousText === null ? "create" : "update",
147
156
  file: manifestPath,
148
- relative: ".lawspec/generated.json",
149
- content: manifest,
157
+ relative: manifest,
158
+ content: manifestContent,
150
159
  expected: previousText,
151
160
  });
152
161
  return { root, changes, preserved, adapterUpdates };
package/index.d.ts CHANGED
@@ -1,29 +1,299 @@
1
1
  // Generated from LawSpec.Gen. Do not edit.
2
- export type Target = 'java' | 'python' | 'javascript' | 'typescript' | 'go' | 'haskell' | 'kotlin' | 'rust';
3
- export interface Source { path: string; content: string }
4
- export interface Location { file: string; line: number; column: number }
5
- export interface Span { start: Location; end: Location }
6
- export interface Diagnostic { code: string; message: string; at: Location | null }
7
- export interface Artifact { path: string; content: string; ownership: 'user' | 'generated'; placement: 'source' | 'test' }
8
- export type Type = {kind:'constructor'; name:string; arguments:TypeArgument[]} | {kind:'variable'; id:string} | {kind:'function'; parameter:Type; result:Type};
9
- export type TypeArgument = {kind:'type'; type:Type} | {kind:'natural'; value:string} | {kind:'indexVariable'; id:string};
10
- export type Origin = {kind:'source'; span:Span} | {kind:'generated'; declaration:string};
11
- export type Evidence = {kind:'numeric'|'structural'; type:Type};
12
- export interface Expr {type:Type; origin:Origin; text:string; node:ExprNode}
13
- export type ExprNode = {kind:'constant'; value:ScalarValue} | {kind:'local'; id:string} | {kind:'call'; declaration:string; arguments:Expr[]} | {kind:'binary'; operator:string; evidence:Evidence; left:Expr; right:Expr} | {kind:'unary'; operator:'-'|'!'; argument:Expr} | {kind:'shortCircuit'; operator:'&&'|'||'; left:Expr; right:Expr} | {kind:'convert'; conversion:'explicit'|'checked'; argument:Expr} | {kind:'helper'; name:string; arguments:Expr[]};
14
- export type Assertion = {kind:'equal'; evidence:Evidence; left:Expr; right:Expr} | {kind:'implies'; guard:Expr; body:Assertion} | {kind:'all'; items:Assertion[]};
15
- export interface Generation {cases:number; maxAttempts:number; maxShrinks:number; exhaustiveLimit:number}
16
- export interface Binder {id:string; name:string; type:Type}
17
- export interface Input extends Binder {predicates:Expr[]; bounds:{operator:string; value:Expr}[]}
18
- export interface Example {name:string; bindings:(Binder & {value:ScalarValue})[]; expectations:Assertion[]}
19
- export interface Law {id:string; owner:string; name:string; inputs:Input[]; assertion:Assertion; examples:Example[]; description:string; rationale:string; references:string[]; location:Location; trace:string[]; generation:Generation}
20
- export interface Unit {id:string; declarations:(Binder & {origin:Origin})[]}
21
- export interface Contract {id:string; name:string; arguments:Binder[]; result:Binder; preconditions:Expr[]; postconditions:Expr[]}
22
- export interface Refinement {owner:string; name:string; parameters:{name:string; kind:'type'|'value'; type:string}[]; requirements:{capability:string; type:string}[]; definition:string}
23
- export interface CheckRequest {sources:Source[]; schemaVersion?:3; machineBits?:32|64; generation?:Partial<Generation>}
24
- export interface GenerationRequest extends CheckRequest {target:Target; sourceDir?:string; testDir?:string}
25
- export interface Result {schemaVersion:3; machineBits?:32|64; generation?:Generation; units?:Unit[]; laws?:Law[]; contracts?:{owner:string; contract:Contract}[]; refinements?:Refinement[]; diagnostics:Diagnostic[]; expansions?:string[]; files?:Artifact[]}
26
- export type IntegerType = 'Int8' | 'Int16' | 'Int32' | 'Int64' | 'UInt8' | 'UInt16' | 'UInt32' | 'UInt64' | 'IntSize' | 'UIntSize' | 'UIntPtr' | 'Integer' | 'BigInt' | 'BigUInt';
27
- export type ScalarValue = {type: IntegerType; value: string} | {type: 'Bool'; value: boolean} | {type: 'Decimal'; coefficient: string; exponent: string} | {type: 'Rational'; numerator: string; denominator: string} | {type: 'Float32' | 'Float64'; bits: string} | {type: 'Complex64' | 'Complex128'; real: ScalarValue; imaginary: ScalarValue} | {type: 'Char' | 'CodePoint' | 'CodeUnit16'; value: number} | {type: 'Text' | 'CodePointText' | 'Utf16Text' | 'Bytes'; units: number[]} | {type: 'Symbol'; id: string; description: string} | {type: 'Unit' | 'Null' | 'Undefined'} | {type: 'Nullable' | 'Optional'; value: ScalarValue | null};
28
- export interface Compiler { check(input: CheckRequest): Promise<Result>; expand(input: CheckRequest): Promise<Result>; planGeneration(input: GenerationRequest): Promise<Result> }
2
+ export type Target =
3
+ 'java' |
4
+ 'python' |
5
+ 'javascript' |
6
+ 'typescript' |
7
+ 'go' |
8
+ 'haskell' |
9
+ 'kotlin' |
10
+ 'rust';
11
+
12
+ export interface Source {
13
+ path: string;
14
+ content: string;
15
+ }
16
+
17
+ export interface Location {
18
+ file: string;
19
+ line: number;
20
+ column: number;
21
+ }
22
+
23
+ export interface Span {
24
+ start: Location;
25
+ end: Location;
26
+ }
27
+
28
+ export interface Diagnostic {
29
+ code: string;
30
+ message: string;
31
+ at: Location | null;
32
+ }
33
+
34
+ export interface Artifact {
35
+ path: string;
36
+ content: string;
37
+ ownership: 'user' | 'generated';
38
+ placement: 'source' | 'test';
39
+ adapterReference?: string;
40
+ }
41
+
42
+ export type Type =
43
+ {kind: 'constructor'; name: string; arguments: TypeArgument[];} |
44
+ {kind: 'variable'; id: string;} |
45
+ {kind: 'function'; parameter: Type; result: Type;};
46
+
47
+ export type TypeArgument =
48
+ {kind: 'type'; type: Type;} |
49
+ {kind: 'natural'; value: string;} |
50
+ {kind: 'indexVariable'; id: string;};
51
+
52
+ export type Origin =
53
+ {kind: 'source'; span: Span;} | {kind: 'generated'; declaration: string;};
54
+
55
+ export type Evidence = {kind: 'numeric' | 'structural'; type: Type;};
56
+
57
+ export interface Expr {
58
+ type: Type;
59
+ origin: Origin;
60
+ text: string;
61
+ node: ExprNode;
62
+ }
63
+
64
+ export type ExprNode =
65
+ {kind: 'constant'; value: ScalarValue;} |
66
+ {kind: 'match'; value: Expr; cases: MatchCase[];} |
67
+ {kind: 'allElements'; value: Expr; binder: Binder; predicate: Expr;} |
68
+ {kind: 'allPayloads'; value: Expr; predicates: PayloadPredicate[];} |
69
+ {kind: 'construct'; constructor: string; arguments: Expr[];} |
70
+ {kind: 'local'; id: string;} |
71
+ {kind: 'call'; declaration: string; arguments: Expr[];} |
72
+ {
73
+ kind: 'binary';
74
+ operator: string;
75
+ evidence: Evidence;
76
+ left: Expr;
77
+ right: Expr;
78
+ } |
79
+ {kind: 'unary'; operator: '-' | '!'; argument: Expr;} |
80
+ {kind: 'shortCircuit'; operator: '&&' | '||'; left: Expr; right: Expr;} |
81
+ {kind: 'convert'; conversion: 'explicit' | 'checked'; argument: Expr;} |
82
+ {kind: 'helper'; name: string; arguments: Expr[];};
83
+
84
+ export type Assertion =
85
+ {kind: 'equal'; evidence: Evidence; left: Expr; right: Expr;} |
86
+ {kind: 'implies'; guard: Expr; body: Assertion;} |
87
+ {kind: 'all'; items: Assertion[];};
88
+
89
+ export interface Generation {
90
+ cases: number;
91
+ maxAttempts: number;
92
+ maxShrinks: number;
93
+ exhaustiveLimit: number;
94
+ }
95
+
96
+ export interface Binder {
97
+ id: string;
98
+ name: string;
99
+ type: Type;
100
+ }
101
+
102
+ export interface Definition {
103
+ owner: string;
104
+ id: string;
105
+ arguments: Binder[];
106
+ body: Expr;
107
+ }
108
+
109
+ export interface Input extends Binder {
110
+ predicates: Expr[];
111
+ bounds: {operator: string; value: Expr;}[];
112
+ }
113
+
114
+ export interface Example {
115
+ name: string;
116
+ bindings: (Binder & {value: DataValue;})[];
117
+ expectations: Assertion[];
118
+ }
119
+
120
+ export interface Law {
121
+ id: string;
122
+ owner: string;
123
+ name: string;
124
+ inputs: Input[];
125
+ assertion: Assertion;
126
+ examples: Example[];
127
+ description: string;
128
+ rationale: string;
129
+ references: string[];
130
+ location: Location;
131
+ trace: string[];
132
+ generation: Generation;
133
+ }
134
+
135
+ export interface Unit {
136
+ id: string;
137
+ declarations: (Binder & {origin: Origin;})[];
138
+ }
139
+
140
+ export interface DataTypeDeclaration {
141
+ id: string;
142
+ name: string;
143
+ parameters: string[];
144
+ origin: Origin;
145
+ constructors: {id: string; name: string; fields: Binder[]; origin: Origin;}[];
146
+ }
147
+
148
+ export interface Contract {
149
+ id: string;
150
+ name: string;
151
+ arguments: Binder[];
152
+ result: Binder;
153
+ preconditions: Expr[];
154
+ postconditions: Expr[];
155
+ }
156
+
157
+ export interface Refinement {
158
+ owner: string;
159
+ name: string;
160
+ parameters: {name: string; kind: 'type' | 'value'; type: string;}[];
161
+ requirements: {capability: string; type: string;}[];
162
+ definition: string;
163
+ }
164
+
165
+ export type NativeReference = string[];
166
+
167
+ export interface NativeFieldBinding {
168
+ field: string;
169
+ native: string;
170
+ }
171
+
172
+ export interface NativeConstructorBinding {
173
+ constructor: string;
174
+ native: NativeReference;
175
+ fields?: NativeFieldBinding[];
176
+ style: 'record' | 'variant' | 'unit';
177
+ }
178
+
179
+ export interface NativeCodecBinding {
180
+ toNative: NativeReference;
181
+ fromNative: NativeReference;
182
+ }
183
+
184
+ export interface NativeTypeBinding {
185
+ type: string;
186
+ native: NativeReference;
187
+ constructors?: NativeConstructorBinding[];
188
+ codec?: NativeCodecBinding;
189
+ }
190
+
191
+ export interface NativeGeneratorBinding {
192
+ type: string;
193
+ factory: NativeReference;
194
+ stub?: boolean;
195
+ }
196
+
197
+ export interface NativeFunctionBinding {
198
+ declaration: string;
199
+ native: NativeReference;
200
+ }
201
+
202
+ export interface NativeGoImport {
203
+ alias: string;
204
+ path: string;
205
+ }
206
+
207
+ export interface NativeBindings {
208
+ types?: NativeTypeBinding[];
209
+ generators?: NativeGeneratorBinding[];
210
+ functions?: NativeFunctionBinding[];
211
+ rustCrate?: string;
212
+ goImports?: NativeGoImport[];
213
+ }
214
+
215
+ export interface CheckRequest {
216
+ sources: Source[];
217
+ schemaVersion?: 3 | 4;
218
+ machineBits?: 32 | 64;
219
+ generation?: Partial<Generation>;
220
+ nativeBindings?: NativeBindings;
221
+ }
222
+
223
+ export interface GenerationRequest extends CheckRequest {
224
+ target: Target;
225
+ sourceDir?: string;
226
+ testDir?: string;
227
+ minify?: boolean;
228
+ }
229
+
230
+ export interface Result {
231
+ schemaVersion: 3 | 4;
232
+ machineBits?: 32 | 64;
233
+ generation?: Generation;
234
+ units?: Unit[];
235
+ dataTypes?: DataTypeDeclaration[];
236
+ definitions?: Definition[];
237
+ laws?: Law[];
238
+ contracts?: {owner: string; contract: Contract;}[];
239
+ refinements?: Refinement[];
240
+ diagnostics: Diagnostic[];
241
+ expansions?: string[];
242
+ files?: Artifact[];
243
+ }
244
+
245
+ export interface PayloadPredicate {
246
+ binder: Binder;
247
+ predicate: Expr;
248
+ }
249
+
250
+ export interface MatchCase {
251
+ constructor: string;
252
+ binders: Binder[];
253
+ body: Expr;
254
+ }
255
+
256
+ export type DataValue =
257
+ ScalarValue |
258
+ {kind: 'data'; type: Type; constructor: string; fields: DataValue[];};
259
+
260
+ export type IntegerType =
261
+ 'Int8' |
262
+ 'Int16' |
263
+ 'Int32' |
264
+ 'Int64' |
265
+ 'UInt8' |
266
+ 'UInt16' |
267
+ 'UInt32' |
268
+ 'UInt64' |
269
+ 'IntSize' |
270
+ 'UIntSize' |
271
+ 'UIntPtr' |
272
+ 'Integer' |
273
+ 'BigInt' |
274
+ 'BigUInt';
275
+
276
+ export type ScalarValue =
277
+ {type: IntegerType; value: string;} |
278
+ {type: 'Bool'; value: boolean;} |
279
+ {type: 'Decimal'; coefficient: string; exponent: string;} |
280
+ {type: 'Rational'; numerator: string; denominator: string;} |
281
+ {type: 'Float32' | 'Float64'; bits: string;} |
282
+ {
283
+ type: 'Complex64' | 'Complex128';
284
+ real: ScalarValue;
285
+ imaginary: ScalarValue;
286
+ } |
287
+ {type: 'Char' | 'CodePoint' | 'CodeUnit16'; value: number;} |
288
+ {type: 'Text' | 'CodePointText' | 'Utf16Text' | 'Bytes'; units: number[];} |
289
+ {type: 'Symbol'; id: string; description: string;} |
290
+ {type: 'Unit' | 'Null' | 'Undefined';} |
291
+ {type: 'Nullable' | 'Optional'; value: ScalarValue | null;};
292
+
293
+ export interface Compiler {
294
+ check(input: CheckRequest): Promise<Result>;
295
+ expand(input: CheckRequest): Promise<Result>;
296
+ planGeneration(input: GenerationRequest): Promise<Result>;
297
+ }
298
+
29
299
  export function createCompiler(): Promise<Compiler>;