@lokascript/semantic 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 +21 -0
- package/README.md +686 -0
- package/dist/browser-ar.ar.global.js +2 -0
- package/dist/browser-core.core.global.js +2 -0
- package/dist/browser-de.de.global.js +2 -0
- package/dist/browser-east-asian.east-asian.global.js +2 -0
- package/dist/browser-en-tr.en-tr.global.js +2 -0
- package/dist/browser-en.en.global.js +2 -0
- package/dist/browser-es-en.es-en.global.js +2 -0
- package/dist/browser-es.es.global.js +2 -0
- package/dist/browser-fr.fr.global.js +2 -0
- package/dist/browser-id.id.global.js +2 -0
- package/dist/browser-ja.ja.global.js +2 -0
- package/dist/browser-ko.ko.global.js +2 -0
- package/dist/browser-lazy.lazy.global.js +2 -0
- package/dist/browser-priority.priority.global.js +2 -0
- package/dist/browser-pt.pt.global.js +2 -0
- package/dist/browser-qu.qu.global.js +2 -0
- package/dist/browser-sw.sw.global.js +2 -0
- package/dist/browser-tr.tr.global.js +2 -0
- package/dist/browser-western.western.global.js +2 -0
- package/dist/browser-zh.zh.global.js +2 -0
- package/dist/browser.global.js +3 -0
- package/dist/browser.global.js.map +1 -0
- package/dist/index.cjs +35051 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3426 -0
- package/dist/index.d.ts +3426 -0
- package/dist/index.js +34890 -0
- package/dist/index.js.map +1 -0
- package/dist/languages/ar.d.ts +78 -0
- package/dist/languages/ar.js +1622 -0
- package/dist/languages/ar.js.map +1 -0
- package/dist/languages/de.d.ts +38 -0
- package/dist/languages/de.js +1168 -0
- package/dist/languages/de.js.map +1 -0
- package/dist/languages/en.d.ts +44 -0
- package/dist/languages/en.js +3491 -0
- package/dist/languages/en.js.map +1 -0
- package/dist/languages/es.d.ts +52 -0
- package/dist/languages/es.js +1493 -0
- package/dist/languages/es.js.map +1 -0
- package/dist/languages/fr.d.ts +37 -0
- package/dist/languages/fr.js +1159 -0
- package/dist/languages/fr.js.map +1 -0
- package/dist/languages/id.d.ts +35 -0
- package/dist/languages/id.js +1152 -0
- package/dist/languages/id.js.map +1 -0
- package/dist/languages/ja.d.ts +53 -0
- package/dist/languages/ja.js +1430 -0
- package/dist/languages/ja.js.map +1 -0
- package/dist/languages/ko.d.ts +51 -0
- package/dist/languages/ko.js +1729 -0
- package/dist/languages/ko.js.map +1 -0
- package/dist/languages/pt.d.ts +37 -0
- package/dist/languages/pt.js +1127 -0
- package/dist/languages/pt.js.map +1 -0
- package/dist/languages/qu.d.ts +36 -0
- package/dist/languages/qu.js +1143 -0
- package/dist/languages/qu.js.map +1 -0
- package/dist/languages/sw.d.ts +35 -0
- package/dist/languages/sw.js +1147 -0
- package/dist/languages/sw.js.map +1 -0
- package/dist/languages/tr.d.ts +45 -0
- package/dist/languages/tr.js +1529 -0
- package/dist/languages/tr.js.map +1 -0
- package/dist/languages/zh.d.ts +58 -0
- package/dist/languages/zh.js +1257 -0
- package/dist/languages/zh.js.map +1 -0
- package/dist/types-C4dcj53L.d.ts +600 -0
- package/package.json +202 -0
- package/src/__test-utils__/index.ts +7 -0
- package/src/__test-utils__/test-helpers.ts +8 -0
- package/src/__types__/test-helpers.ts +122 -0
- package/src/analysis/index.ts +479 -0
- package/src/ast-builder/command-mappers.ts +1133 -0
- package/src/ast-builder/expression-parser/index.ts +41 -0
- package/src/ast-builder/expression-parser/parser.ts +563 -0
- package/src/ast-builder/expression-parser/tokenizer.ts +394 -0
- package/src/ast-builder/expression-parser/types.ts +208 -0
- package/src/ast-builder/index.ts +536 -0
- package/src/ast-builder/value-converters.ts +172 -0
- package/src/bridge.ts +275 -0
- package/src/browser-ar.ts +162 -0
- package/src/browser-core.ts +231 -0
- package/src/browser-de.ts +162 -0
- package/src/browser-east-asian.ts +173 -0
- package/src/browser-en-tr.ts +165 -0
- package/src/browser-en.ts +157 -0
- package/src/browser-es-en.ts +200 -0
- package/src/browser-es.ts +170 -0
- package/src/browser-fr.ts +162 -0
- package/src/browser-id.ts +162 -0
- package/src/browser-ja.ts +162 -0
- package/src/browser-ko.ts +162 -0
- package/src/browser-lazy.ts +189 -0
- package/src/browser-priority.ts +214 -0
- package/src/browser-pt.ts +162 -0
- package/src/browser-qu.ts +162 -0
- package/src/browser-sw.ts +162 -0
- package/src/browser-tr.ts +162 -0
- package/src/browser-western.ts +181 -0
- package/src/browser-zh.ts +162 -0
- package/src/browser.ts +268 -0
- package/src/cache/index.ts +14 -0
- package/src/cache/semantic-cache.ts +344 -0
- package/src/core-bridge.ts +372 -0
- package/src/explicit/converter.ts +258 -0
- package/src/explicit/index.ts +18 -0
- package/src/explicit/parser.ts +236 -0
- package/src/explicit/renderer.ts +424 -0
- package/src/generators/command-schemas.ts +1636 -0
- package/src/generators/event-handler-generator.ts +109 -0
- package/src/generators/index.ts +117 -0
- package/src/generators/language-profiles.ts +139 -0
- package/src/generators/pattern-generator.ts +537 -0
- package/src/generators/profiles/arabic.ts +131 -0
- package/src/generators/profiles/bengali.ts +132 -0
- package/src/generators/profiles/chinese.ts +124 -0
- package/src/generators/profiles/english.ts +113 -0
- package/src/generators/profiles/french.ts +125 -0
- package/src/generators/profiles/german.ts +126 -0
- package/src/generators/profiles/hindi.ts +146 -0
- package/src/generators/profiles/index.ts +46 -0
- package/src/generators/profiles/indonesian.ts +125 -0
- package/src/generators/profiles/italian.ts +139 -0
- package/src/generators/profiles/japanese.ts +149 -0
- package/src/generators/profiles/korean.ts +127 -0
- package/src/generators/profiles/marker-templates.ts +288 -0
- package/src/generators/profiles/ms.ts +130 -0
- package/src/generators/profiles/polish.ts +249 -0
- package/src/generators/profiles/portuguese.ts +115 -0
- package/src/generators/profiles/quechua.ts +113 -0
- package/src/generators/profiles/russian.ts +260 -0
- package/src/generators/profiles/spanish.ts +130 -0
- package/src/generators/profiles/swahili.ts +129 -0
- package/src/generators/profiles/thai.ts +132 -0
- package/src/generators/profiles/tl.ts +128 -0
- package/src/generators/profiles/turkish.ts +124 -0
- package/src/generators/profiles/types.ts +165 -0
- package/src/generators/profiles/ukrainian.ts +270 -0
- package/src/generators/profiles/vietnamese.ts +133 -0
- package/src/generators/schema-error-codes.ts +160 -0
- package/src/generators/schema-validator.ts +391 -0
- package/src/index.ts +429 -0
- package/src/language-building-schema.ts +3170 -0
- package/src/language-loader.ts +394 -0
- package/src/languages/_all.ts +65 -0
- package/src/languages/ar.ts +15 -0
- package/src/languages/bn.ts +16 -0
- package/src/languages/de.ts +15 -0
- package/src/languages/en.ts +29 -0
- package/src/languages/es.ts +15 -0
- package/src/languages/fr.ts +15 -0
- package/src/languages/hi.ts +26 -0
- package/src/languages/id.ts +15 -0
- package/src/languages/index.ts +18 -0
- package/src/languages/it.ts +15 -0
- package/src/languages/ja.ts +15 -0
- package/src/languages/ko.ts +15 -0
- package/src/languages/ms.ts +16 -0
- package/src/languages/pl.ts +18 -0
- package/src/languages/pt.ts +15 -0
- package/src/languages/qu.ts +15 -0
- package/src/languages/ru.ts +26 -0
- package/src/languages/sw.ts +15 -0
- package/src/languages/th.ts +16 -0
- package/src/languages/tl.ts +16 -0
- package/src/languages/tr.ts +15 -0
- package/src/languages/uk.ts +26 -0
- package/src/languages/vi.ts +16 -0
- package/src/languages/zh.ts +15 -0
- package/src/parser/index.ts +15 -0
- package/src/parser/pattern-matcher.ts +1181 -0
- package/src/parser/semantic-parser.ts +573 -0
- package/src/parser/utils/index.ts +35 -0
- package/src/parser/utils/marker-resolution.ts +111 -0
- package/src/parser/utils/possessive-keywords.ts +43 -0
- package/src/parser/utils/role-positioning.ts +70 -0
- package/src/parser/utils/type-validation.ts +134 -0
- package/src/patterns/add/ar.ts +71 -0
- package/src/patterns/add/bn.ts +70 -0
- package/src/patterns/add/hi.ts +69 -0
- package/src/patterns/add/index.ts +87 -0
- package/src/patterns/add/it.ts +61 -0
- package/src/patterns/add/ja.ts +93 -0
- package/src/patterns/add/ko.ts +74 -0
- package/src/patterns/add/ms.ts +30 -0
- package/src/patterns/add/pl.ts +62 -0
- package/src/patterns/add/ru.ts +62 -0
- package/src/patterns/add/th.ts +49 -0
- package/src/patterns/add/tl.ts +30 -0
- package/src/patterns/add/tr.ts +71 -0
- package/src/patterns/add/uk.ts +62 -0
- package/src/patterns/add/vi.ts +61 -0
- package/src/patterns/add/zh.ts +71 -0
- package/src/patterns/builders.ts +207 -0
- package/src/patterns/decrement/bn.ts +70 -0
- package/src/patterns/decrement/de.ts +42 -0
- package/src/patterns/decrement/hi.ts +68 -0
- package/src/patterns/decrement/index.ts +79 -0
- package/src/patterns/decrement/it.ts +69 -0
- package/src/patterns/decrement/ms.ts +30 -0
- package/src/patterns/decrement/pl.ts +58 -0
- package/src/patterns/decrement/ru.ts +58 -0
- package/src/patterns/decrement/th.ts +49 -0
- package/src/patterns/decrement/tl.ts +30 -0
- package/src/patterns/decrement/tr.ts +48 -0
- package/src/patterns/decrement/uk.ts +58 -0
- package/src/patterns/decrement/vi.ts +61 -0
- package/src/patterns/decrement/zh.ts +32 -0
- package/src/patterns/en.ts +302 -0
- package/src/patterns/event-handler/ar.ts +151 -0
- package/src/patterns/event-handler/bn.ts +72 -0
- package/src/patterns/event-handler/de.ts +117 -0
- package/src/patterns/event-handler/en.ts +117 -0
- package/src/patterns/event-handler/es.ts +136 -0
- package/src/patterns/event-handler/fr.ts +117 -0
- package/src/patterns/event-handler/hi.ts +64 -0
- package/src/patterns/event-handler/id.ts +117 -0
- package/src/patterns/event-handler/index.ts +119 -0
- package/src/patterns/event-handler/it.ts +54 -0
- package/src/patterns/event-handler/ja.ts +118 -0
- package/src/patterns/event-handler/ko.ts +133 -0
- package/src/patterns/event-handler/ms.ts +30 -0
- package/src/patterns/event-handler/pl.ts +62 -0
- package/src/patterns/event-handler/pt.ts +117 -0
- package/src/patterns/event-handler/qu.ts +66 -0
- package/src/patterns/event-handler/ru.ts +62 -0
- package/src/patterns/event-handler/shared.ts +270 -0
- package/src/patterns/event-handler/sw.ts +117 -0
- package/src/patterns/event-handler/th.ts +53 -0
- package/src/patterns/event-handler/tl.ts +30 -0
- package/src/patterns/event-handler/tr.ts +170 -0
- package/src/patterns/event-handler/uk.ts +62 -0
- package/src/patterns/event-handler/vi.ts +61 -0
- package/src/patterns/event-handler/zh.ts +150 -0
- package/src/patterns/get/ar.ts +49 -0
- package/src/patterns/get/bn.ts +47 -0
- package/src/patterns/get/de.ts +32 -0
- package/src/patterns/get/hi.ts +52 -0
- package/src/patterns/get/index.ts +83 -0
- package/src/patterns/get/it.ts +56 -0
- package/src/patterns/get/ja.ts +53 -0
- package/src/patterns/get/ko.ts +53 -0
- package/src/patterns/get/ms.ts +30 -0
- package/src/patterns/get/pl.ts +57 -0
- package/src/patterns/get/ru.ts +57 -0
- package/src/patterns/get/th.ts +29 -0
- package/src/patterns/get/tl.ts +30 -0
- package/src/patterns/get/uk.ts +57 -0
- package/src/patterns/get/vi.ts +48 -0
- package/src/patterns/grammar-transformed/index.ts +39 -0
- package/src/patterns/grammar-transformed/ja.ts +1713 -0
- package/src/patterns/grammar-transformed/ko.ts +1311 -0
- package/src/patterns/grammar-transformed/tr.ts +1067 -0
- package/src/patterns/hide/ar.ts +67 -0
- package/src/patterns/hide/bn.ts +47 -0
- package/src/patterns/hide/de.ts +36 -0
- package/src/patterns/hide/hi.ts +61 -0
- package/src/patterns/hide/index.ts +91 -0
- package/src/patterns/hide/it.ts +56 -0
- package/src/patterns/hide/ja.ts +69 -0
- package/src/patterns/hide/ko.ts +69 -0
- package/src/patterns/hide/ms.ts +30 -0
- package/src/patterns/hide/pl.ts +57 -0
- package/src/patterns/hide/ru.ts +57 -0
- package/src/patterns/hide/th.ts +29 -0
- package/src/patterns/hide/tl.ts +30 -0
- package/src/patterns/hide/tr.ts +65 -0
- package/src/patterns/hide/uk.ts +57 -0
- package/src/patterns/hide/vi.ts +56 -0
- package/src/patterns/hide/zh.ts +68 -0
- package/src/patterns/increment/bn.ts +70 -0
- package/src/patterns/increment/de.ts +36 -0
- package/src/patterns/increment/hi.ts +68 -0
- package/src/patterns/increment/index.ts +79 -0
- package/src/patterns/increment/it.ts +69 -0
- package/src/patterns/increment/ms.ts +30 -0
- package/src/patterns/increment/pl.ts +58 -0
- package/src/patterns/increment/ru.ts +58 -0
- package/src/patterns/increment/th.ts +49 -0
- package/src/patterns/increment/tl.ts +30 -0
- package/src/patterns/increment/tr.ts +52 -0
- package/src/patterns/increment/uk.ts +58 -0
- package/src/patterns/increment/vi.ts +61 -0
- package/src/patterns/increment/zh.ts +32 -0
- package/src/patterns/index.ts +84 -0
- package/src/patterns/languages/en/control-flow.ts +93 -0
- package/src/patterns/languages/en/fetch.ts +62 -0
- package/src/patterns/languages/en/index.ts +42 -0
- package/src/patterns/languages/en/repeat.ts +67 -0
- package/src/patterns/languages/en/set.ts +48 -0
- package/src/patterns/languages/en/swap.ts +38 -0
- package/src/patterns/languages/en/temporal.ts +57 -0
- package/src/patterns/put/ar.ts +74 -0
- package/src/patterns/put/bn.ts +53 -0
- package/src/patterns/put/en.ts +74 -0
- package/src/patterns/put/es.ts +74 -0
- package/src/patterns/put/hi.ts +69 -0
- package/src/patterns/put/id.ts +96 -0
- package/src/patterns/put/index.ts +99 -0
- package/src/patterns/put/it.ts +56 -0
- package/src/patterns/put/ja.ts +75 -0
- package/src/patterns/put/ko.ts +67 -0
- package/src/patterns/put/ms.ts +30 -0
- package/src/patterns/put/pl.ts +81 -0
- package/src/patterns/put/ru.ts +85 -0
- package/src/patterns/put/th.ts +32 -0
- package/src/patterns/put/tl.ts +30 -0
- package/src/patterns/put/tr.ts +67 -0
- package/src/patterns/put/uk.ts +85 -0
- package/src/patterns/put/vi.ts +72 -0
- package/src/patterns/put/zh.ts +62 -0
- package/src/patterns/registry.ts +163 -0
- package/src/patterns/remove/ar.ts +71 -0
- package/src/patterns/remove/bn.ts +68 -0
- package/src/patterns/remove/hi.ts +69 -0
- package/src/patterns/remove/index.ts +87 -0
- package/src/patterns/remove/it.ts +69 -0
- package/src/patterns/remove/ja.ts +74 -0
- package/src/patterns/remove/ko.ts +78 -0
- package/src/patterns/remove/ms.ts +30 -0
- package/src/patterns/remove/pl.ts +62 -0
- package/src/patterns/remove/ru.ts +62 -0
- package/src/patterns/remove/th.ts +49 -0
- package/src/patterns/remove/tl.ts +30 -0
- package/src/patterns/remove/tr.ts +78 -0
- package/src/patterns/remove/uk.ts +62 -0
- package/src/patterns/remove/vi.ts +61 -0
- package/src/patterns/remove/zh.ts +72 -0
- package/src/patterns/set/ar.ts +84 -0
- package/src/patterns/set/bn.ts +53 -0
- package/src/patterns/set/de.ts +84 -0
- package/src/patterns/set/es.ts +92 -0
- package/src/patterns/set/fr.ts +88 -0
- package/src/patterns/set/hi.ts +56 -0
- package/src/patterns/set/id.ts +84 -0
- package/src/patterns/set/index.ts +107 -0
- package/src/patterns/set/it.ts +56 -0
- package/src/patterns/set/ja.ts +86 -0
- package/src/patterns/set/ko.ts +85 -0
- package/src/patterns/set/ms.ts +30 -0
- package/src/patterns/set/pl.ts +57 -0
- package/src/patterns/set/pt.ts +84 -0
- package/src/patterns/set/ru.ts +57 -0
- package/src/patterns/set/th.ts +31 -0
- package/src/patterns/set/tl.ts +30 -0
- package/src/patterns/set/tr.ts +107 -0
- package/src/patterns/set/uk.ts +57 -0
- package/src/patterns/set/vi.ts +53 -0
- package/src/patterns/set/zh.ts +84 -0
- package/src/patterns/show/ar.ts +67 -0
- package/src/patterns/show/bn.ts +47 -0
- package/src/patterns/show/de.ts +32 -0
- package/src/patterns/show/fr.ts +32 -0
- package/src/patterns/show/hi.ts +61 -0
- package/src/patterns/show/index.ts +95 -0
- package/src/patterns/show/it.ts +56 -0
- package/src/patterns/show/ja.ts +69 -0
- package/src/patterns/show/ko.ts +73 -0
- package/src/patterns/show/ms.ts +30 -0
- package/src/patterns/show/pl.ts +57 -0
- package/src/patterns/show/ru.ts +57 -0
- package/src/patterns/show/th.ts +29 -0
- package/src/patterns/show/tl.ts +30 -0
- package/src/patterns/show/tr.ts +65 -0
- package/src/patterns/show/uk.ts +57 -0
- package/src/patterns/show/vi.ts +56 -0
- package/src/patterns/show/zh.ts +68 -0
- package/src/patterns/take/ar.ts +51 -0
- package/src/patterns/take/index.ts +31 -0
- package/src/patterns/toggle/ar.ts +61 -0
- package/src/patterns/toggle/bn.ts +70 -0
- package/src/patterns/toggle/en.ts +61 -0
- package/src/patterns/toggle/es.ts +61 -0
- package/src/patterns/toggle/hi.ts +80 -0
- package/src/patterns/toggle/index.ts +95 -0
- package/src/patterns/toggle/it.ts +69 -0
- package/src/patterns/toggle/ja.ts +156 -0
- package/src/patterns/toggle/ko.ts +113 -0
- package/src/patterns/toggle/ms.ts +30 -0
- package/src/patterns/toggle/pl.ts +62 -0
- package/src/patterns/toggle/ru.ts +62 -0
- package/src/patterns/toggle/th.ts +50 -0
- package/src/patterns/toggle/tl.ts +30 -0
- package/src/patterns/toggle/tr.ts +88 -0
- package/src/patterns/toggle/uk.ts +62 -0
- package/src/patterns/toggle/vi.ts +61 -0
- package/src/patterns/toggle/zh.ts +99 -0
- package/src/public-api.ts +286 -0
- package/src/registry.ts +441 -0
- package/src/tokenizers/arabic.ts +723 -0
- package/src/tokenizers/base.ts +1300 -0
- package/src/tokenizers/bengali.ts +289 -0
- package/src/tokenizers/chinese.ts +481 -0
- package/src/tokenizers/english.ts +416 -0
- package/src/tokenizers/french.ts +326 -0
- package/src/tokenizers/german.ts +324 -0
- package/src/tokenizers/hindi.ts +319 -0
- package/src/tokenizers/index.ts +127 -0
- package/src/tokenizers/indonesian.ts +306 -0
- package/src/tokenizers/italian.ts +458 -0
- package/src/tokenizers/japanese.ts +447 -0
- package/src/tokenizers/korean.ts +642 -0
- package/src/tokenizers/morphology/arabic-normalizer.ts +242 -0
- package/src/tokenizers/morphology/french-normalizer.ts +268 -0
- package/src/tokenizers/morphology/german-normalizer.ts +256 -0
- package/src/tokenizers/morphology/index.ts +46 -0
- package/src/tokenizers/morphology/italian-normalizer.ts +329 -0
- package/src/tokenizers/morphology/japanese-normalizer.ts +288 -0
- package/src/tokenizers/morphology/korean-normalizer.ts +428 -0
- package/src/tokenizers/morphology/polish-normalizer.ts +264 -0
- package/src/tokenizers/morphology/portuguese-normalizer.ts +310 -0
- package/src/tokenizers/morphology/spanish-normalizer.ts +327 -0
- package/src/tokenizers/morphology/turkish-normalizer.ts +412 -0
- package/src/tokenizers/morphology/types.ts +211 -0
- package/src/tokenizers/ms.ts +198 -0
- package/src/tokenizers/polish.ts +354 -0
- package/src/tokenizers/portuguese.ts +304 -0
- package/src/tokenizers/quechua.ts +339 -0
- package/src/tokenizers/russian.ts +375 -0
- package/src/tokenizers/spanish.ts +403 -0
- package/src/tokenizers/swahili.ts +303 -0
- package/src/tokenizers/thai.ts +236 -0
- package/src/tokenizers/tl.ts +198 -0
- package/src/tokenizers/turkish.ts +411 -0
- package/src/tokenizers/ukrainian.ts +369 -0
- package/src/tokenizers/vietnamese.ts +410 -0
- package/src/types/grammar-types.ts +617 -0
- package/src/types/unified-profile.ts +267 -0
- package/src/types.ts +709 -0
- package/src/utils/confidence-calculator.ts +147 -0
- package/src/validators/command-validator.ts +380 -0
- package/src/validators/index.ts +15 -0
|
@@ -0,0 +1,1133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command-specific AST Mappers
|
|
3
|
+
*
|
|
4
|
+
* Each command can have a custom mapper that knows how to convert
|
|
5
|
+
* its semantic roles to the appropriate AST structure.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { CommandSemanticNode, ActionType, SemanticValue, SemanticRole } from '../types';
|
|
9
|
+
import { convertValue } from './value-converters';
|
|
10
|
+
import type { ASTBuilder, CommandNode } from './index';
|
|
11
|
+
import type { ExpressionNode } from './expression-parser';
|
|
12
|
+
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// Command Mapper Interface
|
|
15
|
+
// =============================================================================
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Result from command mapping, including the AST and any warnings.
|
|
19
|
+
*/
|
|
20
|
+
export interface CommandMapperResult {
|
|
21
|
+
ast: CommandNode;
|
|
22
|
+
warnings: string[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Interface for command-specific AST mappers.
|
|
27
|
+
*/
|
|
28
|
+
export interface CommandMapper {
|
|
29
|
+
/**
|
|
30
|
+
* The action type this mapper handles.
|
|
31
|
+
*/
|
|
32
|
+
readonly action: ActionType;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Convert a CommandSemanticNode to a CommandNode.
|
|
36
|
+
*
|
|
37
|
+
* @param node - The semantic command node
|
|
38
|
+
* @param builder - The AST builder (for recursive building if needed)
|
|
39
|
+
* @returns The AST command node with any warnings, or just the AST node for backward compatibility
|
|
40
|
+
*/
|
|
41
|
+
toAST(node: CommandSemanticNode, builder: ASTBuilder): CommandMapperResult | CommandNode;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// =============================================================================
|
|
45
|
+
// Helper Functions
|
|
46
|
+
// =============================================================================
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Get a semantic value from a node's roles, returning undefined if not present.
|
|
50
|
+
*/
|
|
51
|
+
function getRole(node: CommandSemanticNode, role: SemanticRole): SemanticValue | undefined {
|
|
52
|
+
return node.roles.get(role);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Convert a semantic value to an AST expression, or return undefined.
|
|
57
|
+
*
|
|
58
|
+
* @param node - The semantic node containing roles
|
|
59
|
+
* @param role - The semantic role to extract
|
|
60
|
+
* @param warnings - Optional array to collect warnings
|
|
61
|
+
*/
|
|
62
|
+
function convertRoleValue(
|
|
63
|
+
node: CommandSemanticNode,
|
|
64
|
+
role: SemanticRole,
|
|
65
|
+
warnings?: string[]
|
|
66
|
+
): ExpressionNode | undefined {
|
|
67
|
+
const value = getRole(node, role);
|
|
68
|
+
return value ? convertValue(value, warnings) : undefined;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Create a basic command node with standard structure.
|
|
73
|
+
* Handles exactOptionalPropertyTypes by not including undefined properties.
|
|
74
|
+
*/
|
|
75
|
+
function createCommandNode(
|
|
76
|
+
name: string,
|
|
77
|
+
args: ExpressionNode[] = [],
|
|
78
|
+
modifiers?: Record<string, ExpressionNode>,
|
|
79
|
+
options: { isBlocking?: boolean; implicitTarget?: ExpressionNode } = {}
|
|
80
|
+
): CommandNode {
|
|
81
|
+
const result: CommandNode = {
|
|
82
|
+
type: 'command',
|
|
83
|
+
name,
|
|
84
|
+
args,
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Only add optional properties if they have values (exactOptionalPropertyTypes)
|
|
88
|
+
if (modifiers && Object.keys(modifiers).length > 0) {
|
|
89
|
+
(result as { modifiers: Record<string, ExpressionNode> }).modifiers = modifiers;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (options.isBlocking) {
|
|
93
|
+
(result as { isBlocking: boolean }).isBlocking = options.isBlocking;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (options.implicitTarget) {
|
|
97
|
+
(result as { implicitTarget: ExpressionNode }).implicitTarget = options.implicitTarget;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// =============================================================================
|
|
104
|
+
// Command Mappers
|
|
105
|
+
// =============================================================================
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Toggle command mapper.
|
|
109
|
+
*
|
|
110
|
+
* Semantic: toggle patient:.active destination:#button
|
|
111
|
+
* AST: { name: 'toggle', args: ['.active'], modifiers: { on: '#button' } }
|
|
112
|
+
*/
|
|
113
|
+
const toggleMapper: CommandMapper = {
|
|
114
|
+
action: 'toggle',
|
|
115
|
+
toAST(node, _builder) {
|
|
116
|
+
const patient = convertRoleValue(node, 'patient');
|
|
117
|
+
const destination = convertRoleValue(node, 'destination');
|
|
118
|
+
const duration = convertRoleValue(node, 'duration');
|
|
119
|
+
|
|
120
|
+
const args: ExpressionNode[] = patient ? [patient] : [];
|
|
121
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
122
|
+
|
|
123
|
+
if (destination) modifiers['on'] = destination;
|
|
124
|
+
if (duration) modifiers['for'] = duration;
|
|
125
|
+
|
|
126
|
+
return createCommandNode('toggle', args, modifiers);
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Add command mapper.
|
|
132
|
+
*
|
|
133
|
+
* Semantic: add patient:.active destination:#button
|
|
134
|
+
* AST: { name: 'add', args: ['.active'], modifiers: { to: '#button' } }
|
|
135
|
+
*/
|
|
136
|
+
const addMapper: CommandMapper = {
|
|
137
|
+
action: 'add',
|
|
138
|
+
toAST(node, _builder) {
|
|
139
|
+
const patient = convertRoleValue(node, 'patient');
|
|
140
|
+
const destination = convertRoleValue(node, 'destination');
|
|
141
|
+
|
|
142
|
+
const args: ExpressionNode[] = patient ? [patient] : [];
|
|
143
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
144
|
+
|
|
145
|
+
if (destination) modifiers['to'] = destination;
|
|
146
|
+
|
|
147
|
+
return createCommandNode('add', args, modifiers);
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Remove command mapper.
|
|
153
|
+
*
|
|
154
|
+
* Semantic: remove patient:.active source:#button
|
|
155
|
+
* AST: { name: 'remove', args: ['.active'], modifiers: { from: '#button' } }
|
|
156
|
+
*/
|
|
157
|
+
const removeMapper: CommandMapper = {
|
|
158
|
+
action: 'remove',
|
|
159
|
+
toAST(node, _builder) {
|
|
160
|
+
const patient = convertRoleValue(node, 'patient');
|
|
161
|
+
const source = convertRoleValue(node, 'source');
|
|
162
|
+
|
|
163
|
+
const args: ExpressionNode[] = patient ? [patient] : [];
|
|
164
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
165
|
+
|
|
166
|
+
if (source) modifiers['from'] = source;
|
|
167
|
+
|
|
168
|
+
return createCommandNode('remove', args, modifiers);
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Set command mapper.
|
|
174
|
+
*
|
|
175
|
+
* Semantic: set destination:#element's value patient:"hello"
|
|
176
|
+
* AST: { name: 'set', args: [#element's value], modifiers: { to: "hello" } }
|
|
177
|
+
*
|
|
178
|
+
* Note: The destination typically includes the property path (e.g., #element's value)
|
|
179
|
+
* and patient is the value being set.
|
|
180
|
+
*/
|
|
181
|
+
const setMapper: CommandMapper = {
|
|
182
|
+
action: 'set',
|
|
183
|
+
toAST(node, _builder) {
|
|
184
|
+
const destination = convertRoleValue(node, 'destination');
|
|
185
|
+
const patient = convertRoleValue(node, 'patient');
|
|
186
|
+
|
|
187
|
+
const args: ExpressionNode[] = [];
|
|
188
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
189
|
+
|
|
190
|
+
// The destination is typically the property path to set
|
|
191
|
+
if (destination) {
|
|
192
|
+
args.push(destination);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// The patient is the value being set
|
|
196
|
+
if (patient) modifiers['to'] = patient;
|
|
197
|
+
|
|
198
|
+
return createCommandNode('set', args, modifiers);
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Show command mapper.
|
|
204
|
+
*/
|
|
205
|
+
const showMapper: CommandMapper = {
|
|
206
|
+
action: 'show',
|
|
207
|
+
toAST(node, _builder) {
|
|
208
|
+
const destination = convertRoleValue(node, 'destination');
|
|
209
|
+
const patient = convertRoleValue(node, 'patient');
|
|
210
|
+
const duration = convertRoleValue(node, 'duration');
|
|
211
|
+
|
|
212
|
+
const args: ExpressionNode[] = [];
|
|
213
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
214
|
+
|
|
215
|
+
// Target can be in destination or patient
|
|
216
|
+
const target = destination ?? patient;
|
|
217
|
+
if (target) args.push(target);
|
|
218
|
+
if (duration) modifiers['with'] = duration;
|
|
219
|
+
|
|
220
|
+
return createCommandNode('show', args, modifiers);
|
|
221
|
+
},
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Hide command mapper.
|
|
226
|
+
*/
|
|
227
|
+
const hideMapper: CommandMapper = {
|
|
228
|
+
action: 'hide',
|
|
229
|
+
toAST(node, _builder) {
|
|
230
|
+
const destination = convertRoleValue(node, 'destination');
|
|
231
|
+
const patient = convertRoleValue(node, 'patient');
|
|
232
|
+
const duration = convertRoleValue(node, 'duration');
|
|
233
|
+
|
|
234
|
+
const args: ExpressionNode[] = [];
|
|
235
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
236
|
+
|
|
237
|
+
const target = destination ?? patient;
|
|
238
|
+
if (target) args.push(target);
|
|
239
|
+
if (duration) modifiers['with'] = duration;
|
|
240
|
+
|
|
241
|
+
return createCommandNode('hide', args, modifiers);
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Increment command mapper.
|
|
247
|
+
*
|
|
248
|
+
* Semantic: increment patient:#count quantity:5
|
|
249
|
+
* AST: { name: 'increment', args: [#count], modifiers: { by: 5 } }
|
|
250
|
+
*/
|
|
251
|
+
const incrementMapper: CommandMapper = {
|
|
252
|
+
action: 'increment',
|
|
253
|
+
toAST(node, _builder) {
|
|
254
|
+
const destination = convertRoleValue(node, 'destination');
|
|
255
|
+
const patient = convertRoleValue(node, 'patient');
|
|
256
|
+
const quantity = convertRoleValue(node, 'quantity'); // Amount
|
|
257
|
+
|
|
258
|
+
const args: ExpressionNode[] = [];
|
|
259
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
260
|
+
|
|
261
|
+
const target = destination ?? patient;
|
|
262
|
+
if (target) args.push(target);
|
|
263
|
+
if (quantity) modifiers['by'] = quantity;
|
|
264
|
+
|
|
265
|
+
return createCommandNode('increment', args, modifiers);
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Decrement command mapper.
|
|
271
|
+
*
|
|
272
|
+
* Semantic: decrement patient:#count quantity:5
|
|
273
|
+
* AST: { name: 'decrement', args: [#count], modifiers: { by: 5 } }
|
|
274
|
+
*/
|
|
275
|
+
const decrementMapper: CommandMapper = {
|
|
276
|
+
action: 'decrement',
|
|
277
|
+
toAST(node, _builder) {
|
|
278
|
+
const destination = convertRoleValue(node, 'destination');
|
|
279
|
+
const patient = convertRoleValue(node, 'patient');
|
|
280
|
+
const quantity = convertRoleValue(node, 'quantity');
|
|
281
|
+
|
|
282
|
+
const args: ExpressionNode[] = [];
|
|
283
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
284
|
+
|
|
285
|
+
const target = destination ?? patient;
|
|
286
|
+
if (target) args.push(target);
|
|
287
|
+
if (quantity) modifiers['by'] = quantity;
|
|
288
|
+
|
|
289
|
+
return createCommandNode('decrement', args, modifiers);
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Wait command mapper.
|
|
295
|
+
*/
|
|
296
|
+
const waitMapper: CommandMapper = {
|
|
297
|
+
action: 'wait',
|
|
298
|
+
toAST(node, _builder) {
|
|
299
|
+
const duration = convertRoleValue(node, 'duration');
|
|
300
|
+
|
|
301
|
+
const args: ExpressionNode[] = duration ? [duration] : [];
|
|
302
|
+
|
|
303
|
+
return createCommandNode('wait', args, undefined, { isBlocking: true });
|
|
304
|
+
},
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Log command mapper.
|
|
309
|
+
*
|
|
310
|
+
* Semantic: log patient:"hello"
|
|
311
|
+
* AST: { name: 'log', args: ["hello"] }
|
|
312
|
+
*/
|
|
313
|
+
const logMapper: CommandMapper = {
|
|
314
|
+
action: 'log',
|
|
315
|
+
toAST(node, _builder) {
|
|
316
|
+
const patient = convertRoleValue(node, 'patient');
|
|
317
|
+
|
|
318
|
+
const args: ExpressionNode[] = [];
|
|
319
|
+
if (patient) args.push(patient);
|
|
320
|
+
|
|
321
|
+
return createCommandNode('log', args);
|
|
322
|
+
},
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Put command mapper.
|
|
327
|
+
*
|
|
328
|
+
* Semantic: put patient:"hello" destination:#output method:into
|
|
329
|
+
* AST: { name: 'put', args: ["hello"], modifiers: { into: #output } }
|
|
330
|
+
*/
|
|
331
|
+
const putMapper: CommandMapper = {
|
|
332
|
+
action: 'put',
|
|
333
|
+
toAST(node, _builder) {
|
|
334
|
+
const patient = convertRoleValue(node, 'patient');
|
|
335
|
+
const destination = convertRoleValue(node, 'destination');
|
|
336
|
+
const method = getRole(node, 'method'); // before, after, into, etc.
|
|
337
|
+
|
|
338
|
+
const args: ExpressionNode[] = patient ? [patient] : [];
|
|
339
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
340
|
+
|
|
341
|
+
if (destination) {
|
|
342
|
+
// Determine the preposition based on method or default to 'into'
|
|
343
|
+
const prep = method?.type === 'literal' ? String(method.value) : 'into';
|
|
344
|
+
modifiers[prep] = destination;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return createCommandNode('put', args, modifiers);
|
|
348
|
+
},
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Fetch command mapper.
|
|
353
|
+
*
|
|
354
|
+
* Semantic: fetch source:"/api/data" responseType:json method:GET
|
|
355
|
+
* AST: { name: 'fetch', args: ["/api/data"], modifiers: { as: json, with: GET } }
|
|
356
|
+
*/
|
|
357
|
+
const fetchMapper: CommandMapper = {
|
|
358
|
+
action: 'fetch',
|
|
359
|
+
toAST(node, _builder) {
|
|
360
|
+
const source = convertRoleValue(node, 'source'); // URL
|
|
361
|
+
const method = convertRoleValue(node, 'method'); // GET, POST, etc.
|
|
362
|
+
const responseType = convertRoleValue(node, 'responseType'); // json, text, etc.
|
|
363
|
+
const patient = convertRoleValue(node, 'patient'); // Body
|
|
364
|
+
|
|
365
|
+
const args: ExpressionNode[] = source ? [source] : [];
|
|
366
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
367
|
+
|
|
368
|
+
if (method) modifiers['with'] = method;
|
|
369
|
+
if (responseType) modifiers['as'] = responseType;
|
|
370
|
+
if (patient) modifiers['body'] = patient;
|
|
371
|
+
|
|
372
|
+
return createCommandNode('fetch', args, modifiers, { isBlocking: true });
|
|
373
|
+
},
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Append command mapper.
|
|
378
|
+
*
|
|
379
|
+
* Semantic: append patient:"text" destination:#output
|
|
380
|
+
* AST: { name: 'append', args: ["text"], modifiers: { to: #output } }
|
|
381
|
+
*/
|
|
382
|
+
const appendMapper: CommandMapper = {
|
|
383
|
+
action: 'append',
|
|
384
|
+
toAST(node, _builder) {
|
|
385
|
+
const patient = convertRoleValue(node, 'patient');
|
|
386
|
+
const destination = convertRoleValue(node, 'destination');
|
|
387
|
+
|
|
388
|
+
const args: ExpressionNode[] = patient ? [patient] : [];
|
|
389
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
390
|
+
|
|
391
|
+
if (destination) modifiers['to'] = destination;
|
|
392
|
+
|
|
393
|
+
return createCommandNode('append', args, modifiers);
|
|
394
|
+
},
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Prepend command mapper.
|
|
399
|
+
*
|
|
400
|
+
* Semantic: prepend patient:"text" destination:#output
|
|
401
|
+
* AST: { name: 'prepend', args: ["text"], modifiers: { to: #output } }
|
|
402
|
+
*/
|
|
403
|
+
const prependMapper: CommandMapper = {
|
|
404
|
+
action: 'prepend',
|
|
405
|
+
toAST(node, _builder) {
|
|
406
|
+
const patient = convertRoleValue(node, 'patient');
|
|
407
|
+
const destination = convertRoleValue(node, 'destination');
|
|
408
|
+
|
|
409
|
+
const args: ExpressionNode[] = patient ? [patient] : [];
|
|
410
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
411
|
+
|
|
412
|
+
if (destination) modifiers['to'] = destination;
|
|
413
|
+
|
|
414
|
+
return createCommandNode('prepend', args, modifiers);
|
|
415
|
+
},
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Trigger command mapper.
|
|
420
|
+
*
|
|
421
|
+
* Semantic: trigger event:click destination:#button
|
|
422
|
+
* AST: { name: 'trigger', args: [click], modifiers: { on: #button } }
|
|
423
|
+
*/
|
|
424
|
+
const triggerMapper: CommandMapper = {
|
|
425
|
+
action: 'trigger',
|
|
426
|
+
toAST(node, _builder) {
|
|
427
|
+
const event = convertRoleValue(node, 'event');
|
|
428
|
+
const destination = convertRoleValue(node, 'destination');
|
|
429
|
+
|
|
430
|
+
const args: ExpressionNode[] = event ? [event] : [];
|
|
431
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
432
|
+
|
|
433
|
+
if (destination) modifiers['on'] = destination;
|
|
434
|
+
|
|
435
|
+
return createCommandNode('trigger', args, modifiers);
|
|
436
|
+
},
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Send command mapper.
|
|
441
|
+
*
|
|
442
|
+
* Semantic: send event:customEvent destination:#target patient:{detail}
|
|
443
|
+
* AST: { name: 'send', args: [customEvent], modifiers: { to: #target, detail: ... } }
|
|
444
|
+
*/
|
|
445
|
+
const sendMapper: CommandMapper = {
|
|
446
|
+
action: 'send',
|
|
447
|
+
toAST(node, _builder) {
|
|
448
|
+
const event = convertRoleValue(node, 'event');
|
|
449
|
+
const destination = convertRoleValue(node, 'destination');
|
|
450
|
+
const patient = convertRoleValue(node, 'patient');
|
|
451
|
+
|
|
452
|
+
const args: ExpressionNode[] = event ? [event] : [];
|
|
453
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
454
|
+
|
|
455
|
+
if (destination) modifiers['to'] = destination;
|
|
456
|
+
if (patient) modifiers['detail'] = patient;
|
|
457
|
+
|
|
458
|
+
return createCommandNode('send', args, modifiers);
|
|
459
|
+
},
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Go command mapper (navigation).
|
|
464
|
+
*
|
|
465
|
+
* Semantic: go source:/page destination:url
|
|
466
|
+
* AST: { name: 'go', args: [/page], modifiers: { to: url } }
|
|
467
|
+
*/
|
|
468
|
+
const goMapper: CommandMapper = {
|
|
469
|
+
action: 'go',
|
|
470
|
+
toAST(node, _builder) {
|
|
471
|
+
const source = convertRoleValue(node, 'source');
|
|
472
|
+
const destination = convertRoleValue(node, 'destination');
|
|
473
|
+
|
|
474
|
+
const args: ExpressionNode[] = [];
|
|
475
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
476
|
+
|
|
477
|
+
// Source is the URL/location to navigate to
|
|
478
|
+
if (source) args.push(source);
|
|
479
|
+
if (destination) modifiers['to'] = destination;
|
|
480
|
+
|
|
481
|
+
return createCommandNode('go', args, modifiers);
|
|
482
|
+
},
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Transition command mapper.
|
|
487
|
+
*
|
|
488
|
+
* Semantic: transition patient:*background-color goal:'red' duration:500ms destination:#element
|
|
489
|
+
* AST: { name: 'transition', args: [*background-color], modifiers: { to: 'red', over: 500ms, on: #element } }
|
|
490
|
+
*/
|
|
491
|
+
const transitionMapper: CommandMapper = {
|
|
492
|
+
action: 'transition',
|
|
493
|
+
toAST(node, _builder) {
|
|
494
|
+
const patient = convertRoleValue(node, 'patient');
|
|
495
|
+
const goal = convertRoleValue(node, 'goal');
|
|
496
|
+
const duration = convertRoleValue(node, 'duration');
|
|
497
|
+
const destination = convertRoleValue(node, 'destination');
|
|
498
|
+
|
|
499
|
+
const args: ExpressionNode[] = patient ? [patient] : [];
|
|
500
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
501
|
+
|
|
502
|
+
if (goal) modifiers['to'] = goal;
|
|
503
|
+
if (duration) modifiers['over'] = duration;
|
|
504
|
+
if (destination) modifiers['on'] = destination;
|
|
505
|
+
|
|
506
|
+
return createCommandNode('transition', args, modifiers);
|
|
507
|
+
},
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Focus command mapper.
|
|
512
|
+
*
|
|
513
|
+
* Semantic: focus destination:#input
|
|
514
|
+
* AST: { name: 'focus', args: [], modifiers: { on: #input } }
|
|
515
|
+
*/
|
|
516
|
+
const focusMapper: CommandMapper = {
|
|
517
|
+
action: 'focus',
|
|
518
|
+
toAST(node, _builder) {
|
|
519
|
+
const destination = convertRoleValue(node, 'destination');
|
|
520
|
+
const patient = convertRoleValue(node, 'patient');
|
|
521
|
+
|
|
522
|
+
const args: ExpressionNode[] = [];
|
|
523
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
524
|
+
|
|
525
|
+
// Target can be in destination or patient
|
|
526
|
+
const target = destination ?? patient;
|
|
527
|
+
if (target) args.push(target);
|
|
528
|
+
|
|
529
|
+
return createCommandNode('focus', args, modifiers);
|
|
530
|
+
},
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Blur command mapper.
|
|
535
|
+
*
|
|
536
|
+
* Semantic: blur destination:#input
|
|
537
|
+
* AST: { name: 'blur', args: [#input] }
|
|
538
|
+
*/
|
|
539
|
+
const blurMapper: CommandMapper = {
|
|
540
|
+
action: 'blur',
|
|
541
|
+
toAST(node, _builder) {
|
|
542
|
+
const destination = convertRoleValue(node, 'destination');
|
|
543
|
+
const patient = convertRoleValue(node, 'patient');
|
|
544
|
+
|
|
545
|
+
const args: ExpressionNode[] = [];
|
|
546
|
+
const target = destination ?? patient;
|
|
547
|
+
if (target) args.push(target);
|
|
548
|
+
|
|
549
|
+
return createCommandNode('blur', args);
|
|
550
|
+
},
|
|
551
|
+
};
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Get command mapper.
|
|
555
|
+
*
|
|
556
|
+
* Semantic: get source:myValue
|
|
557
|
+
* AST: { name: 'get', args: [myValue] }
|
|
558
|
+
*/
|
|
559
|
+
const getMapper: CommandMapper = {
|
|
560
|
+
action: 'get',
|
|
561
|
+
toAST(node, _builder) {
|
|
562
|
+
const source = convertRoleValue(node, 'source');
|
|
563
|
+
const patient = convertRoleValue(node, 'patient');
|
|
564
|
+
|
|
565
|
+
const args: ExpressionNode[] = [];
|
|
566
|
+
const value = source ?? patient;
|
|
567
|
+
if (value) args.push(value);
|
|
568
|
+
|
|
569
|
+
return createCommandNode('get', args);
|
|
570
|
+
},
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Take command mapper.
|
|
575
|
+
*
|
|
576
|
+
* Semantic: take patient:.active source:#parent
|
|
577
|
+
* AST: { name: 'take', args: [.active], modifiers: { from: #parent } }
|
|
578
|
+
*/
|
|
579
|
+
const takeMapper: CommandMapper = {
|
|
580
|
+
action: 'take',
|
|
581
|
+
toAST(node, _builder) {
|
|
582
|
+
const patient = convertRoleValue(node, 'patient');
|
|
583
|
+
const source = convertRoleValue(node, 'source');
|
|
584
|
+
|
|
585
|
+
const args: ExpressionNode[] = patient ? [patient] : [];
|
|
586
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
587
|
+
|
|
588
|
+
if (source) modifiers['from'] = source;
|
|
589
|
+
|
|
590
|
+
return createCommandNode('take', args, modifiers);
|
|
591
|
+
},
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Call command mapper.
|
|
596
|
+
*
|
|
597
|
+
* Semantic: call patient:functionName
|
|
598
|
+
* AST: { name: 'call', args: [functionName] }
|
|
599
|
+
*/
|
|
600
|
+
const callMapper: CommandMapper = {
|
|
601
|
+
action: 'call',
|
|
602
|
+
toAST(node, _builder) {
|
|
603
|
+
const patient = convertRoleValue(node, 'patient');
|
|
604
|
+
|
|
605
|
+
const args: ExpressionNode[] = patient ? [patient] : [];
|
|
606
|
+
|
|
607
|
+
return createCommandNode('call', args);
|
|
608
|
+
},
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* Return command mapper.
|
|
613
|
+
*
|
|
614
|
+
* Semantic: return patient:value
|
|
615
|
+
* AST: { name: 'return', args: [value] }
|
|
616
|
+
*/
|
|
617
|
+
const returnMapper: CommandMapper = {
|
|
618
|
+
action: 'return',
|
|
619
|
+
toAST(node, _builder) {
|
|
620
|
+
const patient = convertRoleValue(node, 'patient');
|
|
621
|
+
|
|
622
|
+
const args: ExpressionNode[] = patient ? [patient] : [];
|
|
623
|
+
|
|
624
|
+
return createCommandNode('return', args);
|
|
625
|
+
},
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Halt command mapper.
|
|
630
|
+
*
|
|
631
|
+
* Semantic: halt
|
|
632
|
+
* AST: { name: 'halt', args: [] }
|
|
633
|
+
*/
|
|
634
|
+
const haltMapper: CommandMapper = {
|
|
635
|
+
action: 'halt',
|
|
636
|
+
toAST(_node, _builder) {
|
|
637
|
+
return createCommandNode('halt', []);
|
|
638
|
+
},
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* Throw command mapper.
|
|
643
|
+
*
|
|
644
|
+
* Semantic: throw patient:"error message"
|
|
645
|
+
* AST: { name: 'throw', args: ["error message"] }
|
|
646
|
+
*/
|
|
647
|
+
const throwMapper: CommandMapper = {
|
|
648
|
+
action: 'throw',
|
|
649
|
+
toAST(node, _builder) {
|
|
650
|
+
const patient = convertRoleValue(node, 'patient');
|
|
651
|
+
|
|
652
|
+
const args: ExpressionNode[] = patient ? [patient] : [];
|
|
653
|
+
|
|
654
|
+
return createCommandNode('throw', args);
|
|
655
|
+
},
|
|
656
|
+
};
|
|
657
|
+
|
|
658
|
+
/**
|
|
659
|
+
* Settle command mapper.
|
|
660
|
+
*
|
|
661
|
+
* Semantic: settle destination:#element
|
|
662
|
+
* AST: { name: 'settle', args: [#element] }
|
|
663
|
+
*/
|
|
664
|
+
const settleMapper: CommandMapper = {
|
|
665
|
+
action: 'settle',
|
|
666
|
+
toAST(node, _builder) {
|
|
667
|
+
const destination = convertRoleValue(node, 'destination');
|
|
668
|
+
const patient = convertRoleValue(node, 'patient');
|
|
669
|
+
|
|
670
|
+
const args: ExpressionNode[] = [];
|
|
671
|
+
const target = destination ?? patient;
|
|
672
|
+
if (target) args.push(target);
|
|
673
|
+
|
|
674
|
+
return createCommandNode('settle', args, undefined, { isBlocking: true });
|
|
675
|
+
},
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
// =============================================================================
|
|
679
|
+
// Tier 3: Advanced Commands
|
|
680
|
+
// =============================================================================
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* Swap command mapper.
|
|
684
|
+
*
|
|
685
|
+
* Semantic: swap patient:innerHTML destination:#element source:"<p>new</p>"
|
|
686
|
+
* AST: { name: 'swap', args: [innerHTML, "<p>new</p>"], modifiers: { on: #element } }
|
|
687
|
+
*/
|
|
688
|
+
const swapMapper: CommandMapper = {
|
|
689
|
+
action: 'swap',
|
|
690
|
+
toAST(node, _builder) {
|
|
691
|
+
const patient = convertRoleValue(node, 'patient'); // What to swap (e.g., innerHTML)
|
|
692
|
+
const source = convertRoleValue(node, 'source'); // New content
|
|
693
|
+
const destination = convertRoleValue(node, 'destination'); // Target element
|
|
694
|
+
const style = convertRoleValue(node, 'style'); // Swap strategy (innerHTML, outerHTML, etc.)
|
|
695
|
+
|
|
696
|
+
const args: ExpressionNode[] = [];
|
|
697
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
698
|
+
|
|
699
|
+
if (patient) args.push(patient);
|
|
700
|
+
if (source) args.push(source);
|
|
701
|
+
if (destination) modifiers['on'] = destination;
|
|
702
|
+
if (style) modifiers['with'] = style;
|
|
703
|
+
|
|
704
|
+
return createCommandNode('swap', args, modifiers);
|
|
705
|
+
},
|
|
706
|
+
};
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* Morph command mapper.
|
|
710
|
+
*
|
|
711
|
+
* Semantic: morph destination:#element source:"<div>new</div>"
|
|
712
|
+
* AST: { name: 'morph', args: ["<div>new</div>"], modifiers: { on: #element } }
|
|
713
|
+
*/
|
|
714
|
+
const morphMapper: CommandMapper = {
|
|
715
|
+
action: 'morph',
|
|
716
|
+
toAST(node, _builder) {
|
|
717
|
+
const source = convertRoleValue(node, 'source'); // New HTML
|
|
718
|
+
const destination = convertRoleValue(node, 'destination'); // Target element
|
|
719
|
+
const patient = convertRoleValue(node, 'patient');
|
|
720
|
+
|
|
721
|
+
const args: ExpressionNode[] = [];
|
|
722
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
723
|
+
|
|
724
|
+
const content = source ?? patient;
|
|
725
|
+
if (content) args.push(content);
|
|
726
|
+
if (destination) modifiers['on'] = destination;
|
|
727
|
+
|
|
728
|
+
return createCommandNode('morph', args, modifiers);
|
|
729
|
+
},
|
|
730
|
+
};
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* Clone command mapper.
|
|
734
|
+
*
|
|
735
|
+
* Semantic: clone source:#template destination:#container
|
|
736
|
+
* AST: { name: 'clone', args: [#template], modifiers: { into: #container } }
|
|
737
|
+
*/
|
|
738
|
+
const cloneMapper: CommandMapper = {
|
|
739
|
+
action: 'clone',
|
|
740
|
+
toAST(node, _builder) {
|
|
741
|
+
const source = convertRoleValue(node, 'source'); // Element to clone
|
|
742
|
+
const destination = convertRoleValue(node, 'destination'); // Where to put clone
|
|
743
|
+
const patient = convertRoleValue(node, 'patient');
|
|
744
|
+
|
|
745
|
+
const args: ExpressionNode[] = [];
|
|
746
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
747
|
+
|
|
748
|
+
const target = source ?? patient;
|
|
749
|
+
if (target) args.push(target);
|
|
750
|
+
if (destination) modifiers['into'] = destination;
|
|
751
|
+
|
|
752
|
+
return createCommandNode('clone', args, modifiers);
|
|
753
|
+
},
|
|
754
|
+
};
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Make command mapper.
|
|
758
|
+
*
|
|
759
|
+
* Semantic: make patient:Date
|
|
760
|
+
* AST: { name: 'make', args: [Date] }
|
|
761
|
+
*/
|
|
762
|
+
const makeMapper: CommandMapper = {
|
|
763
|
+
action: 'make',
|
|
764
|
+
toAST(node, _builder) {
|
|
765
|
+
const patient = convertRoleValue(node, 'patient'); // Constructor/type
|
|
766
|
+
|
|
767
|
+
const args: ExpressionNode[] = patient ? [patient] : [];
|
|
768
|
+
|
|
769
|
+
return createCommandNode('make', args);
|
|
770
|
+
},
|
|
771
|
+
};
|
|
772
|
+
|
|
773
|
+
/**
|
|
774
|
+
* Measure command mapper.
|
|
775
|
+
*
|
|
776
|
+
* Semantic: measure destination:#element patient:width
|
|
777
|
+
* AST: { name: 'measure', args: [width], modifiers: { of: #element } }
|
|
778
|
+
*/
|
|
779
|
+
const measureMapper: CommandMapper = {
|
|
780
|
+
action: 'measure',
|
|
781
|
+
toAST(node, _builder) {
|
|
782
|
+
const patient = convertRoleValue(node, 'patient'); // What to measure
|
|
783
|
+
const destination = convertRoleValue(node, 'destination'); // Element
|
|
784
|
+
const source = convertRoleValue(node, 'source');
|
|
785
|
+
|
|
786
|
+
const args: ExpressionNode[] = [];
|
|
787
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
788
|
+
|
|
789
|
+
if (patient) args.push(patient);
|
|
790
|
+
const element = destination ?? source;
|
|
791
|
+
if (element) modifiers['of'] = element;
|
|
792
|
+
|
|
793
|
+
return createCommandNode('measure', args, modifiers);
|
|
794
|
+
},
|
|
795
|
+
};
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* Tell command mapper.
|
|
799
|
+
*
|
|
800
|
+
* Semantic: tell destination:#element
|
|
801
|
+
* AST: { name: 'tell', args: [#element] }
|
|
802
|
+
*/
|
|
803
|
+
const tellMapper: CommandMapper = {
|
|
804
|
+
action: 'tell',
|
|
805
|
+
toAST(node, _builder) {
|
|
806
|
+
const destination = convertRoleValue(node, 'destination');
|
|
807
|
+
const patient = convertRoleValue(node, 'patient');
|
|
808
|
+
|
|
809
|
+
const args: ExpressionNode[] = [];
|
|
810
|
+
const target = destination ?? patient;
|
|
811
|
+
if (target) args.push(target);
|
|
812
|
+
|
|
813
|
+
return createCommandNode('tell', args);
|
|
814
|
+
},
|
|
815
|
+
};
|
|
816
|
+
|
|
817
|
+
/**
|
|
818
|
+
* JS command mapper (inline JavaScript).
|
|
819
|
+
*
|
|
820
|
+
* Semantic: js patient:"console.log('hello')"
|
|
821
|
+
* AST: { name: 'js', args: ["console.log('hello')"] }
|
|
822
|
+
*/
|
|
823
|
+
const jsMapper: CommandMapper = {
|
|
824
|
+
action: 'js',
|
|
825
|
+
toAST(node, _builder) {
|
|
826
|
+
const patient = convertRoleValue(node, 'patient'); // JS code
|
|
827
|
+
|
|
828
|
+
const args: ExpressionNode[] = patient ? [patient] : [];
|
|
829
|
+
|
|
830
|
+
return createCommandNode('js', args);
|
|
831
|
+
},
|
|
832
|
+
};
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* Async command mapper.
|
|
836
|
+
*
|
|
837
|
+
* Semantic: async
|
|
838
|
+
* AST: { name: 'async', args: [] }
|
|
839
|
+
*/
|
|
840
|
+
const asyncMapper: CommandMapper = {
|
|
841
|
+
action: 'async',
|
|
842
|
+
toAST(_node, _builder) {
|
|
843
|
+
return createCommandNode('async', []);
|
|
844
|
+
},
|
|
845
|
+
};
|
|
846
|
+
|
|
847
|
+
/**
|
|
848
|
+
* If command mapper.
|
|
849
|
+
*
|
|
850
|
+
* Semantic: if condition:x > 5
|
|
851
|
+
* AST: { name: 'if', args: [], modifiers: { condition: x > 5 } }
|
|
852
|
+
*/
|
|
853
|
+
const ifMapper: CommandMapper = {
|
|
854
|
+
action: 'if',
|
|
855
|
+
toAST(node, _builder) {
|
|
856
|
+
const condition = convertRoleValue(node, 'condition');
|
|
857
|
+
|
|
858
|
+
const args: ExpressionNode[] = condition ? [condition] : [];
|
|
859
|
+
|
|
860
|
+
return createCommandNode('if', args);
|
|
861
|
+
},
|
|
862
|
+
};
|
|
863
|
+
|
|
864
|
+
/**
|
|
865
|
+
* Unless command mapper.
|
|
866
|
+
*
|
|
867
|
+
* Semantic: unless condition:x < 5
|
|
868
|
+
* AST: { name: 'unless', args: [x < 5] }
|
|
869
|
+
*/
|
|
870
|
+
const unlessMapper: CommandMapper = {
|
|
871
|
+
action: 'unless',
|
|
872
|
+
toAST(node, _builder) {
|
|
873
|
+
const condition = convertRoleValue(node, 'condition');
|
|
874
|
+
|
|
875
|
+
const args: ExpressionNode[] = condition ? [condition] : [];
|
|
876
|
+
|
|
877
|
+
return createCommandNode('unless', args);
|
|
878
|
+
},
|
|
879
|
+
};
|
|
880
|
+
|
|
881
|
+
/**
|
|
882
|
+
* Repeat command mapper.
|
|
883
|
+
*
|
|
884
|
+
* Semantic: repeat quantity:5
|
|
885
|
+
* AST: { name: 'repeat', args: [5] }
|
|
886
|
+
*/
|
|
887
|
+
const repeatMapper: CommandMapper = {
|
|
888
|
+
action: 'repeat',
|
|
889
|
+
toAST(node, _builder) {
|
|
890
|
+
const quantity = convertRoleValue(node, 'quantity');
|
|
891
|
+
const patient = convertRoleValue(node, 'patient');
|
|
892
|
+
|
|
893
|
+
const args: ExpressionNode[] = [];
|
|
894
|
+
const count = quantity ?? patient;
|
|
895
|
+
if (count) args.push(count);
|
|
896
|
+
|
|
897
|
+
return createCommandNode('repeat', args);
|
|
898
|
+
},
|
|
899
|
+
};
|
|
900
|
+
|
|
901
|
+
/**
|
|
902
|
+
* For command mapper.
|
|
903
|
+
*
|
|
904
|
+
* Semantic: for patient:item source:items
|
|
905
|
+
* AST: { name: 'for', args: [item], modifiers: { in: items } }
|
|
906
|
+
*/
|
|
907
|
+
const forMapper: CommandMapper = {
|
|
908
|
+
action: 'for',
|
|
909
|
+
toAST(node, _builder) {
|
|
910
|
+
const patient = convertRoleValue(node, 'patient'); // Loop variable
|
|
911
|
+
const source = convertRoleValue(node, 'source'); // Collection
|
|
912
|
+
|
|
913
|
+
const args: ExpressionNode[] = patient ? [patient] : [];
|
|
914
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
915
|
+
|
|
916
|
+
if (source) modifiers['in'] = source;
|
|
917
|
+
|
|
918
|
+
return createCommandNode('for', args, modifiers);
|
|
919
|
+
},
|
|
920
|
+
};
|
|
921
|
+
|
|
922
|
+
/**
|
|
923
|
+
* While command mapper.
|
|
924
|
+
*
|
|
925
|
+
* Semantic: while condition:x < 10
|
|
926
|
+
* AST: { name: 'while', args: [x < 10] }
|
|
927
|
+
*/
|
|
928
|
+
const whileMapper: CommandMapper = {
|
|
929
|
+
action: 'while',
|
|
930
|
+
toAST(node, _builder) {
|
|
931
|
+
const condition = convertRoleValue(node, 'condition');
|
|
932
|
+
|
|
933
|
+
const args: ExpressionNode[] = condition ? [condition] : [];
|
|
934
|
+
|
|
935
|
+
return createCommandNode('while', args);
|
|
936
|
+
},
|
|
937
|
+
};
|
|
938
|
+
|
|
939
|
+
/**
|
|
940
|
+
* Continue command mapper.
|
|
941
|
+
*
|
|
942
|
+
* Semantic: continue
|
|
943
|
+
* AST: { name: 'continue', args: [] }
|
|
944
|
+
*/
|
|
945
|
+
const continueMapper: CommandMapper = {
|
|
946
|
+
action: 'continue',
|
|
947
|
+
toAST(_node, _builder) {
|
|
948
|
+
return createCommandNode('continue', []);
|
|
949
|
+
},
|
|
950
|
+
};
|
|
951
|
+
|
|
952
|
+
/**
|
|
953
|
+
* Default command mapper.
|
|
954
|
+
*
|
|
955
|
+
* Semantic: default patient:myVar source:0
|
|
956
|
+
* AST: { name: 'default', args: [myVar], modifiers: { to: 0 } }
|
|
957
|
+
*/
|
|
958
|
+
const defaultMapper: CommandMapper = {
|
|
959
|
+
action: 'default',
|
|
960
|
+
toAST(node, _builder) {
|
|
961
|
+
const patient = convertRoleValue(node, 'patient'); // Variable
|
|
962
|
+
const source = convertRoleValue(node, 'source'); // Default value
|
|
963
|
+
|
|
964
|
+
const args: ExpressionNode[] = patient ? [patient] : [];
|
|
965
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
966
|
+
|
|
967
|
+
if (source) modifiers['to'] = source;
|
|
968
|
+
|
|
969
|
+
return createCommandNode('default', args, modifiers);
|
|
970
|
+
},
|
|
971
|
+
};
|
|
972
|
+
|
|
973
|
+
/**
|
|
974
|
+
* Init command mapper.
|
|
975
|
+
*
|
|
976
|
+
* Semantic: init
|
|
977
|
+
* AST: { name: 'init', args: [] }
|
|
978
|
+
*/
|
|
979
|
+
const initMapper: CommandMapper = {
|
|
980
|
+
action: 'init',
|
|
981
|
+
toAST(_node, _builder) {
|
|
982
|
+
return createCommandNode('init', []);
|
|
983
|
+
},
|
|
984
|
+
};
|
|
985
|
+
|
|
986
|
+
/**
|
|
987
|
+
* Behavior command mapper.
|
|
988
|
+
*
|
|
989
|
+
* Semantic: behavior patient:MyBehavior
|
|
990
|
+
* AST: { name: 'behavior', args: [MyBehavior] }
|
|
991
|
+
*/
|
|
992
|
+
const behaviorMapper: CommandMapper = {
|
|
993
|
+
action: 'behavior',
|
|
994
|
+
toAST(node, _builder) {
|
|
995
|
+
const patient = convertRoleValue(node, 'patient'); // Behavior name
|
|
996
|
+
|
|
997
|
+
const args: ExpressionNode[] = patient ? [patient] : [];
|
|
998
|
+
|
|
999
|
+
return createCommandNode('behavior', args);
|
|
1000
|
+
},
|
|
1001
|
+
};
|
|
1002
|
+
|
|
1003
|
+
/**
|
|
1004
|
+
* Install command mapper.
|
|
1005
|
+
*
|
|
1006
|
+
* Semantic: install patient:MyBehavior destination:#element
|
|
1007
|
+
* AST: { name: 'install', args: [MyBehavior], modifiers: { on: #element } }
|
|
1008
|
+
*/
|
|
1009
|
+
const installMapper: CommandMapper = {
|
|
1010
|
+
action: 'install',
|
|
1011
|
+
toAST(node, _builder) {
|
|
1012
|
+
const patient = convertRoleValue(node, 'patient'); // Behavior to install
|
|
1013
|
+
const destination = convertRoleValue(node, 'destination'); // Target element
|
|
1014
|
+
|
|
1015
|
+
const args: ExpressionNode[] = patient ? [patient] : [];
|
|
1016
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
1017
|
+
|
|
1018
|
+
if (destination) modifiers['on'] = destination;
|
|
1019
|
+
|
|
1020
|
+
return createCommandNode('install', args, modifiers);
|
|
1021
|
+
},
|
|
1022
|
+
};
|
|
1023
|
+
|
|
1024
|
+
/**
|
|
1025
|
+
* On command mapper (event handler declaration).
|
|
1026
|
+
*
|
|
1027
|
+
* Semantic: on event:click
|
|
1028
|
+
* AST: { name: 'on', args: [click] }
|
|
1029
|
+
*/
|
|
1030
|
+
const onMapper: CommandMapper = {
|
|
1031
|
+
action: 'on',
|
|
1032
|
+
toAST(node, _builder) {
|
|
1033
|
+
const event = convertRoleValue(node, 'event');
|
|
1034
|
+
const source = convertRoleValue(node, 'source'); // 'from' clause
|
|
1035
|
+
|
|
1036
|
+
const args: ExpressionNode[] = event ? [event] : [];
|
|
1037
|
+
const modifiers: Record<string, ExpressionNode> = {};
|
|
1038
|
+
|
|
1039
|
+
if (source) modifiers['from'] = source;
|
|
1040
|
+
|
|
1041
|
+
return createCommandNode('on', args, modifiers);
|
|
1042
|
+
},
|
|
1043
|
+
};
|
|
1044
|
+
|
|
1045
|
+
// =============================================================================
|
|
1046
|
+
// Mapper Registry
|
|
1047
|
+
// =============================================================================
|
|
1048
|
+
|
|
1049
|
+
const mappers: Map<ActionType, CommandMapper> = new Map([
|
|
1050
|
+
// Tier 1: Core commands
|
|
1051
|
+
['toggle', toggleMapper],
|
|
1052
|
+
['add', addMapper],
|
|
1053
|
+
['remove', removeMapper],
|
|
1054
|
+
['set', setMapper],
|
|
1055
|
+
['show', showMapper],
|
|
1056
|
+
['hide', hideMapper],
|
|
1057
|
+
['increment', incrementMapper],
|
|
1058
|
+
['decrement', decrementMapper],
|
|
1059
|
+
['wait', waitMapper],
|
|
1060
|
+
['log', logMapper],
|
|
1061
|
+
['put', putMapper],
|
|
1062
|
+
['fetch', fetchMapper],
|
|
1063
|
+
// Tier 2: Content manipulation
|
|
1064
|
+
['append', appendMapper],
|
|
1065
|
+
['prepend', prependMapper],
|
|
1066
|
+
['get', getMapper],
|
|
1067
|
+
['take', takeMapper],
|
|
1068
|
+
// Tier 2: Events
|
|
1069
|
+
['trigger', triggerMapper],
|
|
1070
|
+
['send', sendMapper],
|
|
1071
|
+
['on', onMapper],
|
|
1072
|
+
// Tier 2: Navigation & DOM
|
|
1073
|
+
['go', goMapper],
|
|
1074
|
+
['transition', transitionMapper],
|
|
1075
|
+
['focus', focusMapper],
|
|
1076
|
+
['blur', blurMapper],
|
|
1077
|
+
// Tier 2: Control flow
|
|
1078
|
+
['call', callMapper],
|
|
1079
|
+
['return', returnMapper],
|
|
1080
|
+
['halt', haltMapper],
|
|
1081
|
+
['throw', throwMapper],
|
|
1082
|
+
['settle', settleMapper],
|
|
1083
|
+
// Tier 3: Advanced DOM
|
|
1084
|
+
['swap', swapMapper],
|
|
1085
|
+
['morph', morphMapper],
|
|
1086
|
+
['clone', cloneMapper],
|
|
1087
|
+
['measure', measureMapper],
|
|
1088
|
+
// Tier 3: Object/Types
|
|
1089
|
+
['make', makeMapper],
|
|
1090
|
+
['tell', tellMapper],
|
|
1091
|
+
['default', defaultMapper],
|
|
1092
|
+
// Tier 3: JavaScript integration
|
|
1093
|
+
['js', jsMapper],
|
|
1094
|
+
['async', asyncMapper],
|
|
1095
|
+
// Tier 3: Conditionals
|
|
1096
|
+
['if', ifMapper],
|
|
1097
|
+
['unless', unlessMapper],
|
|
1098
|
+
// Tier 3: Loops
|
|
1099
|
+
['repeat', repeatMapper],
|
|
1100
|
+
['for', forMapper],
|
|
1101
|
+
['while', whileMapper],
|
|
1102
|
+
['continue', continueMapper],
|
|
1103
|
+
// Tier 3: Behaviors
|
|
1104
|
+
['init', initMapper],
|
|
1105
|
+
['behavior', behaviorMapper],
|
|
1106
|
+
['install', installMapper],
|
|
1107
|
+
]);
|
|
1108
|
+
|
|
1109
|
+
/**
|
|
1110
|
+
* Get the command mapper for an action type.
|
|
1111
|
+
*
|
|
1112
|
+
* @param action - The action type
|
|
1113
|
+
* @returns The mapper, or undefined if no specific mapper exists
|
|
1114
|
+
*/
|
|
1115
|
+
export function getCommandMapper(action: ActionType): CommandMapper | undefined {
|
|
1116
|
+
return mappers.get(action);
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
/**
|
|
1120
|
+
* Register a custom command mapper.
|
|
1121
|
+
*
|
|
1122
|
+
* @param mapper - The command mapper to register
|
|
1123
|
+
*/
|
|
1124
|
+
export function registerCommandMapper(mapper: CommandMapper): void {
|
|
1125
|
+
mappers.set(mapper.action, mapper);
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
/**
|
|
1129
|
+
* Get all registered command mappers.
|
|
1130
|
+
*/
|
|
1131
|
+
export function getRegisteredMappers(): Map<ActionType, CommandMapper> {
|
|
1132
|
+
return new Map(mappers);
|
|
1133
|
+
}
|