@elaraai/east 0.0.1-beta.8 → 1.0.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/LICENSE.md +15 -666
- package/README.md +113 -88
- package/dist/src/analyze.d.ts +3 -0
- package/dist/src/analyze.d.ts.map +1 -1
- package/dist/src/analyze.js +223 -111
- package/dist/src/analyze.js.map +1 -1
- package/dist/src/analyze.spec.d.ts +2 -0
- package/dist/src/analyze.spec.d.ts.map +1 -0
- package/dist/src/analyze.spec.js +445 -0
- package/dist/src/analyze.spec.js.map +1 -0
- package/dist/src/ast.d.ts +54 -35
- package/dist/src/ast.d.ts.map +1 -1
- package/dist/src/ast_to_ir.coerce_to.spec.d.ts +15 -0
- package/dist/src/ast_to_ir.coerce_to.spec.d.ts.map +1 -0
- package/dist/src/ast_to_ir.coerce_to.spec.js +420 -0
- package/dist/src/ast_to_ir.coerce_to.spec.js.map +1 -0
- package/dist/src/ast_to_ir.d.ts +18 -4
- package/dist/src/ast_to_ir.d.ts.map +1 -1
- package/dist/src/ast_to_ir.js +233 -178
- package/dist/src/ast_to_ir.js.map +1 -1
- package/dist/src/builtins.d.ts +1 -1
- package/dist/src/builtins.d.ts.map +1 -1
- package/dist/src/builtins.js +194 -2
- package/dist/src/builtins.js.map +1 -1
- package/dist/src/comparison.d.ts +2 -2
- package/dist/src/comparison.d.ts.map +1 -1
- package/dist/src/comparison.js +115 -40
- package/dist/src/comparison.js.map +1 -1
- package/dist/src/comparison.spec.d.ts +2 -0
- package/dist/src/comparison.spec.d.ts.map +1 -0
- package/dist/src/comparison.spec.js +1200 -0
- package/dist/src/comparison.spec.js.map +1 -0
- package/dist/src/compile.d.ts +31 -9
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +1048 -548
- package/dist/src/compile.js.map +1 -1
- package/dist/src/containers/matrix.d.ts +15 -0
- package/dist/src/containers/matrix.d.ts.map +1 -0
- package/dist/src/containers/matrix.js +15 -0
- package/dist/src/containers/matrix.js.map +1 -0
- package/dist/src/containers/ref.d.ts.map +1 -1
- package/dist/src/containers/ref.js +1 -1
- package/dist/src/containers/ref.js.map +1 -1
- package/dist/src/containers/sortedmap.spec.d.ts +2 -0
- package/dist/src/containers/sortedmap.spec.d.ts.map +1 -0
- package/dist/src/containers/sortedmap.spec.js +180 -0
- package/dist/src/containers/sortedmap.spec.js.map +1 -0
- package/dist/src/containers/sortedset.spec.d.ts +2 -0
- package/dist/src/containers/sortedset.spec.d.ts.map +1 -0
- package/dist/src/containers/sortedset.spec.js +228 -0
- package/dist/src/containers/sortedset.spec.js.map +1 -0
- package/dist/src/containers/variant.d.ts.map +1 -1
- package/dist/src/containers/variant.js +1 -1
- package/dist/src/containers/variant.js.map +1 -1
- package/dist/src/containers/variant.spec.d.ts +2 -0
- package/dist/src/containers/variant.spec.d.ts.map +1 -0
- package/dist/src/containers/variant.spec.js +217 -0
- package/dist/src/containers/variant.spec.js.map +1 -0
- package/dist/src/datetime_format/parse.spec.d.ts +6 -0
- package/dist/src/datetime_format/parse.spec.d.ts.map +1 -0
- package/dist/src/datetime_format/parse.spec.js +379 -0
- package/dist/src/datetime_format/parse.spec.js.map +1 -0
- package/dist/src/datetime_format/print.spec.d.ts +6 -0
- package/dist/src/datetime_format/print.spec.d.ts.map +1 -0
- package/dist/src/datetime_format/print.spec.js +257 -0
- package/dist/src/datetime_format/print.spec.js.map +1 -0
- package/dist/src/datetime_format/tokenize.spec.d.ts +2 -0
- package/dist/src/datetime_format/tokenize.spec.d.ts.map +1 -0
- package/dist/src/datetime_format/tokenize.spec.js +508 -0
- package/dist/src/datetime_format/tokenize.spec.js.map +1 -0
- package/dist/src/datetime_format/types.d.ts +23 -23
- package/dist/src/default.d.ts.map +1 -1
- package/dist/src/default.js +33 -0
- package/dist/src/default.js.map +1 -1
- package/dist/src/default.spec.d.ts +2 -0
- package/dist/src/default.spec.d.ts.map +1 -0
- package/dist/src/default.spec.js +178 -0
- package/dist/src/default.spec.js.map +1 -0
- package/dist/src/eastir.d.ts +7 -0
- package/dist/src/eastir.d.ts.map +1 -1
- package/dist/src/eastir.js +55 -7
- package/dist/src/eastir.js.map +1 -1
- package/dist/src/error.d.ts +14 -4
- package/dist/src/error.d.ts.map +1 -1
- package/dist/src/error.js +28 -3
- package/dist/src/error.js.map +1 -1
- package/dist/src/example.d.ts +87 -0
- package/dist/src/example.d.ts.map +1 -0
- package/dist/src/example.js +18 -0
- package/dist/src/example.js.map +1 -0
- package/dist/src/expr/array.d.ts +43 -1
- package/dist/src/expr/array.d.ts.map +1 -1
- package/dist/src/expr/array.js +103 -53
- package/dist/src/expr/array.js.map +1 -1
- package/dist/src/expr/ast.d.ts +1 -1
- package/dist/src/expr/ast.d.ts.map +1 -1
- package/dist/src/expr/ast.js +112 -54
- package/dist/src/expr/ast.js.map +1 -1
- package/dist/src/expr/asyncfunction.d.ts.map +1 -1
- package/dist/src/expr/asyncfunction.js +6 -4
- package/dist/src/expr/asyncfunction.js.map +1 -1
- package/dist/src/expr/blob.d.ts +48 -0
- package/dist/src/expr/blob.d.ts.map +1 -1
- package/dist/src/expr/blob.js +63 -8
- package/dist/src/expr/blob.js.map +1 -1
- package/dist/src/expr/block.d.ts +213 -12
- package/dist/src/expr/block.d.ts.map +1 -1
- package/dist/src/expr/block.js +796 -293
- package/dist/src/expr/block.js.map +1 -1
- package/dist/src/expr/boolean.d.ts +44 -0
- package/dist/src/expr/boolean.d.ts.map +1 -1
- package/dist/src/expr/boolean.js +58 -6
- package/dist/src/expr/boolean.js.map +1 -1
- package/dist/src/expr/datetime.d.ts +135 -0
- package/dist/src/expr/datetime.d.ts.map +1 -1
- package/dist/src/expr/datetime.js +184 -34
- package/dist/src/expr/datetime.js.map +1 -1
- package/dist/src/expr/dict.d.ts +47 -2
- package/dist/src/expr/dict.d.ts.map +1 -1
- package/dist/src/expr/dict.js +122 -61
- package/dist/src/expr/dict.js.map +1 -1
- package/dist/src/expr/expr.d.ts +3 -1
- package/dist/src/expr/expr.d.ts.map +1 -1
- package/dist/src/expr/expr.js +4 -3
- package/dist/src/expr/expr.js.map +1 -1
- package/dist/src/expr/float.d.ts +153 -0
- package/dist/src/expr/float.d.ts.map +1 -1
- package/dist/src/expr/float.js +191 -17
- package/dist/src/expr/float.js.map +1 -1
- package/dist/src/expr/function.d.ts +7 -2
- package/dist/src/expr/function.d.ts.map +1 -1
- package/dist/src/expr/function.js +6 -4
- package/dist/src/expr/function.js.map +1 -1
- package/dist/src/expr/index.d.ts +186 -2
- package/dist/src/expr/index.d.ts.map +1 -1
- package/dist/src/expr/index.js +183 -2
- package/dist/src/expr/index.js.map +1 -1
- package/dist/src/expr/integer.d.ts +180 -0
- package/dist/src/expr/integer.d.ts.map +1 -1
- package/dist/src/expr/integer.js +189 -18
- package/dist/src/expr/integer.js.map +1 -1
- package/dist/src/expr/libs/array.js +3 -3
- package/dist/src/expr/libs/array.js.map +1 -1
- package/dist/src/expr/libs/blob.js +3 -3
- package/dist/src/expr/libs/blob.js.map +1 -1
- package/dist/src/expr/libs/dict.js +1 -1
- package/dist/src/expr/libs/dict.js.map +1 -1
- package/dist/src/expr/libs/matrix.d.ts +17 -0
- package/dist/src/expr/libs/matrix.d.ts.map +1 -0
- package/dist/src/expr/libs/matrix.js +60 -0
- package/dist/src/expr/libs/matrix.js.map +1 -0
- package/dist/src/expr/libs/set.js +1 -1
- package/dist/src/expr/libs/set.js.map +1 -1
- package/dist/src/expr/libs/string.d.ts.map +1 -1
- package/dist/src/expr/libs/string.js +2 -1
- package/dist/src/expr/libs/string.js.map +1 -1
- package/dist/src/expr/libs/vector.d.ts +16 -0
- package/dist/src/expr/libs/vector.d.ts.map +1 -0
- package/dist/src/expr/libs/vector.js +44 -0
- package/dist/src/expr/libs/vector.js.map +1 -0
- package/dist/src/expr/matrix.d.ts +109 -0
- package/dist/src/expr/matrix.d.ts.map +1 -0
- package/dist/src/expr/matrix.js +224 -0
- package/dist/src/expr/matrix.js.map +1 -0
- package/dist/src/expr/recursive.d.ts +83 -0
- package/dist/src/expr/recursive.d.ts.map +1 -0
- package/dist/src/expr/recursive.js +99 -0
- package/dist/src/expr/recursive.js.map +1 -0
- package/dist/src/expr/ref.js +5 -5
- package/dist/src/expr/ref.js.map +1 -1
- package/dist/src/expr/set.d.ts +44 -2
- package/dist/src/expr/set.d.ts.map +1 -1
- package/dist/src/expr/set.js +102 -52
- package/dist/src/expr/set.js.map +1 -1
- package/dist/src/expr/string.d.ts +134 -0
- package/dist/src/expr/string.d.ts.map +1 -1
- package/dist/src/expr/string.js +173 -23
- package/dist/src/expr/string.js.map +1 -1
- package/dist/src/expr/struct.d.ts +1 -1
- package/dist/src/expr/struct.d.ts.map +1 -1
- package/dist/src/expr/struct.js +2 -2
- package/dist/src/expr/struct.js.map +1 -1
- package/dist/src/expr/types.d.ts +12 -9
- package/dist/src/expr/types.d.ts.map +1 -1
- package/dist/src/expr/variant.d.ts +108 -11
- package/dist/src/expr/variant.d.ts.map +1 -1
- package/dist/src/expr/variant.js +76 -38
- package/dist/src/expr/variant.js.map +1 -1
- package/dist/src/expr/vector.d.ts +102 -0
- package/dist/src/expr/vector.d.ts.map +1 -0
- package/dist/src/expr/vector.js +202 -0
- package/dist/src/expr/vector.js.map +1 -0
- package/dist/src/fuzz.d.ts +36 -2
- package/dist/src/fuzz.d.ts.map +1 -1
- package/dist/src/fuzz.js +409 -77
- package/dist/src/fuzz.js.map +1 -1
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/internal.d.ts +12 -2
- package/dist/src/internal.d.ts.map +1 -1
- package/dist/src/internal.js +13 -2
- package/dist/src/internal.js.map +1 -1
- package/dist/src/ir.d.ts +1754 -1484
- package/dist/src/ir.d.ts.map +1 -1
- package/dist/src/ir.js +51 -34
- package/dist/src/ir.js.map +1 -1
- package/dist/src/ir.spec.d.ts +2 -0
- package/dist/src/ir.spec.d.ts.map +1 -0
- package/dist/src/ir.spec.js +35 -0
- package/dist/src/ir.spec.js.map +1 -0
- package/dist/src/location.d.ts +56 -17
- package/dist/src/location.d.ts.map +1 -1
- package/dist/src/location.js +226 -29
- package/dist/src/location.js.map +1 -1
- package/dist/src/location.spec.d.ts +2 -0
- package/dist/src/location.spec.d.ts.map +1 -0
- package/dist/src/location.spec.js +102 -0
- package/dist/src/location.spec.js.map +1 -0
- package/dist/src/patch/apply.d.ts +15 -0
- package/dist/src/patch/apply.d.ts.map +1 -0
- package/dist/src/patch/apply.js +352 -0
- package/dist/src/patch/apply.js.map +1 -0
- package/dist/src/patch/compose.d.ts +15 -0
- package/dist/src/patch/compose.d.ts.map +1 -0
- package/dist/src/patch/compose.js +448 -0
- package/dist/src/patch/compose.js.map +1 -0
- package/dist/src/patch/diff.d.ts +15 -0
- package/dist/src/patch/diff.d.ts.map +1 -0
- package/dist/src/patch/diff.js +347 -0
- package/dist/src/patch/diff.js.map +1 -0
- package/dist/src/patch/fuzz.d.ts +73 -0
- package/dist/src/patch/fuzz.d.ts.map +1 -0
- package/dist/src/patch/fuzz.js +159 -0
- package/dist/src/patch/fuzz.js.map +1 -0
- package/dist/src/patch/index.d.ts +32 -0
- package/dist/src/patch/index.d.ts.map +1 -0
- package/dist/src/patch/index.js +48 -0
- package/dist/src/patch/index.js.map +1 -0
- package/dist/src/patch/invert.d.ts +15 -0
- package/dist/src/patch/invert.d.ts.map +1 -0
- package/dist/src/patch/invert.js +284 -0
- package/dist/src/patch/invert.js.map +1 -0
- package/dist/src/patch/merge.d.ts +56 -0
- package/dist/src/patch/merge.d.ts.map +1 -0
- package/dist/src/patch/merge.js +586 -0
- package/dist/src/patch/merge.js.map +1 -0
- package/dist/src/patch/merge.spec.d.ts +2 -0
- package/dist/src/patch/merge.spec.d.ts.map +1 -0
- package/dist/src/patch/merge.spec.js +1139 -0
- package/dist/src/patch/merge.spec.js.map +1 -0
- package/dist/src/patch/patch.spec.d.ts +2 -0
- package/dist/src/patch/patch.spec.d.ts.map +1 -0
- package/dist/src/patch/patch.spec.js +452 -0
- package/dist/src/patch/patch.spec.js.map +1 -0
- package/dist/src/patch/path.d.ts +115 -0
- package/dist/src/patch/path.d.ts.map +1 -0
- package/dist/src/patch/path.js +192 -0
- package/dist/src/patch/path.js.map +1 -0
- package/dist/src/patch/path.spec.d.ts +6 -0
- package/dist/src/patch/path.spec.d.ts.map +1 -0
- package/dist/src/patch/path.spec.js +322 -0
- package/dist/src/patch/path.spec.js.map +1 -0
- package/dist/src/patch/prune.d.ts +77 -0
- package/dist/src/patch/prune.d.ts.map +1 -0
- package/dist/src/patch/prune.js +115 -0
- package/dist/src/patch/prune.js.map +1 -0
- package/dist/src/patch/prune.spec.d.ts +6 -0
- package/dist/src/patch/prune.spec.d.ts.map +1 -0
- package/dist/src/patch/prune.spec.js +473 -0
- package/dist/src/patch/prune.spec.js.map +1 -0
- package/dist/src/patch/type_of_patch.d.ts +25 -0
- package/dist/src/patch/type_of_patch.d.ts.map +1 -0
- package/dist/src/patch/type_of_patch.js +144 -0
- package/dist/src/patch/type_of_patch.js.map +1 -0
- package/dist/src/patch/types.d.ts +220 -0
- package/dist/src/patch/types.d.ts.map +1 -0
- package/dist/src/patch/types.js +62 -0
- package/dist/src/patch/types.js.map +1 -0
- package/dist/src/patch/validate.d.ts +44 -0
- package/dist/src/patch/validate.d.ts.map +1 -0
- package/dist/src/patch/validate.js +190 -0
- package/dist/src/patch/validate.js.map +1 -0
- package/dist/src/patch/validate.spec.d.ts +6 -0
- package/dist/src/patch/validate.spec.d.ts.map +1 -0
- package/dist/src/patch/validate.spec.js +225 -0
- package/dist/src/patch/validate.spec.js.map +1 -0
- package/dist/src/patch/walk.d.ts +121 -0
- package/dist/src/patch/walk.d.ts.map +1 -0
- package/dist/src/patch/walk.js +385 -0
- package/dist/src/patch/walk.js.map +1 -0
- package/dist/src/patch/walk.spec.d.ts +6 -0
- package/dist/src/patch/walk.spec.d.ts.map +1 -0
- package/dist/src/patch/walk.spec.js +621 -0
- package/dist/src/patch/walk.spec.js.map +1 -0
- package/dist/src/platform.d.ts +6 -0
- package/dist/src/platform.d.ts.map +1 -1
- package/dist/src/platform.spec.d.ts +2 -0
- package/dist/src/platform.spec.d.ts.map +1 -0
- package/dist/src/platform.spec.js +330 -0
- package/dist/src/platform.spec.js.map +1 -0
- package/dist/src/serialization/beast.d.ts.map +1 -1
- package/dist/src/serialization/beast.js +12 -0
- package/dist/src/serialization/beast.js.map +1 -1
- package/dist/src/serialization/beast.spec.d.ts +6 -0
- package/dist/src/serialization/beast.spec.d.ts.map +1 -0
- package/dist/src/serialization/beast.spec.js +406 -0
- package/dist/src/serialization/beast.spec.js.map +1 -0
- package/dist/src/serialization/beast2/index.d.ts +50 -0
- package/dist/src/serialization/beast2/index.d.ts.map +1 -0
- package/dist/src/serialization/beast2/index.js +756 -0
- package/dist/src/serialization/beast2/index.js.map +1 -0
- package/dist/src/serialization/beast2/index.spec.d.ts +6 -0
- package/dist/src/serialization/beast2/index.spec.d.ts.map +1 -0
- package/dist/src/serialization/beast2/index.spec.js +528 -0
- package/dist/src/serialization/beast2/index.spec.js.map +1 -0
- package/dist/src/serialization/beast2/sourcemap-table.d.ts +29 -0
- package/dist/src/serialization/beast2/sourcemap-table.d.ts.map +1 -0
- package/dist/src/serialization/beast2/sourcemap-table.js +82 -0
- package/dist/src/serialization/beast2/sourcemap-table.js.map +1 -0
- package/dist/src/serialization/beast2/string-table.d.ts +16 -0
- package/dist/src/serialization/beast2/string-table.d.ts.map +1 -0
- package/dist/src/serialization/beast2/string-table.js +38 -0
- package/dist/src/serialization/beast2/string-table.js.map +1 -0
- package/dist/src/serialization/beast2/type-table.d.ts +86 -0
- package/dist/src/serialization/beast2/type-table.d.ts.map +1 -0
- package/dist/src/serialization/beast2/type-table.js +618 -0
- package/dist/src/serialization/beast2/type-table.js.map +1 -0
- package/dist/src/serialization/beast2/value-table.d.ts +40 -0
- package/dist/src/serialization/beast2/value-table.d.ts.map +1 -0
- package/dist/src/serialization/beast2/value-table.js +157 -0
- package/dist/src/serialization/beast2/value-table.js.map +1 -0
- package/dist/src/serialization/binary-utils.d.ts +33 -0
- package/dist/src/serialization/binary-utils.d.ts.map +1 -1
- package/dist/src/serialization/binary-utils.js +157 -0
- package/dist/src/serialization/binary-utils.js.map +1 -1
- package/dist/src/serialization/csv.d.ts +17 -17
- package/dist/src/serialization/csv.d.ts.map +1 -1
- package/dist/src/serialization/csv.js +10 -8
- package/dist/src/serialization/csv.js.map +1 -1
- package/dist/src/serialization/csv.spec.d.ts +2 -0
- package/dist/src/serialization/csv.spec.d.ts.map +1 -0
- package/dist/src/serialization/csv.spec.js +556 -0
- package/dist/src/serialization/csv.spec.js.map +1 -0
- package/dist/src/serialization/east-inferred.spec.d.ts +2 -0
- package/dist/src/serialization/east-inferred.spec.d.ts.map +1 -0
- package/dist/src/serialization/east-inferred.spec.js +322 -0
- package/dist/src/serialization/east-inferred.spec.js.map +1 -0
- package/dist/src/serialization/east.d.ts +1 -1
- package/dist/src/serialization/east.d.ts.map +1 -1
- package/dist/src/serialization/east.js +178 -26
- package/dist/src/serialization/east.js.map +1 -1
- package/dist/src/serialization/east.spec.d.ts +2 -0
- package/dist/src/serialization/east.spec.d.ts.map +1 -0
- package/dist/src/serialization/east.spec.js +1548 -0
- package/dist/src/serialization/east.spec.js.map +1 -0
- package/dist/src/serialization/index.d.ts +1 -2
- package/dist/src/serialization/index.d.ts.map +1 -1
- package/dist/src/serialization/index.js +1 -2
- package/dist/src/serialization/index.js.map +1 -1
- package/dist/src/serialization/json.d.ts +1 -1
- package/dist/src/serialization/json.d.ts.map +1 -1
- package/dist/src/serialization/json.js +123 -24
- package/dist/src/serialization/json.js.map +1 -1
- package/dist/src/serialization/json.spec.d.ts +2 -0
- package/dist/src/serialization/json.spec.d.ts.map +1 -0
- package/dist/src/serialization/json.spec.js +1297 -0
- package/dist/src/serialization/json.spec.js.map +1 -0
- package/dist/src/type_of_type.d.ts +72 -35
- package/dist/src/type_of_type.d.ts.map +1 -1
- package/dist/src/type_of_type.is_data.spec.d.ts +6 -0
- package/dist/src/type_of_type.is_data.spec.d.ts.map +1 -0
- package/dist/src/type_of_type.is_data.spec.js +221 -0
- package/dist/src/type_of_type.is_data.spec.js.map +1 -0
- package/dist/src/type_of_type.js +355 -80
- package/dist/src/type_of_type.js.map +1 -1
- package/dist/src/type_of_type.to_etv.spec.d.ts +6 -0
- package/dist/src/type_of_type.to_etv.spec.d.ts.map +1 -0
- package/dist/src/type_of_type.to_etv.spec.js +263 -0
- package/dist/src/type_of_type.to_etv.spec.js.map +1 -0
- package/dist/src/types.d.ts +82 -12
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.error.spec.d.ts +2 -0
- package/dist/src/types.error.spec.d.ts.map +1 -0
- package/dist/src/types.error.spec.js +665 -0
- package/dist/src/types.error.spec.js.map +1 -0
- package/dist/src/types.js +663 -156
- package/dist/src/types.js.map +1 -1
- package/dist/src/types.spec.d.ts +2 -0
- package/dist/src/types.spec.d.ts.map +1 -0
- package/dist/src/types.spec.js +946 -0
- package/dist/src/types.spec.js.map +1 -0
- package/dist/src/walker.d.ts +65 -0
- package/dist/src/walker.d.ts.map +1 -0
- package/dist/src/walker.js +165 -0
- package/dist/src/walker.js.map +1 -0
- package/dist/src/walker.spec.d.ts +6 -0
- package/dist/src/walker.spec.d.ts.map +1 -0
- package/dist/src/walker.spec.js +109 -0
- package/dist/src/walker.spec.js.map +1 -0
- package/package.json +16 -38
- package/dist/src/serialization/beast2-stream.d.ts +0 -38
- package/dist/src/serialization/beast2-stream.d.ts.map +0 -1
- package/dist/src/serialization/beast2-stream.js +0 -670
- package/dist/src/serialization/beast2-stream.js.map +0 -1
- package/dist/src/serialization/beast2.d.ts +0 -41
- package/dist/src/serialization/beast2.d.ts.map +0 -1
- package/dist/src/serialization/beast2.js +0 -495
- package/dist/src/serialization/beast2.js.map +0 -1
package/dist/src/analyze.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
3
|
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
|
-
import { printLocationValue } from "./ir.js";
|
|
6
5
|
import { isTypeValueEqual, isSubtypeValue, expandTypeValue, toEastTypeValue } from "./type_of_type.js";
|
|
7
6
|
import { printTypeValue } from "./compile.js";
|
|
8
7
|
import { variant } from "./containers/variant.js";
|
|
@@ -37,20 +36,30 @@ import { Builtins } from "./builtins.js";
|
|
|
37
36
|
export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
38
37
|
// Working data for tracking during analysis
|
|
39
38
|
const analysis = new Map();
|
|
39
|
+
// Pre-populate analysis Map with definedBy nodes from external context.
|
|
40
|
+
// This is needed when analyzing deserialized functions with captures - the external
|
|
41
|
+
// context contains variable metadata with definedBy references that need to be in
|
|
42
|
+
// the analysis Map so nested functions can properly mark them as captured.
|
|
43
|
+
for (const varName of Object.keys(ctx)) {
|
|
44
|
+
const varMeta = ctx[varName];
|
|
45
|
+
if (varMeta?.definedBy && !analysis.has(varMeta.definedBy)) {
|
|
46
|
+
analysis.set(varMeta.definedBy, { captured: varMeta.captured });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
40
49
|
// Build a lookup map for platform functions
|
|
41
50
|
const platformMap = new Map();
|
|
42
51
|
for (const p of platformDef) {
|
|
43
52
|
if (platformMap.has(p.name)) {
|
|
44
53
|
throw new Error(`Duplicate platform function definition for '${p.name}'`);
|
|
45
54
|
}
|
|
46
|
-
platformMap.set(p.name,
|
|
55
|
+
platformMap.set(p.name, p);
|
|
47
56
|
}
|
|
48
57
|
// Track circular references
|
|
49
58
|
const visiting = new Set();
|
|
50
59
|
function visit(node, ctx, expectedReturnType) {
|
|
51
60
|
// Detect circular IR (we don't cache because we're building new nodes)
|
|
52
61
|
if (visiting.has(node)) {
|
|
53
|
-
throw new Error(`Circular IR reference detected at ${
|
|
62
|
+
throw new Error(`Circular IR reference detected at loc_id ${node.value.loc_id}`);
|
|
54
63
|
}
|
|
55
64
|
visiting.add(node);
|
|
56
65
|
try {
|
|
@@ -67,7 +76,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
67
76
|
// Validate that the type matches the value
|
|
68
77
|
if (node.value.type.type !== node.value.value.type) {
|
|
69
78
|
throw new Error(`Value node expected value of type .${node.value.type.type} ` +
|
|
70
|
-
`but got .${node.value.value.type} at ${
|
|
79
|
+
`but got .${node.value.value.type} at loc_id ${node.value.loc_id}`);
|
|
71
80
|
}
|
|
72
81
|
// Value is always sync (literal constant)
|
|
73
82
|
return {
|
|
@@ -83,19 +92,19 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
83
92
|
const varMeta = ctx[name];
|
|
84
93
|
// Validate variable is in scope
|
|
85
94
|
if (varMeta === undefined) {
|
|
86
|
-
throw new Error(`Variable ${name} not in scope at ${
|
|
95
|
+
throw new Error(`Variable ${name} not in scope at loc_id ${node.value.loc_id}`);
|
|
87
96
|
}
|
|
88
97
|
// Validate type matches
|
|
89
98
|
if (!isTypeValueEqual(varMeta.type, node.value.type)) {
|
|
90
99
|
throw new Error(`Variable ${name} has type ${printTypeValue(varMeta.type)} ` +
|
|
91
|
-
`but expected ${printTypeValue(node.value.type)} at ${
|
|
100
|
+
`but expected ${printTypeValue(node.value.type)} at loc_id ${node.value.loc_id}`);
|
|
92
101
|
}
|
|
93
102
|
// Validate mutability matches
|
|
94
103
|
if (varMeta.mutable !== node.value.mutable) {
|
|
95
104
|
throw new Error(`Variable ${name} mutability mismatch: ` +
|
|
96
105
|
`context has ${varMeta.mutable ? 'mutable' : 'const'} ` +
|
|
97
106
|
`but IR expects ${node.value.mutable ? 'mutable' : 'const'} ` +
|
|
98
|
-
`at ${
|
|
107
|
+
`at loc_id ${node.value.loc_id}`);
|
|
99
108
|
}
|
|
100
109
|
// Detect capture: if variable is not in current scope but in parent, mark as captured
|
|
101
110
|
if (!Object.hasOwn(ctx, name)) {
|
|
@@ -138,7 +147,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
138
147
|
`has type ${printTypeValue(node.value.variable.value.type)} ` +
|
|
139
148
|
`but value has type ${printTypeValue(valueInfo.value.type)}. ` +
|
|
140
149
|
`Insert an As node if subtyping is intended. ` +
|
|
141
|
-
`at ${
|
|
150
|
+
`at loc_id ${node.value.loc_id}`);
|
|
142
151
|
}
|
|
143
152
|
// Analyze the VariableIR node itself (so it has an entry in the analysis map)
|
|
144
153
|
analysis.set(node.value.variable, {
|
|
@@ -168,17 +177,17 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
168
177
|
// Validate variable exists in scope
|
|
169
178
|
if (varMeta === undefined) {
|
|
170
179
|
throw new Error(`Cannot assign to variable ${varName} which is not in scope ` +
|
|
171
|
-
`at ${
|
|
180
|
+
`at loc_id ${node.value.loc_id}`);
|
|
172
181
|
}
|
|
173
182
|
// Validate variable is mutable in IR
|
|
174
183
|
if (!node.value.variable.value.mutable) {
|
|
175
184
|
throw new Error(`Cannot reassign const variable ${varName} ` +
|
|
176
|
-
`at ${
|
|
185
|
+
`at loc_id ${node.value.loc_id}`);
|
|
177
186
|
}
|
|
178
187
|
// Validate variable is mutable in context (matches IR)
|
|
179
188
|
if (!varMeta.mutable) {
|
|
180
189
|
throw new Error(`Cannot reassign variable ${varName} - context says it's const ` +
|
|
181
|
-
`at ${
|
|
190
|
+
`at loc_id ${node.value.loc_id}`);
|
|
182
191
|
}
|
|
183
192
|
// Visit the value expression
|
|
184
193
|
const valueInfo = visit(node.value.value, ctx, expectedReturnType);
|
|
@@ -189,7 +198,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
189
198
|
`Variable ${varName} has type ${printTypeValue(varMeta.type)} ` +
|
|
190
199
|
`but value has type ${printTypeValue(valueInfo.value.type)}. ` +
|
|
191
200
|
`Insert an As node if subtyping is intended. ` +
|
|
192
|
-
`at ${
|
|
201
|
+
`at loc_id ${node.value.loc_id}`);
|
|
193
202
|
}
|
|
194
203
|
isAsync = valueInfo.value.isAsync; // Async if the value expression is async
|
|
195
204
|
}
|
|
@@ -214,7 +223,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
214
223
|
if (!isTypeValueEqual(lastType, node.value.type)) {
|
|
215
224
|
throw new Error(`Block evaluates to type ${printTypeValue(lastType)} ` +
|
|
216
225
|
`but expected ${printTypeValue(node.value.type)} ` +
|
|
217
|
-
`at ${
|
|
226
|
+
`at loc_id ${node.value.loc_id}`);
|
|
218
227
|
}
|
|
219
228
|
// Return analyzed Block with analyzed statements
|
|
220
229
|
return {
|
|
@@ -233,17 +242,17 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
233
242
|
if (!isSubtypeValue(valueInfo.value.type, node.value.type)) {
|
|
234
243
|
throw new Error(`Cannot cast value of type ${printTypeValue(valueInfo.value.type)} ` +
|
|
235
244
|
`to type ${printTypeValue(node.value.type)} ` +
|
|
236
|
-
`at ${
|
|
245
|
+
`at loc_id ${node.value.loc_id}`);
|
|
237
246
|
}
|
|
238
247
|
// More thorough checks for "unnecessary" As IR nodes:
|
|
239
248
|
// Cannot cast Never to a value
|
|
240
249
|
if (valueInfo.value.type.type === "Never") {
|
|
241
250
|
throw new Error(`Cannot cast .Never to type ${printTypeValue(node.value.type)} ` +
|
|
242
|
-
`at ${
|
|
251
|
+
`at loc_id ${node.value.loc_id}`);
|
|
243
252
|
}
|
|
244
253
|
if (isTypeValueEqual(valueInfo.value.type, node.value.type)) {
|
|
245
254
|
throw new Error(`Unnecessary As node: value is already of type ${printTypeValue(node.value.type)} ` +
|
|
246
|
-
`at ${
|
|
255
|
+
`at loc_id ${node.value.loc_id}`);
|
|
247
256
|
}
|
|
248
257
|
isAsync = valueInfo.value.isAsync; // Propagate async from child
|
|
249
258
|
}
|
|
@@ -251,14 +260,57 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
251
260
|
// Look up platform function
|
|
252
261
|
const platformFn = platformMap.get(node.value.name);
|
|
253
262
|
if (!platformFn) {
|
|
254
|
-
|
|
255
|
-
|
|
263
|
+
// Allow missing platforms only if this specific platform function is marked as optional in the IR
|
|
264
|
+
if (!node.value.optional) {
|
|
265
|
+
throw new Error(`Platform function '${node.value.name}' not found ` +
|
|
266
|
+
`at loc_id ${node.value.loc_id}`);
|
|
267
|
+
}
|
|
268
|
+
// allowMissingPlatform is true - analyze arguments without type validation
|
|
269
|
+
// and let compile inject a runtime error stub
|
|
270
|
+
const analyzedArgs = [];
|
|
271
|
+
for (const arg of node.value.arguments) {
|
|
272
|
+
const argAnalyzed = visit(arg, ctx, expectedReturnType);
|
|
273
|
+
analyzedArgs.push(argAnalyzed);
|
|
274
|
+
if (argAnalyzed.value.isAsync) {
|
|
275
|
+
isAsync = true;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
// Return analyzed Platform node with analyzed arguments (no type validation)
|
|
279
|
+
return {
|
|
280
|
+
...node,
|
|
281
|
+
value: {
|
|
282
|
+
...node.value,
|
|
283
|
+
arguments: analyzedArgs,
|
|
284
|
+
isAsync,
|
|
285
|
+
}
|
|
286
|
+
};
|
|
256
287
|
}
|
|
257
|
-
//
|
|
258
|
-
|
|
259
|
-
|
|
288
|
+
// Handle generic platform functions
|
|
289
|
+
const typeParams = node.value.type_parameters ?? [];
|
|
290
|
+
const expectedTypeParamCount = platformFn.type_parameters?.length ?? 0;
|
|
291
|
+
if (typeParams.length !== expectedTypeParamCount) {
|
|
292
|
+
throw new Error(`Platform function '${node.value.name}' expects ${expectedTypeParamCount} ` +
|
|
293
|
+
`type parameters, got ${typeParams.length} ` +
|
|
294
|
+
`at loc_id ${node.value.loc_id}`);
|
|
295
|
+
}
|
|
296
|
+
// Compute concrete input/output types by substituting type parameters
|
|
297
|
+
let inputTypes;
|
|
298
|
+
let outputType;
|
|
299
|
+
if (expectedTypeParamCount > 0 && platformFn.inputsFn && platformFn.outputsFn) {
|
|
300
|
+
// Generic platform function - use callbacks to compute types
|
|
301
|
+
inputTypes = platformFn.inputsFn(...typeParams);
|
|
302
|
+
outputType = platformFn.outputsFn(...typeParams);
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
// Non-generic - use stored concrete types
|
|
306
|
+
inputTypes = platformFn.inputs;
|
|
307
|
+
outputType = platformFn.output;
|
|
308
|
+
}
|
|
309
|
+
// Validate argument count (now using computed inputTypes)
|
|
310
|
+
if (node.value.arguments.length !== inputTypes.length) {
|
|
311
|
+
throw new Error(`Platform function '${node.value.name}' expects ${inputTypes.length} arguments ` +
|
|
260
312
|
`but got ${node.value.arguments.length} ` +
|
|
261
|
-
`at ${
|
|
313
|
+
`at loc_id ${node.value.loc_id}`);
|
|
262
314
|
}
|
|
263
315
|
// Visit all arguments, check if any are async, and validate types
|
|
264
316
|
const analyzedArgs = [];
|
|
@@ -269,28 +321,28 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
269
321
|
if (argAnalyzed.value.isAsync) {
|
|
270
322
|
isAsync = true;
|
|
271
323
|
}
|
|
272
|
-
// Validate argument type exactly matches expected
|
|
324
|
+
// Validate argument type exactly matches expected (using computed inputTypes)
|
|
273
325
|
// (Subtyping should be handled by explicit As nodes)
|
|
274
|
-
const expectedType =
|
|
326
|
+
const expectedType = inputTypes[i];
|
|
275
327
|
if (argAnalyzed.value.type.type !== "Never" && !isTypeValueEqual(argAnalyzed.value.type, expectedType)) {
|
|
276
328
|
throw new Error(`Platform function '${node.value.name}' argument ${i + 1} ` +
|
|
277
329
|
`requires exact type match. ` +
|
|
278
330
|
`Expected type ${printTypeValue(expectedType)} ` +
|
|
279
331
|
`but got ${printTypeValue(argAnalyzed.value.type)}. ` +
|
|
280
332
|
`Insert an As node if subtyping is intended. ` +
|
|
281
|
-
`at ${
|
|
333
|
+
`at loc_id ${node.value.loc_id}`);
|
|
282
334
|
}
|
|
283
335
|
}
|
|
284
336
|
// Platform function itself might be async
|
|
285
337
|
if (platformFn.type === 'async') {
|
|
286
338
|
isAsync = true;
|
|
287
339
|
}
|
|
288
|
-
// Validate return type matches
|
|
289
|
-
if (!isTypeValueEqual(node.value.type,
|
|
340
|
+
// Validate return type matches (using computed outputType)
|
|
341
|
+
if (!isTypeValueEqual(node.value.type, outputType)) {
|
|
290
342
|
throw new Error(`Platform function '${node.value.name}' return type ` +
|
|
291
|
-
`expected to be ${printTypeValue(
|
|
343
|
+
`expected to be ${printTypeValue(outputType)} ` +
|
|
292
344
|
`but IR has ${printTypeValue(node.value.type)} ` +
|
|
293
|
-
`at ${
|
|
345
|
+
`at loc_id ${node.value.loc_id}`);
|
|
294
346
|
}
|
|
295
347
|
// Return analyzed Platform node with analyzed arguments
|
|
296
348
|
return {
|
|
@@ -306,7 +358,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
306
358
|
// Validate it has a Function type
|
|
307
359
|
if (node.value.type.type !== "Function") {
|
|
308
360
|
throw new Error(`Expected Function type, got ${printTypeValue(node.value.type)} ` +
|
|
309
|
-
`at ${
|
|
361
|
+
`at loc_id ${node.value.loc_id}`);
|
|
310
362
|
}
|
|
311
363
|
// Create new context for function body
|
|
312
364
|
const fnCtx = {};
|
|
@@ -315,27 +367,31 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
315
367
|
const outerVar = ctx[captureVar.value.name];
|
|
316
368
|
if (outerVar === undefined) {
|
|
317
369
|
throw new Error(`Captured variable ${captureVar.value.name} not in scope ` +
|
|
318
|
-
`at ${
|
|
370
|
+
`at loc_id ${node.value.loc_id}`);
|
|
319
371
|
}
|
|
320
372
|
if (!isTypeValueEqual(outerVar.type, captureVar.value.type)) {
|
|
321
373
|
throw new Error(`Captured variable ${captureVar.value.name} has type ${printTypeValue(outerVar.type)} ` +
|
|
322
374
|
`but expected ${printTypeValue(captureVar.value.type)} ` +
|
|
323
|
-
`at ${
|
|
375
|
+
`at loc_id ${node.value.loc_id}`);
|
|
324
376
|
}
|
|
325
377
|
if (outerVar.mutable !== captureVar.value.mutable) {
|
|
326
378
|
throw new Error(`Captured variable ${captureVar.value.name} mutability mismatch: ` +
|
|
327
379
|
`context has ${outerVar.mutable ? 'mutable' : 'const'} ` +
|
|
328
380
|
`but IR expects ${captureVar.value.mutable ? 'mutable' : 'const'} ` +
|
|
329
|
-
`at ${
|
|
381
|
+
`at loc_id ${node.value.loc_id}`);
|
|
330
382
|
}
|
|
331
383
|
// Mark the outer variable as captured (it's being closed over by this function)
|
|
384
|
+
const wasAlreadyCaptured = outerVar.captured;
|
|
332
385
|
outerVar.captured = true;
|
|
333
386
|
const defVarAnalysis = analysis.get(outerVar.definedBy);
|
|
334
|
-
if (
|
|
387
|
+
if (defVarAnalysis) {
|
|
388
|
+
defVarAnalysis.captured = true;
|
|
389
|
+
}
|
|
390
|
+
else if (!wasAlreadyCaptured) {
|
|
391
|
+
// Only error if this wasn't already marked as captured (from a synthetic/external context)
|
|
335
392
|
throw new Error(`Internal error: VariableIR node for captured variable ${captureVar.value.name} not analyzed. ` +
|
|
336
393
|
`This should never happen - all VariableIR nodes should be analyzed when encountered.`);
|
|
337
394
|
}
|
|
338
|
-
defVarAnalysis.captured = true;
|
|
339
395
|
fnCtx[captureVar.value.name] = {
|
|
340
396
|
type: captureVar.value.type,
|
|
341
397
|
mutable: captureVar.value.mutable,
|
|
@@ -365,7 +421,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
365
421
|
if (bodyInfo.value.type.type !== "Never" && !isTypeValueEqual(bodyInfo.value.type, expectedOutput)) {
|
|
366
422
|
throw new Error(`Function body returns type ${printTypeValue(bodyInfo.value.type)} ` +
|
|
367
423
|
`but function signature expects ${printTypeValue(expectedOutput)} ` +
|
|
368
|
-
`at ${
|
|
424
|
+
`at loc_id ${node.value.loc_id}`);
|
|
369
425
|
}
|
|
370
426
|
// Creating a function is sync (it just captures variables at this stage)
|
|
371
427
|
return {
|
|
@@ -381,7 +437,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
381
437
|
// Validate it has a Function type
|
|
382
438
|
if (node.value.type.type !== "AsyncFunction") {
|
|
383
439
|
throw new Error(`Expected AsyncFunction type, got ${printTypeValue(node.value.type)} ` +
|
|
384
|
-
`at ${
|
|
440
|
+
`at loc_id ${node.value.loc_id}`);
|
|
385
441
|
}
|
|
386
442
|
// Create new context for function body
|
|
387
443
|
const fnCtx = {};
|
|
@@ -390,27 +446,31 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
390
446
|
const outerVar = ctx[captureVar.value.name];
|
|
391
447
|
if (outerVar === undefined) {
|
|
392
448
|
throw new Error(`Captured variable ${captureVar.value.name} not in scope ` +
|
|
393
|
-
`at ${
|
|
449
|
+
`at loc_id ${node.value.loc_id}`);
|
|
394
450
|
}
|
|
395
451
|
if (!isTypeValueEqual(outerVar.type, captureVar.value.type)) {
|
|
396
452
|
throw new Error(`Captured variable ${captureVar.value.name} has type ${printTypeValue(outerVar.type)} ` +
|
|
397
453
|
`but expected ${printTypeValue(captureVar.value.type)} ` +
|
|
398
|
-
`at ${
|
|
454
|
+
`at loc_id ${node.value.loc_id}`);
|
|
399
455
|
}
|
|
400
456
|
if (outerVar.mutable !== captureVar.value.mutable) {
|
|
401
457
|
throw new Error(`Captured variable ${captureVar.value.name} mutability mismatch: ` +
|
|
402
458
|
`context has ${outerVar.mutable ? 'mutable' : 'const'} ` +
|
|
403
459
|
`but IR expects ${captureVar.value.mutable ? 'mutable' : 'const'} ` +
|
|
404
|
-
`at ${
|
|
460
|
+
`at loc_id ${node.value.loc_id}`);
|
|
405
461
|
}
|
|
406
462
|
// Mark the outer variable as captured (it's being closed over by this function)
|
|
463
|
+
const wasAlreadyCaptured = outerVar.captured;
|
|
407
464
|
outerVar.captured = true;
|
|
408
465
|
const defVarAnalysis = analysis.get(outerVar.definedBy);
|
|
409
|
-
if (
|
|
466
|
+
if (defVarAnalysis) {
|
|
467
|
+
defVarAnalysis.captured = true;
|
|
468
|
+
}
|
|
469
|
+
else if (!wasAlreadyCaptured) {
|
|
470
|
+
// Only error if this wasn't already marked as captured (from a synthetic/external context)
|
|
410
471
|
throw new Error(`Internal error: VariableIR node for captured variable ${captureVar.value.name} not analyzed. ` +
|
|
411
472
|
`This should never happen - all VariableIR nodes should be analyzed when encountered.`);
|
|
412
473
|
}
|
|
413
|
-
defVarAnalysis.captured = true;
|
|
414
474
|
fnCtx[captureVar.value.name] = {
|
|
415
475
|
type: captureVar.value.type,
|
|
416
476
|
mutable: captureVar.value.mutable,
|
|
@@ -440,7 +500,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
440
500
|
if (bodyInfo.value.type.type !== "Never" && !isTypeValueEqual(bodyInfo.value.type, expectedOutput)) {
|
|
441
501
|
throw new Error(`AsyncFunction body returns type ${printTypeValue(bodyInfo.value.type)} ` +
|
|
442
502
|
`but function signature expects ${printTypeValue(expectedOutput)} ` +
|
|
443
|
-
`at ${
|
|
503
|
+
`at loc_id ${node.value.loc_id}`);
|
|
444
504
|
}
|
|
445
505
|
// Creating a function is sync (it just captures variables at this stage)
|
|
446
506
|
return {
|
|
@@ -458,13 +518,13 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
458
518
|
// Validate it's a function type
|
|
459
519
|
if (fnInfo.value.type.type !== "Function") {
|
|
460
520
|
throw new Error(`Call expects Function type, got ${printTypeValue(fnInfo.value.type)} ` +
|
|
461
|
-
`at ${
|
|
521
|
+
`at loc_id ${node.value.loc_id}`);
|
|
462
522
|
}
|
|
463
523
|
// Validate argument count
|
|
464
524
|
if (fnInfo.value.type.value.inputs.length !== node.value.arguments.length) {
|
|
465
525
|
throw new Error(`Function expects ${fnInfo.value.type.value.inputs.length} arguments, ` +
|
|
466
526
|
`got ${node.value.arguments.length} ` +
|
|
467
|
-
`at ${
|
|
527
|
+
`at loc_id ${node.value.loc_id}`);
|
|
468
528
|
}
|
|
469
529
|
// Analyze all arguments
|
|
470
530
|
const analyzedArgs = [];
|
|
@@ -482,14 +542,14 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
482
542
|
`Expected type ${printTypeValue(expectedType)} ` +
|
|
483
543
|
`but got ${printTypeValue(argInfo.value.type)}. ` +
|
|
484
544
|
`Insert an As node if subtyping is intended. ` +
|
|
485
|
-
`at ${
|
|
545
|
+
`at loc_id ${node.value.loc_id}`);
|
|
486
546
|
}
|
|
487
547
|
}
|
|
488
548
|
// Validate return type matches
|
|
489
549
|
if (!isTypeValueEqual(node.value.type, fnInfo.value.type.value.output)) {
|
|
490
550
|
throw new Error(`Function call return type expected to be ${printTypeValue(fnInfo.value.type.value.output)} ` +
|
|
491
551
|
`but IR has ${printTypeValue(node.value.type)} ` +
|
|
492
|
-
`at ${
|
|
552
|
+
`at loc_id ${node.value.loc_id}`);
|
|
493
553
|
}
|
|
494
554
|
// Return analyzed Call with analyzed function and arguments
|
|
495
555
|
return {
|
|
@@ -510,13 +570,13 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
510
570
|
// Validate it's an async function type
|
|
511
571
|
if (fnInfo.value.type.type !== "AsyncFunction") {
|
|
512
572
|
throw new Error(`CallAsync expects AsyncFunction type, got ${printTypeValue(fnInfo.value.type)} ` +
|
|
513
|
-
`at ${
|
|
573
|
+
`at loc_id ${node.value.loc_id}`);
|
|
514
574
|
}
|
|
515
575
|
// Validate argument count
|
|
516
576
|
if (fnInfo.value.type.value.inputs.length !== node.value.arguments.length) {
|
|
517
577
|
throw new Error(`Function expects ${fnInfo.value.type.value.inputs.length} arguments, ` +
|
|
518
578
|
`got ${node.value.arguments.length} ` +
|
|
519
|
-
`at ${
|
|
579
|
+
`at loc_id ${node.value.loc_id}`);
|
|
520
580
|
}
|
|
521
581
|
// Analyze all arguments
|
|
522
582
|
const analyzedArgs = [];
|
|
@@ -531,14 +591,14 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
531
591
|
`Expected type ${printTypeValue(expectedType)} ` +
|
|
532
592
|
`but got ${printTypeValue(argInfo.value.type)}. ` +
|
|
533
593
|
`Insert an As node if subtyping is intended. ` +
|
|
534
|
-
`at ${
|
|
594
|
+
`at loc_id ${node.value.loc_id}`);
|
|
535
595
|
}
|
|
536
596
|
}
|
|
537
597
|
// Validate return type matches
|
|
538
598
|
if (!isTypeValueEqual(node.value.type, fnInfo.value.type.value.output)) {
|
|
539
599
|
throw new Error(`Function call return type expected to be ${printTypeValue(fnInfo.value.type.value.output)} ` +
|
|
540
600
|
`but IR has ${printTypeValue(node.value.type)} ` +
|
|
541
|
-
`at ${
|
|
601
|
+
`at loc_id ${node.value.loc_id}`);
|
|
542
602
|
}
|
|
543
603
|
// Return analyzed Call with analyzed function and arguments
|
|
544
604
|
return {
|
|
@@ -559,12 +619,12 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
559
619
|
const builtin = Builtins[builtinName];
|
|
560
620
|
if (!builtin) {
|
|
561
621
|
throw new Error(`Unknown builtin function '${builtinName}' ` +
|
|
562
|
-
`at ${
|
|
622
|
+
`at loc_id ${node.value.loc_id}`);
|
|
563
623
|
}
|
|
564
624
|
if (node.value.arguments.length !== builtin.inputs.length) {
|
|
565
625
|
throw new Error(`Builtin function '${builtinName}' expects ${builtin.inputs.length} arguments, ` +
|
|
566
626
|
`but got ${node.value.arguments.length} ` +
|
|
567
|
-
`at ${
|
|
627
|
+
`at loc_id ${node.value.loc_id}`);
|
|
568
628
|
}
|
|
569
629
|
// Visit all arguments
|
|
570
630
|
const analyzedArgs = [];
|
|
@@ -588,7 +648,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
588
648
|
else if (node.type === "Return") {
|
|
589
649
|
// Validate we're inside a function
|
|
590
650
|
if (!expectedReturnType) {
|
|
591
|
-
throw new Error(`Return statement outside of function at ${
|
|
651
|
+
throw new Error(`Return statement outside of function at loc_id ${node.value.loc_id}`);
|
|
592
652
|
}
|
|
593
653
|
// Analyze the return value expression
|
|
594
654
|
const valueInfo = visit(node.value.value, ctx, expectedReturnType);
|
|
@@ -596,7 +656,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
596
656
|
if (valueInfo.value.type.type !== "Never" && !isTypeValueEqual(valueInfo.value.type, expectedReturnType)) {
|
|
597
657
|
throw new Error(`Return statement returns type ${printTypeValue(valueInfo.value.type)} ` +
|
|
598
658
|
`but function signature expects ${printTypeValue(expectedReturnType)} ` +
|
|
599
|
-
`at ${
|
|
659
|
+
`at loc_id ${node.value.loc_id}`);
|
|
600
660
|
}
|
|
601
661
|
// Return analyzed Return node with analyzed value
|
|
602
662
|
return {
|
|
@@ -612,7 +672,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
612
672
|
// Validate type is Ref
|
|
613
673
|
if (node.value.type.type !== "Ref") {
|
|
614
674
|
throw new Error(`NewRef node must have Ref type, got ${printTypeValue(node.value.type)} ` +
|
|
615
|
-
`at ${
|
|
675
|
+
`at loc_id ${node.value.loc_id}`);
|
|
616
676
|
}
|
|
617
677
|
const elementType = node.value.type.value;
|
|
618
678
|
const valueInfo = visit(node.value.value, ctx, expectedReturnType);
|
|
@@ -621,14 +681,14 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
621
681
|
if (valueInfo.value.type.type !== "Never" && !isTypeValueEqual(valueInfo.value.type, elementType)) {
|
|
622
682
|
throw new Error(`Ref value has type ${printTypeValue(valueInfo.value.type)} ` +
|
|
623
683
|
`but Ref expects ${printTypeValue(elementType)} ` +
|
|
624
|
-
`at ${
|
|
684
|
+
`at loc_id ${node.value.loc_id}`);
|
|
625
685
|
}
|
|
626
686
|
}
|
|
627
687
|
else if (node.type === "NewArray") {
|
|
628
688
|
// Validate type is Array
|
|
629
689
|
if (node.value.type.type !== "Array") {
|
|
630
690
|
throw new Error(`NewArray node must have Array type, got ${printTypeValue(node.value.type)} ` +
|
|
631
|
-
`at ${
|
|
691
|
+
`at loc_id ${node.value.loc_id}`);
|
|
632
692
|
}
|
|
633
693
|
const elementType = node.value.type.value;
|
|
634
694
|
isAsync = false;
|
|
@@ -643,7 +703,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
643
703
|
if (valueInfo.value.type.type !== "Never" && !isTypeValueEqual(valueInfo.value.type, elementType)) {
|
|
644
704
|
throw new Error(`Array element ${i} has type ${printTypeValue(valueInfo.value.type)} ` +
|
|
645
705
|
`but array expects ${printTypeValue(elementType)} ` +
|
|
646
|
-
`at ${
|
|
706
|
+
`at loc_id ${node.value.loc_id}`);
|
|
647
707
|
}
|
|
648
708
|
}
|
|
649
709
|
}
|
|
@@ -651,7 +711,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
651
711
|
// Validate type is Set
|
|
652
712
|
if (node.value.type.type !== "Set") {
|
|
653
713
|
throw new Error(`NewSet node must have Set type, got ${printTypeValue(node.value.type)} ` +
|
|
654
|
-
`at ${
|
|
714
|
+
`at loc_id ${node.value.loc_id}`);
|
|
655
715
|
}
|
|
656
716
|
const keyType = node.value.type.value;
|
|
657
717
|
isAsync = false;
|
|
@@ -666,7 +726,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
666
726
|
if (keyInfo.value.type.type !== "Never" && !isTypeValueEqual(keyInfo.value.type, keyType)) {
|
|
667
727
|
throw new Error(`Set element ${i} has type ${printTypeValue(keyInfo.value.type)} ` +
|
|
668
728
|
`but set expects ${printTypeValue(keyType)} ` +
|
|
669
|
-
`at ${
|
|
729
|
+
`at loc_id ${node.value.loc_id}`);
|
|
670
730
|
}
|
|
671
731
|
}
|
|
672
732
|
}
|
|
@@ -674,7 +734,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
674
734
|
// Validate type is Dict
|
|
675
735
|
if (node.value.type.type !== "Dict") {
|
|
676
736
|
throw new Error(`NewDict node must have Dict type, got ${printTypeValue(node.value.type)} ` +
|
|
677
|
-
`at ${
|
|
737
|
+
`at loc_id ${node.value.loc_id}`);
|
|
678
738
|
}
|
|
679
739
|
const keyType = node.value.type.value.key;
|
|
680
740
|
const valueType = node.value.type.value.value;
|
|
@@ -694,13 +754,13 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
694
754
|
if (keyInfo.value.type.type !== "Never" && !isTypeValueEqual(keyInfo.value.type, keyType)) {
|
|
695
755
|
throw new Error(`Dict key ${i} has type ${printTypeValue(keyInfo.value.type)} ` +
|
|
696
756
|
`but dict expects ${printTypeValue(keyType)} ` +
|
|
697
|
-
`at ${
|
|
757
|
+
`at loc_id ${node.value.loc_id}`);
|
|
698
758
|
}
|
|
699
759
|
// Validate value type exactly matches
|
|
700
760
|
if (valInfo.value.type.type !== "Never" && !isTypeValueEqual(valInfo.value.type, valueType)) {
|
|
701
761
|
throw new Error(`Dict value ${i} has type ${printTypeValue(valInfo.value.type)} ` +
|
|
702
762
|
`but dict expects ${printTypeValue(valueType)} ` +
|
|
703
|
-
`at ${
|
|
763
|
+
`at loc_id ${node.value.loc_id}`);
|
|
704
764
|
}
|
|
705
765
|
}
|
|
706
766
|
}
|
|
@@ -710,19 +770,19 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
710
770
|
// Validate it's an Array type (not Never)
|
|
711
771
|
if (arrayInfo.value.type.type !== "Array") {
|
|
712
772
|
throw new Error(`ForArray expects Array type, got ${printTypeValue(arrayInfo.value.type)} ` +
|
|
713
|
-
`at ${
|
|
773
|
+
`at loc_id ${node.value.loc_id}`);
|
|
714
774
|
}
|
|
715
775
|
const elementType = arrayInfo.value.type.value;
|
|
716
776
|
// Validate key variable is Integer type
|
|
717
777
|
if (node.value.key.value.type.type !== "Integer") {
|
|
718
778
|
throw new Error(`ForArray key must be Integer type, got ${printTypeValue(node.value.key.value.type)} ` +
|
|
719
|
-
`at ${
|
|
779
|
+
`at loc_id ${node.value.loc_id}`);
|
|
720
780
|
}
|
|
721
781
|
// Validate value variable matches array element type
|
|
722
782
|
if (!isTypeValueEqual(node.value.value.value.type, elementType)) {
|
|
723
783
|
throw new Error(`ForArray value variable has type ${printTypeValue(node.value.value.value.type)} ` +
|
|
724
784
|
`but array elements have type ${printTypeValue(elementType)} ` +
|
|
725
|
-
`at ${
|
|
785
|
+
`at loc_id ${node.value.loc_id}`);
|
|
726
786
|
}
|
|
727
787
|
// Analyze the key and value VariableIR nodes
|
|
728
788
|
analysis.set(node.value.key, {
|
|
@@ -764,14 +824,14 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
764
824
|
// Validate it's a Set type (not Never)
|
|
765
825
|
if (setInfo.value.type.type !== "Set") {
|
|
766
826
|
throw new Error(`ForSet expects Set type, got ${printTypeValue(setInfo.value.type)} ` +
|
|
767
|
-
`at ${
|
|
827
|
+
`at loc_id ${node.value.loc_id}`);
|
|
768
828
|
}
|
|
769
829
|
const elementType = setInfo.value.type.value;
|
|
770
830
|
// Validate key variable matches set element type
|
|
771
831
|
if (!isTypeValueEqual(node.value.key.value.type, elementType)) {
|
|
772
832
|
throw new Error(`ForSet key variable has type ${printTypeValue(node.value.key.value.type)} ` +
|
|
773
833
|
`but set elements have type ${printTypeValue(elementType)} ` +
|
|
774
|
-
`at ${
|
|
834
|
+
`at loc_id ${node.value.loc_id}`);
|
|
775
835
|
}
|
|
776
836
|
// Analyze the key VariableIR node
|
|
777
837
|
analysis.set(node.value.key, {
|
|
@@ -795,7 +855,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
795
855
|
// Validate it's a Dict type (not Never)
|
|
796
856
|
if (dictInfo.value.type.type !== "Dict") {
|
|
797
857
|
throw new Error(`ForDict expects Dict type, got ${printTypeValue(dictInfo.value.type)} ` +
|
|
798
|
-
`at ${
|
|
858
|
+
`at loc_id ${node.value.loc_id}`);
|
|
799
859
|
}
|
|
800
860
|
const keyType = dictInfo.value.type.value.key;
|
|
801
861
|
const valueType = dictInfo.value.type.value.value;
|
|
@@ -803,13 +863,13 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
803
863
|
if (!isTypeValueEqual(node.value.key.value.type, keyType)) {
|
|
804
864
|
throw new Error(`ForDict key variable has type ${printTypeValue(node.value.key.value.type)} ` +
|
|
805
865
|
`but dict keys have type ${printTypeValue(keyType)} ` +
|
|
806
|
-
`at ${
|
|
866
|
+
`at loc_id ${node.value.loc_id}`);
|
|
807
867
|
}
|
|
808
868
|
// Validate value variable matches dict value type
|
|
809
869
|
if (!isTypeValueEqual(node.value.value.value.type, valueType)) {
|
|
810
870
|
throw new Error(`ForDict value variable has type ${printTypeValue(node.value.value.value.type)} ` +
|
|
811
871
|
`but dict values have type ${printTypeValue(valueType)} ` +
|
|
812
|
-
`at ${
|
|
872
|
+
`at loc_id ${node.value.loc_id}`);
|
|
813
873
|
}
|
|
814
874
|
// Analyze the key and value VariableIR nodes
|
|
815
875
|
analysis.set(node.value.key, {
|
|
@@ -850,7 +910,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
850
910
|
}
|
|
851
911
|
if (predicateInfo.value.type.type !== "Boolean") {
|
|
852
912
|
throw new Error(`IfElse predicate ${i} must be Boolean type, got ${printTypeValue(predicateInfo.value.type)} ` +
|
|
853
|
-
`at ${
|
|
913
|
+
`at loc_id ${node.value.loc_id}`);
|
|
854
914
|
}
|
|
855
915
|
// Visit branch body and validate type
|
|
856
916
|
const bodyInfo = visit(branch.body, ctx, expectedReturnType);
|
|
@@ -865,7 +925,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
865
925
|
if (bodyInfo.value.type.type !== "Never" && !isTypeValueEqual(bodyInfo.value.type, node.value.type)) {
|
|
866
926
|
throw new Error(`IfElse branch ${i} returns type ${printTypeValue(bodyInfo.value.type)} ` +
|
|
867
927
|
`but IfElse expects ${printTypeValue(node.value.type)} ` +
|
|
868
|
-
`at ${
|
|
928
|
+
`at loc_id ${node.value.loc_id}`);
|
|
869
929
|
}
|
|
870
930
|
analyzedIfs.push({ predicate: predicateInfo, body: bodyInfo });
|
|
871
931
|
}
|
|
@@ -882,18 +942,18 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
882
942
|
if (elseInfo.value.type.type !== "Never" && !isTypeValueEqual(elseInfo.value.type, node.value.type)) {
|
|
883
943
|
throw new Error(`IfElse else branch returns type ${printTypeValue(elseInfo.value.type)} ` +
|
|
884
944
|
`but IfElse expects ${printTypeValue(node.value.type)} ` +
|
|
885
|
-
`at ${
|
|
945
|
+
`at loc_id ${node.value.loc_id}`);
|
|
886
946
|
}
|
|
887
947
|
// If all branches diverge, IfElse must be Never
|
|
888
948
|
if (allBranchesNever && node.value.type.type !== "Never") {
|
|
889
949
|
throw new Error(`IfElse has all branches returning Never, so it must have type Never, ` +
|
|
890
950
|
`but has type ${printTypeValue(node.value.type)} ` +
|
|
891
|
-
`at ${
|
|
951
|
+
`at loc_id ${node.value.loc_id}`);
|
|
892
952
|
}
|
|
893
953
|
// If IfElse is Never, all branches must be Never
|
|
894
954
|
if (node.value.type.type === "Never" && !allBranchesNever) {
|
|
895
955
|
throw new Error(`IfElse has type Never but not all branches diverge ` +
|
|
896
|
-
`at ${
|
|
956
|
+
`at loc_id ${node.value.loc_id}`);
|
|
897
957
|
}
|
|
898
958
|
// Return analyzed IfElse with analyzed branches
|
|
899
959
|
return {
|
|
@@ -911,7 +971,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
911
971
|
const predicateInfo = visit(node.value.predicate, ctx, expectedReturnType);
|
|
912
972
|
if (predicateInfo.value.type.type !== "Boolean") {
|
|
913
973
|
throw new Error(`While predicate must be Boolean type, got ${printTypeValue(predicateInfo.value.type)} ` +
|
|
914
|
-
`at ${
|
|
974
|
+
`at loc_id ${node.value.loc_id}`);
|
|
915
975
|
}
|
|
916
976
|
// Visit loop body
|
|
917
977
|
const bodyInfo = visit(node.value.body, ctx, expectedReturnType);
|
|
@@ -939,7 +999,7 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
939
999
|
const messageInfo = visit(node.value.message, ctx, expectedReturnType);
|
|
940
1000
|
if (messageInfo.value.type.type !== "String") {
|
|
941
1001
|
throw new Error(`Error message must be String type, got ${printTypeValue(messageInfo.value.type)} ` +
|
|
942
|
-
`at ${
|
|
1002
|
+
`at loc_id ${node.value.loc_id}`);
|
|
943
1003
|
}
|
|
944
1004
|
// Error always has type Never (throws exception, diverges control flow)
|
|
945
1005
|
isAsync = messageInfo.value.isAsync; // Error is async if message is async
|
|
@@ -950,13 +1010,13 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
950
1010
|
// Validate message variable is String type
|
|
951
1011
|
if (node.value.message.value.type.type !== "String") {
|
|
952
1012
|
throw new Error(`TryCatch message variable must be String type, got ${printTypeValue(node.value.message.value.type)} ` +
|
|
953
|
-
`at ${
|
|
1013
|
+
`at loc_id ${node.value.loc_id}`);
|
|
954
1014
|
}
|
|
955
1015
|
// Validate stack variable is correct type
|
|
956
1016
|
const stackType = toEastTypeValue(ArrayType(StructType({ filename: StringType, line: IntegerType, column: IntegerType })));
|
|
957
1017
|
if (!isTypeValueEqual(node.value.stack.value.type, stackType)) {
|
|
958
1018
|
throw new Error(`TryCatch stack variable must be ${printTypeValue(stackType)} type, got ${printTypeValue(node.value.stack.value.type)} ` +
|
|
959
|
-
`at ${
|
|
1019
|
+
`at loc_id ${node.value.loc_id}`);
|
|
960
1020
|
}
|
|
961
1021
|
// Analyze the message and stack VariableIR nodes
|
|
962
1022
|
analysis.set(node.value.message, {
|
|
@@ -985,19 +1045,19 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
985
1045
|
if (tryInfo.value.type.type !== "Never" && !isTypeValueEqual(tryInfo.value.type, node.value.type)) {
|
|
986
1046
|
throw new Error(`TryCatch try body returns type ${printTypeValue(tryInfo.value.type)} ` +
|
|
987
1047
|
`but TryCatch expects ${printTypeValue(node.value.type)} ` +
|
|
988
|
-
`at ${
|
|
1048
|
+
`at loc_id ${node.value.loc_id}`);
|
|
989
1049
|
}
|
|
990
1050
|
if (catchInfo.value.type.type !== "Never" && !isTypeValueEqual(catchInfo.value.type, node.value.type)) {
|
|
991
1051
|
throw new Error(`TryCatch catch body returns type ${printTypeValue(catchInfo.value.type)} ` +
|
|
992
1052
|
`but TryCatch expects ${printTypeValue(node.value.type)} ` +
|
|
993
|
-
`at ${
|
|
1053
|
+
`at loc_id ${node.value.loc_id}`);
|
|
994
1054
|
}
|
|
995
1055
|
// If both bodies diverge, TryCatch must be Never
|
|
996
1056
|
const bothNever = tryInfo.value.type.type === "Never" && catchInfo.value.type.type === "Never";
|
|
997
1057
|
if (bothNever && node.value.type.type !== "Never") {
|
|
998
1058
|
throw new Error(`TryCatch has both try and catch bodies returning Never, so it must have type Never, ` +
|
|
999
1059
|
`but has type ${printTypeValue(node.value.type)} ` +
|
|
1000
|
-
`at ${
|
|
1060
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1001
1061
|
}
|
|
1002
1062
|
// Visit finally body
|
|
1003
1063
|
const finallyInfo = visit(node.value.finally_body, ctx, expectedReturnType);
|
|
@@ -1018,14 +1078,14 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
1018
1078
|
// Validate type is Struct
|
|
1019
1079
|
if (node.value.type.type !== "Struct") {
|
|
1020
1080
|
throw new Error(`Struct node must have Struct type, got ${printTypeValue(node.value.type)} ` +
|
|
1021
|
-
`at ${
|
|
1081
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1022
1082
|
}
|
|
1023
1083
|
const structType = expandTypeValue(node.value.type);
|
|
1024
1084
|
isAsync = false;
|
|
1025
1085
|
if (structType.value.length !== node.value.fields.length) {
|
|
1026
1086
|
throw new Error(`Struct type has ${structType.value.length} fields but struct value has ` +
|
|
1027
1087
|
`${node.value.fields.length} fields ` +
|
|
1028
|
-
`at ${
|
|
1088
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1029
1089
|
}
|
|
1030
1090
|
// Visit all field values and validate types
|
|
1031
1091
|
for (const [i, field] of node.value.fields.entries()) {
|
|
@@ -1037,13 +1097,13 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
1037
1097
|
const typeField = structType.value[i];
|
|
1038
1098
|
if (typeField.name !== field.name) {
|
|
1039
1099
|
throw new Error(`Struct has field ${typeField.name} at position ${i}, but value does not ` +
|
|
1040
|
-
`at ${
|
|
1100
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1041
1101
|
}
|
|
1042
1102
|
// Validate field type exactly matches
|
|
1043
1103
|
if (!isTypeValueEqual(fieldInfo.value.type, typeField.type)) {
|
|
1044
1104
|
throw new Error(`Struct field ${field.name} has type ${printTypeValue(fieldInfo.value.type)} ` +
|
|
1045
1105
|
`but struct type expects ${printTypeValue(typeField.type)} ` +
|
|
1046
|
-
`at ${
|
|
1106
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1047
1107
|
}
|
|
1048
1108
|
}
|
|
1049
1109
|
}
|
|
@@ -1053,20 +1113,20 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
1053
1113
|
// Validate it's a Struct type
|
|
1054
1114
|
if (structInfo.value.type.type !== "Struct") {
|
|
1055
1115
|
throw new Error(`GetField expects Struct type, got ${printTypeValue(structInfo.value.type)} ` +
|
|
1056
|
-
`at ${
|
|
1116
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1057
1117
|
}
|
|
1058
1118
|
// Find the field in struct type
|
|
1059
1119
|
const structType = expandTypeValue(structInfo.value.type);
|
|
1060
1120
|
const field = structType.value.find(f => f.name === node.value.field);
|
|
1061
1121
|
if (!field) {
|
|
1062
1122
|
throw new Error(`Struct does not have field ${node.value.field} ` +
|
|
1063
|
-
`at ${
|
|
1123
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1064
1124
|
}
|
|
1065
1125
|
// Validate return type matches field type
|
|
1066
1126
|
if (!isTypeValueEqual(node.value.type, field.type)) {
|
|
1067
1127
|
throw new Error(`GetField result type ${printTypeValue(node.value.type)} ` +
|
|
1068
1128
|
`does not match field type ${printTypeValue(field.type)} ` +
|
|
1069
|
-
`at ${
|
|
1129
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1070
1130
|
}
|
|
1071
1131
|
isAsync = structInfo.value.isAsync;
|
|
1072
1132
|
}
|
|
@@ -1076,25 +1136,25 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
1076
1136
|
// Validate type is Variant
|
|
1077
1137
|
if (node.value.type.type !== "Variant") {
|
|
1078
1138
|
throw new Error(`Variant node must have Variant type, got ${printTypeValue(node.value.type)} ` +
|
|
1079
|
-
`at ${
|
|
1139
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1080
1140
|
}
|
|
1081
1141
|
// Expand recursive types to get well-formed variant type
|
|
1082
1142
|
const variantType = expandTypeValue(node.value.type);
|
|
1083
1143
|
if (variantType.type !== "Variant") {
|
|
1084
1144
|
throw new Error(`Expanded Variant type is not Variant, got ${printTypeValue(variantType)} ` +
|
|
1085
|
-
`at ${
|
|
1145
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1086
1146
|
}
|
|
1087
1147
|
// Find the case in variant type
|
|
1088
1148
|
const caseType = variantType.value.find((c) => c.name === node.value.case);
|
|
1089
1149
|
if (!caseType) {
|
|
1090
1150
|
throw new Error(`Variant type does not have case ${node.value.case} ` +
|
|
1091
|
-
`at ${
|
|
1151
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1092
1152
|
}
|
|
1093
1153
|
// Validate value type exactly matches case type
|
|
1094
1154
|
if (!isTypeValueEqual(valueInfo.value.type, caseType.type)) {
|
|
1095
1155
|
throw new Error(`Variant case ${node.value.case} value has type ${printTypeValue(valueInfo.value.type)} ` +
|
|
1096
1156
|
`but variant type expects ${printTypeValue(caseType.type)} ` +
|
|
1097
|
-
`at ${
|
|
1157
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1098
1158
|
}
|
|
1099
1159
|
isAsync = valueInfo.value.isAsync;
|
|
1100
1160
|
}
|
|
@@ -1104,19 +1164,19 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
1104
1164
|
// Validate it's a Variant type
|
|
1105
1165
|
if (variantInfo.value.type.type !== "Variant") {
|
|
1106
1166
|
throw new Error(`Match expects Variant type, got ${printTypeValue(variantInfo.value.type)} ` +
|
|
1107
|
-
`at ${
|
|
1167
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1108
1168
|
}
|
|
1109
1169
|
// Expand recursive types to get well-formed variant type
|
|
1110
1170
|
const variantType = expandTypeValue(variantInfo.value.type);
|
|
1111
1171
|
if (variantType.type !== "Variant") {
|
|
1112
1172
|
throw new Error(`Expanded Match variant type is not Variant, got ${printTypeValue(variantType)} ` +
|
|
1113
|
-
`at ${
|
|
1173
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1114
1174
|
}
|
|
1115
1175
|
// Validate case count matches
|
|
1116
1176
|
if (variantType.value.length !== node.value.cases.length) {
|
|
1117
1177
|
throw new Error(`Match has ${node.value.cases.length} cases but variant type has ` +
|
|
1118
1178
|
`${variantType.value.length} cases ` +
|
|
1119
|
-
`at ${
|
|
1179
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1120
1180
|
}
|
|
1121
1181
|
isAsync = variantInfo.value.isAsync;
|
|
1122
1182
|
let allCasesNever = true;
|
|
@@ -1126,13 +1186,13 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
1126
1186
|
const typeCase = variantType.value.find((c) => c.name === matchCase.case);
|
|
1127
1187
|
if (!typeCase) {
|
|
1128
1188
|
throw new Error(`Match has case ${matchCase.case} but variant type does not ` +
|
|
1129
|
-
`at ${
|
|
1189
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1130
1190
|
}
|
|
1131
1191
|
// Validate variable type matches case type
|
|
1132
1192
|
if (!isTypeValueEqual(matchCase.variable.value.type, typeCase.type)) {
|
|
1133
1193
|
throw new Error(`Match case ${matchCase.case} variable has type ${printTypeValue(matchCase.variable.value.type)} ` +
|
|
1134
1194
|
`but variant case has type ${printTypeValue(typeCase.type)} ` +
|
|
1135
|
-
`at ${
|
|
1195
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1136
1196
|
}
|
|
1137
1197
|
// Analyze the variable VariableIR node
|
|
1138
1198
|
analysis.set(matchCase.variable, {
|
|
@@ -1159,41 +1219,93 @@ export function analyzeIR(ir, platformDef, ctx = {}) {
|
|
|
1159
1219
|
if (bodyInfo.value.type.type !== "Never" && !isTypeValueEqual(bodyInfo.value.type, node.value.type)) {
|
|
1160
1220
|
throw new Error(`Match case ${matchCase.case} returns type ${printTypeValue(bodyInfo.value.type)} ` +
|
|
1161
1221
|
`but Match expects ${printTypeValue(node.value.type)} ` +
|
|
1162
|
-
`at ${
|
|
1222
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1163
1223
|
}
|
|
1164
1224
|
}
|
|
1165
1225
|
// If all cases diverge, Match must be Never
|
|
1166
1226
|
if (allCasesNever && node.value.type.type !== "Never") {
|
|
1167
1227
|
throw new Error(`Match has all cases returning Never, so it must have type Never, ` +
|
|
1168
1228
|
`but has type ${printTypeValue(node.value.type)} ` +
|
|
1169
|
-
`at ${
|
|
1229
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1170
1230
|
}
|
|
1171
1231
|
// isAsync already set from loop above
|
|
1172
1232
|
}
|
|
1173
1233
|
else if (node.type === "UnwrapRecursive") {
|
|
1174
1234
|
// Visit the value expression
|
|
1175
1235
|
const valueInfo = visit(node.value.value, ctx, expectedReturnType);
|
|
1176
|
-
// Validate result type matches expanded type
|
|
1177
|
-
|
|
1236
|
+
// Validate result type matches expanded type.
|
|
1237
|
+
// The value type may be Recursive(wrapper({id, inner})) — unwrap for comparison.
|
|
1238
|
+
const inputType = valueInfo.value.type.type === "Recursive" && valueInfo.value.type.value.type === "wrapper"
|
|
1239
|
+
? valueInfo.value.type.value.value.inner : valueInfo.value.type;
|
|
1240
|
+
if (inputType.type !== "Never" && !isTypeValueEqual(node.value.type, inputType)) {
|
|
1178
1241
|
throw new Error(`UnwrapRecursive result type ${printTypeValue(node.value.type)} ` +
|
|
1179
|
-
`does not match recursive type ${printTypeValue(
|
|
1180
|
-
`at ${
|
|
1242
|
+
`does not match recursive type ${printTypeValue(inputType)} ` +
|
|
1243
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1181
1244
|
}
|
|
1182
1245
|
isAsync = valueInfo.value.isAsync;
|
|
1183
1246
|
}
|
|
1184
1247
|
else if (node.type === "WrapRecursive") {
|
|
1185
1248
|
// Visit the value expression
|
|
1186
1249
|
const valueInfo = visit(node.value.value, ctx, expectedReturnType);
|
|
1187
|
-
// Validate value type matches
|
|
1188
|
-
|
|
1250
|
+
// Validate value type matches the inner type of the recursive wrapper.
|
|
1251
|
+
// node.value.type is Recursive(wrapper({id, inner})) — the value has the inner type.
|
|
1252
|
+
const expectedType = node.value.type.type === "Recursive" && node.value.type.value.type === "wrapper"
|
|
1253
|
+
? node.value.type.value.value.inner : node.value.type;
|
|
1254
|
+
if (valueInfo.value.type.type !== "Never" && !isTypeValueEqual(valueInfo.value.type, expectedType)) {
|
|
1189
1255
|
throw new Error(`WrapRecursive value has type ${printTypeValue(valueInfo.value.type)} ` +
|
|
1190
|
-
`but expects ${printTypeValue(
|
|
1191
|
-
`at ${
|
|
1256
|
+
`but expects ${printTypeValue(expectedType)} ` +
|
|
1257
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1192
1258
|
}
|
|
1193
1259
|
isAsync = valueInfo.value.isAsync;
|
|
1194
1260
|
}
|
|
1261
|
+
else if (node.type === "NewVector") {
|
|
1262
|
+
// Validate type is Vector
|
|
1263
|
+
if (node.value.type.type !== "Vector") {
|
|
1264
|
+
throw new Error(`NewVector node must have Vector type, got ${printTypeValue(node.value.type)} ` +
|
|
1265
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1266
|
+
}
|
|
1267
|
+
const elementType = node.value.type.value;
|
|
1268
|
+
isAsync = false;
|
|
1269
|
+
// Visit all element values and validate types
|
|
1270
|
+
for (let i = 0; i < node.value.values.length; i++) {
|
|
1271
|
+
const valueExpr = node.value.values[i];
|
|
1272
|
+
const valueInfo = visit(valueExpr, ctx, expectedReturnType);
|
|
1273
|
+
if (valueInfo.value.isAsync) {
|
|
1274
|
+
isAsync = true;
|
|
1275
|
+
}
|
|
1276
|
+
// Validate element type exactly matches
|
|
1277
|
+
if (valueInfo.value.type.type !== "Never" && !isTypeValueEqual(valueInfo.value.type, elementType)) {
|
|
1278
|
+
throw new Error(`Vector element ${i} has type ${printTypeValue(valueInfo.value.type)} ` +
|
|
1279
|
+
`but vector expects ${printTypeValue(elementType)} ` +
|
|
1280
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
else if (node.type === "NewMatrix") {
|
|
1285
|
+
// Validate type is Matrix
|
|
1286
|
+
if (node.value.type.type !== "Matrix") {
|
|
1287
|
+
throw new Error(`NewMatrix node must have Matrix type, got ${printTypeValue(node.value.type)} ` +
|
|
1288
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1289
|
+
}
|
|
1290
|
+
const elementType = node.value.type.value;
|
|
1291
|
+
isAsync = false;
|
|
1292
|
+
// Visit all element values and validate types
|
|
1293
|
+
for (let i = 0; i < node.value.values.length; i++) {
|
|
1294
|
+
const valueExpr = node.value.values[i];
|
|
1295
|
+
const valueInfo = visit(valueExpr, ctx, expectedReturnType);
|
|
1296
|
+
if (valueInfo.value.isAsync) {
|
|
1297
|
+
isAsync = true;
|
|
1298
|
+
}
|
|
1299
|
+
// Validate element type exactly matches
|
|
1300
|
+
if (valueInfo.value.type.type !== "Never" && !isTypeValueEqual(valueInfo.value.type, elementType)) {
|
|
1301
|
+
throw new Error(`Matrix element ${i} has type ${printTypeValue(valueInfo.value.type)} ` +
|
|
1302
|
+
`but matrix expects ${printTypeValue(elementType)} ` +
|
|
1303
|
+
`at loc_id ${node.value.loc_id}`);
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1195
1307
|
else {
|
|
1196
|
-
throw new Error(`Unhandled IR type: ${node.type} at ${
|
|
1308
|
+
throw new Error(`Unhandled IR type: ${node.type} at loc_id ${node.value?.loc_id ?? -1n}`);
|
|
1197
1309
|
}
|
|
1198
1310
|
return {
|
|
1199
1311
|
...node,
|