semantifold 0.2.0 → 0.3.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/README.md +37 -12
- package/build/index.js +2 -2
- package/build/src/acceptance.d.ts +10 -0
- package/build/src/acceptance.d.ts.map +1 -1
- package/build/src/acceptance.js +24 -5
- package/build/src/backends/c-runtime.d.ts +3 -0
- package/build/src/backends/c-runtime.d.ts.map +1 -0
- package/build/src/backends/c-runtime.js +151 -0
- package/build/src/backends/c-validation.d.ts +12 -0
- package/build/src/backends/c-validation.d.ts.map +1 -0
- package/build/src/backends/c-validation.js +85 -0
- package/build/src/backends/c.d.ts +31 -0
- package/build/src/backends/c.d.ts.map +1 -0
- package/build/src/backends/c.js +308 -0
- package/build/src/backends/cpp-runtime.d.ts +3 -0
- package/build/src/backends/cpp-runtime.d.ts.map +1 -0
- package/build/src/backends/cpp-runtime.js +99 -0
- package/build/src/backends/cpp-validation.d.ts +9 -0
- package/build/src/backends/cpp-validation.d.ts.map +1 -0
- package/build/src/backends/cpp-validation.js +74 -0
- package/build/src/backends/cpp.d.ts +16 -0
- package/build/src/backends/cpp.d.ts.map +1 -0
- package/build/src/backends/cpp.js +285 -0
- package/build/src/backends/csharp.d.ts +20 -0
- package/build/src/backends/csharp.d.ts.map +1 -0
- package/build/src/backends/csharp.js +259 -0
- package/build/src/backends/go.d.ts +20 -0
- package/build/src/backends/go.d.ts.map +1 -0
- package/build/src/backends/go.js +374 -0
- package/build/src/backends/identifiers.d.ts +12 -0
- package/build/src/backends/identifiers.d.ts.map +1 -1
- package/build/src/backends/identifiers.js +71 -2
- package/build/src/backends/index.d.ts.map +1 -1
- package/build/src/backends/index.js +9 -1
- package/build/src/backends/native-validation.d.ts +9 -0
- package/build/src/backends/native-validation.d.ts.map +1 -0
- package/build/src/backends/native-validation.js +59 -0
- package/build/src/backends/ordered-expressions.d.ts +74 -0
- package/build/src/backends/ordered-expressions.d.ts.map +1 -0
- package/build/src/backends/ordered-expressions.js +159 -0
- package/build/src/backends/scalars.d.ts.map +1 -1
- package/build/src/backends/scalars.js +7 -2
- package/build/src/backends/shared.d.ts.map +1 -1
- package/build/src/backends/shared.js +59 -14
- package/build/src/frontends/c-parser.d.ts +20 -0
- package/build/src/frontends/c-parser.d.ts.map +1 -0
- package/build/src/frontends/c-parser.js +14 -0
- package/build/src/frontends/c.d.ts +220 -0
- package/build/src/frontends/c.d.ts.map +1 -0
- package/build/src/frontends/c.js +750 -0
- package/build/src/frontends/cpp-parser.d.ts +11 -0
- package/build/src/frontends/cpp-parser.d.ts.map +1 -0
- package/build/src/frontends/cpp-parser.js +15 -0
- package/build/src/frontends/cpp.d.ts +227 -0
- package/build/src/frontends/cpp.d.ts.map +1 -0
- package/build/src/frontends/cpp.js +784 -0
- package/build/src/frontends/csharp.d.ts +14 -0
- package/build/src/frontends/csharp.d.ts.map +1 -0
- package/build/src/frontends/csharp.js +708 -0
- package/build/src/frontends/go.d.ts +15 -0
- package/build/src/frontends/go.d.ts.map +1 -0
- package/build/src/frontends/go.js +712 -0
- package/build/src/frontends/scalars.d.ts.map +1 -1
- package/build/src/frontends/scalars.js +16 -1
- package/build/src/language-registry.d.ts.map +1 -1
- package/build/src/language-registry.js +51 -2
- package/build/src/mapping.js +2 -2
- package/build/src/semantic/provenance.js +3 -3
- package/build/src/semantic/types.d.ts +4 -4
- package/build/src/semantic/types.d.ts.map +1 -1
- package/build/src/semantic/types.js +3 -3
- package/build/src/subprocess.d.ts +10 -1
- package/build/src/subprocess.d.ts.map +1 -1
- package/build/src/subprocess.js +29 -3
- package/build/src/toolchains.d.ts +24 -0
- package/build/src/toolchains.d.ts.map +1 -1
- package/build/src/toolchains.js +6 -2
- package/docs/architecture.md +20 -6
- package/docs/c.md +60 -0
- package/docs/cpp.md +61 -0
- package/docs/goals.md +4 -2
- package/docs/language-support.md +27 -8
- package/docs/parser-qualification.md +153 -4
- package/docs/plans/2026-09-05-standard-library-portability.md +46 -0
- package/docs/source-maps.md +11 -5
- package/docs/standard-library-portability.md +190 -0
- package/docs/testing.md +113 -4
- package/index.js +1 -1
- package/node_modules/node-addon-api/LICENSE.md +9 -0
- package/node_modules/node-addon-api/README.md +95 -0
- package/node_modules/node-addon-api/common.gypi +21 -0
- package/node_modules/node-addon-api/except.gypi +25 -0
- package/node_modules/node-addon-api/index.js +14 -0
- package/node_modules/node-addon-api/napi-inl.deprecated.h +186 -0
- package/node_modules/node-addon-api/napi-inl.h +7250 -0
- package/node_modules/node-addon-api/napi.h +3463 -0
- package/node_modules/node-addon-api/node_addon_api.gyp +42 -0
- package/node_modules/node-addon-api/node_api.gyp +9 -0
- package/node_modules/node-addon-api/noexcept.gypi +26 -0
- package/node_modules/node-addon-api/nothing.c +0 -0
- package/node_modules/node-addon-api/package-support.json +21 -0
- package/node_modules/node-addon-api/package.json +481 -0
- package/node_modules/node-addon-api/tools/README.md +73 -0
- package/node_modules/node-addon-api/tools/check-napi.js +99 -0
- package/node_modules/node-addon-api/tools/clang-format.js +71 -0
- package/node_modules/node-addon-api/tools/conversion.js +301 -0
- package/node_modules/node-gyp-build/LICENSE +21 -0
- package/node_modules/node-gyp-build/README.md +58 -0
- package/node_modules/node-gyp-build/SECURITY.md +5 -0
- package/node_modules/node-gyp-build/bin.js +84 -0
- package/node_modules/node-gyp-build/build-test.js +19 -0
- package/node_modules/node-gyp-build/index.js +6 -0
- package/node_modules/node-gyp-build/node-gyp-build.js +207 -0
- package/node_modules/node-gyp-build/optional.js +7 -0
- package/node_modules/node-gyp-build/package.json +43 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/LICENSE +15 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/README.md +7 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/LICENSE +21 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/README.md +90 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/binding.gyp +79 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/index.js +895 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/package.json +62 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/prebuilds/darwin-arm64/tree-sitter.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/prebuilds/darwin-x64/tree-sitter.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/prebuilds/linux-x64/tree-sitter.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/prebuilds/win32-x64/tree-sitter.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/addon_data.h +47 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/binding.cc +35 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/conversions.cc +140 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/conversions.h +22 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/language.cc +106 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/language.h +17 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/logger.cc +70 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/logger.h +19 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/lookaheaditerator.cc +122 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/lookaheaditerator.h +33 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/node.cc +1056 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/node.h +30 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/parser.cc +298 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/parser.h +35 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/query.cc +383 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/query.h +39 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/tree.cc +307 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/tree.h +45 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/tree_cursor.cc +213 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/src/tree_cursor.h +52 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/tree-sitter.d.ts +211 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/include/tree_sitter/api.h +1266 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.c +48 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.h +41 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/array.h +290 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/atomic.h +68 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/clock.h +146 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/error_costs.h +11 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.c +501 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.h +36 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/host.h +21 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.c +221 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.h +299 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/length.h +52 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.c +419 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.h +49 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lib.c +14 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/node.c +774 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.c +2151 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.h +230 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/point.h +62 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/query.c +4134 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reduce_action.h +34 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reusable_node.h +95 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.c +899 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.h +133 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.c +1060 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.h +382 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.c +165 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.h +31 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.c +714 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.h +48 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ICU_SHA +1 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/LICENSE +414 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/README.md +29 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ptypes.h +1 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/umachine.h +448 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/urename.h +1 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf.h +1 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf16.h +733 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf8.h +881 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode.h +50 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib-symbols.txt +23 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib.c +109 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/wasm-stdlib.h +1294 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.c +1823 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.h +31 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/LICENSE +21 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/README.md +18 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/binding.gyp +29 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/bindings/node/binding.cc +20 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/bindings/node/binding_test.js +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/bindings/node/index.d.ts +28 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/bindings/node/index.js +11 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/grammar.js +1470 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/package.json +60 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/prebuilds/darwin-arm64/tree-sitter-c.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/prebuilds/darwin-x64/tree-sitter-c.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/prebuilds/linux-arm64/tree-sitter-c.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/prebuilds/linux-x64/tree-sitter-c.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/prebuilds/win32-arm64/tree-sitter-c.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/prebuilds/win32-x64/tree-sitter-c.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/queries/highlights.scm +81 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/queries/tags.scm +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/src/grammar.json +9735 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/src/node-types.json +4614 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/src/parser.c +119615 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/src/tree_sitter/alloc.h +54 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/src/tree_sitter/array.h +290 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/src/tree_sitter/parser.h +266 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/tree-sitter-c.wasm +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-c/tree-sitter.json +43 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/LICENSE +21 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/README.md +22 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/binding.gyp +30 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/bindings/node/binding.cc +20 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/bindings/node/binding_test.js +9 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/bindings/node/index.d.ts +28 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/bindings/node/index.js +11 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/grammar.js +1436 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/package.json +61 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/prebuilds/darwin-arm64/tree-sitter-cpp.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/prebuilds/darwin-x64/tree-sitter-cpp.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/prebuilds/linux-arm64/tree-sitter-cpp.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/prebuilds/linux-x64/tree-sitter-cpp.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/prebuilds/win32-arm64/tree-sitter-cpp.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/prebuilds/win32-x64/tree-sitter-cpp.node +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/queries/highlights.scm +70 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/queries/injections.scm +3 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/queries/tags.scm +15 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/src/grammar.json +17084 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/src/node-types.json +7997 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/src/parser.c +530368 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/src/scanner.c +148 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/src/tree_sitter/alloc.h +54 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/src/tree_sitter/array.h +290 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/src/tree_sitter/parser.h +266 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/tree-sitter-cpp.wasm +0 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/node_modules/tree-sitter-cpp/tree-sitter.json +55 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/package.json +22 -0
- package/node_modules/semantifold-tree-sitter-legacy-internal/src/c.js +152 -0
- package/node_modules/tree-sitter/LICENSE +21 -0
- package/node_modules/tree-sitter/README.md +128 -0
- package/node_modules/tree-sitter/binding.gyp +88 -0
- package/node_modules/tree-sitter/index.js +950 -0
- package/node_modules/tree-sitter/package.json +76 -0
- package/node_modules/tree-sitter/prebuilds/darwin-arm64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/prebuilds/darwin-x64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/prebuilds/linux-arm64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/prebuilds/linux-x64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/prebuilds/win32-arm64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/prebuilds/win32-x64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/src/addon_data.h +47 -0
- package/node_modules/tree-sitter/src/binding.cc +35 -0
- package/node_modules/tree-sitter/src/conversions.cc +140 -0
- package/node_modules/tree-sitter/src/conversions.h +22 -0
- package/node_modules/tree-sitter/src/language.cc +105 -0
- package/node_modules/tree-sitter/src/language.h +17 -0
- package/node_modules/tree-sitter/src/logger.cc +70 -0
- package/node_modules/tree-sitter/src/logger.h +19 -0
- package/node_modules/tree-sitter/src/lookaheaditerator.cc +122 -0
- package/node_modules/tree-sitter/src/lookaheaditerator.h +33 -0
- package/node_modules/tree-sitter/src/node.cc +1088 -0
- package/node_modules/tree-sitter/src/node.h +30 -0
- package/node_modules/tree-sitter/src/parser.cc +332 -0
- package/node_modules/tree-sitter/src/parser.h +35 -0
- package/node_modules/tree-sitter/src/query.cc +425 -0
- package/node_modules/tree-sitter/src/query.h +40 -0
- package/node_modules/tree-sitter/src/tree.cc +316 -0
- package/node_modules/tree-sitter/src/tree.h +45 -0
- package/node_modules/tree-sitter/src/tree_cursor.cc +213 -0
- package/node_modules/tree-sitter/src/tree_cursor.h +52 -0
- package/node_modules/tree-sitter/tree-sitter.d.ts +1083 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/include/tree_sitter/api.h +1478 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.c +48 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.h +41 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/array.h +291 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/atomic.h +68 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/clock.h +146 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/error_costs.h +11 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.c +523 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.h +36 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/host.h +21 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.c +293 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.h +293 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/length.h +52 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.c +483 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.h +54 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lib.c +12 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/node.c +875 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.c +2297 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.h +286 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/point.h +48 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/portable/endian.h +241 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/query.c +4347 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reduce_action.h +34 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reusable_node.h +95 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.c +912 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.h +133 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.c +1034 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.h +399 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.c +170 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.h +31 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.c +716 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.h +48 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/ts_assert.h +11 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ICU_SHA +1 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/LICENSE +414 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/README.md +29 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ptypes.h +1 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/umachine.h +448 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/urename.h +1 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf.h +1 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf16.h +733 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf8.h +881 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode.h +75 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib-symbols.txt +24 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib.c +137 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/wasm-stdlib.h +1314 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.c +1937 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.h +31 -0
- package/package.json +21 -5
- package/src/acceptance.js +25 -4
- package/src/backends/c-runtime.js +151 -0
- package/src/backends/c-validation.js +83 -0
- package/src/backends/c.js +308 -0
- package/src/backends/cpp-runtime.js +99 -0
- package/src/backends/cpp-validation.js +70 -0
- package/src/backends/cpp.js +285 -0
- package/src/backends/csharp.js +270 -0
- package/src/backends/go.js +383 -0
- package/src/backends/identifiers.js +72 -1
- package/src/backends/index.js +7 -0
- package/src/backends/native-validation.js +64 -0
- package/src/backends/ordered-expressions.js +161 -0
- package/src/backends/scalars.js +7 -1
- package/src/backends/shared.js +56 -12
- package/src/frontends/c-parser.js +17 -0
- package/src/frontends/c.js +780 -0
- package/src/frontends/cpp-parser.js +18 -0
- package/src/frontends/cpp.js +816 -0
- package/src/frontends/csharp.js +759 -0
- package/src/frontends/go.js +770 -0
- package/src/frontends/scalars.js +15 -0
- package/src/language-registry.js +52 -1
- package/src/mapping.js +1 -1
- package/src/semantic/provenance.js +2 -2
- package/src/semantic/types.js +2 -2
- package/src/subprocess.js +31 -2
- package/src/toolchains.js +5 -1
|
@@ -0,0 +1,759 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import Parser from "tree-sitter"
|
|
4
|
+
import CSharpLanguage from "tree-sitter-c-sharp/bindings/node/index.js"
|
|
5
|
+
import {missingType, parseFailure, SemantifoldDiagnostic, unsupportedSyntax} from "../diagnostic.js"
|
|
6
|
+
import {locationFromOffsets, moduleLocation, utf8ByteOffsetToUtf16Offset} from "../semantic/location.js"
|
|
7
|
+
import {withAdaptedOperation} from "../semantic/operators.js"
|
|
8
|
+
import {withParserRanges} from "../semantic/provenance.js"
|
|
9
|
+
import {hasOnlyUnicodeScalars} from "../semantic/scalars.js"
|
|
10
|
+
import {validateParsedModule} from "../semantic/validate.js"
|
|
11
|
+
import {sourceScalarType} from "./scalars.js"
|
|
12
|
+
|
|
13
|
+
const parser = new Parser()
|
|
14
|
+
|
|
15
|
+
parser.setLanguage(/** @type {import("tree-sitter").Language} */ (/** @type {unknown} */ (CSharpLanguage)))
|
|
16
|
+
|
|
17
|
+
const immutableMarker = "// @semantifold-immutable"
|
|
18
|
+
const checkedArithmetic = new WeakSet()
|
|
19
|
+
const csharpReservedIdentifiers = new Set([
|
|
20
|
+
"abstract", "add", "alias", "allows", "and", "as", "ascending", "async", "await", "base", "bool", "break",
|
|
21
|
+
"by", "byte", "case", "catch", "char", "checked", "class", "const", "continue", "decimal", "default",
|
|
22
|
+
"delegate", "descending", "do", "double", "dynamic", "else", "enum", "equals", "event", "explicit", "extension", "extern",
|
|
23
|
+
"false", "field", "file", "finally", "fixed", "float", "for", "foreach", "from", "get", "global", "goto",
|
|
24
|
+
"group", "if", "implicit", "in", "init", "int", "interface", "internal", "into", "is", "join", "let", "lock",
|
|
25
|
+
"long", "managed", "nameof", "namespace", "new", "nint", "not", "notnull", "null", "nuint", "object", "on",
|
|
26
|
+
"operator", "or", "orderby", "out", "override", "params", "partial", "private", "protected", "public", "readonly",
|
|
27
|
+
"record", "ref", "remove", "required", "return", "sbyte", "scoped", "sealed", "select", "set", "short", "sizeof",
|
|
28
|
+
"stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong",
|
|
29
|
+
"unchecked", "unmanaged", "unsafe", "ushort", "using", "value", "var", "virtual", "void", "volatile", "when",
|
|
30
|
+
"where", "while", "with", "yield"
|
|
31
|
+
])
|
|
32
|
+
const binaryOperations = new Map([
|
|
33
|
+
["+", "Add"], ["-", "Subtract"], ["*", "Multiply"], ["==", "Equal"], ["!=", "NotEqual"],
|
|
34
|
+
["<", "LessThan"], ["<=", "LessThanOrEqual"], [">", "GreaterThan"], [">=", "GreaterThanOrEqual"],
|
|
35
|
+
["&&", "And"], ["||", "Or"]
|
|
36
|
+
])
|
|
37
|
+
|
|
38
|
+
/** @typedef {{comments: import("tree-sitter").SyntaxNode[], usedImmutableMarkers: Set<import("tree-sitter").SyntaxNode>}} CSharpContext */
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Verifies one Tree-sitter binding index through the shared byte converter.
|
|
42
|
+
* @param {string} source - Complete source text.
|
|
43
|
+
* @param {number} index - Binding-reported UTF-16 index.
|
|
44
|
+
* @returns {number} Verified UTF-16 offset.
|
|
45
|
+
*/
|
|
46
|
+
function bindingIndexToUtf16Offset(source, index) {
|
|
47
|
+
if (!Number.isInteger(index) || index < 0 || index > source.length ||
|
|
48
|
+
index > 0 && index < source.length && /[\uD800-\uDBFF]/u.test(source[index - 1]) && /[\uDC00-\uDFFF]/u.test(source[index])) {
|
|
49
|
+
throw new RangeError(`Invalid Tree-sitter source index: ${index}`)
|
|
50
|
+
}
|
|
51
|
+
return utf8ByteOffsetToUtf16Offset(source, new TextEncoder().encode(source.slice(0, index)).length)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Finds the first unpaired UTF-16 surrogate.
|
|
56
|
+
* @param {string} source - Complete source text.
|
|
57
|
+
* @returns {number} Invalid offset, or -1.
|
|
58
|
+
*/
|
|
59
|
+
function firstLoneSurrogateOffset(source) {
|
|
60
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
61
|
+
const unit = source.charCodeAt(index)
|
|
62
|
+
|
|
63
|
+
if (unit >= 0xD800 && unit <= 0xDBFF) {
|
|
64
|
+
const next = source.charCodeAt(index + 1)
|
|
65
|
+
|
|
66
|
+
if (next >= 0xDC00 && next <= 0xDFFF) index += 1
|
|
67
|
+
else return index
|
|
68
|
+
} else if (unit >= 0xDC00 && unit <= 0xDFFF) return index
|
|
69
|
+
}
|
|
70
|
+
return -1
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Converts one binding range to a semantic source location.
|
|
75
|
+
* @param {import("tree-sitter").SyntaxNode} node - Parser node.
|
|
76
|
+
* @param {string} filename - Source filename.
|
|
77
|
+
* @param {string} source - Complete source text.
|
|
78
|
+
* @returns {import("../semantic/types.js").SourceLocation} Exact location.
|
|
79
|
+
*/
|
|
80
|
+
function nodeLocation(node, filename, source) {
|
|
81
|
+
return locationFromOffsets(filename, source, bindingIndexToUtf16Offset(source, node.startIndex),
|
|
82
|
+
bindingIndexToUtf16Offset(source, node.endIndex))
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Requires one named grammar field.
|
|
87
|
+
* @param {import("tree-sitter").SyntaxNode} node - Field owner.
|
|
88
|
+
* @param {string} field - Grammar field name.
|
|
89
|
+
* @param {string} filename - Source filename.
|
|
90
|
+
* @param {string} source - Complete source text.
|
|
91
|
+
* @returns {import("tree-sitter").SyntaxNode} Required child.
|
|
92
|
+
*/
|
|
93
|
+
function requiredField(node, field, filename, source) {
|
|
94
|
+
const child = node.childForFieldName(field)
|
|
95
|
+
|
|
96
|
+
if (!child) return unsupportedSyntax("csharp", `${node.type} without ${field}`, nodeLocation(node, filename, source))
|
|
97
|
+
return child
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Traverses every parser child and rejects explicit or propagated recovery.
|
|
102
|
+
* @param {import("tree-sitter").SyntaxNode} node - Current parser node.
|
|
103
|
+
* @param {string} filename - Source filename.
|
|
104
|
+
* @param {string} source - Complete source text.
|
|
105
|
+
* @returns {void}
|
|
106
|
+
*/
|
|
107
|
+
function validateParserTree(node, filename, source) {
|
|
108
|
+
if (node.hasError || node.isError || node.isMissing) {
|
|
109
|
+
throw new SemantifoldDiagnostic({
|
|
110
|
+
code: "PARSE_ERROR",
|
|
111
|
+
language: "csharp",
|
|
112
|
+
location: nodeLocation(node, filename, source),
|
|
113
|
+
message: `Tree-sitter exposed recovery at '${node.type}'.`
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
for (let index = 0; index < node.childCount; index += 1) {
|
|
117
|
+
const child = node.child(index)
|
|
118
|
+
|
|
119
|
+
if (!child) throw new Error(`Tree-sitter omitted child ${index} of ${node.type}.`)
|
|
120
|
+
validateParserTree(child, filename, source)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Selects named semantic children while retaining comments in the parser tree.
|
|
126
|
+
* @param {import("tree-sitter").SyntaxNode} node - Parent parser node.
|
|
127
|
+
* @returns {import("tree-sitter").SyntaxNode[]} Non-comment named children.
|
|
128
|
+
*/
|
|
129
|
+
function semanticChildren(node) {
|
|
130
|
+
return node.namedChildren.filter((child) => child.type != "comment")
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Validates one identifier against the exact C# source profile.
|
|
135
|
+
* @param {import("tree-sitter").SyntaxNode} node - Identifier node.
|
|
136
|
+
* @param {string} role - Diagnostic role.
|
|
137
|
+
* @param {string} filename - Source filename.
|
|
138
|
+
* @param {string} source - Complete source text.
|
|
139
|
+
* @returns {string} Accepted identifier.
|
|
140
|
+
*/
|
|
141
|
+
function identifier(node, role, filename, source) {
|
|
142
|
+
const name = node.text
|
|
143
|
+
|
|
144
|
+
if (node.type != "identifier" || !/^[A-Za-z_][A-Za-z0-9_]*$/u.test(name) || csharpReservedIdentifiers.has(name)) {
|
|
145
|
+
return unsupportedSyntax("csharp", `${role} identifier '${name}'`, nodeLocation(node, filename, source))
|
|
146
|
+
}
|
|
147
|
+
return name
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Converts one exact supported scalar type.
|
|
152
|
+
* @param {import("tree-sitter").SyntaxNode | null} node - Type node, if present.
|
|
153
|
+
* @param {string} subject - Typed subject for diagnostics.
|
|
154
|
+
* @param {import("../semantic/types.js").SourceLocation} ownerLocation - Owning declaration location.
|
|
155
|
+
* @param {string} filename - Source filename.
|
|
156
|
+
* @param {string} source - Complete source text.
|
|
157
|
+
* @param {boolean} [allowVar] - Whether inferred `var` produces MISSING_TYPE.
|
|
158
|
+
* @returns {import("../semantic/types.js").TypeReference} Semantic scalar type.
|
|
159
|
+
*/
|
|
160
|
+
function convertType(node, subject, ownerLocation, filename, source, allowVar = false) {
|
|
161
|
+
if (!node) return missingType("csharp", subject, ownerLocation)
|
|
162
|
+
const location = nodeLocation(node, filename, source)
|
|
163
|
+
|
|
164
|
+
if (allowVar && node.text == "var") return missingType("csharp", subject, ownerLocation)
|
|
165
|
+
const type = sourceScalarType("csharp", node.text, location)
|
|
166
|
+
|
|
167
|
+
if (!type || !["predefined_type", "qualified_name"].includes(node.type)) {
|
|
168
|
+
return unsupportedSyntax("csharp", `unsupported scalar type '${node.text}'`, location)
|
|
169
|
+
}
|
|
170
|
+
return type
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Finds exactly one accepted operator token owned by a parser node.
|
|
175
|
+
* @param {import("tree-sitter").SyntaxNode} node - Operation node.
|
|
176
|
+
* @param {Set<string>} spellings - Accepted operator spellings.
|
|
177
|
+
* @param {string} filename - Source filename.
|
|
178
|
+
* @param {string} source - Complete source text.
|
|
179
|
+
* @returns {import("tree-sitter").SyntaxNode} Operator token.
|
|
180
|
+
*/
|
|
181
|
+
function operatorToken(node, spellings, filename, source) {
|
|
182
|
+
const field = node.childForFieldName("operator")
|
|
183
|
+
const candidates = field ? [field] : node.children.filter((child) => !child.isNamed && spellings.has(child.type))
|
|
184
|
+
|
|
185
|
+
if (candidates.length != 1 || !spellings.has(candidates[0].type)) {
|
|
186
|
+
return unsupportedSyntax("csharp", `${node.type} operator`, nodeLocation(node, filename, source))
|
|
187
|
+
}
|
|
188
|
+
return candidates[0]
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Converts one expression and records exact checked-wrapper ownership.
|
|
193
|
+
* @param {import("tree-sitter").SyntaxNode} node - Expression node.
|
|
194
|
+
* @param {string} filename - Source filename.
|
|
195
|
+
* @param {string} source - Complete source text.
|
|
196
|
+
* @param {boolean} [checkedRoot] - Whether the node is the direct checked-expression operand.
|
|
197
|
+
* @returns {import("../semantic/types.js").Expression} Semantic expression.
|
|
198
|
+
*/
|
|
199
|
+
function convertExpression(node, filename, source, checkedRoot = false) {
|
|
200
|
+
const location = nodeLocation(node, filename, source)
|
|
201
|
+
|
|
202
|
+
if (node.type == "parenthesized_expression") {
|
|
203
|
+
const children = semanticChildren(node)
|
|
204
|
+
|
|
205
|
+
if (children.length != 1) return unsupportedSyntax("csharp", node.type, location)
|
|
206
|
+
return convertExpression(children[0], filename, source)
|
|
207
|
+
}
|
|
208
|
+
if (node.type == "checked_expression") {
|
|
209
|
+
const children = semanticChildren(node)
|
|
210
|
+
const checkedTokens = node.children.filter((child) => !child.isNamed && child.type == "checked")
|
|
211
|
+
|
|
212
|
+
if (checkedTokens.length != 1 || children.length != 1 ||
|
|
213
|
+
!["binary_expression", "prefix_unary_expression"].includes(children[0].type)) {
|
|
214
|
+
return unsupportedSyntax("csharp", "checked expression shape", location)
|
|
215
|
+
}
|
|
216
|
+
const expression = convertExpression(children[0], filename, source, true)
|
|
217
|
+
|
|
218
|
+
checkedArithmetic.add(expression)
|
|
219
|
+
expression.location = location
|
|
220
|
+
return expression
|
|
221
|
+
}
|
|
222
|
+
if (node.type == "identifier") {
|
|
223
|
+
const name = identifier(node, "reference", filename, source)
|
|
224
|
+
|
|
225
|
+
return withParserRanges({kind: /** @type {const} */ ("IdentifierExpression"), location, name}, {name: location})
|
|
226
|
+
}
|
|
227
|
+
if (node.type == "integer_literal") {
|
|
228
|
+
if (!/^(?:0|[1-9][0-9]*)L$/u.test(node.text)) return unsupportedSyntax("csharp", "noncanonical long literal", location)
|
|
229
|
+
const value = Number(BigInt(node.text.slice(0, -1)))
|
|
230
|
+
|
|
231
|
+
if (!Number.isSafeInteger(value)) return unsupportedSyntax("csharp", "non-safe integer literal", location)
|
|
232
|
+
return withParserRanges({kind: /** @type {const} */ ("IntegerLiteral"), location, value}, {literal: location})
|
|
233
|
+
}
|
|
234
|
+
if (node.type == "boolean_literal") {
|
|
235
|
+
if (node.text != "true" && node.text != "false") return unsupportedSyntax("csharp", "boolean literal", location)
|
|
236
|
+
return withParserRanges({kind: /** @type {const} */ ("BooleanLiteral"), location, value: node.text == "true"}, {literal: location})
|
|
237
|
+
}
|
|
238
|
+
if (node.type == "string_literal") {
|
|
239
|
+
return withParserRanges({kind: /** @type {const} */ ("StringLiteral"), location, value: decodeString(node, filename, source)}, {
|
|
240
|
+
literal: location
|
|
241
|
+
})
|
|
242
|
+
}
|
|
243
|
+
if (node.type == "prefix_unary_expression") {
|
|
244
|
+
const children = semanticChildren(node)
|
|
245
|
+
const operator = operatorToken(node, new Set(["!", "-"]), filename, source)
|
|
246
|
+
|
|
247
|
+
if (children.length != 1 || operator.type == "-" && !checkedRoot) {
|
|
248
|
+
return unsupportedSyntax("csharp", "unwrapped or malformed unary expression", location)
|
|
249
|
+
}
|
|
250
|
+
const expression = /** @type {import("../semantic/types.js").Expression} */ (/** @type {unknown} */ (withAdaptedOperation(withParserRanges({
|
|
251
|
+
kind: "UnaryExpression",
|
|
252
|
+
location,
|
|
253
|
+
operand: convertExpression(children[0], filename, source)
|
|
254
|
+
}, {operator: nodeLocation(operator, filename, source)}), operator.type == "!" ? "Not" : "Negate")))
|
|
255
|
+
|
|
256
|
+
if (checkedRoot) checkedArithmetic.add(expression)
|
|
257
|
+
return expression
|
|
258
|
+
}
|
|
259
|
+
if (node.type == "binary_expression") {
|
|
260
|
+
const leftNode = requiredField(node, "left", filename, source)
|
|
261
|
+
const rightNode = requiredField(node, "right", filename, source)
|
|
262
|
+
const operator = operatorToken(node, new Set(binaryOperations.keys()), filename, source)
|
|
263
|
+
const adapted = binaryOperations.get(operator.type)
|
|
264
|
+
|
|
265
|
+
if (!adapted || semanticChildren(node).length != 2 || ["-", "*"].includes(operator.type) && !checkedRoot) {
|
|
266
|
+
return unsupportedSyntax("csharp", "unwrapped or unsupported binary expression", location)
|
|
267
|
+
}
|
|
268
|
+
const expression = /** @type {import("../semantic/types.js").Expression} */ (/** @type {unknown} */ (withAdaptedOperation(withParserRanges({
|
|
269
|
+
kind: "BinaryExpression",
|
|
270
|
+
left: convertExpression(leftNode, filename, source),
|
|
271
|
+
location,
|
|
272
|
+
right: convertExpression(rightNode, filename, source)
|
|
273
|
+
}, {operator: nodeLocation(operator, filename, source)}), /** @type {import("../semantic/operators.js").AdaptedOperation} */ (adapted))))
|
|
274
|
+
|
|
275
|
+
if (checkedRoot) checkedArithmetic.add(expression)
|
|
276
|
+
return expression
|
|
277
|
+
}
|
|
278
|
+
if (node.type == "invocation_expression") {
|
|
279
|
+
const calleeNode = requiredField(node, "function", filename, source)
|
|
280
|
+
const argumentsNode = requiredField(node, "arguments", filename, source)
|
|
281
|
+
|
|
282
|
+
if (calleeNode.type != "identifier" || argumentsNode.type != "argument_list") {
|
|
283
|
+
return unsupportedSyntax("csharp", "qualified or dynamic call", location)
|
|
284
|
+
}
|
|
285
|
+
const arguments_ = /** @type {import("../semantic/types.js").Expression[]} */ (
|
|
286
|
+
semanticChildren(argumentsNode).map((argument) => convertArgument(argument, filename, source)))
|
|
287
|
+
const callee = identifier(calleeNode, "callee", filename, source)
|
|
288
|
+
|
|
289
|
+
return withParserRanges({arguments: arguments_, callee, kind: /** @type {const} */ ("CallExpression"), location}, {
|
|
290
|
+
callee: nodeLocation(calleeNode, filename, source)
|
|
291
|
+
})
|
|
292
|
+
}
|
|
293
|
+
return unsupportedSyntax("csharp", node.type, location)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Converts one positional argument.
|
|
298
|
+
* @param {import("tree-sitter").SyntaxNode} node - Argument node.
|
|
299
|
+
* @param {string} filename - Source filename.
|
|
300
|
+
* @param {string} source - Complete source text.
|
|
301
|
+
* @returns {import("../semantic/types.js").Expression} Semantic argument expression.
|
|
302
|
+
*/
|
|
303
|
+
function convertArgument(node, filename, source) {
|
|
304
|
+
const children = semanticChildren(node)
|
|
305
|
+
|
|
306
|
+
if (node.type != "argument" || children.length != 1 || node.children.some((child) => !child.isNamed && child.type == ":")) {
|
|
307
|
+
return unsupportedSyntax("csharp", "non-positional argument", nodeLocation(node, filename, source))
|
|
308
|
+
}
|
|
309
|
+
return convertExpression(children[0], filename, source)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Decodes one ordinary C# string literal without interpolation or raw forms.
|
|
314
|
+
* @param {import("tree-sitter").SyntaxNode} node - String literal node.
|
|
315
|
+
* @param {string} filename - Source filename.
|
|
316
|
+
* @param {string} source - Complete source text.
|
|
317
|
+
* @returns {string} Decoded Unicode scalar string.
|
|
318
|
+
*/
|
|
319
|
+
function decodeString(node, filename, source) {
|
|
320
|
+
const location = nodeLocation(node, filename, source)
|
|
321
|
+
const text = node.text
|
|
322
|
+
|
|
323
|
+
if (!text.startsWith("\"") || !text.endsWith("\"") || text.startsWith("\"\"\"") || /[\r\n]/u.test(text)) {
|
|
324
|
+
return unsupportedSyntax("csharp", "noncanonical string literal", location)
|
|
325
|
+
}
|
|
326
|
+
let decoded = ""
|
|
327
|
+
const simple = new Map([["\"", "\""], ["\\", "\\"], ["0", "\0"], ["a", "\u0007"], ["b", "\b"], ["f", "\f"],
|
|
328
|
+
["n", "\n"], ["r", "\r"], ["t", "\t"], ["v", "\v"]])
|
|
329
|
+
|
|
330
|
+
for (let index = 1; index < text.length - 1; index += 1) {
|
|
331
|
+
const character = text[index]
|
|
332
|
+
|
|
333
|
+
if (character != "\\") {
|
|
334
|
+
decoded += character
|
|
335
|
+
continue
|
|
336
|
+
}
|
|
337
|
+
const escape = text[++index]
|
|
338
|
+
|
|
339
|
+
if (escape === undefined) return unsupportedSyntax("csharp", "invalid string escape", location)
|
|
340
|
+
if (simple.has(escape)) {
|
|
341
|
+
decoded += simple.get(escape)
|
|
342
|
+
continue
|
|
343
|
+
}
|
|
344
|
+
const width = escape == "u" ? 4 : escape == "U" ? 8 : 0
|
|
345
|
+
const digits = text.slice(index + 1, index + 1 + width)
|
|
346
|
+
|
|
347
|
+
if (!width || digits.length != width || !/^[0-9A-Fa-f]+$/u.test(digits)) {
|
|
348
|
+
return unsupportedSyntax("csharp", "unsupported string escape", location)
|
|
349
|
+
}
|
|
350
|
+
index += width
|
|
351
|
+
const value = Number.parseInt(digits, 16)
|
|
352
|
+
|
|
353
|
+
if (escape == "U" && (value > 0x10FFFF || value >= 0xD800 && value <= 0xDFFF)) {
|
|
354
|
+
return unsupportedSyntax("csharp", "invalid Unicode string escape", location)
|
|
355
|
+
}
|
|
356
|
+
decoded += escape == "U" ? String.fromCodePoint(value) : String.fromCharCode(value)
|
|
357
|
+
}
|
|
358
|
+
if (!hasOnlyUnicodeScalars(decoded)) return unsupportedSyntax("csharp", "invalid Unicode string literal", location)
|
|
359
|
+
return decoded
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Converts one exact initialized local declaration.
|
|
364
|
+
* @param {import("tree-sitter").SyntaxNode} node - Local statement node.
|
|
365
|
+
* @param {CSharpContext} context - Comment-carrier state.
|
|
366
|
+
* @param {string} filename - Source filename.
|
|
367
|
+
* @param {string} source - Complete source text.
|
|
368
|
+
* @returns {import("../semantic/types.js").LocalDeclaration} Semantic declaration.
|
|
369
|
+
*/
|
|
370
|
+
function convertLocal(node, context, filename, source) {
|
|
371
|
+
const location = nodeLocation(node, filename, source)
|
|
372
|
+
const declaration = semanticChildren(node)[0]
|
|
373
|
+
|
|
374
|
+
if (semanticChildren(node).length != 1 || declaration?.type != "variable_declaration") {
|
|
375
|
+
return unsupportedSyntax("csharp", node.type, location)
|
|
376
|
+
}
|
|
377
|
+
const typeNode = declaration.childForFieldName("type")
|
|
378
|
+
const declarators = semanticChildren(declaration).filter((child) => child.type == "variable_declarator")
|
|
379
|
+
|
|
380
|
+
if (declarators.length != 1 || semanticChildren(declaration).length != 2) {
|
|
381
|
+
return unsupportedSyntax("csharp", "local declaration shape", location)
|
|
382
|
+
}
|
|
383
|
+
const declarator = declarators[0]
|
|
384
|
+
const nameNode = requiredField(declarator, "name", filename, source)
|
|
385
|
+
const values = semanticChildren(declarator).filter((child) => child.id != nameNode.id)
|
|
386
|
+
|
|
387
|
+
if (values.length != 1) return unsupportedSyntax("csharp", "local without one initializer", location)
|
|
388
|
+
const name = identifier(nameNode, "local", filename, source)
|
|
389
|
+
|
|
390
|
+
if (name == "System") return unsupportedSyntax("csharp", "local captures System", nodeLocation(nameNode, filename, source))
|
|
391
|
+
const operator = operatorToken(declarator, new Set(["="]), filename, source)
|
|
392
|
+
const mutable = !takeImmutableMarker(node, context)
|
|
393
|
+
|
|
394
|
+
return withParserRanges({
|
|
395
|
+
initializer: convertExpression(values[0], filename, source),
|
|
396
|
+
kind: /** @type {const} */ ("LocalDeclaration"),
|
|
397
|
+
location,
|
|
398
|
+
mutable,
|
|
399
|
+
name,
|
|
400
|
+
type: convertType(typeNode, `Local '${name}'`, location, filename, source, true)
|
|
401
|
+
}, {name: nodeLocation(nameNode, filename, source), operator: nodeLocation(operator, filename, source)})
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Claims an exactly adjacent immutable-local carrier if present.
|
|
406
|
+
* @param {import("tree-sitter").SyntaxNode} node - Local declaration node.
|
|
407
|
+
* @param {CSharpContext} context - Comment-carrier state.
|
|
408
|
+
* @returns {boolean} Whether the local is immutable.
|
|
409
|
+
*/
|
|
410
|
+
function takeImmutableMarker(node, context) {
|
|
411
|
+
const marker = context.comments.find((comment) => comment.text == immutableMarker &&
|
|
412
|
+
comment.endPosition.row + 1 == node.startPosition.row && comment.startPosition.column == node.startPosition.column)
|
|
413
|
+
|
|
414
|
+
if (!marker) return false
|
|
415
|
+
context.usedImmutableMarkers.add(marker)
|
|
416
|
+
return true
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Converts one supported C# statement.
|
|
421
|
+
* @param {import("tree-sitter").SyntaxNode} node - Statement node.
|
|
422
|
+
* @param {CSharpContext} context - Comment-carrier state.
|
|
423
|
+
* @param {string} filename - Source filename.
|
|
424
|
+
* @param {string} source - Complete source text.
|
|
425
|
+
* @returns {import("../semantic/types.js").Statement} Semantic statement.
|
|
426
|
+
*/
|
|
427
|
+
function convertStatement(node, context, filename, source) {
|
|
428
|
+
const location = nodeLocation(node, filename, source)
|
|
429
|
+
|
|
430
|
+
if (node.type == "local_declaration_statement") return convertLocal(node, context, filename, source)
|
|
431
|
+
if (node.type == "return_statement") {
|
|
432
|
+
const children = semanticChildren(node)
|
|
433
|
+
|
|
434
|
+
if (children.length != 1) return unsupportedSyntax("csharp", "return without one expression", location)
|
|
435
|
+
return {expression: convertExpression(children[0], filename, source), kind: /** @type {const} */ ("ReturnStatement"), location}
|
|
436
|
+
}
|
|
437
|
+
if (node.type == "if_statement") return convertIf(node, context, filename, source)
|
|
438
|
+
if (node.type == "expression_statement") {
|
|
439
|
+
const children = semanticChildren(node)
|
|
440
|
+
|
|
441
|
+
if (children.length != 1) return unsupportedSyntax("csharp", node.type, location)
|
|
442
|
+
if (children[0].type == "assignment_expression") return convertAssignment(children[0], filename, source, location)
|
|
443
|
+
return convertPrint(children[0], filename, source, location)
|
|
444
|
+
}
|
|
445
|
+
return unsupportedSyntax("csharp", node.type, location)
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Converts one plain identifier assignment.
|
|
450
|
+
* @param {import("tree-sitter").SyntaxNode} node - Assignment expression node.
|
|
451
|
+
* @param {string} filename - Source filename.
|
|
452
|
+
* @param {string} source - Complete source text.
|
|
453
|
+
* @param {import("../semantic/types.js").SourceLocation} location - Owning statement location.
|
|
454
|
+
* @returns {import("../semantic/types.js").AssignmentStatement} Semantic assignment.
|
|
455
|
+
*/
|
|
456
|
+
function convertAssignment(node, filename, source, location) {
|
|
457
|
+
const left = requiredField(node, "left", filename, source)
|
|
458
|
+
const right = requiredField(node, "right", filename, source)
|
|
459
|
+
const operator = operatorToken(node, new Set(["="]), filename, source)
|
|
460
|
+
|
|
461
|
+
if (left.type != "identifier") return unsupportedSyntax("csharp", "assignment target", nodeLocation(left, filename, source))
|
|
462
|
+
const name = identifier(left, "assignment target", filename, source)
|
|
463
|
+
const nameLocation = nodeLocation(left, filename, source)
|
|
464
|
+
|
|
465
|
+
return withParserRanges({
|
|
466
|
+
expression: convertExpression(right, filename, source),
|
|
467
|
+
kind: /** @type {const} */ ("AssignmentStatement"),
|
|
468
|
+
location,
|
|
469
|
+
target: withParserRanges({kind: /** @type {const} */ ("IdentifierExpression"), location: nameLocation, name}, {name: nameLocation})
|
|
470
|
+
}, {operator: nodeLocation(operator, filename, source)})
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Converts the exact System.Console.WriteLine print scaffold.
|
|
475
|
+
* @param {import("tree-sitter").SyntaxNode} node - Invocation node.
|
|
476
|
+
* @param {string} filename - Source filename.
|
|
477
|
+
* @param {string} source - Complete source text.
|
|
478
|
+
* @param {import("../semantic/types.js").SourceLocation} location - Owning statement location.
|
|
479
|
+
* @returns {import("../semantic/types.js").PrintStatement} Semantic print statement.
|
|
480
|
+
*/
|
|
481
|
+
function convertPrint(node, filename, source, location) {
|
|
482
|
+
if (node.type != "invocation_expression") return unsupportedSyntax("csharp", "expression statement other than print", nodeLocation(node, filename, source))
|
|
483
|
+
const callee = requiredField(node, "function", filename, source)
|
|
484
|
+
const argumentsNode = requiredField(node, "arguments", filename, source)
|
|
485
|
+
const arguments_ = semanticChildren(argumentsNode)
|
|
486
|
+
|
|
487
|
+
if (!isPrintReceiver(callee) || argumentsNode.type != "argument_list" || arguments_.length != 1) {
|
|
488
|
+
return unsupportedSyntax("csharp", "print call shape", nodeLocation(node, filename, source))
|
|
489
|
+
}
|
|
490
|
+
return {expression: convertArgument(arguments_[0], filename, source), kind: /** @type {const} */ ("PrintStatement"), location}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Recognizes only the fully qualified print receiver.
|
|
495
|
+
* @param {import("tree-sitter").SyntaxNode} node - Candidate callee.
|
|
496
|
+
* @returns {boolean} Whether the callee is the exact print receiver.
|
|
497
|
+
*/
|
|
498
|
+
function isPrintReceiver(node) {
|
|
499
|
+
if (node.type != "member_access_expression") return false
|
|
500
|
+
const outerExpression = node.childForFieldName("expression")
|
|
501
|
+
const outerName = node.childForFieldName("name")
|
|
502
|
+
|
|
503
|
+
if (outerName?.text != "WriteLine" || outerExpression?.type != "member_access_expression") return false
|
|
504
|
+
return outerExpression.childForFieldName("expression")?.type == "identifier" &&
|
|
505
|
+
outerExpression.childForFieldName("expression")?.text == "System" && outerExpression.childForFieldName("name")?.text == "Console"
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Converts one braced conditional and optional alternate.
|
|
510
|
+
* @param {import("tree-sitter").SyntaxNode} node - If-statement node.
|
|
511
|
+
* @param {CSharpContext} context - Comment-carrier state.
|
|
512
|
+
* @param {string} filename - Source filename.
|
|
513
|
+
* @param {string} source - Complete source text.
|
|
514
|
+
* @returns {import("../semantic/types.js").IfStatement} Semantic conditional.
|
|
515
|
+
*/
|
|
516
|
+
function convertIf(node, context, filename, source) {
|
|
517
|
+
const location = nodeLocation(node, filename, source)
|
|
518
|
+
const condition = requiredField(node, "condition", filename, source)
|
|
519
|
+
const consequence = requiredField(node, "consequence", filename, source)
|
|
520
|
+
const alternative = node.childForFieldName("alternative")
|
|
521
|
+
|
|
522
|
+
return {
|
|
523
|
+
...(alternative ? {alternate: alternative.type == "if_statement"
|
|
524
|
+
? {kind: /** @type {const} */ ("Block"), location: nodeLocation(alternative, filename, source),
|
|
525
|
+
statements: [convertIf(alternative, context, filename, source)]}
|
|
526
|
+
: convertBlock(alternative, context, filename, source)} : {}),
|
|
527
|
+
condition: convertExpression(condition, filename, source),
|
|
528
|
+
consequent: convertBlock(consequence, context, filename, source),
|
|
529
|
+
kind: /** @type {const} */ ("IfStatement"),
|
|
530
|
+
location
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Converts one lexical C# block.
|
|
536
|
+
* @param {import("tree-sitter").SyntaxNode} node - Block node.
|
|
537
|
+
* @param {CSharpContext} context - Comment-carrier state.
|
|
538
|
+
* @param {string} filename - Source filename.
|
|
539
|
+
* @param {string} source - Complete source text.
|
|
540
|
+
* @returns {import("../semantic/types.js").Block} Semantic block.
|
|
541
|
+
*/
|
|
542
|
+
function convertBlock(node, context, filename, source) {
|
|
543
|
+
const location = nodeLocation(node, filename, source)
|
|
544
|
+
|
|
545
|
+
if (node.type != "block") return unsupportedSyntax("csharp", node.type, location)
|
|
546
|
+
return {kind: /** @type {const} */ ("Block"), location,
|
|
547
|
+
statements: semanticChildren(node).map((statement) => convertStatement(statement, context, filename, source))}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Converts one exact private static semantic method.
|
|
552
|
+
* @param {import("tree-sitter").SyntaxNode} node - Method node.
|
|
553
|
+
* @param {CSharpContext} context - Comment-carrier state.
|
|
554
|
+
* @param {string} filename - Source filename.
|
|
555
|
+
* @param {string} source - Complete source text.
|
|
556
|
+
* @returns {import("../semantic/types.js").FunctionDeclaration} Semantic function.
|
|
557
|
+
*/
|
|
558
|
+
function convertFunction(node, context, filename, source) {
|
|
559
|
+
const location = nodeLocation(node, filename, source)
|
|
560
|
+
const children = semanticChildren(node)
|
|
561
|
+
const modifiers = children.filter((child) => child.type == "modifier")
|
|
562
|
+
|
|
563
|
+
if (node.type != "method_declaration" || modifiers.map(({text}) => text).join(" ") != "private static" ||
|
|
564
|
+
children.length != 6 || node.childForFieldName("type_parameters") || node.childForFieldName("constraints") ||
|
|
565
|
+
!node.childForFieldName("body")) {
|
|
566
|
+
return unsupportedSyntax("csharp", "method scaffolding", location)
|
|
567
|
+
}
|
|
568
|
+
const nameNode = requiredField(node, "name", filename, source)
|
|
569
|
+
const parametersNode = requiredField(node, "parameters", filename, source)
|
|
570
|
+
const returnNode = requiredField(node, "returns", filename, source)
|
|
571
|
+
const bodyNode = requiredField(node, "body", filename, source)
|
|
572
|
+
const name = identifier(nameNode, "function", filename, source)
|
|
573
|
+
|
|
574
|
+
if (["Main", "Program", "System"].includes(name)) {
|
|
575
|
+
return unsupportedSyntax("csharp", `reserved semantic method '${name}'`, nodeLocation(nameNode, filename, source))
|
|
576
|
+
}
|
|
577
|
+
const parameterNodes = semanticChildren(parametersNode)
|
|
578
|
+
|
|
579
|
+
if (parameterNodes.length != 2 || parameterNodes.some((parameter) => parameter.type != "parameter")) {
|
|
580
|
+
return unsupportedSyntax("csharp", "function parameter count or shape", nodeLocation(parametersNode, filename, source))
|
|
581
|
+
}
|
|
582
|
+
const parameters = parameterNodes.map((parameterNode) => convertParameter(parameterNode, filename, source))
|
|
583
|
+
|
|
584
|
+
return withParserRanges({
|
|
585
|
+
body: convertBlock(bodyNode, context, filename, source),
|
|
586
|
+
kind: /** @type {const} */ ("FunctionDeclaration"),
|
|
587
|
+
location,
|
|
588
|
+
name,
|
|
589
|
+
parameters,
|
|
590
|
+
returnType: convertType(returnNode, `Function '${name}' return`, location, filename, source)
|
|
591
|
+
}, {name: nodeLocation(nameNode, filename, source)})
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Converts one explicitly typed unmodified parameter.
|
|
596
|
+
* @param {import("tree-sitter").SyntaxNode} node - Parameter node.
|
|
597
|
+
* @param {string} filename - Source filename.
|
|
598
|
+
* @param {string} source - Complete source text.
|
|
599
|
+
* @returns {import("../semantic/types.js").Parameter} Semantic parameter.
|
|
600
|
+
*/
|
|
601
|
+
function convertParameter(node, filename, source) {
|
|
602
|
+
const location = nodeLocation(node, filename, source)
|
|
603
|
+
const nameNode = requiredField(node, "name", filename, source)
|
|
604
|
+
const typeNode = node.childForFieldName("type")
|
|
605
|
+
|
|
606
|
+
if (semanticChildren(node).length != 2) return unsupportedSyntax("csharp", "parameter modifiers or defaults", location)
|
|
607
|
+
const name = identifier(nameNode, "parameter", filename, source)
|
|
608
|
+
|
|
609
|
+
if (name == "System") return unsupportedSyntax("csharp", "parameter captures System", nodeLocation(nameNode, filename, source))
|
|
610
|
+
return withParserRanges({
|
|
611
|
+
kind: /** @type {const} */ ("Parameter"), location, name,
|
|
612
|
+
type: convertType(typeNode, `Parameter '${name}'`, location, filename, source)
|
|
613
|
+
}, {name: nodeLocation(nameNode, filename, source)})
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Converts the exact final zero-argument Main method.
|
|
618
|
+
* @param {import("tree-sitter").SyntaxNode} node - Main method node.
|
|
619
|
+
* @param {CSharpContext} context - Comment-carrier state.
|
|
620
|
+
* @param {string} filename - Source filename.
|
|
621
|
+
* @param {string} source - Complete source text.
|
|
622
|
+
* @returns {import("../semantic/types.js").EntryPoint} Semantic entry point.
|
|
623
|
+
*/
|
|
624
|
+
function convertMain(node, context, filename, source) {
|
|
625
|
+
const location = nodeLocation(node, filename, source)
|
|
626
|
+
const children = semanticChildren(node)
|
|
627
|
+
const modifiers = children.filter((child) => child.type == "modifier")
|
|
628
|
+
const name = requiredField(node, "name", filename, source)
|
|
629
|
+
const returns = requiredField(node, "returns", filename, source)
|
|
630
|
+
const parameters = requiredField(node, "parameters", filename, source)
|
|
631
|
+
const body = requiredField(node, "body", filename, source)
|
|
632
|
+
|
|
633
|
+
if (children.length != 6 || modifiers.map(({text}) => text).join(" ") != "private static" || name.text != "Main" || returns.text != "void" ||
|
|
634
|
+
semanticChildren(parameters).length != 0) return unsupportedSyntax("csharp", "Main scaffolding", location)
|
|
635
|
+
return {body: convertBlock(body, context, filename, source), kind: /** @type {const} */ ("EntryPoint"), location}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* Requires exactly one checked wrapper around every integer arithmetic root.
|
|
640
|
+
* @param {import("../semantic/types.js").SemanticModule} module - Resolved semantic module.
|
|
641
|
+
* @returns {void}
|
|
642
|
+
*/
|
|
643
|
+
function validateCheckedArithmetic(module) {
|
|
644
|
+
/** @type {import("../semantic/types.js").Expression[]} */
|
|
645
|
+
const expressions = []
|
|
646
|
+
/**
|
|
647
|
+
* Collects expressions recursively.
|
|
648
|
+
* @param {import("../semantic/types.js").Expression} expression - Current expression.
|
|
649
|
+
* @returns {void}
|
|
650
|
+
*/
|
|
651
|
+
const visitExpression = (expression) => {
|
|
652
|
+
expressions.push(expression)
|
|
653
|
+
if (expression.kind == "UnaryExpression") visitExpression(expression.operand)
|
|
654
|
+
else if (expression.kind == "BinaryExpression") {
|
|
655
|
+
visitExpression(expression.left)
|
|
656
|
+
visitExpression(expression.right)
|
|
657
|
+
} else if (expression.kind == "CallExpression") expression.arguments.forEach(visitExpression)
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Collects expressions from a semantic block.
|
|
661
|
+
* @param {import("../semantic/types.js").Block} block - Current block.
|
|
662
|
+
* @returns {void}
|
|
663
|
+
*/
|
|
664
|
+
const visitBlock = (block) => block.statements.forEach((statement) => {
|
|
665
|
+
if (statement.kind == "LocalDeclaration") visitExpression(statement.initializer)
|
|
666
|
+
else if (statement.kind == "AssignmentStatement" || statement.kind == "PrintStatement" || statement.kind == "ReturnStatement") {
|
|
667
|
+
visitExpression(statement.expression)
|
|
668
|
+
} else {
|
|
669
|
+
visitExpression(statement.condition)
|
|
670
|
+
visitBlock(statement.consequent)
|
|
671
|
+
if (statement.alternate) visitBlock(statement.alternate)
|
|
672
|
+
}
|
|
673
|
+
})
|
|
674
|
+
|
|
675
|
+
module.functions.forEach((declaration) => visitBlock(declaration.body))
|
|
676
|
+
visitBlock(module.entryPoint.body)
|
|
677
|
+
for (const expression of expressions) {
|
|
678
|
+
const arithmetic = expression.kind == "UnaryExpression" && expression.operation == "IntegerNegate" ||
|
|
679
|
+
expression.kind == "BinaryExpression" && ["IntegerAdd", "IntegerSubtract", "IntegerMultiply"].includes(expression.operation)
|
|
680
|
+
|
|
681
|
+
if (arithmetic != checkedArithmetic.has(expression)) {
|
|
682
|
+
return unsupportedSyntax("csharp", arithmetic ? "integer arithmetic without exact checked wrapper" : "checked non-integer expression",
|
|
683
|
+
expression.location)
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* Parses the strict Task 017 C# profile.
|
|
690
|
+
* @param {{filename: string, source: string}} input - Parser input.
|
|
691
|
+
* @returns {import("../semantic/types.js").SemanticModule} Semantic module.
|
|
692
|
+
*/
|
|
693
|
+
export function parseCSharp({filename, source}) {
|
|
694
|
+
if (!hasOnlyUnicodeScalars(source)) {
|
|
695
|
+
const invalidOffset = firstLoneSurrogateOffset(source)
|
|
696
|
+
|
|
697
|
+
throw new SemantifoldDiagnostic({code: "PARSE_ERROR", language: "csharp",
|
|
698
|
+
location: locationFromOffsets(filename, source, invalidOffset, invalidOffset + 1),
|
|
699
|
+
message: "C# source contains an invalid lone UTF-16 surrogate."})
|
|
700
|
+
}
|
|
701
|
+
let tree
|
|
702
|
+
|
|
703
|
+
try {
|
|
704
|
+
tree = parser.parse(source)
|
|
705
|
+
} catch (error) {
|
|
706
|
+
return parseFailure("csharp", error)
|
|
707
|
+
}
|
|
708
|
+
const root = tree.rootNode
|
|
709
|
+
|
|
710
|
+
validateParserTree(root, filename, source)
|
|
711
|
+
if (root.type != "compilation_unit") throw new Error(`Tree-sitter returned C# root '${root.type}'.`)
|
|
712
|
+
const children = semanticChildren(root)
|
|
713
|
+
const location = moduleLocation(filename, source)
|
|
714
|
+
|
|
715
|
+
if (children.length != 3 || children[0].type != "preproc_nullable" ||
|
|
716
|
+
!/^#nullable enable(?:(?:\r\n|\n|\r))+$/u.test(children[0].text) ||
|
|
717
|
+
children[1].type != "file_scoped_namespace_declaration" || children[2].type != "class_declaration") {
|
|
718
|
+
return unsupportedSyntax("csharp", "compilation-unit scaffolding", location)
|
|
719
|
+
}
|
|
720
|
+
const namespaceName = requiredField(children[1], "name", filename, source)
|
|
721
|
+
|
|
722
|
+
if (namespaceName.text != "Semantifold.Generated") {
|
|
723
|
+
return unsupportedSyntax("csharp", "namespace scaffolding", nodeLocation(children[1], filename, source))
|
|
724
|
+
}
|
|
725
|
+
const classNode = children[2]
|
|
726
|
+
const className = requiredField(classNode, "name", filename, source)
|
|
727
|
+
const classBody = requiredField(classNode, "body", filename, source)
|
|
728
|
+
const classChildren = semanticChildren(classNode)
|
|
729
|
+
const classModifiers = classChildren.filter((child) => child.type == "modifier")
|
|
730
|
+
|
|
731
|
+
if (classChildren.length != 4 || className.text != "Program" ||
|
|
732
|
+
classModifiers.map(({text}) => text).join(" ") != "internal static") {
|
|
733
|
+
return unsupportedSyntax("csharp", "Program class scaffolding", nodeLocation(classNode, filename, source))
|
|
734
|
+
}
|
|
735
|
+
const members = semanticChildren(classBody)
|
|
736
|
+
|
|
737
|
+
if (members.length < 2 || members.some((member) => member.type != "method_declaration")) {
|
|
738
|
+
return unsupportedSyntax("csharp", "Program members", nodeLocation(classBody, filename, source))
|
|
739
|
+
}
|
|
740
|
+
const mainNodes = members.filter((member) => member.childForFieldName("name")?.text == "Main")
|
|
741
|
+
|
|
742
|
+
if (mainNodes.length != 1 || members.at(-1)?.id != mainNodes[0].id) {
|
|
743
|
+
return unsupportedSyntax("csharp", "Main ordering", nodeLocation(classBody, filename, source))
|
|
744
|
+
}
|
|
745
|
+
const comments = root.descendantsOfType("comment")
|
|
746
|
+
const context = {comments, usedImmutableMarkers: new Set()}
|
|
747
|
+
const module = {
|
|
748
|
+
entryPoint: convertMain(mainNodes[0], context, filename, source),
|
|
749
|
+
functions: members.slice(0, -1).map((member) => convertFunction(member, context, filename, source)),
|
|
750
|
+
kind: /** @type {const} */ ("Module"),
|
|
751
|
+
location
|
|
752
|
+
}
|
|
753
|
+
const unusedMarker = comments.find((comment) => comment.text == immutableMarker && !context.usedImmutableMarkers.has(comment))
|
|
754
|
+
|
|
755
|
+
if (unusedMarker) return unsupportedSyntax("csharp", "unattached immutable marker", nodeLocation(unusedMarker, filename, source))
|
|
756
|
+
validateParsedModule(module, "csharp")
|
|
757
|
+
validateCheckedArithmetic(module)
|
|
758
|
+
return module
|
|
759
|
+
}
|