typia 14.0.3 → 14.0.5
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/native/cmd/ttsc-typia/bigint_literal_precision_transform_test.go +135 -0
- package/native/cmd/ttsc-typia/recursive_container_helper_index_transform_test.go +206 -0
- package/native/cmd/ttsc-typia/reflect_literals_bigint_transform_test.go +148 -0
- package/native/cmd/ttsc-typia/reflect_literals_non_literal_rejection_transform_test.go +24 -18
- package/native/cmd/ttsc-typia/reflect_schema_bigint_transform_test.go +173 -0
- package/native/cmd/ttsc-typia/wrong_type_tag_target_diagnostic_test.go +88 -0
- package/native/core/factories/ExpressionFactory.go +11 -1
- package/native/core/factories/LiteralFactory.go +3 -0
- package/native/core/factories/MetadataTypeTagFactory.go +27 -6
- package/native/core/factories/internal/metadata/iterate_metadata_constant.go +3 -0
- package/native/core/programmers/RandomProgrammer.go +10 -4
- package/native/core/programmers/internal/CheckerProgrammer.go +14 -6
- package/native/core/programmers/json/JsonStringifyProgrammer.go +14 -6
- package/native/core/programmers/notations/NotationGeneralProgrammer.go +14 -6
- package/native/core/programmers/plain/PlainClassifyProgrammer.go +14 -6
- package/native/core/programmers/plain/PlainCloneProgrammer.go +14 -6
- package/native/core/programmers/plain/PlainPruneProgrammer.go +30 -10
- package/native/core/programmers/reflect/ReflectLiteralsProgrammer.go +10 -27
- package/native/core/schemas/metadata/MetadataBigint.go +37 -0
- package/native/core/schemas/metadata/metadata_bigint_is_comparable_test.go +65 -0
- package/native/transform/features/reflect/ReflectSchemaTransformer.go +15 -46
- package/package.json +3 -3
- package/native/cmd/ttsc-typia/reflect_literals_empty_union_transform_test.go +0 -161
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"os"
|
|
5
|
+
"os/exec"
|
|
6
|
+
"path/filepath"
|
|
7
|
+
"testing"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// TestReflectSchemaBigintTransform verifies the metadata a reflect operation
|
|
11
|
+
// hands back carries a bigint constant as a bigint.
|
|
12
|
+
//
|
|
13
|
+
// `IMetadataSchema.IValue<Atomic.Type>` declares `value: bigint` for a bigint
|
|
14
|
+
// constant, but this transformer lowered the whole metadata tree through
|
|
15
|
+
// `encoding/json` before writing it. JSON has no bigint, so that one member
|
|
16
|
+
// could not survive the trip: it arrived as whatever object its fields happened
|
|
17
|
+
// to spell. The trip was also redundant -- it marshaled structs into maps and
|
|
18
|
+
// lowercased each key's initial, which is what `LiteralFactory` already does
|
|
19
|
+
// when it reflects a struct -- so writing the tree directly both fixes the
|
|
20
|
+
// value and removes the step.
|
|
21
|
+
//
|
|
22
|
+
// `literals` and `schema` reach the emit by different routes, so a case on one
|
|
23
|
+
// says nothing about the other.
|
|
24
|
+
//
|
|
25
|
+
// 1. Reflect a bigint constant union through `schema` and through `schemas`.
|
|
26
|
+
// 2. Execute the emitted CommonJS.
|
|
27
|
+
// 3. Assert each reported value is `typeof "bigint"` and exact, and that the
|
|
28
|
+
// surrounding metadata still reports the constant and its neighbors.
|
|
29
|
+
func TestReflectSchemaBigintTransform(t *testing.T) {
|
|
30
|
+
node, err := exec.LookPath("node")
|
|
31
|
+
if err != nil {
|
|
32
|
+
t.Skip("node executable not found")
|
|
33
|
+
}
|
|
34
|
+
root := ttscTypiaTestRepoRoot(t)
|
|
35
|
+
base := filepath.Join(root, "packages", "typia", "native", ".tmp-ttsc-typia-tests")
|
|
36
|
+
if err := os.MkdirAll(base, 0o755); err != nil {
|
|
37
|
+
t.Fatalf("mkdir temp base: %v", err)
|
|
38
|
+
}
|
|
39
|
+
dir, err := os.MkdirTemp(base, "reflect-schema-bigint-")
|
|
40
|
+
if err != nil {
|
|
41
|
+
t.Fatalf("create temp fixture: %v", err)
|
|
42
|
+
}
|
|
43
|
+
t.Cleanup(func() { _ = os.RemoveAll(dir) })
|
|
44
|
+
src := filepath.Join(dir, "src")
|
|
45
|
+
if err := os.MkdirAll(src, 0o755); err != nil {
|
|
46
|
+
t.Fatalf("mkdir fixture src: %v", err)
|
|
47
|
+
}
|
|
48
|
+
if err := os.WriteFile(filepath.Join(dir, "tsconfig.json"), []byte(atomicIntersectionSchemaTSConfig), 0o644); err != nil {
|
|
49
|
+
t.Fatalf("write tsconfig: %v", err)
|
|
50
|
+
}
|
|
51
|
+
if err := os.WriteFile(filepath.Join(src, "main.ts"), []byte(reflectSchemaBigintSource), 0o644); err != nil {
|
|
52
|
+
t.Fatalf("write source: %v", err)
|
|
53
|
+
}
|
|
54
|
+
ttscTypiaTestTypecheck(t, dir)
|
|
55
|
+
|
|
56
|
+
out, errText, code := ttscTypiaTestCapture(func() int {
|
|
57
|
+
return runTransform([]string{
|
|
58
|
+
"--cwd", dir,
|
|
59
|
+
"--tsconfig", "tsconfig.json",
|
|
60
|
+
"--file", "src/main.ts",
|
|
61
|
+
"--output", "js",
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
if code != 0 {
|
|
65
|
+
t.Fatalf("reflect.schema bigint transform failed: code=%d stderr=\n%s", code, errText)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
runtimeDir := filepath.Join(dir, "runtime")
|
|
69
|
+
if err := os.MkdirAll(runtimeDir, 0o755); err != nil {
|
|
70
|
+
t.Fatalf("mkdir runtime dir: %v", err)
|
|
71
|
+
}
|
|
72
|
+
ttscTypiaTestWriteCommonRuntimeStubs(t, runtimeDir)
|
|
73
|
+
runtimeJS := ttscTypiaTestRewriteCommonJS(t, out)
|
|
74
|
+
if err := os.WriteFile(filepath.Join(runtimeDir, "main.cjs"), []byte(runtimeJS), 0o644); err != nil {
|
|
75
|
+
t.Fatalf("write runtime module: %v", err)
|
|
76
|
+
}
|
|
77
|
+
runner := filepath.Join(runtimeDir, "run.cjs")
|
|
78
|
+
if err := os.WriteFile(runner, []byte(reflectSchemaBigintRunner), 0o644); err != nil {
|
|
79
|
+
t.Fatalf("write runtime runner: %v", err)
|
|
80
|
+
}
|
|
81
|
+
cmd := exec.Command(node, runner)
|
|
82
|
+
cmd.Dir = runtimeDir
|
|
83
|
+
output, err := cmd.CombinedOutput()
|
|
84
|
+
if err != nil {
|
|
85
|
+
t.Fatalf("reflect.schema bigint runtime cases failed: %v\n%s", err, output)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const reflectSchemaBigintSource = `import typia, { tags } from "typia";
|
|
90
|
+
|
|
91
|
+
export const unit = typia.reflect.schema<1n | 9007199254740993n>();
|
|
92
|
+
export const collection = typia.reflect.schemas<[2n, "a" | 3]>();
|
|
93
|
+
export const objects = typia.reflect.schema<{ big: 7n; name: string }>();
|
|
94
|
+
|
|
95
|
+
// A tag reaches a constant by matching the child's value against the merged
|
|
96
|
+
// parent's, so the constant value has to compare by value. The number and
|
|
97
|
+
// string constants are the controls that were never at risk.
|
|
98
|
+
export const tagged = typia.reflect.schema<(1n | 2n) & tags.Type<"int64">>();
|
|
99
|
+
export const taggedNumber = typia.reflect.schema<(1 | 2) & tags.Type<"uint32">>();
|
|
100
|
+
`
|
|
101
|
+
|
|
102
|
+
const reflectSchemaBigintRunner = `const mod = require("./main.cjs");
|
|
103
|
+
|
|
104
|
+
const render = (value) =>
|
|
105
|
+
typeof value === "bigint" ? value.toString() + "n" : JSON.stringify(value);
|
|
106
|
+
|
|
107
|
+
const constantsOf = (schema, type) => {
|
|
108
|
+
const constant = (schema.constants ?? []).find((c) => c.type === type);
|
|
109
|
+
return constant === undefined ? [] : constant.values.map((v) => v.value);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const check = (label, actual, expected) => {
|
|
113
|
+
if (actual.length !== expected.length) {
|
|
114
|
+
throw new Error(
|
|
115
|
+
label + ": expected " + expected.map(render).join(", ") +
|
|
116
|
+
", got " + actual.map(render).join(", "),
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
actual.forEach((item, index) => {
|
|
120
|
+
if (typeof item !== typeof expected[index] || item !== expected[index]) {
|
|
121
|
+
throw new Error(
|
|
122
|
+
label + "[" + index + "]: expected " + render(expected[index]) +
|
|
123
|
+
" (" + typeof expected[index] + "), got " + render(item) +
|
|
124
|
+
" (" + typeof item + ")",
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
check("schema", constantsOf(mod.unit.schema, "bigint"), [1n, 9007199254740993n]);
|
|
131
|
+
check("schemas[0]", constantsOf(mod.collection.schemas[0], "bigint"), [2n]);
|
|
132
|
+
|
|
133
|
+
// A neighboring constant kind must keep its own representation.
|
|
134
|
+
check("schemas[1] string", constantsOf(mod.collection.schemas[1], "string"), ["a"]);
|
|
135
|
+
check("schemas[1] number", constantsOf(mod.collection.schemas[1], "number"), [3]);
|
|
136
|
+
|
|
137
|
+
// The surrounding tree still reports the object and its members.
|
|
138
|
+
const object = mod.objects.components.objects[0];
|
|
139
|
+
if (object === undefined || object.properties.length !== 2) {
|
|
140
|
+
throw new Error("object metadata was not emitted: " + JSON.stringify(mod.objects, (k, v) => typeof v === "bigint" ? v.toString() : v));
|
|
141
|
+
}
|
|
142
|
+
const big = object.properties.find(
|
|
143
|
+
(p) => constantsOf(p.key, "string")[0] === "big",
|
|
144
|
+
);
|
|
145
|
+
if (big === undefined) {
|
|
146
|
+
throw new Error("the 'big' property is missing from the object metadata");
|
|
147
|
+
}
|
|
148
|
+
check("object property", constantsOf(big.value, "bigint"), [7n]);
|
|
149
|
+
|
|
150
|
+
const tagNames = (schema, type) => {
|
|
151
|
+
const constant = (schema.constants ?? []).find((c) => c.type === type);
|
|
152
|
+
if (constant === undefined) {
|
|
153
|
+
throw new Error("no " + type + " constant was emitted");
|
|
154
|
+
}
|
|
155
|
+
return constant.values.map((v) =>
|
|
156
|
+
(v.tags ?? []).flat().map((t) => t.name).join(","),
|
|
157
|
+
);
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// Every member keeps the tag the intersection put on it.
|
|
161
|
+
const expectTags = (label, actual, expected) => {
|
|
162
|
+
if (actual.length === 0 || actual.some((names) => names !== expected)) {
|
|
163
|
+
throw new Error(
|
|
164
|
+
label + ": expected every member tagged " + expected +
|
|
165
|
+
", got " + JSON.stringify(actual),
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
expectTags("bigint constant", tagNames(mod.tagged.schema, "bigint"), 'Type<"int64">');
|
|
170
|
+
expectTags("number constant", tagNames(mod.taggedNumber.schema, "number"), 'Type<"uint32">');
|
|
171
|
+
|
|
172
|
+
console.log("ok");
|
|
173
|
+
`
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"os"
|
|
5
|
+
"path/filepath"
|
|
6
|
+
"strings"
|
|
7
|
+
"testing"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// TestWrongTypeTagTargetDiagnostic verifies a rejected tag names its declared
|
|
11
|
+
// target once and leaves a compatible tag untouched.
|
|
12
|
+
func TestWrongTypeTagTargetDiagnostic(t *testing.T) {
|
|
13
|
+
project := wrongTypeTagTargetDiagnosticProject(t)
|
|
14
|
+
_, errText, code := ttscTypiaTestCapture(func() int {
|
|
15
|
+
return runTransform([]string{
|
|
16
|
+
"--cwd", project,
|
|
17
|
+
"--tsconfig", "tsconfig.json",
|
|
18
|
+
"--file", "src/main.ts",
|
|
19
|
+
"--output", "js",
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
if code == 0 {
|
|
23
|
+
t.Fatal("wrong-target tag unexpectedly transformed without diagnostics")
|
|
24
|
+
}
|
|
25
|
+
const expected = `the property ["typia.tag"] target must contain array type.`
|
|
26
|
+
if count := strings.Count(errText, expected); count != 1 {
|
|
27
|
+
t.Fatalf("wrong-target diagnostic count mismatch: got %d, want 1\n%s", count, errText)
|
|
28
|
+
}
|
|
29
|
+
if count := strings.Count(errText, "Payload.invalid:"); count != 1 {
|
|
30
|
+
t.Fatalf("diagnostic ownership mismatch: got %d, want 1\n%s", count, errText)
|
|
31
|
+
}
|
|
32
|
+
if strings.Contains(errText, "target must contain boolean type") {
|
|
33
|
+
t.Fatalf("diagnostic named the host type:\n%s", errText)
|
|
34
|
+
}
|
|
35
|
+
if strings.Contains(errText, "Payload.valid:") {
|
|
36
|
+
t.Fatalf("valid array control produced a diagnostic:\n%s", errText)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
func wrongTypeTagTargetDiagnosticProject(t *testing.T) string {
|
|
41
|
+
t.Helper()
|
|
42
|
+
root := ttscTypiaTestRepoRoot(t)
|
|
43
|
+
base := filepath.Join(root, "packages", "typia", "native", ".tmp-ttsc-typia-tests")
|
|
44
|
+
if err := os.MkdirAll(base, 0o755); err != nil {
|
|
45
|
+
t.Fatalf("mkdir temp base: %v", err)
|
|
46
|
+
}
|
|
47
|
+
project, err := os.MkdirTemp(base, "wrong-tag-target-")
|
|
48
|
+
if err != nil {
|
|
49
|
+
t.Fatalf("create temp fixture: %v", err)
|
|
50
|
+
}
|
|
51
|
+
t.Cleanup(func() { _ = os.RemoveAll(project) })
|
|
52
|
+
src := filepath.Join(project, "src")
|
|
53
|
+
if err := os.MkdirAll(src, 0o755); err != nil {
|
|
54
|
+
t.Fatalf("mkdir fixture src: %v", err)
|
|
55
|
+
}
|
|
56
|
+
if err := os.WriteFile(filepath.Join(project, "tsconfig.json"), []byte(wrongTypeTagTargetDiagnosticTSConfig), 0o644); err != nil {
|
|
57
|
+
t.Fatalf("write tsconfig: %v", err)
|
|
58
|
+
}
|
|
59
|
+
if err := os.WriteFile(filepath.Join(src, "main.ts"), []byte(wrongTypeTagTargetDiagnosticSource), 0o644); err != nil {
|
|
60
|
+
t.Fatalf("write source: %v", err)
|
|
61
|
+
}
|
|
62
|
+
return project
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const wrongTypeTagTargetDiagnosticTSConfig = `{
|
|
66
|
+
"compilerOptions": {
|
|
67
|
+
"target": "ES2022",
|
|
68
|
+
"module": "commonjs",
|
|
69
|
+
"moduleResolution": "bundler",
|
|
70
|
+
"ignoreDeprecations": "6.0",
|
|
71
|
+
"types": ["*"],
|
|
72
|
+
"esModuleInterop": true,
|
|
73
|
+
"strict": true,
|
|
74
|
+
"skipLibCheck": true
|
|
75
|
+
},
|
|
76
|
+
"include": ["src"]
|
|
77
|
+
}
|
|
78
|
+
`
|
|
79
|
+
|
|
80
|
+
const wrongTypeTagTargetDiagnosticSource = `import typia, { tags } from "typia";
|
|
81
|
+
|
|
82
|
+
interface Payload {
|
|
83
|
+
invalid: boolean & tags.MinItems<1>;
|
|
84
|
+
valid: string[] & tags.MinItems<1>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const test = (input: unknown) => typia.is<Payload>(input);
|
|
88
|
+
`
|
|
@@ -66,6 +66,16 @@ func (expressionFactoryNamespace) Number(value any, emit ...*shimprinter.EmitCon
|
|
|
66
66
|
return f.NewNumericLiteral(text, shimast.TokenFlagsNone)
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
// Bigint emits `BigInt("<value>")` for a bigint literal.
|
|
70
|
+
//
|
|
71
|
+
// The argument has to stay a string literal. This used to spell the digits as a
|
|
72
|
+
// bare `number` literal, so `9007199254740993n` reached the emit as
|
|
73
|
+
// `BigInt(9007199254740993)` and JavaScript rounded the literal to
|
|
74
|
+
// 9007199254740992 before `BigInt` ever parsed it -- exactly the rounding
|
|
75
|
+
// `numericRangeFactory_bigint_literal` and `_isTypeInt64Bigint` already spell
|
|
76
|
+
// out and avoid. Every bigint an argument can carry is exact in base 10, and
|
|
77
|
+
// `BigInt` parses the digits of a string directly, so the string form is exact
|
|
78
|
+
// at any magnitude.
|
|
69
79
|
func (expressionFactoryNamespace) Bigint(value any, emit ...*shimprinter.EmitContext) *shimast.Node {
|
|
70
80
|
f := nativecontext.EmitFactoryOf(expressionFactory_factory, emit...)
|
|
71
81
|
return f.NewCallExpression(
|
|
@@ -73,7 +83,7 @@ func (expressionFactoryNamespace) Bigint(value any, emit ...*shimprinter.EmitCon
|
|
|
73
83
|
nil,
|
|
74
84
|
nil,
|
|
75
85
|
f.NewNodeList([]*shimast.Node{
|
|
76
|
-
f.
|
|
86
|
+
f.NewStringLiteral(fmt.Sprint(value), shimast.TokenFlagsNone),
|
|
77
87
|
}),
|
|
78
88
|
shimast.NodeFlagsNone,
|
|
79
89
|
)
|
|
@@ -11,6 +11,7 @@ import (
|
|
|
11
11
|
shimast "github.com/microsoft/typescript-go/shim/ast"
|
|
12
12
|
shimprinter "github.com/microsoft/typescript-go/shim/printer"
|
|
13
13
|
nativecontext "github.com/samchon/typia/packages/typia/native/core/context"
|
|
14
|
+
schemametadata "github.com/samchon/typia/packages/typia/native/core/schemas/metadata"
|
|
14
15
|
)
|
|
15
16
|
|
|
16
17
|
type literalFactoryNamespace struct{}
|
|
@@ -93,6 +94,8 @@ func (literalFactoryNamespace) Write(input any, emit ...*shimprinter.EmitContext
|
|
|
93
94
|
switch value := input.(type) {
|
|
94
95
|
case bool:
|
|
95
96
|
return literalFactory_writeBoolean(value, emit...)
|
|
97
|
+
case schemametadata.MetadataBigint:
|
|
98
|
+
return literalFactory_writeBigint(value, emit...)
|
|
96
99
|
case *big.Int:
|
|
97
100
|
return literalFactory_writeBigint(value, emit...)
|
|
98
101
|
case int:
|
|
@@ -2,6 +2,7 @@ package factories
|
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
4
|
"fmt"
|
|
5
|
+
"reflect"
|
|
5
6
|
"strings"
|
|
6
7
|
|
|
7
8
|
schemametadata "github.com/samchon/typia/packages/typia/native/core/schemas/metadata"
|
|
@@ -162,12 +163,15 @@ func (metadataTypeTagFactoryNamespace) Analyze(props struct {
|
|
|
162
163
|
if tag == nil {
|
|
163
164
|
continue
|
|
164
165
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
166
|
+
if metadataTypeTagFactory_includes(tag.Target, props.Type) == false {
|
|
167
|
+
report(struct {
|
|
168
|
+
Property *string
|
|
169
|
+
Message string
|
|
170
|
+
}{Property: nil, Message: metadataTypeTagFactory_target_message(tag.Target)})
|
|
171
|
+
continue
|
|
168
172
|
}
|
|
169
173
|
output = append(output, schemametadata.IMetadataTypeTag{
|
|
170
|
-
Target:
|
|
174
|
+
Target: props.Type,
|
|
171
175
|
Name: tag.Name,
|
|
172
176
|
Kind: tag.Kind,
|
|
173
177
|
Value: tag.Value,
|
|
@@ -195,7 +199,7 @@ func (metadataTypeTagFactoryNamespace) Analyze(props struct {
|
|
|
195
199
|
for _, object := range props.Objects {
|
|
196
200
|
names = append(names, object.Name)
|
|
197
201
|
}
|
|
198
|
-
|
|
202
|
+
metadataTypeTagFactory_append_error(props.Errors, MetadataFactory_IError{
|
|
199
203
|
Name: strings.Join(names, " & "),
|
|
200
204
|
Explore: props.Explore,
|
|
201
205
|
Messages: messages,
|
|
@@ -218,10 +222,14 @@ func (metadataTypeTagFactoryNamespace) Validate(props struct {
|
|
|
218
222
|
for _, tag := range props.Tags {
|
|
219
223
|
if tag.Target != props.Type {
|
|
220
224
|
if success {
|
|
225
|
+
target := tag.Target
|
|
226
|
+
if target == "" {
|
|
227
|
+
target = props.Type
|
|
228
|
+
}
|
|
221
229
|
success = props.Report(struct {
|
|
222
230
|
Property *string
|
|
223
231
|
Message string
|
|
224
|
-
}{Property: nil, Message:
|
|
232
|
+
}{Property: nil, Message: metadataTypeTagFactory_target_message([]string{target})})
|
|
225
233
|
}
|
|
226
234
|
}
|
|
227
235
|
}
|
|
@@ -570,3 +578,16 @@ func metadataTypeTagFactory_essentialFieldsMessage() string {
|
|
|
570
578
|
}
|
|
571
579
|
return strings.Join(values, ", ")
|
|
572
580
|
}
|
|
581
|
+
|
|
582
|
+
func metadataTypeTagFactory_target_message(targets []string) string {
|
|
583
|
+
return "target must contain " + strings.Join(targets, " or ") + " type"
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
func metadataTypeTagFactory_append_error(errors *[]MetadataFactory_IError, next MetadataFactory_IError) {
|
|
587
|
+
for _, previous := range *errors {
|
|
588
|
+
if reflect.DeepEqual(previous, next) {
|
|
589
|
+
return
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
*errors = append(*errors, next)
|
|
593
|
+
}
|
|
@@ -50,6 +50,9 @@ func Iterate_metadata_constant(props IMetadataIteratorProps) bool {
|
|
|
50
50
|
typ = "number"
|
|
51
51
|
} else if filter(nativechecker.TypeFlagsBigIntLiteral) {
|
|
52
52
|
typ = "bigint"
|
|
53
|
+
// Normalize away the checker's unnameable `jsnum.PseudoBigInt`; see
|
|
54
|
+
// MetadataBigint for why the stand-in has to be a comparable value.
|
|
55
|
+
value = schemametadata.MetadataBigint{Text: fmt.Sprint(value)}
|
|
53
56
|
}
|
|
54
57
|
constant := iterate_metadata_constant_take(props.Metadata, typ)
|
|
55
58
|
info := comment()
|
|
@@ -345,11 +345,14 @@ func randomProgrammer_write_array_functions(props struct {
|
|
|
345
345
|
}) []*shimast.Node {
|
|
346
346
|
f := nativecontext.EmitFactoryOf(randomProgrammer_factory, props.Context.Emit)
|
|
347
347
|
output := []*shimast.Node{}
|
|
348
|
-
for
|
|
348
|
+
for _, array := range props.Collection.Arrays() {
|
|
349
349
|
if array.Recursive == false {
|
|
350
350
|
continue
|
|
351
351
|
}
|
|
352
|
-
index :=
|
|
352
|
+
index := 0
|
|
353
|
+
if array.Index != nil {
|
|
354
|
+
index = *array.Index
|
|
355
|
+
}
|
|
353
356
|
array := array
|
|
354
357
|
output = append(output, nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
|
|
355
358
|
Name: randomProgrammer_prefix_array(index),
|
|
@@ -396,11 +399,14 @@ func randomProgrammer_write_tuple_functions(props struct {
|
|
|
396
399
|
f := nativecontext.EmitFactoryOf(randomProgrammer_factory, props.Context.Emit)
|
|
397
400
|
output := []*shimast.Node{}
|
|
398
401
|
_, unsatisfiableTuples := nativehelpers.RandomJoiner.UnsatisfiableRecursives(props.Collection.Objects(), props.Collection.Tuples())
|
|
399
|
-
for
|
|
402
|
+
for _, tuple := range props.Collection.Tuples() {
|
|
400
403
|
if tuple.Recursive == false {
|
|
401
404
|
continue
|
|
402
405
|
}
|
|
403
|
-
index :=
|
|
406
|
+
index := 0
|
|
407
|
+
if tuple.Index != nil {
|
|
408
|
+
index = *tuple.Index
|
|
409
|
+
}
|
|
404
410
|
tuple := tuple
|
|
405
411
|
if unsatisfiableTuples[tuple] {
|
|
406
412
|
panic(nativecontext.NewTransformerError(nativecontext.TransformerError_IProps{
|
|
@@ -181,13 +181,17 @@ func (checkerProgrammerNamespace) Write_array_functions(props CheckerProgrammer_
|
|
|
181
181
|
f := nativecontext.EmitFactoryOf(checkerProgrammer_factory, props.Context.Emit)
|
|
182
182
|
arrays := props.Collection.Arrays()
|
|
183
183
|
output := []*shimast.Node{}
|
|
184
|
-
for
|
|
184
|
+
for _, typ := range arrays {
|
|
185
185
|
if typ.Recursive == false {
|
|
186
186
|
continue
|
|
187
187
|
}
|
|
188
|
+
index := 0
|
|
189
|
+
if typ.Index != nil {
|
|
190
|
+
index = *typ.Index
|
|
191
|
+
}
|
|
188
192
|
input := f.NewIdentifier("input")
|
|
189
193
|
output = append(output, nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
|
|
190
|
-
Name: fmt.Sprintf("%sa%d", props.Config.Prefix,
|
|
194
|
+
Name: fmt.Sprintf("%sa%d", props.Config.Prefix, index),
|
|
191
195
|
Value: f.NewArrowFunction(
|
|
192
196
|
nil,
|
|
193
197
|
nil,
|
|
@@ -200,7 +204,7 @@ func (checkerProgrammerNamespace) Write_array_functions(props CheckerProgrammer_
|
|
|
200
204
|
nativefactories.TypeFactory.Keyword("any", props.Context.Emit),
|
|
201
205
|
nil,
|
|
202
206
|
f.NewToken(shimast.KindEqualsGreaterThanToken),
|
|
203
|
-
checkerProgrammer_visit_guard(FeatureProgrammer.VisitKey(props.Config.Prefix, "a",
|
|
207
|
+
checkerProgrammer_visit_guard(FeatureProgrammer.VisitKey(props.Config.Prefix, "a", index), checkerProgrammer_decode_array_inline(checkerProgrammer_decodeArrayInlineProps{
|
|
204
208
|
Config: props.Config,
|
|
205
209
|
Context: props.Context,
|
|
206
210
|
Functor: props.Functor,
|
|
@@ -226,13 +230,17 @@ func (checkerProgrammerNamespace) Write_tuple_functions(props CheckerProgrammer_
|
|
|
226
230
|
f := nativecontext.EmitFactoryOf(checkerProgrammer_factory, props.Context.Emit)
|
|
227
231
|
tuples := props.Collection.Tuples()
|
|
228
232
|
output := []*shimast.Node{}
|
|
229
|
-
for
|
|
233
|
+
for _, tuple := range tuples {
|
|
230
234
|
if tuple.Recursive == false {
|
|
231
235
|
continue
|
|
232
236
|
}
|
|
237
|
+
index := 0
|
|
238
|
+
if tuple.Index != nil {
|
|
239
|
+
index = *tuple.Index
|
|
240
|
+
}
|
|
233
241
|
input := f.NewIdentifier("input")
|
|
234
242
|
output = append(output, nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
|
|
235
|
-
Name: fmt.Sprintf("%st%d", props.Config.Prefix,
|
|
243
|
+
Name: fmt.Sprintf("%st%d", props.Config.Prefix, index),
|
|
236
244
|
Value: f.NewArrowFunction(
|
|
237
245
|
nil,
|
|
238
246
|
nil,
|
|
@@ -245,7 +253,7 @@ func (checkerProgrammerNamespace) Write_tuple_functions(props CheckerProgrammer_
|
|
|
245
253
|
nativefactories.TypeFactory.Keyword("any", props.Context.Emit),
|
|
246
254
|
nil,
|
|
247
255
|
f.NewToken(shimast.KindEqualsGreaterThanToken),
|
|
248
|
-
checkerProgrammer_visit_guard(FeatureProgrammer.VisitKey(props.Config.Prefix, "t",
|
|
256
|
+
checkerProgrammer_visit_guard(FeatureProgrammer.VisitKey(props.Config.Prefix, "t", index), checkerProgrammer_decode_tuple_inline(checkerProgrammer_decodeTupleInlineProps{
|
|
249
257
|
Config: props.Config,
|
|
250
258
|
Context: props.Context,
|
|
251
259
|
Functor: props.Functor,
|
|
@@ -100,12 +100,16 @@ func jsonStringifyProgrammer_write_array_functions(props struct {
|
|
|
100
100
|
}) []*shimast.Node {
|
|
101
101
|
f := nativecontext.EmitFactoryOf(jsonStringifyProgrammer_factory, props.Context.Emit)
|
|
102
102
|
output := []*shimast.Node{}
|
|
103
|
-
for
|
|
103
|
+
for _, typ := range props.Collection.Arrays() {
|
|
104
104
|
if typ.Recursive == false {
|
|
105
105
|
continue
|
|
106
106
|
}
|
|
107
|
+
index := 0
|
|
108
|
+
if typ.Index != nil {
|
|
109
|
+
index = *typ.Index
|
|
110
|
+
}
|
|
107
111
|
output = append(output, nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
|
|
108
|
-
Name: fmt.Sprintf("%sa%d", props.Config.Prefix,
|
|
112
|
+
Name: fmt.Sprintf("%sa%d", props.Config.Prefix, index),
|
|
109
113
|
Value: f.NewArrowFunction(
|
|
110
114
|
nil,
|
|
111
115
|
nil,
|
|
@@ -118,7 +122,7 @@ func jsonStringifyProgrammer_write_array_functions(props struct {
|
|
|
118
122
|
nil,
|
|
119
123
|
f.NewToken(shimast.KindEqualsGreaterThanToken),
|
|
120
124
|
nativeinternal.FeatureProgrammer.VisitGuardSerialize(
|
|
121
|
-
nativeinternal.FeatureProgrammer.VisitKey(props.Config.Prefix, "a",
|
|
125
|
+
nativeinternal.FeatureProgrammer.VisitKey(props.Config.Prefix, "a", index),
|
|
122
126
|
jsonStringifyProgrammer_circular_thrower(props.Context, props.Functor),
|
|
123
127
|
jsonStringifyProgrammer_decode_array_inline(jsonStringifyProgrammer_decodeArrayProps{
|
|
124
128
|
Context: props.Context,
|
|
@@ -153,12 +157,16 @@ func jsonStringifyProgrammer_write_tuple_functions(props struct {
|
|
|
153
157
|
}) []*shimast.Node {
|
|
154
158
|
f := nativecontext.EmitFactoryOf(jsonStringifyProgrammer_factory, props.Context.Emit)
|
|
155
159
|
output := []*shimast.Node{}
|
|
156
|
-
for
|
|
160
|
+
for _, tuple := range props.Collection.Tuples() {
|
|
157
161
|
if tuple.Recursive == false {
|
|
158
162
|
continue
|
|
159
163
|
}
|
|
164
|
+
index := 0
|
|
165
|
+
if tuple.Index != nil {
|
|
166
|
+
index = *tuple.Index
|
|
167
|
+
}
|
|
160
168
|
output = append(output, nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
|
|
161
|
-
Name: fmt.Sprintf("%st%d", props.Config.Prefix,
|
|
169
|
+
Name: fmt.Sprintf("%st%d", props.Config.Prefix, index),
|
|
162
170
|
Value: f.NewArrowFunction(
|
|
163
171
|
nil,
|
|
164
172
|
nil,
|
|
@@ -171,7 +179,7 @@ func jsonStringifyProgrammer_write_tuple_functions(props struct {
|
|
|
171
179
|
nil,
|
|
172
180
|
f.NewToken(shimast.KindEqualsGreaterThanToken),
|
|
173
181
|
nativeinternal.FeatureProgrammer.VisitGuardSerialize(
|
|
174
|
-
nativeinternal.FeatureProgrammer.VisitKey(props.Config.Prefix, "t",
|
|
182
|
+
nativeinternal.FeatureProgrammer.VisitKey(props.Config.Prefix, "t", index),
|
|
175
183
|
jsonStringifyProgrammer_circular_thrower(props.Context, props.Functor),
|
|
176
184
|
jsonStringifyProgrammer_decode_tuple_inline(jsonStringifyProgrammer_decodeTupleInlineProps{
|
|
177
185
|
Context: props.Context,
|
|
@@ -131,12 +131,16 @@ func notationGeneralProgrammer_write_array_functions(props struct {
|
|
|
131
131
|
}) []*shimast.Node {
|
|
132
132
|
f := nativecontext.EmitFactoryOf(notationGeneralProgrammer_factory, props.Context.Emit)
|
|
133
133
|
output := []*shimast.Node{}
|
|
134
|
-
for
|
|
134
|
+
for _, typ := range props.Collection.Arrays() {
|
|
135
135
|
if typ.Recursive == false {
|
|
136
136
|
continue
|
|
137
137
|
}
|
|
138
|
+
index := 0
|
|
139
|
+
if typ.Index != nil {
|
|
140
|
+
index = *typ.Index
|
|
141
|
+
}
|
|
138
142
|
output = append(output, nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
|
|
139
|
-
Name: fmt.Sprintf("%sa%d", props.Config.Prefix,
|
|
143
|
+
Name: fmt.Sprintf("%sa%d", props.Config.Prefix, index),
|
|
140
144
|
Value: f.NewArrowFunction(
|
|
141
145
|
nil,
|
|
142
146
|
nil,
|
|
@@ -149,7 +153,7 @@ func notationGeneralProgrammer_write_array_functions(props struct {
|
|
|
149
153
|
nil,
|
|
150
154
|
f.NewToken(shimast.KindEqualsGreaterThanToken),
|
|
151
155
|
nativeinternal.FeatureProgrammer.VisitGuardRebuild(
|
|
152
|
-
nativeinternal.FeatureProgrammer.VisitKey(props.Config.Prefix, "a",
|
|
156
|
+
nativeinternal.FeatureProgrammer.VisitKey(props.Config.Prefix, "a", index),
|
|
153
157
|
true,
|
|
154
158
|
notationGeneralProgrammer_decode_array_inline(notationGeneralProgrammer_decodeArrayProps{
|
|
155
159
|
Context: props.Context,
|
|
@@ -184,12 +188,16 @@ func notationGeneralProgrammer_write_tuple_functions(props struct {
|
|
|
184
188
|
}) []*shimast.Node {
|
|
185
189
|
f := nativecontext.EmitFactoryOf(notationGeneralProgrammer_factory, props.Context.Emit)
|
|
186
190
|
output := []*shimast.Node{}
|
|
187
|
-
for
|
|
191
|
+
for _, tuple := range props.Collection.Tuples() {
|
|
188
192
|
if tuple.Recursive == false {
|
|
189
193
|
continue
|
|
190
194
|
}
|
|
195
|
+
index := 0
|
|
196
|
+
if tuple.Index != nil {
|
|
197
|
+
index = *tuple.Index
|
|
198
|
+
}
|
|
191
199
|
output = append(output, nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
|
|
192
|
-
Name: fmt.Sprintf("%st%d", props.Config.Prefix,
|
|
200
|
+
Name: fmt.Sprintf("%st%d", props.Config.Prefix, index),
|
|
193
201
|
Value: f.NewArrowFunction(
|
|
194
202
|
nil,
|
|
195
203
|
nil,
|
|
@@ -202,7 +210,7 @@ func notationGeneralProgrammer_write_tuple_functions(props struct {
|
|
|
202
210
|
nil,
|
|
203
211
|
f.NewToken(shimast.KindEqualsGreaterThanToken),
|
|
204
212
|
nativeinternal.FeatureProgrammer.VisitGuardRebuild(
|
|
205
|
-
nativeinternal.FeatureProgrammer.VisitKey(props.Config.Prefix, "t",
|
|
213
|
+
nativeinternal.FeatureProgrammer.VisitKey(props.Config.Prefix, "t", index),
|
|
206
214
|
true,
|
|
207
215
|
notationGeneralProgrammer_decode_tuple_inline(notationGeneralProgrammer_decodeTupleInlineProps{
|
|
208
216
|
Context: props.Context,
|
|
@@ -135,12 +135,16 @@ func plainClassifyProgrammer_write_array_functions(props struct {
|
|
|
135
135
|
}) []*shimast.Node {
|
|
136
136
|
f := nativecontext.EmitFactoryOf(plainClassifyProgrammer_factory, props.Context.Emit)
|
|
137
137
|
output := []*shimast.Node{}
|
|
138
|
-
for
|
|
138
|
+
for _, typ := range props.Collection.Arrays() {
|
|
139
139
|
if typ.Recursive == false {
|
|
140
140
|
continue
|
|
141
141
|
}
|
|
142
|
+
index := 0
|
|
143
|
+
if typ.Index != nil {
|
|
144
|
+
index = *typ.Index
|
|
145
|
+
}
|
|
142
146
|
output = append(output, nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
|
|
143
|
-
Name: fmt.Sprintf("%sa%d", props.Config.Prefix,
|
|
147
|
+
Name: fmt.Sprintf("%sa%d", props.Config.Prefix, index),
|
|
144
148
|
Value: f.NewArrowFunction(
|
|
145
149
|
nil,
|
|
146
150
|
nil,
|
|
@@ -153,7 +157,7 @@ func plainClassifyProgrammer_write_array_functions(props struct {
|
|
|
153
157
|
nil,
|
|
154
158
|
f.NewToken(shimast.KindEqualsGreaterThanToken),
|
|
155
159
|
nativeinternal.FeatureProgrammer.VisitGuardRebuild(
|
|
156
|
-
nativeinternal.FeatureProgrammer.VisitKey(props.Config.Prefix, "a",
|
|
160
|
+
nativeinternal.FeatureProgrammer.VisitKey(props.Config.Prefix, "a", index),
|
|
157
161
|
true,
|
|
158
162
|
plainClassifyProgrammer_decode_array_inline(plainClassifyProgrammer_decodeArrayProps{
|
|
159
163
|
Context: props.Context,
|
|
@@ -187,12 +191,16 @@ func plainClassifyProgrammer_write_tuple_functions(props struct {
|
|
|
187
191
|
}) []*shimast.Node {
|
|
188
192
|
f := nativecontext.EmitFactoryOf(plainClassifyProgrammer_factory, props.Context.Emit)
|
|
189
193
|
output := []*shimast.Node{}
|
|
190
|
-
for
|
|
194
|
+
for _, tuple := range props.Collection.Tuples() {
|
|
191
195
|
if tuple.Recursive == false {
|
|
192
196
|
continue
|
|
193
197
|
}
|
|
198
|
+
index := 0
|
|
199
|
+
if tuple.Index != nil {
|
|
200
|
+
index = *tuple.Index
|
|
201
|
+
}
|
|
194
202
|
output = append(output, nativefactories.StatementFactory.Constant(nativefactories.StatementFactory_ConstantProps{
|
|
195
|
-
Name: fmt.Sprintf("%st%d", props.Config.Prefix,
|
|
203
|
+
Name: fmt.Sprintf("%st%d", props.Config.Prefix, index),
|
|
196
204
|
Value: f.NewArrowFunction(
|
|
197
205
|
nil,
|
|
198
206
|
nil,
|
|
@@ -205,7 +213,7 @@ func plainClassifyProgrammer_write_tuple_functions(props struct {
|
|
|
205
213
|
nil,
|
|
206
214
|
f.NewToken(shimast.KindEqualsGreaterThanToken),
|
|
207
215
|
nativeinternal.FeatureProgrammer.VisitGuardRebuild(
|
|
208
|
-
nativeinternal.FeatureProgrammer.VisitKey(props.Config.Prefix, "t",
|
|
216
|
+
nativeinternal.FeatureProgrammer.VisitKey(props.Config.Prefix, "t", index),
|
|
209
217
|
true,
|
|
210
218
|
plainClassifyProgrammer_decode_tuple_inline(plainClassifyProgrammer_decodeTupleInlineProps{
|
|
211
219
|
Context: props.Context,
|