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/API-MIGRATION.md +103 -0
- package/LANGUAGE.md +136 -0
- package/PRIMITIVES.md +150 -0
- package/README.md +55 -30
- package/REFINEMENTS.md +158 -0
- package/RUST.md +97 -0
- package/api.mjs +1 -1
- package/bin/lawspec.mjs +24 -35
- package/build.json +67 -11
- package/compatibility.json +102 -19
- package/core.wasm +0 -0
- package/doctor.mjs +31 -2
- package/examples/specs/algebra.lawspec +36 -8
- package/examples/specs/currying.lawspec +1 -1
- package/examples/specs/refinements.lawspec +86 -0
- package/examples/specs/scalar_adapters.lawspec +83 -0
- package/examples/specs/scalar_catalog.lawspec +166 -0
- package/examples/specs/scalars.lawspec +138 -0
- package/examples-command.mjs +2 -2
- package/index.d.ts +23 -13
- package/package.json +2 -2
- package/scalars.mjs +13 -0
- package/templates.mjs +25 -1
package/doctor.mjs
CHANGED
|
@@ -67,14 +67,14 @@ async function installed(req, name) {
|
|
|
67
67
|
dir = parent;
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
-
export async function doctor(target, root) {
|
|
70
|
+
export async function doctor(target, root, plannedArtifacts = []) {
|
|
71
71
|
const name = target.language;
|
|
72
72
|
const defaults =
|
|
73
73
|
name === "java"
|
|
74
74
|
? ["src/main/java", "src/test/java"]
|
|
75
75
|
: name === "kotlin"
|
|
76
76
|
? ["src/main/kotlin", "src/test/kotlin"]
|
|
77
|
-
: ["src",
|
|
77
|
+
: ["src", ["python", "rust"].includes(name) ? "tests" : "test"];
|
|
78
78
|
const sourceDir = target.sourceDir ?? defaults[0];
|
|
79
79
|
const testDir = target.testDir ?? defaults[1];
|
|
80
80
|
try {
|
|
@@ -257,6 +257,8 @@ export async function doctor(target, root) {
|
|
|
257
257
|
"The Stack profile requires one package per target root",
|
|
258
258
|
);
|
|
259
259
|
const cabal = await readFile(path.join(root, cabals[0]), "utf8");
|
|
260
|
+
const components = cabal.split(/^(?:library(?:[ \t]+\S+)?|test-suite[ \t]+\S+)[ \t]*\n/m).slice(1).map(s => s.split(/\n(?=\S)/)[0]);
|
|
261
|
+
requireThat(components.some(s => s.includes(sourceDir) && ['text','bytestring'].every(dep => new RegExp(`(?:^|[\\s,])${dep}(?=[\\s,<>=]|$)`).test(s))), "The component compiling generated source must directly depend on text and bytestring");
|
|
260
262
|
const suites = cabal
|
|
261
263
|
.split(/^test-suite\s+/m)
|
|
262
264
|
.slice(1)
|
|
@@ -355,6 +357,33 @@ export async function doctor(target, root) {
|
|
|
355
357
|
),
|
|
356
358
|
"The JUnit Jupiter test engine must be on the test classpath",
|
|
357
359
|
);
|
|
360
|
+
} else if (name === "rust") {
|
|
361
|
+
const compiler = target.rustc || "rustc";
|
|
362
|
+
const cargo = target.cargo || "cargo";
|
|
363
|
+
versions.rust = (await run(compiler, ["--version"], root)).match(/^rustc (\d+\.\d+\.\d+)/)?.[1];
|
|
364
|
+
requireThat(versions.rust && compare(versions.rust, "1.85.0") >= 0, "Rust 1.85+ is required");
|
|
365
|
+
const data = JSON.parse(await run(cargo, ["metadata", "--format-version", "1"], root));
|
|
366
|
+
const pkg = data.packages.find(p => path.resolve(p.manifest_path) === path.join(root, "Cargo.toml"));
|
|
367
|
+
requireThat(pkg, "Select a Cargo package directory containing Cargo.toml");
|
|
368
|
+
requireThat(pkg.edition === "2024", "Cargo package must use edition 2024");
|
|
369
|
+
const node = data.resolve.nodes.find(n => n.id === pkg.id);
|
|
370
|
+
for (const dep of ["proptest", "num-bigint", "num-rational", "num-complex", "num-traits"]) {
|
|
371
|
+
const reference = node.deps.find(d => d.name === dep.replaceAll("-", "_"));
|
|
372
|
+
versions[dep] = data.packages.find(p => p.id === reference?.pkg)?.version;
|
|
373
|
+
requireThat(versions[dep], `Missing direct Cargo dependency: ${dep}`);
|
|
374
|
+
}
|
|
375
|
+
const manifest = await readFile(path.join(root, "Cargo.toml"), "utf8");
|
|
376
|
+
requireThat(!/harness\s*=\s*false/.test(manifest), "Rust generated tests require the standard Cargo test harness");
|
|
377
|
+
const testRoot = path.resolve(root, testDir);
|
|
378
|
+
const expectedTests = plannedArtifacts.length
|
|
379
|
+
? plannedArtifacts.filter(f => f.placement === "test" && f.path.endsWith("_lawspec.rs")).map(f => path.resolve(root, f.path))
|
|
380
|
+
: (await readdir(testRoot).catch(error => {if(error.code === "ENOENT") return []; throw error;})).filter(n => n.endsWith("_lawspec.rs")).map(n => path.join(testRoot,n));
|
|
381
|
+
if (testDir !== "tests" || /autotests\s*=\s*false/.test(manifest)) {
|
|
382
|
+
const registered = new Set(pkg.targets.filter(t => t.kind.includes("test") && t.test).map(t => path.resolve(t.src_path)));
|
|
383
|
+
requireThat(expectedTests.length ? expectedTests.every(file => registered.has(file)) : [...registered].some(file => file.startsWith(testRoot + path.sep)), "Register every generated Rust test file with Cargo [[test]] entries for this custom layout");
|
|
384
|
+
}
|
|
385
|
+
const library = pkg.targets.find(t => t.kind.includes("lib"));
|
|
386
|
+
requireThat(!library || path.dirname(path.resolve(library.src_path)) === path.resolve(root, sourceDir), "Cargo library path must match the configured sourceDir");
|
|
358
387
|
} else if (name === "kotlin") {
|
|
359
388
|
const command =
|
|
360
389
|
target.gradle ||
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
unit example.algebra
|
|
2
2
|
|
|
3
|
-
--
|
|
4
|
-
add ::
|
|
5
|
-
multiply ::
|
|
6
|
-
negateValue ::
|
|
7
|
-
maximumValue ::
|
|
8
|
-
subtractValue ::
|
|
9
|
-
divideLeft ::
|
|
10
|
-
divideRight ::
|
|
3
|
+
-- Integer denotes mathematical integers. Adapter results must remain exact.
|
|
4
|
+
add :: Integer -> Integer -> Integer
|
|
5
|
+
multiply :: Integer -> Integer -> Integer
|
|
6
|
+
negateValue :: Integer -> Integer
|
|
7
|
+
maximumValue :: Integer -> Integer -> Integer
|
|
8
|
+
subtractValue :: Integer -> Integer -> Integer
|
|
9
|
+
divideLeft :: Integer -> Integer -> Integer
|
|
10
|
+
divideRight :: Integer -> Integer -> Integer
|
|
11
11
|
|
|
12
12
|
law `addition is commutative` is
|
|
13
13
|
definition is
|
|
@@ -20,6 +20,20 @@ law `addition is commutative` is
|
|
|
20
20
|
expect add x y = 8
|
|
21
21
|
expect add y x = 8
|
|
22
22
|
end
|
|
23
|
+
|
|
24
|
+
example `addition exceeds the Int32 maximum without wrapping` is
|
|
25
|
+
x = 2147483647
|
|
26
|
+
y = 1
|
|
27
|
+
expect add x y = 2147483648
|
|
28
|
+
expect add y x = 2147483648
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
example `addition remains exact beyond machine and safe-number bounds` is
|
|
32
|
+
x = 18446744073709551615
|
|
33
|
+
y = 2
|
|
34
|
+
expect add x y = 18446744073709551617
|
|
35
|
+
expect add y x = 18446744073709551617
|
|
36
|
+
end
|
|
23
37
|
end
|
|
24
38
|
|
|
25
39
|
law `addition is associative` is
|
|
@@ -116,6 +130,14 @@ law `multiplication distributes over addition left` is
|
|
|
116
130
|
expect multiply x (add y z) = 36
|
|
117
131
|
expect add (multiply x y) (multiply x z) = 36
|
|
118
132
|
end
|
|
133
|
+
|
|
134
|
+
example `multiplication preserves products outside Int32` is
|
|
135
|
+
x = 2147483647
|
|
136
|
+
y = 2147483647
|
|
137
|
+
z = 1
|
|
138
|
+
expect multiply x y = 4611686014132420609
|
|
139
|
+
expect multiply x (add y z) = 4611686016279904256
|
|
140
|
+
end
|
|
119
141
|
end
|
|
120
142
|
|
|
121
143
|
law `multiplication distributes over addition right` is
|
|
@@ -251,4 +273,10 @@ law `negation is an involution` is
|
|
|
251
273
|
expect negateValue x = 3
|
|
252
274
|
expect negateValue (negateValue x) = -3
|
|
253
275
|
end
|
|
276
|
+
|
|
277
|
+
example `negating the Int32 minimum produces a positive integer` is
|
|
278
|
+
x = -2147483648
|
|
279
|
+
expect negateValue x = 2147483648
|
|
280
|
+
expect negateValue (negateValue x) = -2147483648
|
|
281
|
+
end
|
|
254
282
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
unit example.currying
|
|
2
2
|
|
|
3
|
-
sumFour ::
|
|
3
|
+
sumFour :: Integer -> Integer -> Integer -> Integer -> Integer
|
|
4
4
|
format :: Text -> Bool -> Int32 -> Text -> Text
|
|
5
5
|
referenceFormat :: Text -> Bool -> Int32 -> Text -> Text
|
|
6
6
|
trim :: Text -> Text
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
unit example.refinements
|
|
2
|
+
|
|
3
|
+
refinement Between (T :: Type) (minimum :: T) (maximum :: T)
|
|
4
|
+
requires Ordered T is
|
|
5
|
+
(value :: T where minimum <= value && value <= maximum)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
refinement Positive (T :: Type) requires Integer T is
|
|
9
|
+
(value :: T where value > 0)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
refinement AdditionOverflows (T :: Type) (left :: T)
|
|
13
|
+
requires Integer T Bounded T is
|
|
14
|
+
(right :: T where left + right > T.max)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
add :: (x :: Int8)
|
|
18
|
+
-> (y :: AdditionOverflows Int8 x)
|
|
19
|
+
-> (result :: Integer where result == x + y)
|
|
20
|
+
successor :: (x :: Int8) -> (result :: Integer where result == x + 1)
|
|
21
|
+
count :: (text :: Text where prelude.length text > 0)
|
|
22
|
+
-> (result :: Integer where result == prelude.length text)
|
|
23
|
+
preserve :: (x :: UInt64) -> (result :: Integer where result == x)
|
|
24
|
+
positive :: (x :: Positive Int8) -> (result :: Positive Int8 where result == x)
|
|
25
|
+
|
|
26
|
+
law `maximum input` is
|
|
27
|
+
definition is `for all` (x :: Int8) . successor x = x + 1 end
|
|
28
|
+
example `beyond Int8` is x = 127 expect successor x = 128 end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
law `overflow pairs` is
|
|
32
|
+
definition is
|
|
33
|
+
`for all` (x :: Int8) (y :: AdditionOverflows Int8 x) .
|
|
34
|
+
add x y = x + y
|
|
35
|
+
end
|
|
36
|
+
example `smallest overflowing sum` is x = 127 y = 1 expect add x y = 128 end
|
|
37
|
+
example `largest sum` is x = 127 y = 127 expect add x y = 254 end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
law `bounded input` is
|
|
41
|
+
definition is `for all` (x :: Between Int8 1 3) . positive x = x end
|
|
42
|
+
example `middle` is x = 2 expect positive x = 2 end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
law `large integer` is
|
|
46
|
+
definition is `for all` (x :: UInt64) . preserve x = x end
|
|
47
|
+
example `maximum UInt64` is x = 18446744073709551615 expect preserve x = 18446744073709551615 end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
abstractEcho :: (x :: Integer) -> (result :: Integer where result == x)
|
|
51
|
+
|
|
52
|
+
law `nested presence` is
|
|
53
|
+
definition is `for all` (x :: Optional (Nullable (Positive Int8))) . x = x end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
law `finite positive floats` is
|
|
57
|
+
definition is
|
|
58
|
+
`for all` (x :: Float32 where prelude.isFinite x && x > 0) .
|
|
59
|
+
prelude.isFinite x
|
|
60
|
+
end
|
|
61
|
+
example `positive` is x = 0.5 expect x = 0.5 end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
law `raw byte length` is
|
|
65
|
+
definition is `for all` (x :: Bytes where prelude.length x == 3) . prelude.length x = 3 end
|
|
66
|
+
example `arbitrary octets` is x = bytes([0,128,255]) expect prelude.length x = 3 end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
law `guarded predicate arithmetic` is
|
|
70
|
+
definition is `for all` (x :: Int8) (y :: Int8 where x != 0 && y > 10 / x) . y > 10 / x end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
law `machine bound` is
|
|
74
|
+
definition is `for all` (x :: IntSize where x == IntSize.max) . x = IntSize.max end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
law `symbol fixture refinement` is
|
|
78
|
+
definition is
|
|
79
|
+
`for all` (x :: Symbol where x == symbol("selected", "fixture")) .
|
|
80
|
+
x = symbol("selected", "fixture")
|
|
81
|
+
end
|
|
82
|
+
example `selected identity` is
|
|
83
|
+
x = symbol("selected", "fixture")
|
|
84
|
+
expect x = symbol("selected", "fixture")
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
unit example.scalar_adapters
|
|
2
|
+
echoChar :: Char -> Char
|
|
3
|
+
echoCodePoint :: CodePoint -> CodePoint
|
|
4
|
+
echoCodeUnit :: CodeUnit16 -> CodeUnit16
|
|
5
|
+
echoBytes :: Bytes -> Bytes
|
|
6
|
+
echoComplex :: Complex64 -> Complex64
|
|
7
|
+
successor :: Int8 -> BigInt
|
|
8
|
+
narrow :: Int8 -> Int8
|
|
9
|
+
addDecimal :: Decimal -> Decimal -> Decimal
|
|
10
|
+
sameSymbol :: Symbol -> Symbol -> Bool
|
|
11
|
+
echoRaw :: Utf16Text -> Utf16Text
|
|
12
|
+
echoPresence :: Optional (Nullable Int8) -> Optional (Nullable Int8)
|
|
13
|
+
finish :: Unit -> Unit
|
|
14
|
+
preserveBig :: UInt64 -> UInt64
|
|
15
|
+
machineEcho :: IntSize -> IntSize
|
|
16
|
+
|
|
17
|
+
law `promoted successor` is
|
|
18
|
+
definition is `for all` (x :: Int8) . successor x = x + 1 end
|
|
19
|
+
example `no overflow` is x = 127 expect successor x = 128 end
|
|
20
|
+
end
|
|
21
|
+
law `checked bridge` is
|
|
22
|
+
definition is `for all` (x :: Int8) . narrow (x + 0) = x end
|
|
23
|
+
example `maximum` is x = 127 expect narrow (x + 0) = 127 end
|
|
24
|
+
end
|
|
25
|
+
law `exact decimal adapter` is
|
|
26
|
+
definition is `for all` (x :: Decimal) (y :: Decimal) . addDecimal x y = x + y end
|
|
27
|
+
example `tenths` is x = 0.1 y = 0.2 expect addDecimal x y = 0.3 end
|
|
28
|
+
end
|
|
29
|
+
law `symbol identity adapter` is
|
|
30
|
+
definition is `for all` (x :: Symbol) (y :: Symbol) . sameSymbol x x and sameSymbol y y end
|
|
31
|
+
example `same description distinct identities` is
|
|
32
|
+
x = symbol("a", "same") y = symbol("b", "same")
|
|
33
|
+
expect sameSymbol x y = false
|
|
34
|
+
expect sameSymbol x x = true
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
law `raw adapter` is
|
|
38
|
+
definition is `for all` (x :: Utf16Text) . echoRaw x = x end
|
|
39
|
+
example `lone surrogate` is x = utf16([55296]) expect echoRaw x = utf16([55296]) end
|
|
40
|
+
end
|
|
41
|
+
law `presence adapter` is
|
|
42
|
+
definition is `for all` (x :: Optional (Nullable Int8)) . echoPresence x = x end
|
|
43
|
+
example `missing` is x = undefined expect echoPresence x = undefined end
|
|
44
|
+
example `null present` is x = optional(null) expect echoPresence x = optional(null) end
|
|
45
|
+
end
|
|
46
|
+
law `unit adapter` is
|
|
47
|
+
definition is `for all` (x :: Unit) . finish x = unitValue end
|
|
48
|
+
example `completed` is x = unitValue expect finish x = unitValue end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
law `no safe-number truncation` is
|
|
52
|
+
definition is `for all` (x :: UInt64) . preserveBig x = x end
|
|
53
|
+
example `unsigned maximum` is x = 18446744073709551615 expect preserveBig x = 18446744073709551615 end
|
|
54
|
+
end
|
|
55
|
+
law `machine profile binding` is
|
|
56
|
+
definition is `for all` (x :: IntSize) . machineEcho x = x end
|
|
57
|
+
example `portable width` is x = 2147483647 expect machineEcho x = 2147483647 end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
law `Char native bridge` is
|
|
61
|
+
definition is `for all` (x :: Char) . echoChar x = x end
|
|
62
|
+
example `native value` is x = char(128512) expect echoChar x = char(128512) end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
law `CodePoint native bridge` is
|
|
66
|
+
definition is `for all` (x :: CodePoint) . echoCodePoint x = x end
|
|
67
|
+
example `native value` is x = codePoint(55296) expect echoCodePoint x = codePoint(55296) end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
law `CodeUnit16 native bridge` is
|
|
71
|
+
definition is `for all` (x :: CodeUnit16) . echoCodeUnit x = x end
|
|
72
|
+
example `native value` is x = codeUnit16(65535) expect echoCodeUnit x = codeUnit16(65535) end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
law `Bytes native bridge` is
|
|
76
|
+
definition is `for all` (x :: Bytes) . echoBytes x = x end
|
|
77
|
+
example `native value` is x = bytes([0,128,255]) expect echoBytes x = bytes([0,128,255]) end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
law `Complex64 native bridge` is
|
|
81
|
+
definition is `for all` (x :: Complex64) . prelude.isNaN (prelude.real (echoComplex x)) = prelude.isNaN (prelude.real x) end
|
|
82
|
+
example `native value` is x = complex64(1,2) expect echoComplex x = complex64(1,2) end
|
|
83
|
+
end
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
unit example.scalar_catalog
|
|
2
|
+
|
|
3
|
+
law `Bool representation` is
|
|
4
|
+
definition is `for all` (x :: Bool) . x = x end
|
|
5
|
+
example `explicit value` is x = true expect x = true end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
law `Int8 representation` is
|
|
9
|
+
definition is `for all` (x :: Int8) . x = x end
|
|
10
|
+
example `explicit value` is x = -128 expect x = -128 end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
law `Int16 representation` is
|
|
14
|
+
definition is `for all` (x :: Int16) . x = x end
|
|
15
|
+
example `explicit value` is x = 32767 expect x = 32767 end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
law `Int32 representation` is
|
|
19
|
+
definition is `for all` (x :: Int32) . x = x end
|
|
20
|
+
example `explicit value` is x = 2147483647 expect x = 2147483647 end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
law `Int64 representation` is
|
|
24
|
+
definition is `for all` (x :: Int64) . x = x end
|
|
25
|
+
example `explicit value` is x = 9223372036854775807 expect x = 9223372036854775807 end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
law `UInt8 representation` is
|
|
29
|
+
definition is `for all` (x :: UInt8) . x = x end
|
|
30
|
+
example `explicit value` is x = 255 expect x = 255 end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
law `UInt16 representation` is
|
|
34
|
+
definition is `for all` (x :: UInt16) . x = x end
|
|
35
|
+
example `explicit value` is x = 65535 expect x = 65535 end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
law `UInt32 representation` is
|
|
39
|
+
definition is `for all` (x :: UInt32) . x = x end
|
|
40
|
+
example `explicit value` is x = 4294967295 expect x = 4294967295 end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
law `UInt64 representation` is
|
|
44
|
+
definition is `for all` (x :: UInt64) . x = x end
|
|
45
|
+
example `explicit value` is x = 18446744073709551615 expect x = 18446744073709551615 end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
law `IntSize representation` is
|
|
49
|
+
definition is `for all` (x :: IntSize) . x = x end
|
|
50
|
+
example `explicit value` is x = 2147483647 expect x = 2147483647 end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
law `UIntSize representation` is
|
|
54
|
+
definition is `for all` (x :: UIntSize) . x = x end
|
|
55
|
+
example `explicit value` is x = 4294967295 expect x = 4294967295 end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
law `UIntPtr representation` is
|
|
59
|
+
definition is `for all` (x :: UIntPtr) . x = x end
|
|
60
|
+
example `explicit value` is x = 4294967295 expect x = 4294967295 end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
law `BigInt representation` is
|
|
64
|
+
definition is `for all` (x :: BigInt) . x = x end
|
|
65
|
+
example `explicit value` is x = -1234567890123456789012345678901234567890 expect x = -1234567890123456789012345678901234567890 end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
law `BigUInt representation` is
|
|
69
|
+
definition is `for all` (x :: BigUInt) . x = x end
|
|
70
|
+
example `explicit value` is x = 1234567890123456789012345678901234567890 expect x = 1234567890123456789012345678901234567890 end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
law `Decimal representation` is
|
|
74
|
+
definition is `for all` (x :: Decimal) . x = x end
|
|
75
|
+
example `explicit value` is x = 0.000000000000000000000000000000000001 expect x = 0.000000000000000000000000000000000001 end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
law `Rational representation` is
|
|
79
|
+
definition is `for all` (x :: Rational) . x = x end
|
|
80
|
+
example `explicit value` is x = rational(-7, 11) expect x = rational(-7, 11) end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
law `Float32 representation` is
|
|
84
|
+
definition is `for all` (x :: Float32) . prelude.isNaN x = prelude.isNaN x end
|
|
85
|
+
example `explicit value` is x = float32Bits("80000000") expect x = float32Bits("80000000") end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
law `Float64 representation` is
|
|
89
|
+
definition is `for all` (x :: Float64) . prelude.isNaN x = prelude.isNaN x end
|
|
90
|
+
example `explicit value` is x = float64Bits("7ff0000000000000") expect x = float64Bits("7ff0000000000000") end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
law `Complex64 representation` is
|
|
94
|
+
definition is `for all` (x :: Complex64) . prelude.isNaN (prelude.real x) = prelude.isNaN (prelude.real x) end
|
|
95
|
+
example `explicit value` is x = complex64(1, -2) expect x = complex64(1, -2) end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
law `Complex128 representation` is
|
|
99
|
+
definition is `for all` (x :: Complex128) . prelude.isNaN (prelude.real x) = prelude.isNaN (prelude.real x) end
|
|
100
|
+
example `explicit value` is x = complex128(0.5, -3.5) expect x = complex128(0.5, -3.5) end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
law `Char representation` is
|
|
104
|
+
definition is `for all` (x :: Char) . x = x end
|
|
105
|
+
example `explicit value` is x = char(128512) expect x = char(128512) end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
law `CodePoint representation` is
|
|
109
|
+
definition is `for all` (x :: CodePoint) . x = x end
|
|
110
|
+
example `explicit value` is x = codePoint(55296) expect x = codePoint(55296) end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
law `CodeUnit16 representation` is
|
|
114
|
+
definition is `for all` (x :: CodeUnit16) . x = x end
|
|
115
|
+
example `explicit value` is x = codeUnit16(65535) expect x = codeUnit16(65535) end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
law `Text representation` is
|
|
119
|
+
definition is `for all` (x :: Text) . x = x end
|
|
120
|
+
example `explicit value` is x = "λ日本語😀" expect x = "λ日本語😀" end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
law `CodePointText representation` is
|
|
124
|
+
definition is `for all` (x :: CodePointText) . x = x end
|
|
125
|
+
example `explicit value` is x = codePoints([55296, 1114111]) expect x = codePoints([55296, 1114111]) end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
law `Utf16Text representation` is
|
|
129
|
+
definition is `for all` (x :: Utf16Text) . x = x end
|
|
130
|
+
example `explicit value` is x = utf16([55296, 0, 65535]) expect x = utf16([55296, 0, 65535]) end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
law `Bytes representation` is
|
|
134
|
+
definition is `for all` (x :: Bytes) . x = x end
|
|
135
|
+
example `explicit value` is x = bytes([0, 128, 255]) expect x = bytes([0, 128, 255]) end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
law `Symbol representation` is
|
|
139
|
+
definition is `for all` (x :: Symbol) . x = x end
|
|
140
|
+
example `explicit value` is x = symbol("catalog", "same") expect x = symbol("catalog", "same") end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
law `Unit representation` is
|
|
144
|
+
definition is `for all` (x :: Unit) . x = x end
|
|
145
|
+
example `explicit value` is x = unitValue expect x = unitValue end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
law `Null representation` is
|
|
149
|
+
definition is `for all` (x :: Null) . x = x end
|
|
150
|
+
example `explicit value` is x = null expect x = null end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
law `Undefined representation` is
|
|
154
|
+
definition is `for all` (x :: Undefined) . x = x end
|
|
155
|
+
example `explicit value` is x = undefined expect x = undefined end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
law `Nullable Int8 representation` is
|
|
159
|
+
definition is `for all` (x :: Nullable Int8) . x = x end
|
|
160
|
+
example `explicit value` is x = nullable(127) expect x = nullable(127) end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
law `Optional Int8 representation` is
|
|
164
|
+
definition is `for all` (x :: Optional Int8) . x = x end
|
|
165
|
+
example `explicit value` is x = undefined expect x = undefined end
|
|
166
|
+
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
unit example.scalars
|
|
2
|
+
|
|
3
|
+
law `integer promotion` is
|
|
4
|
+
definition is `for all` (x :: Int8) . x + 1 = 1 + x end
|
|
5
|
+
example `overflow is preserved` is
|
|
6
|
+
x = 127
|
|
7
|
+
expect x + 1 = 128
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
law `unsigned precision` is
|
|
12
|
+
definition is `for all` (x :: UInt64) . x + 0 = x end
|
|
13
|
+
example `maximum` is
|
|
14
|
+
x = 18446744073709551615
|
|
15
|
+
expect x + 1 = 18446744073709551616
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
law `decimal exactness` is
|
|
20
|
+
definition is `for all` (x :: Decimal) . x + 0.1 = 0.1 + x end
|
|
21
|
+
example `tenths` is
|
|
22
|
+
x = 0.1
|
|
23
|
+
expect x + 0.2 = 0.3
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
law `exact division` is
|
|
28
|
+
definition is `for all` (x :: Int16) . x / 2 = x / 2 end
|
|
29
|
+
example `one half` is
|
|
30
|
+
x = 1
|
|
31
|
+
expect x / 2 = rational(1, 2)
|
|
32
|
+
expect prelude.quot -7 3 = -2
|
|
33
|
+
expect prelude.rem -7 3 = -1
|
|
34
|
+
expect prelude.round rational(125, 100) 1 = 1.2
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
law `IEEE classification` is
|
|
39
|
+
definition is `for all` (x :: Float32) . prelude.isNaN x = prelude.isNaN x end
|
|
40
|
+
example `NaN` is
|
|
41
|
+
x = float32Bits("7fc00000")
|
|
42
|
+
expect prelude.isNaN x = true
|
|
43
|
+
end
|
|
44
|
+
example `negative zero` is
|
|
45
|
+
x = float32Bits("80000000")
|
|
46
|
+
expect prelude.isNegativeZero x = true
|
|
47
|
+
expect x = (0 :: Float32)
|
|
48
|
+
end
|
|
49
|
+
example `infinity` is
|
|
50
|
+
x = float32Bits("7f800000")
|
|
51
|
+
expect prelude.isInfinite x = true
|
|
52
|
+
expect prelude.Float32 0.1 = (0.1 :: Float32)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
law `complex arithmetic` is
|
|
57
|
+
definition is `for all` (x :: Unit) . complex64(1, 2) * complex64(3, 4) = complex64(-5, 10) end
|
|
58
|
+
example `product` is
|
|
59
|
+
x = unitValue
|
|
60
|
+
expect complex64(1, 2) * complex64(3, 4) = complex64(-5, 10)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
law `raw units survive` is
|
|
65
|
+
definition is `for all` (x :: Utf16Text) . x = x end
|
|
66
|
+
example `unpaired surrogate` is
|
|
67
|
+
x = utf16([55296, 0, 56320])
|
|
68
|
+
expect x = utf16([55296, 0, 56320])
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
law `arbitrary bytes` is
|
|
73
|
+
definition is `for all` (x :: Bytes) . x = x end
|
|
74
|
+
example `octets` is
|
|
75
|
+
x = bytes([0, 128, 255])
|
|
76
|
+
expect x = bytes([0, 128, 255])
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
law `symbol fixture identity` is
|
|
81
|
+
definition is `for all` (x :: Symbol) . x = x end
|
|
82
|
+
example `same reference` is
|
|
83
|
+
x = symbol("first", "description")
|
|
84
|
+
expect x = symbol("first", "description")
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
law `nested absence` is
|
|
89
|
+
definition is `for all` (x :: Optional (Nullable Int8)) . x = x end
|
|
90
|
+
example `undefined` is
|
|
91
|
+
x = undefined
|
|
92
|
+
expect x = undefined
|
|
93
|
+
end
|
|
94
|
+
example `present null` is
|
|
95
|
+
x = optional(null)
|
|
96
|
+
expect x = optional(null)
|
|
97
|
+
end
|
|
98
|
+
example `present integer` is
|
|
99
|
+
x = optional(nullable(7))
|
|
100
|
+
expect x = optional(nullable(7))
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
law `supplementary scalar` is
|
|
105
|
+
definition is `for all` (x :: Char) . x = x end
|
|
106
|
+
example `emoji` is
|
|
107
|
+
x = char(128512)
|
|
108
|
+
expect x = char(128512)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
law `surrogate code point` is
|
|
113
|
+
definition is `for all` (x :: CodePointText) . x = x end
|
|
114
|
+
example `surrogate` is
|
|
115
|
+
x = codePoints([55296, 128512])
|
|
116
|
+
expect x = codePoints([55296, 128512])
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
law `explicit float rounding` is
|
|
121
|
+
definition is `for all` (x :: Unit) . x = x end
|
|
122
|
+
example `IEEE halfway cases` is
|
|
123
|
+
x = unitValue
|
|
124
|
+
expect prelude.Complex128 complex64(1, 2) = complex128(1, 2)
|
|
125
|
+
expect prelude.Complex64 complex128(1.25, -2.5) = complex64(1.25, -2.5)
|
|
126
|
+
expect prelude.Float32 rational(16777217, 16777216) = float32Bits("3f800000")
|
|
127
|
+
expect prelude.Float32 rational(1208925891672223212634113, 1208925819614629174706176) = float32Bits("3f800001")
|
|
128
|
+
expect prelude.Float64 rational(9007199254740993, 9007199254740992) = float64Bits("3ff0000000000000")
|
|
129
|
+
expect prelude.Float64 rational(1606938044258990453947923680586147734807949174969684883144705, 1606938044258990275541962092341162602522202993782792835301376) = float64Bits("3ff0000000000001")
|
|
130
|
+
expect prelude.Float32 rational(1, 1427247692705959881058285969449495136382746624) = float32Bits("00000000")
|
|
131
|
+
expect prelude.Float32 rational(1125899906842625, 1606938044258990275541962092341162602522202993782792835301376) = float32Bits("00000001")
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
law `short circuit exact failures` is
|
|
136
|
+
definition is `for all` (x :: Unit) . false implies 1 / 0 = rational(1, 2) end
|
|
137
|
+
example `guard prevents division` is x = unitValue expect x = unitValue end
|
|
138
|
+
end
|
package/examples-command.mjs
CHANGED
|
@@ -21,7 +21,7 @@ export async function generateExamples(options) {
|
|
|
21
21
|
const compiler = await createCompiler();
|
|
22
22
|
const artifacts = [];
|
|
23
23
|
for (const target of selected) {
|
|
24
|
-
const result = await compiler.planGeneration({ sources, target });
|
|
24
|
+
const result = await compiler.planGeneration({ sources, target, machineBits: options.machineBits ?? 64 });
|
|
25
25
|
if (result.diagnostics.length)
|
|
26
26
|
throw Object.assign(new Error("Bundled examples failed to compile"), {
|
|
27
27
|
diagnostics: result.diagnostics,
|
|
@@ -43,7 +43,7 @@ export async function generateExamples(options) {
|
|
|
43
43
|
return plans.map((plan, i) => ({
|
|
44
44
|
target: selected[i],
|
|
45
45
|
directory: plan.root,
|
|
46
|
-
files: artifacts[i].map((f) => ({ path: f.path, ownership: f.ownership })),
|
|
46
|
+
files: artifacts[i].map((f) => ({ path: f.path, ownership: f.ownership, placement: f.placement })),
|
|
47
47
|
changes: plan.changes.length,
|
|
48
48
|
preservedAdapters: plan.preserved,
|
|
49
49
|
adapterUpdates: plan.adapterUpdates,
|