@holoscript/core 8.0.8 → 8.0.10
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/bin/holoscript.cjs +5 -1
- package/dist/GLTFPipeline-L76YTXKA.js +15 -0
- package/dist/GLTFPipeline-ZWJN7GI6.cjs +36 -0
- package/dist/HoloCompositionParser-K76KTEEE.js +12 -0
- package/dist/HoloCompositionParser-UZH6Y4HO.cjs +45 -0
- package/dist/HoloScriptCodeParser-2D4ERFUZ.js +6 -0
- package/dist/HoloScriptCodeParser-UDRLDA7I.cjs +23 -0
- package/dist/HoloScriptPlusParser-FTMCGWXD.js +13 -0
- package/dist/HoloScriptPlusParser-LQR5GIKF.cjs +30 -0
- package/dist/HoloScriptRuntime-UTRLJI5L.js +12 -0
- package/dist/HoloScriptRuntime-YBYXJHJN.cjs +21 -0
- package/dist/SceneIRCompiler-63KA3M2F.js +17 -0
- package/dist/SceneIRCompiler-KWUFHZ4O.cjs +42 -0
- package/dist/{USDZExporter-AUHZODOF.cjs → USDZExporter-ML4UMIGC.cjs} +3 -3
- package/dist/{USDZExporter-GXB4AUSG.js → USDZExporter-ZFKLQ76G.js} +3 -3
- package/dist/agents/index.cjs +1 -1
- package/dist/agents/index.js +1 -1
- package/dist/audit/AuditLogger.d.ts +106 -0
- package/dist/audit/AuditQueryBuilder.d.ts +79 -0
- package/dist/audit/ComplianceReporter.d.ts +90 -0
- package/dist/audit/index.d.ts +13 -0
- package/dist/{chunk-FGMDMJM7.js → chunk-2BYAUHBO.js} +3 -3
- package/dist/{chunk-EDPYCLRC.cjs → chunk-2E6PP5UE.cjs} +83 -59
- package/dist/{chunk-GASCWJK5.js → chunk-2EGGAZT3.js} +65 -287
- package/dist/{chunk-SIEXCILW.js → chunk-2I3XAGMF.js} +3 -3
- package/dist/{chunk-OS533P33.cjs → chunk-2KKOYZYI.cjs} +1074 -1655
- package/dist/chunk-2MQKNDNH.js +51 -0
- package/dist/{chunk-7DMMMBCY.cjs → chunk-2X3IPCBK.cjs} +10 -10
- package/dist/chunk-2ZOTBO25.cjs +202 -0
- package/dist/chunk-356N4NPM.cjs +152 -0
- package/dist/{chunk-X3GJPRVK.cjs → chunk-36NPLOI4.cjs} +92 -81
- package/dist/{chunk-SLU6UPJI.cjs → chunk-37HHY7RH.cjs} +5 -5
- package/dist/{chunk-YDPEHCCI.cjs → chunk-3CDDRUER.cjs} +3 -118
- package/dist/chunk-3F7ZZWIN.js +1651 -0
- package/dist/chunk-3ILD7TKP.cjs +187 -0
- package/dist/{chunk-X27QRG4C.cjs → chunk-3IUHTGDD.cjs} +153 -41
- package/dist/{chunk-PXNZ6TME.js → chunk-4376VHNJ.js} +60 -36
- package/dist/{chunk-YKGPCZEE.cjs → chunk-4FIBOJW6.cjs} +10 -10
- package/dist/chunk-4Q7RKQQI.cjs +14195 -0
- package/dist/{chunk-YCM6QQRT.cjs → chunk-566ZB4LZ.cjs} +180 -8
- package/dist/{chunk-2Y3V22SG.js → chunk-5CURIYGT.js} +3 -3
- package/dist/{chunk-QBWNJXNR.js → chunk-5FYMCVBY.js} +5 -5
- package/dist/{chunk-ZA34AN3R.js → chunk-5LVFTGKH.js} +841 -12
- package/dist/{chunk-Z6PMDS4G.js → chunk-5OUOMBKK.js} +1090 -53
- package/dist/chunk-63AUAIL6.js +48 -0
- package/dist/chunk-655FATJU.js +110 -0
- package/dist/{chunk-TQ377OLB.cjs → chunk-65S62L4D.cjs} +28 -22
- package/dist/chunk-6NTAZN5Z.cjs +502 -0
- package/dist/chunk-6TRX6AR2.js +9376 -0
- package/dist/chunk-6ZCCLKS2.cjs +51 -0
- package/dist/{chunk-MDR235RZ.js → chunk-734OB5SK.js} +721 -8
- package/dist/{chunk-Q2Q34NF3.js → chunk-77QI552M.js} +6 -6
- package/dist/{chunk-WKX5AMOY.js → chunk-7I74JWPW.js} +3 -3
- package/dist/{chunk-5FSKKMR7.cjs → chunk-7IDJDMPU.cjs} +232 -4
- package/dist/chunk-7VBKRGIZ.cjs +847 -0
- package/dist/{chunk-KCPHASCO.js → chunk-AATYYLYK.js} +5 -5
- package/dist/{chunk-DTGBOSEM.cjs → chunk-AWXFEAQL.cjs} +12 -12
- package/dist/{chunk-THCK6ECW.js → chunk-B3CWTCK2.js} +231 -3
- package/dist/chunk-BCP4E7MD.cjs +997 -0
- package/dist/chunk-BG7RPYJP.js +91 -0
- package/dist/{chunk-VF257YKO.js → chunk-BP4KTMLY.js} +117 -5
- package/dist/{chunk-YN6IETRZ.js → chunk-BQJ3YBF3.js} +6424 -987
- package/dist/{chunk-7X5PNIQJ.js → chunk-BXSOEQI3.js} +27 -25
- package/dist/{chunk-WFKVS2K4.cjs → chunk-C65C5VED.cjs} +1101 -55
- package/dist/{chunk-KOUAQL2B.cjs → chunk-CANAL6CT.cjs} +1569 -168
- package/dist/{chunk-FDSGHPAK.js → chunk-CBSDJF3B.js} +3 -3
- package/dist/{chunk-FEWUHQNM.cjs → chunk-CFVK26P4.cjs} +4 -4
- package/dist/{chunk-M7K4LE66.cjs → chunk-CI33NINL.cjs} +4 -4
- package/dist/{chunk-2OWDB4FB.js → chunk-CKV5NYAE.js} +6 -6
- package/dist/{chunk-LPS5AMQD.cjs → chunk-CM4NHXVO.cjs} +24 -24
- package/dist/chunk-D3HSRXYB.js +115 -0
- package/dist/{chunk-FNHJRI32.js → chunk-DBH3D2MU.js} +1561 -160
- package/dist/{chunk-GW3LKD5C.js → chunk-DJNH4HFW.js} +3 -3
- package/dist/{chunk-2GCNOI2U.cjs → chunk-DN6F4DHH.cjs} +9 -3
- package/dist/chunk-DQRJ5RJG.js +432 -0
- package/dist/{chunk-C7ZBSV2Q.js → chunk-DUG3OQAS.js} +106 -43
- package/dist/chunk-ECUYJOJ2.cjs +199 -0
- package/dist/chunk-EEMTCAK7.js +182 -0
- package/dist/{chunk-3SKLAUDD.cjs → chunk-EI3J6LTW.cjs} +359 -581
- package/dist/{chunk-SSSN7VAM.js → chunk-EM2OGPYE.js} +4 -4
- package/dist/{chunk-56VOWURB.cjs → chunk-ENZCIQZC.cjs} +522 -453
- package/dist/chunk-ESBXUYOC.cjs +836 -0
- package/dist/{chunk-L5U4W6JC.js → chunk-ESSEF6U2.js} +4 -4
- package/dist/chunk-ET3AN4W3.js +824 -0
- package/dist/chunk-EXKSFGSX.cjs +14 -14
- package/dist/{chunk-I76GIKN7.cjs → chunk-F3YT6GUF.cjs} +17 -17
- package/dist/{chunk-WRWEX5ZF.js → chunk-F75DZBBI.js} +3 -3
- package/dist/{chunk-4JGRWHZJ.js → chunk-FG6PYGIZ.js} +12 -6
- package/dist/chunk-FGGJQRLZ.js +14 -14
- package/dist/{chunk-SXOSDZD6.js → chunk-FWCHPCD4.js} +128 -10
- package/dist/{chunk-XW6IXEQH.cjs → chunk-G35CAQ7I.cjs} +5 -5
- package/dist/{chunk-7VMGP2FW.js → chunk-G6KACNMO.js} +132 -188
- package/dist/{chunk-FJPADH77.cjs → chunk-GAWJJAGT.cjs} +6 -6
- package/dist/chunk-GGR7QUKK.cjs +4724 -0
- package/dist/chunk-GIBF4BHH.js +14098 -0
- package/dist/{chunk-AWB7QYY6.cjs → chunk-GILYQ5VH.cjs} +6 -6
- package/dist/{chunk-FWVYAMNW.cjs → chunk-GKFCHGCM.cjs} +4 -4
- package/dist/{chunk-Y3ZFVUUU.js → chunk-GLEJ2TLS.js} +3 -3
- package/dist/{chunk-3GWWJT7L.js → chunk-GP3OKSKT.js} +13 -13
- package/dist/chunk-GTIPOEHN.js +196 -0
- package/dist/{chunk-LMJ5EBV7.cjs → chunk-GZPUA2TL.cjs} +16 -15
- package/dist/{chunk-IELX2OKI.js → chunk-H4LJ4HEA.js} +3 -115
- package/dist/{chunk-ACVWFGBI.cjs → chunk-HCX4SMFK.cjs} +3 -3
- package/dist/{chunk-HYNTS5CP.js → chunk-HHRZ6STP.js} +24 -2
- package/dist/chunk-HIDEIEFG.js +48 -0
- package/dist/{chunk-W6RW64BB.cjs → chunk-HSWBIDZM.cjs} +228 -5
- package/dist/{chunk-GSOUNWEL.js → chunk-HVX7QQYK.js} +1035 -1616
- package/dist/{chunk-TRCGG42I.cjs → chunk-IFW5IW4L.cjs} +6502 -1019
- package/dist/{chunk-F5LKJ6F5.cjs → chunk-IJU6AS67.cjs} +32 -28
- package/dist/{chunk-TVANHNJ7.js → chunk-IK6Z2HNC.js} +173 -3
- package/dist/{chunk-QGMUTVVH.cjs → chunk-IS7NTKY5.cjs} +20 -20
- package/dist/{chunk-YFVQWSNJ.js → chunk-IXWGYWH6.js} +3 -3
- package/dist/chunk-J2DAS2PL.js +148 -0
- package/dist/chunk-JBQXZIWB.js +148 -0
- package/dist/chunk-JBYBMBMW.js +261 -0
- package/dist/{chunk-LWUOUCYL.js → chunk-JEJ7TT54.js} +5 -5
- package/dist/{chunk-DUCB6LGL.js → chunk-JOTCTHN5.js} +211 -5
- package/dist/{chunk-47RUFYKR.js → chunk-K56UVEXV.js} +3 -3
- package/dist/{chunk-XSFNHP2E.js → chunk-KB26H447.js} +3 -3
- package/dist/{chunk-3NGDZZR4.js → chunk-KEYG7HGY.js} +430 -37
- package/dist/{chunk-DY72BMU5.js → chunk-KFVNCW4Q.js} +4 -4
- package/dist/chunk-KPGC7SK2.js +192 -0
- package/dist/chunk-KROXXBK5.cjs +53 -0
- package/dist/{chunk-ZPZAVHXL.cjs → chunk-LB3ZZMKT.cjs} +137 -19
- package/dist/chunk-LDYZWNJW.cjs +1654 -0
- package/dist/{chunk-UGXHYIWT.cjs → chunk-LHNHO27U.cjs} +28 -28
- package/dist/{chunk-ULMSSHCJ.cjs → chunk-LMB555QB.cjs} +405 -38
- package/dist/{chunk-CBJY23VL.js → chunk-MD4IVS42.js} +3 -3
- package/dist/{chunk-VMLKSV26.js → chunk-MDDWEBCX.js} +226 -3
- package/dist/chunk-MUWH4QK5.cjs +94 -0
- package/dist/{chunk-T6W3Z3SH.cjs → chunk-N2ILK7BF.cjs} +4 -4
- package/dist/{chunk-6EX3I5P4.cjs → chunk-N74QRJGP.cjs} +6 -6
- package/dist/chunk-NFFHLX37.cjs +132 -0
- package/dist/chunk-NJSYWX7H.js +190 -0
- package/dist/{chunk-SH5PPVK7.cjs → chunk-NQN5LFN4.cjs} +165 -221
- package/dist/chunk-NTQRFOPP.cjs +56 -0
- package/dist/{chunk-YFWRJW4B.js → chunk-NWMJPTVL.js} +51 -55
- package/dist/{chunk-63ZGNR2T.cjs → chunk-OC6GV5QH.cjs} +42 -42
- package/dist/{chunk-7E7GCQCK.js → chunk-OG3MBHM3.js} +9 -3
- package/dist/chunk-OMNHTCS4.cjs +264 -0
- package/dist/chunk-OQXB6NNC.cjs +117 -0
- package/dist/{chunk-Y57W2CT5.cjs → chunk-OV46CCA2.cjs} +51 -55
- package/dist/{chunk-6PRZIHGL.cjs → chunk-OV6HHKLE.cjs} +21 -266
- package/dist/{chunk-C37BHB7N.cjs → chunk-P26YYPOO.cjs} +5 -5
- package/dist/{chunk-2BZHWUSR.cjs → chunk-P7JEKJTZ.cjs} +16 -16
- package/dist/{chunk-NGBXXZLL.cjs → chunk-PDXX5UI4.cjs} +45 -45
- package/dist/{chunk-FHQFPYV4.js → chunk-PJFTTSKE.js} +8 -7
- package/dist/{chunk-GVFJ6T4S.cjs → chunk-PVODJEJ7.cjs} +721 -8
- package/dist/{chunk-ZZ7RO2UQ.js → chunk-Q265VZJ4.js} +3 -3
- package/dist/{chunk-E7JP3BS3.cjs → chunk-Q47JEE2C.cjs} +4 -4
- package/dist/chunk-QBY7LRN2.js +281 -0
- package/dist/{chunk-GH6C2QGW.cjs → chunk-QEDMOGF3.cjs} +857 -16
- package/dist/{chunk-5WUNN6ZN.cjs → chunk-QHSAVOOL.cjs} +24 -2
- package/dist/chunk-QJNCDVYM.cjs +137 -0
- package/dist/chunk-QM7FJB5W.js +4717 -0
- package/dist/chunk-QQFB4RT2.cjs +448 -0
- package/dist/chunk-QSYBHQAD.cjs +196 -0
- package/dist/{chunk-2YSNA2F2.cjs → chunk-QVJMDVYZ.cjs} +5 -5
- package/dist/chunk-RAJMAX6D.js +131 -0
- package/dist/{chunk-VVKVQZI6.js → chunk-RAN3ECAS.js} +3 -3
- package/dist/chunk-RKGUZBOC.js +79 -0
- package/dist/{chunk-HLFDZ35S.cjs → chunk-RRQIAJLQ.cjs} +8 -8
- package/dist/{chunk-PABONWKI.js → chunk-RXQNRZ5F.js} +3 -3
- package/dist/{chunk-7ZHYEITD.cjs → chunk-S4O7CFHQ.cjs} +10 -11
- package/dist/chunk-SE7ANBGN.js +128 -0
- package/dist/{chunk-X2AVEAZM.cjs → chunk-SJIRCTIS.cjs} +176 -2
- package/dist/{chunk-WXQ57LAO.js → chunk-SQXAZHDG.js} +4 -4
- package/dist/chunk-SR73L5ZP.cjs +84 -0
- package/dist/{chunk-OABEO6HH.js → chunk-SZOLTWWD.js} +2349 -214
- package/dist/{chunk-5JEU52DW.js → chunk-TPZ3BN2D.js} +3 -3
- package/dist/{chunk-QFU53KRH.js → chunk-TSTFYGGX.js} +4 -5
- package/dist/{chunk-EBS32AJI.cjs → chunk-TZCFKZ6Z.cjs} +5 -5
- package/dist/chunk-UCVZXQ63.js +724 -0
- package/dist/chunk-UGQ3QNV6.js +992 -0
- package/dist/chunk-UNMVGZVW.js +142 -0
- package/dist/{chunk-TEVX443G.js → chunk-UTUD6GJI.js} +178 -6
- package/dist/chunk-UXBYA7DV.cjs +155 -0
- package/dist/chunk-V6GXFSK7.cjs +443 -0
- package/dist/chunk-VHORVGCG.cjs +761 -0
- package/dist/{chunk-B4EKV6HQ.js → chunk-VKCTYLDN.js} +500 -442
- package/dist/{chunk-O3MGZDCT.cjs → chunk-VTEXJOSD.cjs} +63 -63
- package/dist/chunk-VVAAZITA.cjs +287 -0
- package/dist/{chunk-V7AKE5VT.cjs → chunk-W2GA3EQB.cjs} +435 -42
- package/dist/chunk-W4GABFCR.js +37 -0
- package/dist/chunk-WKEK4NCA.js +490 -0
- package/dist/{chunk-5A4TCHOC.cjs → chunk-WNYXT4TE.cjs} +4 -4
- package/dist/{chunk-S762UEV5.js → chunk-WTH23ISI.js} +6 -6
- package/dist/{chunk-BTKZGHAV.js → chunk-WWNCM473.js} +10 -6
- package/dist/{chunk-4YNYPHH3.cjs → chunk-X75H75UY.cjs} +2351 -213
- package/dist/{chunk-LYJJI7ZK.cjs → chunk-XCUDDFKC.cjs} +216 -9
- package/dist/chunk-YAO4HPJL.cjs +120 -0
- package/dist/chunk-YKY2JBER.cjs +9443 -0
- package/dist/chunk-YP5CHEYU.cjs +154 -0
- package/dist/{chunk-WRNEH5MO.js → chunk-YW3I2FQL.js} +18 -7
- package/dist/{chunk-BRNUPDHJ.js → chunk-Z557DVYN.js} +386 -19
- package/dist/{chunk-VSACG2AR.js → chunk-Z6LZUYZF.js} +21 -264
- package/dist/chunk-ZHPMP447.cjs +43 -0
- package/dist/{chunk-LODTHGST.cjs → chunk-ZK7KX5CD.cjs} +133 -70
- package/dist/{chunk-CCPSNT6B.cjs → chunk-ZRPALBQB.cjs} +5 -5
- package/dist/chunk-ZVFHPMC5.js +824 -0
- package/dist/chunk-ZVQMKUGJ.js +443 -0
- package/dist/cli/holoscript-runner.cjs +86 -48
- package/dist/cli/holoscript-runner.js +54 -16
- package/dist/codebase/index.cjs +1 -1
- package/dist/codebase/index.js +1 -1
- package/dist/compiler/agent-inference.cjs +11 -11
- package/dist/compiler/agent-inference.js +9 -6
- package/dist/compiler/android-xr.cjs +13 -12
- package/dist/compiler/android-xr.js +11 -10
- package/dist/compiler/android.cjs +12 -12
- package/dist/compiler/android.js +10 -10
- package/dist/compiler/business-quest.cjs +10 -10
- package/dist/compiler/business-quest.js +2 -2
- package/dist/compiler/coco.cjs +1 -1
- package/dist/compiler/coco.js +1 -1
- package/dist/compiler/context.cjs +9 -9
- package/dist/compiler/context.js +6 -6
- package/dist/compiler/daimon-seed.cjs +36 -0
- package/dist/compiler/daimon-seed.js +12 -0
- package/dist/compiler/domain-block-utils.cjs +205 -156
- package/dist/compiler/domain-block-utils.js +8 -7
- package/dist/compiler/dtdl.cjs +10 -10
- package/dist/compiler/dtdl.js +7 -7
- package/dist/compiler/gltf-pipeline.cjs +9 -9
- package/dist/compiler/gltf-pipeline.js +2 -2
- package/dist/compiler/godot.cjs +10 -9
- package/dist/compiler/godot.js +9 -8
- package/dist/compiler/incremental.cjs +11 -11
- package/dist/compiler/incremental.js +6 -6
- package/dist/compiler/index.cjs +2585 -3273
- package/dist/compiler/index.d.ts +149 -35
- package/dist/compiler/index.js +2197 -3102
- package/dist/compiler/ios.cjs +11 -11
- package/dist/compiler/ios.js +9 -9
- package/dist/compiler/llm-provider-capabilities.cjs +9 -9
- package/dist/compiler/llm-provider-capabilities.js +6 -6
- package/dist/compiler/nodetoy.cjs +1 -1
- package/dist/compiler/nodetoy.js +1 -1
- package/dist/compiler/openxr.cjs +11 -10
- package/dist/compiler/openxr.js +10 -9
- package/dist/compiler/remotion.cjs +1 -1
- package/dist/compiler/remotion.js +1 -1
- package/dist/compiler/reproducibility.cjs +1 -1
- package/dist/compiler/reproducibility.js +1 -1
- package/dist/compiler/sdf.cjs +11 -10
- package/dist/compiler/sdf.js +9 -8
- package/dist/compiler/semantic-scene.cjs +7 -7
- package/dist/compiler/semantic-scene.js +2 -2
- package/dist/compiler/state.cjs +9 -9
- package/dist/compiler/state.js +7 -7
- package/dist/compiler/trait-composition.cjs +11 -11
- package/dist/compiler/trait-composition.js +7 -7
- package/dist/compiler/traits/ProvenanceSemiring.d.ts +167 -0
- package/dist/compiler/traits/Semiring.d.ts +26 -0
- package/dist/compiler/unity.cjs +11 -10
- package/dist/compiler/unity.js +10 -9
- package/dist/compiler/unreal.cjs +12 -11
- package/dist/compiler/unreal.js +10 -9
- package/dist/compiler/urdf.cjs +18 -17
- package/dist/compiler/urdf.js +9 -8
- package/dist/compiler/usd-physics.cjs +11 -10
- package/dist/compiler/usd-physics.js +8 -7
- package/dist/compiler/visionos.cjs +11 -10
- package/dist/compiler/visionos.js +10 -9
- package/dist/compiler/vrchat.cjs +11 -10
- package/dist/compiler/vrchat.js +9 -8
- package/dist/compiler/wasm.cjs +14 -13
- package/dist/compiler/wasm.js +9 -8
- package/dist/compiler/webgpu.cjs +10 -9
- package/dist/compiler/webgpu.js +9 -8
- package/dist/constants.cjs +398 -0
- package/dist/constants.js +9 -0
- package/dist/coordinators/index.cjs +4 -1
- package/dist/coordinators/index.js +4 -1
- package/dist/debugger.cjs +11 -9
- package/dist/debugger.js +9 -7
- package/dist/{dist-ACXG6IH5.cjs → dist-GRMOP2UL.cjs} +341 -65
- package/dist/{dist-VD4L6V7Q.js → dist-ZBUKU2JG.js} +333 -63
- package/dist/entries/interop.cjs +23 -23
- package/dist/entries/interop.js +3 -3
- package/dist/entries/scripting.cjs +12 -11
- package/dist/entries/scripting.js +8 -7
- package/dist/evolution/index.cjs +66 -0
- package/dist/evolution/index.d.ts +162 -0
- package/dist/evolution/index.js +17 -0
- package/dist/hololand/index.cjs +41 -37
- package/dist/hololand/index.js +3 -3
- package/dist/index.cjs +12394 -3224
- package/dist/index.d.ts +260 -18
- package/dist/index.js +10755 -2182
- package/dist/keyword-registry/PluginKeywordRegistry.d.ts +138 -0
- package/dist/keyword-registry/index.cjs +29 -0
- package/dist/keyword-registry/index.d.ts +1 -0
- package/dist/keyword-registry/index.js +4 -0
- package/dist/math/tropical-spmv.cjs +11 -11
- package/dist/math/tropical-spmv.d.ts +1 -0
- package/dist/math/tropical-spmv.js +2 -2
- package/dist/math/tropicalSpmv.d.ts +43 -0
- package/dist/math/vec3.cjs +1 -1
- package/dist/math/vec3.js +1 -1
- package/dist/matter/StagedMatter.d.ts +82 -0
- package/dist/matter/index.cjs +17 -0
- package/dist/matter/index.d.ts +1 -0
- package/dist/matter/index.js +4 -0
- package/dist/{ml-dsa-Z7JDKW4L.js → ml-dsa-J6VKVT4K.js} +3 -3
- package/dist/{ml-dsa-FSKBTE3W.cjs → ml-dsa-MTIK4ZUQ.cjs} +23 -23
- package/dist/paper-0c-spike/index.cjs +1 -1
- package/dist/paper-0c-spike/index.js +1 -1
- package/dist/parameter-envelope/ParameterEnvelope.d.ts +128 -0
- package/dist/parameter-envelope/index.cjs +17 -0
- package/dist/parameter-envelope/index.d.ts +2 -0
- package/dist/parameter-envelope/index.js +4 -0
- package/dist/parser/HoloCompositionTypes.d.ts +2013 -0
- package/dist/parser/PipelineParser.d.ts +162 -0
- package/dist/parser.cjs +36 -20
- package/dist/parser.js +13 -9
- package/dist/plugin-manifest/ManifestAutoLoader.d.ts +35 -0
- package/dist/plugin-manifest/PluginManifest.d.ts +156 -0
- package/dist/plugin-manifest/index.cjs +25 -0
- package/dist/plugin-manifest/index.d.ts +2 -0
- package/dist/plugin-manifest/index.js +4 -0
- package/dist/plugin-solver-contract/PluginSolverContract.d.ts +288 -0
- package/dist/plugin-solver-contract/index.cjs +41 -0
- package/dist/plugin-solver-contract/index.d.ts +1 -0
- package/dist/plugin-solver-contract/index.js +4 -0
- package/dist/policy/ContentPolicyGate.d.ts +51 -0
- package/dist/policy/PolicyPack.d.ts +120 -0
- package/dist/policy/blocklist.d.ts +32 -0
- package/dist/policy/defaults.d.ts +44 -0
- package/dist/policy/index.cjs +106 -0
- package/dist/policy/index.d.ts +17 -0
- package/dist/policy/index.js +5 -0
- package/dist/policy/jsonLogic.d.ts +31 -0
- package/dist/policy/types.d.ts +174 -0
- package/dist/proof-composition/ProofCompositionLaw.d.ts +93 -0
- package/dist/proof-composition/index.cjs +25 -0
- package/dist/proof-composition/index.d.ts +1 -0
- package/dist/proof-composition/index.js +4 -0
- package/dist/receipts/hash-policy.d.ts +85 -0
- package/dist/reconstruction/index.cjs +75 -47
- package/dist/reconstruction/index.js +5 -5
- package/dist/runtime/plugin-trait-registrar.d.ts +36 -0
- package/dist/runtime.cjs +81 -79
- package/dist/runtime.js +9 -7
- package/dist/scene-presets-EDKYZ5GW.js +4 -0
- package/dist/scene-presets-NCW2CFRS.cjs +17 -0
- package/dist/self-improvement/index.cjs +1 -1
- package/dist/self-improvement/index.js +1 -1
- package/dist/{src-PT2FERDV.cjs → src-G3D7ZATQ.cjs} +545 -21
- package/dist/{src-J6CM4AUR.js → src-UXYA7HM6.js} +539 -16
- package/dist/storage/index.cjs +10 -10
- package/dist/storage/index.js +3 -3
- package/dist/testing.cjs +1 -1
- package/dist/testing.js +1 -1
- package/dist/tools/index.cjs +3631 -0
- package/dist/tools/index.js +3581 -0
- package/dist/traitDocs/traitDocs.cjs +9 -9
- package/dist/traitDocs/traitDocs.d.ts +1 -0
- package/dist/traitDocs/traitDocs.js +3 -3
- package/dist/traits/ControlLoopTrait.d.ts +154 -0
- package/dist/traits/KinematicChainTrait.d.ts +116 -0
- package/dist/traits/SensorSamplingTrait.d.ts +154 -0
- package/dist/traits/TraitTypes.d.ts +270 -0
- package/dist/traits/TransactionTrait.d.ts +121 -0
- package/dist/traits/botanical-lotus.cjs +54 -50
- package/dist/traits/botanical-lotus.js +2 -5
- package/dist/traits/control-loop.cjs +21 -0
- package/dist/traits/control-loop.d.ts +1 -0
- package/dist/traits/control-loop.js +4 -0
- package/dist/traits/engines/cloth-verlet.d.ts +65 -0
- package/dist/traits/engines/index.cjs +19 -19
- package/dist/traits/engines/index.d.ts +15 -275
- package/dist/traits/engines/index.js +3 -3
- package/dist/traits/engines/motion-data-schema.d.ts +119 -0
- package/dist/traits/engines/motion-matching.d.ts +102 -0
- package/dist/traits/engines/noise.d.ts +25 -0
- package/dist/traits/engines/onnx-adapter.d.ts +173 -0
- package/dist/traits/engines/onnx-motion-matching.d.ts +163 -0
- package/dist/traits/engines/pfnn-network.d.ts +92 -0
- package/dist/traits/engines/synthetic-walk-cycle.d.ts +38 -0
- package/dist/traits/engines/tensor-ops.d.ts +15 -0
- package/dist/traits/index.cjs +2789 -1259
- package/dist/traits/index.d.ts +35 -0
- package/dist/traits/index.js +1692 -411
- package/dist/traits/kinematic-chain.cjs +25 -0
- package/dist/traits/kinematic-chain.d.ts +1 -0
- package/dist/traits/kinematic-chain.js +4 -0
- package/dist/traits/sensor-sampling.cjs +33 -0
- package/dist/traits/sensor-sampling.d.ts +1 -0
- package/dist/traits/sensor-sampling.js +4 -0
- package/dist/traits/simulation-solver-factory.cjs +1 -1
- package/dist/traits/simulation-solver-factory.js +1 -1
- package/dist/traits/transaction.cjs +29 -0
- package/dist/traits/transaction.d.ts +1 -0
- package/dist/traits/transaction.js +4 -0
- package/dist/traits/webcam-gaze.cjs +1 -1
- package/dist/traits/webcam-gaze.js +1 -1
- package/dist/type-checker.cjs +7 -6
- package/dist/type-checker.js +5 -4
- package/dist/types/AdvancedTypeSystem.d.ts +489 -0
- package/dist/types/HoloScriptPlus.d.ts +810 -0
- package/dist/types/base.d.ts +248 -0
- package/dist/types.d.ts +799 -0
- package/dist/world/index.cjs +3 -4
- package/dist/world/index.js +3 -4
- package/dist/world-model/index.cjs +1 -1
- package/dist/world-model/index.js +1 -1
- package/dist/wot/index.cjs +1 -1
- package/dist/wot/index.js +1 -1
- package/package.json +135 -69
- package/dist/GLTFPipeline-3EJLL3TS.cjs +0 -38
- package/dist/GLTFPipeline-3OWJV2VK.js +0 -17
- package/dist/HoloScriptPlusParser-ADWRY5OS.cjs +0 -698
- package/dist/HoloScriptPlusParser-JLJDXHSC.js +0 -693
- package/dist/HoloScriptPlusParser-QCGFPWIL.cjs +0 -27
- package/dist/HoloScriptPlusParser-WENAFEFV.js +0 -10
- package/dist/HoloScriptRuntime-GGRVEU4T.cjs +0 -19
- package/dist/HoloScriptRuntime-GJK6VJPH.js +0 -10
- package/dist/chunk-22Q5A6RV.js +0 -979
- package/dist/chunk-4C57PR42.js +0 -468
- package/dist/chunk-4W5G5QVL.cjs +0 -847
- package/dist/chunk-5ET6L4NS.js +0 -487
- package/dist/chunk-C4GSLCHE.cjs +0 -7153
- package/dist/chunk-F2G6CWFT.js +0 -7089
- package/dist/chunk-G6PNEASF.cjs +0 -814
- package/dist/chunk-GTA4Q3A3.js +0 -1491
- package/dist/chunk-HCCQLAA4.cjs +0 -74
- package/dist/chunk-HFSVMKM3.cjs +0 -72
- package/dist/chunk-KAIVDEIG.cjs +0 -4539
- package/dist/chunk-KQU64CIX.cjs +0 -1508
- package/dist/chunk-MSYSQ2AJ.js +0 -4533
- package/dist/chunk-NHJLP37F.js +0 -70
- package/dist/chunk-NHYRRAGI.cjs +0 -490
- package/dist/chunk-OIQYIIO3.cjs +0 -473
- package/dist/chunk-OL46QLBJ.js +0 -61
- package/dist/chunk-SKZPC5AG.cjs +0 -984
- package/dist/chunk-SLHLXUMO.js +0 -445
- package/dist/chunk-UOIGFQXC.cjs +0 -9750
- package/dist/chunk-UOL6Y5TD.cjs +0 -759
- package/dist/chunk-UVFI7XIR.cjs +0 -452
- package/dist/chunk-VEPGBETF.js +0 -844
- package/dist/chunk-XQ5MWMP2.js +0 -756
- package/dist/chunk-XT6JY5W5.js +0 -9684
- package/dist/chunk-YRRAUB35.js +0 -811
- package/dist/compiler/GasOptimizationAnalyzer.d.ts +0 -73
- package/dist/compiler/NFTMarketplaceCompiler.d.ts +0 -23
- package/dist/compiler/ar.cjs +0 -23
- package/dist/compiler/ar.js +0 -11
- package/dist/compiler/babylon.cjs +0 -21
- package/dist/compiler/babylon.js +0 -15
- package/dist/compiler/multi-layer.cjs +0 -24
- package/dist/compiler/multi-layer.js +0 -15
- package/dist/compiler/playcanvas.cjs +0 -19
- package/dist/compiler/playcanvas.js +0 -13
- package/dist/compiler/r3f.cjs +0 -39
- package/dist/compiler/r3f.d.ts +0 -22
- package/dist/compiler/r3f.js +0 -17
- package/dist/compiler/vrr.cjs +0 -24
- package/dist/compiler/vrr.js +0 -12
- package/dist/parser/NFTMarketplaceTypes.d.ts +0 -191
- package/dist/playwright-3AT3AKTV.cjs +0 -98673
- package/dist/playwright-VZPDVUEQ.js +0 -98660
|
@@ -1,7 +1,34 @@
|
|
|
1
|
-
import { ErrorRecovery, generateQuickFixes, enrichErrorWithSuggestions
|
|
2
|
-
import {
|
|
1
|
+
import { ErrorRecovery, generateQuickFixes, enrichErrorWithSuggestions } from './chunk-Z6LZUYZF.js';
|
|
2
|
+
import { isBrainKeyword, isCognitiveVerb, nearestCognitiveVerb } from './chunk-UNMVGZVW.js';
|
|
3
|
+
import { LIFECYCLE_HOOKS, STRUCTURAL_DIRECTIVES } from './chunk-JBYBMBMW.js';
|
|
4
|
+
import { VR_TRAITS } from './chunk-2EGGAZT3.js';
|
|
5
|
+
import { isLocomotionReactionTrigger } from './chunk-63AUAIL6.js';
|
|
3
6
|
import * as crypto from 'crypto';
|
|
4
7
|
|
|
8
|
+
// src/traits/FrameDeclarationTrait.ts
|
|
9
|
+
var DEFAULT_FRAME = {
|
|
10
|
+
domain: "*",
|
|
11
|
+
horizon: "",
|
|
12
|
+
capability_tier: 2,
|
|
13
|
+
trust_tier: 2};
|
|
14
|
+
function coerceConfig(raw) {
|
|
15
|
+
const domain = typeof raw.domain === "string" ? raw.domain : DEFAULT_FRAME.domain;
|
|
16
|
+
const horizon = typeof raw.horizon === "string" ? raw.horizon : DEFAULT_FRAME.horizon;
|
|
17
|
+
let capability_tier = DEFAULT_FRAME.capability_tier;
|
|
18
|
+
const rawCT = raw.capability_tier;
|
|
19
|
+
if (rawCT === 0 || rawCT === 1 || rawCT === 2 || rawCT === 3) {
|
|
20
|
+
capability_tier = rawCT;
|
|
21
|
+
}
|
|
22
|
+
let trust_tier = DEFAULT_FRAME.trust_tier;
|
|
23
|
+
const rawTT = raw.trust_tier;
|
|
24
|
+
if (rawTT === 0 || rawTT === 1 || rawTT === 2 || rawTT === 3) {
|
|
25
|
+
trust_tier = rawTT;
|
|
26
|
+
}
|
|
27
|
+
const allowed_tools = Array.isArray(raw.allowed_tools) ? raw.allowed_tools.filter((t) => typeof t === "string") : [];
|
|
28
|
+
const denied_domains = Array.isArray(raw.denied_domains) ? raw.denied_domains.filter((d) => typeof d === "string") : [];
|
|
29
|
+
return { domain, horizon, capability_tier, trust_tier, allowed_tools, denied_domains };
|
|
30
|
+
}
|
|
31
|
+
|
|
5
32
|
// src/parser/HybridChunker.ts
|
|
6
33
|
function countTokens(text) {
|
|
7
34
|
return Math.ceil(text.length / 4);
|
|
@@ -1142,13 +1169,18 @@ var Lexer = class {
|
|
|
1142
1169
|
this.tokens.push(this.createToken("DEDENT", ""));
|
|
1143
1170
|
this.pendingDedents--;
|
|
1144
1171
|
}
|
|
1172
|
+
if (this.column === 1) {
|
|
1173
|
+
const beforePos = this.pos;
|
|
1174
|
+
const beforeTokenCount = this.tokens.length;
|
|
1175
|
+
const beforePendingDedents = this.pendingDedents;
|
|
1176
|
+
this.handleIndentation();
|
|
1177
|
+
if (this.pos !== beforePos || this.tokens.length !== beforeTokenCount || this.pendingDedents !== beforePendingDedents) {
|
|
1178
|
+
continue;
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1145
1181
|
const char = this.source[this.pos];
|
|
1146
1182
|
if (char === " " || char === " ") {
|
|
1147
|
-
|
|
1148
|
-
this.handleIndentation();
|
|
1149
|
-
} else {
|
|
1150
|
-
this.advance();
|
|
1151
|
-
}
|
|
1183
|
+
this.advance();
|
|
1152
1184
|
continue;
|
|
1153
1185
|
}
|
|
1154
1186
|
if (char === "/" && this.peek(1) === "/") {
|
|
@@ -1754,13 +1786,15 @@ var Lexer = class {
|
|
|
1754
1786
|
return this.isIdentifierStart(char) || this.isDigit(char) || char === "-";
|
|
1755
1787
|
}
|
|
1756
1788
|
};
|
|
1757
|
-
var HoloScriptPlusParser = class {
|
|
1789
|
+
var HoloScriptPlusParser = class _HoloScriptPlusParser {
|
|
1758
1790
|
constructor(options = {}) {
|
|
1759
1791
|
this.tokens = [];
|
|
1760
1792
|
this.pos = 0;
|
|
1761
1793
|
this.source = "";
|
|
1762
1794
|
this.errors = [];
|
|
1763
1795
|
this.warnings = [];
|
|
1796
|
+
this.blockConfigDirectives = /* @__PURE__ */ new WeakSet();
|
|
1797
|
+
this.blockConfigDirectiveLocations = /* @__PURE__ */ new WeakMap();
|
|
1764
1798
|
this.imports = [];
|
|
1765
1799
|
this.hasState = false;
|
|
1766
1800
|
this.hasVRTraits = false;
|
|
@@ -1829,6 +1863,8 @@ var HoloScriptPlusParser = class {
|
|
|
1829
1863
|
this.source = source;
|
|
1830
1864
|
this.errors = [];
|
|
1831
1865
|
this.warnings = [];
|
|
1866
|
+
this.blockConfigDirectives = /* @__PURE__ */ new WeakSet();
|
|
1867
|
+
this.blockConfigDirectiveLocations = /* @__PURE__ */ new WeakMap();
|
|
1832
1868
|
this.imports = [];
|
|
1833
1869
|
this.hasState = false;
|
|
1834
1870
|
this.hasVRTraits = false;
|
|
@@ -1839,8 +1875,110 @@ var HoloScriptPlusParser = class {
|
|
|
1839
1875
|
const lexer = new Lexer(source);
|
|
1840
1876
|
this.tokens = lexer.tokenize();
|
|
1841
1877
|
const root = this.parseDocument();
|
|
1878
|
+
this.desugarSafeDaemon(root);
|
|
1842
1879
|
return this.buildResult(root);
|
|
1843
1880
|
}
|
|
1881
|
+
/** Canonical safety-trait configs that `@safe_daemon` expands into. */
|
|
1882
|
+
static safeDaemonDefaults() {
|
|
1883
|
+
return {
|
|
1884
|
+
rate_limiter: { strategy: "token_bucket", max_tokens: 20, refill_rate: 4, window_ms: 6e4 },
|
|
1885
|
+
circuit_breaker: {
|
|
1886
|
+
failure_threshold: 5,
|
|
1887
|
+
window_ms: 3e5,
|
|
1888
|
+
reset_timeout_ms: 6e5,
|
|
1889
|
+
success_threshold: 2,
|
|
1890
|
+
failure_rate_threshold: 0,
|
|
1891
|
+
min_requests: 5
|
|
1892
|
+
},
|
|
1893
|
+
timeout_guard: { default_timeout_ms: 3e4, fallback_action: "abort" },
|
|
1894
|
+
economy: {
|
|
1895
|
+
initial_balance: 5,
|
|
1896
|
+
default_spend_limit: 1,
|
|
1897
|
+
spend_limit_period: 36e5,
|
|
1898
|
+
max_transaction_history: 200,
|
|
1899
|
+
escrow_enabled: false
|
|
1900
|
+
},
|
|
1901
|
+
structured_logger: {
|
|
1902
|
+
min_level: "info",
|
|
1903
|
+
max_entries: 500,
|
|
1904
|
+
rotation_count: 100,
|
|
1905
|
+
emit_events: true,
|
|
1906
|
+
console_output: true
|
|
1907
|
+
}
|
|
1908
|
+
};
|
|
1909
|
+
}
|
|
1910
|
+
/**
|
|
1911
|
+
* Expand a `@safe_daemon { ... }` config into the five safety traits it
|
|
1912
|
+
* stands for (@rate_limiter + @circuit_breaker + @timeout_guard + @economy +
|
|
1913
|
+
* @structured_logger). Supports flat convenience overrides (budget / rate /
|
|
1914
|
+
* timeout_ms / …) and nested per-trait overrides (economy: { ... }).
|
|
1915
|
+
*/
|
|
1916
|
+
expandSafeDaemon(config) {
|
|
1917
|
+
const c = config && typeof config === "object" ? config : {};
|
|
1918
|
+
const out = _HoloScriptPlusParser.safeDaemonDefaults();
|
|
1919
|
+
const num = (v) => typeof v === "number";
|
|
1920
|
+
if (num(c.budget)) out.economy.initial_balance = c.budget;
|
|
1921
|
+
if (num(c.spend_limit)) out.economy.default_spend_limit = c.spend_limit;
|
|
1922
|
+
if (num(c.rate)) out.rate_limiter.refill_rate = c.rate;
|
|
1923
|
+
if (num(c.max_tokens)) out.rate_limiter.max_tokens = c.max_tokens;
|
|
1924
|
+
if (num(c.window_ms)) out.rate_limiter.window_ms = c.window_ms;
|
|
1925
|
+
if (num(c.failure_threshold)) out.circuit_breaker.failure_threshold = c.failure_threshold;
|
|
1926
|
+
if (num(c.reset_timeout_ms)) out.circuit_breaker.reset_timeout_ms = c.reset_timeout_ms;
|
|
1927
|
+
if (num(c.timeout_ms)) out.timeout_guard.default_timeout_ms = c.timeout_ms;
|
|
1928
|
+
if (typeof c.log_level === "string") out.structured_logger.min_level = c.log_level;
|
|
1929
|
+
for (const t of ["rate_limiter", "circuit_breaker", "timeout_guard", "economy", "structured_logger"]) {
|
|
1930
|
+
const override = c[t];
|
|
1931
|
+
if (override && typeof override === "object") Object.assign(out[t], override);
|
|
1932
|
+
}
|
|
1933
|
+
return Object.entries(out);
|
|
1934
|
+
}
|
|
1935
|
+
/**
|
|
1936
|
+
* Walk the parsed AST and expand every `@safe_daemon` into its five safety
|
|
1937
|
+
* traits, wherever traits are stored: a node's `traits` Map (composition /
|
|
1938
|
+
* world / object), a brain's `traits` Record, and any `directives` array.
|
|
1939
|
+
* Existing per-trait declarations are not overwritten.
|
|
1940
|
+
*/
|
|
1941
|
+
desugarSafeDaemon(root) {
|
|
1942
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1943
|
+
const visit = (node) => {
|
|
1944
|
+
if (!node || typeof node !== "object" || seen.has(node)) return;
|
|
1945
|
+
seen.add(node);
|
|
1946
|
+
const n = node;
|
|
1947
|
+
if (n.traits instanceof Map && n.traits.has("safe_daemon")) {
|
|
1948
|
+
const cfg = n.traits.get("safe_daemon");
|
|
1949
|
+
n.traits.delete("safe_daemon");
|
|
1950
|
+
for (const [name, c] of this.expandSafeDaemon(cfg)) {
|
|
1951
|
+
if (!n.traits.has(name)) n.traits.set(name, c);
|
|
1952
|
+
}
|
|
1953
|
+
this.hasVRTraits = true;
|
|
1954
|
+
}
|
|
1955
|
+
if (n.traits && !(n.traits instanceof Map) && typeof n.traits === "object") {
|
|
1956
|
+
const rec = n.traits;
|
|
1957
|
+
if ("safe_daemon" in rec) {
|
|
1958
|
+
const cfg = rec["safe_daemon"];
|
|
1959
|
+
delete rec["safe_daemon"];
|
|
1960
|
+
for (const [name, c] of this.expandSafeDaemon(cfg)) {
|
|
1961
|
+
if (!(name in rec)) rec[name] = c;
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
if (Array.isArray(n.directives)) {
|
|
1966
|
+
const dirs = n.directives;
|
|
1967
|
+
const idx = dirs.findIndex((d) => d && d.type === "trait" && d.name === "safe_daemon");
|
|
1968
|
+
if (idx >= 0) {
|
|
1969
|
+
const cfg = dirs[idx].config;
|
|
1970
|
+
const expanded = this.expandSafeDaemon(cfg).map(([name, c]) => ({ type: "trait", name, config: c }));
|
|
1971
|
+
const existing = new Set(dirs.map((d) => d.name));
|
|
1972
|
+
dirs.splice(idx, 1, ...expanded.filter((e) => !existing.has(e.name)));
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
for (const key of ["children", "body", "states"]) {
|
|
1976
|
+
const child = n[key];
|
|
1977
|
+
if (Array.isArray(child)) child.forEach(visit);
|
|
1978
|
+
}
|
|
1979
|
+
};
|
|
1980
|
+
visit(root);
|
|
1981
|
+
}
|
|
1844
1982
|
/**
|
|
1845
1983
|
* Performs an incremental parse using ChunkBasedIncrementalParser with
|
|
1846
1984
|
* AST-aware chunking, hash-based caching, and dependency tracking.
|
|
@@ -2014,28 +2152,48 @@ var HoloScriptPlusParser = class {
|
|
|
2014
2152
|
}
|
|
2015
2153
|
const isNodeStart = this.check("IDENTIFIER") || this.check("STATE_MACHINE") || this.check("STATE") || this.check("TRANSITION") || this.check("INITIAL");
|
|
2016
2154
|
if (isNodeStart) {
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
if (
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2155
|
+
if (this.check("IDENTIFIER") && this.current().value === "connect") {
|
|
2156
|
+
const connectNode = this.parseHsConnectStatement();
|
|
2157
|
+
topLevelNodes.push(connectNode);
|
|
2158
|
+
} else if (this.check("IDENTIFIER") && this.current().value === "execute") {
|
|
2159
|
+
const executeNode = this.parseHsExecuteStatement();
|
|
2160
|
+
topLevelNodes.push(executeNode);
|
|
2161
|
+
} else if (this.check("IDENTIFIER") && isBrainKeyword(this.current().value)) {
|
|
2162
|
+
const brainNode = this.parseBrainDeclaration();
|
|
2163
|
+
brainNode.directives = [
|
|
2164
|
+
...currentDirectives,
|
|
2165
|
+
...brainNode.directives || []
|
|
2166
|
+
];
|
|
2167
|
+
topLevelNodes.push(brainNode);
|
|
2168
|
+
} else {
|
|
2169
|
+
const node = this.parseNode();
|
|
2170
|
+
const existingDirectives = node.directives || [];
|
|
2171
|
+
node.directives = [...currentDirectives, ...existingDirectives];
|
|
2172
|
+
if (node.type === "template") {
|
|
2173
|
+
for (const d of currentDirectives) {
|
|
2174
|
+
if (d.type === "version") {
|
|
2175
|
+
node.version = d.version;
|
|
2176
|
+
} else if (d.type === "migrate") {
|
|
2177
|
+
if (!node.migrations) node.migrations = [];
|
|
2178
|
+
node.migrations.push({
|
|
2179
|
+
type: "Migration",
|
|
2180
|
+
fromVersion: d.fromVersion,
|
|
2181
|
+
body: d.body
|
|
2182
|
+
});
|
|
2183
|
+
}
|
|
2031
2184
|
}
|
|
2032
2185
|
}
|
|
2186
|
+
topLevelNodes.push(node);
|
|
2033
2187
|
}
|
|
2034
|
-
topLevelNodes.push(node);
|
|
2035
2188
|
} else {
|
|
2036
2189
|
if (currentDirectives.length > 0) {
|
|
2037
2190
|
if (this.check("EOF")) {
|
|
2038
2191
|
globalDirectives.push(...currentDirectives);
|
|
2192
|
+
} else if (this.check("LBRACE")) {
|
|
2193
|
+
const block = this.parseBlockContent();
|
|
2194
|
+
const last = currentDirectives[currentDirectives.length - 1];
|
|
2195
|
+
last.config = { ...last.config || {}, ...block };
|
|
2196
|
+
globalDirectives.push(...currentDirectives);
|
|
2039
2197
|
} else {
|
|
2040
2198
|
this.error(
|
|
2041
2199
|
`Expected node after directives, got ${this.current().type}. Valid nodes: orb, template, logic, object, world, composition, scene, group`,
|
|
@@ -2051,21 +2209,6 @@ var HoloScriptPlusParser = class {
|
|
|
2051
2209
|
throw new Error("ParseError");
|
|
2052
2210
|
}
|
|
2053
2211
|
}
|
|
2054
|
-
if (this.check("IDENTIFIER") && this.current().value === "connect") {
|
|
2055
|
-
const connection = this.parseConnectionStatement();
|
|
2056
|
-
const node = {
|
|
2057
|
-
type: "connection",
|
|
2058
|
-
properties: connection,
|
|
2059
|
-
directives: [],
|
|
2060
|
-
children: [],
|
|
2061
|
-
traits: /* @__PURE__ */ new Map(),
|
|
2062
|
-
loc: {
|
|
2063
|
-
start: { line: this.current().line, column: 0 },
|
|
2064
|
-
end: { line: this.current().line, column: 0 }
|
|
2065
|
-
}
|
|
2066
|
-
};
|
|
2067
|
-
topLevelNodes.push(node);
|
|
2068
|
-
}
|
|
2069
2212
|
} catch (e) {
|
|
2070
2213
|
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
2071
2214
|
if (errorMessage !== "ParseError" && errorMessage !== "Unexpected token") {
|
|
@@ -2105,7 +2248,12 @@ var HoloScriptPlusParser = class {
|
|
|
2105
2248
|
]) || this.expect("IDENTIFIER", "Expected element type");
|
|
2106
2249
|
const type = typeToken.value;
|
|
2107
2250
|
if (type === "template") {
|
|
2108
|
-
|
|
2251
|
+
let templateName;
|
|
2252
|
+
if (this.check("IDENTIFIER")) {
|
|
2253
|
+
templateName = this.advance().value;
|
|
2254
|
+
} else {
|
|
2255
|
+
templateName = this.expect("STRING", "Expected template name").value;
|
|
2256
|
+
}
|
|
2109
2257
|
const templateBody = this.parseBlockContent();
|
|
2110
2258
|
let version;
|
|
2111
2259
|
const migrations = [];
|
|
@@ -2167,6 +2315,20 @@ var HoloScriptPlusParser = class {
|
|
|
2167
2315
|
}
|
|
2168
2316
|
};
|
|
2169
2317
|
}
|
|
2318
|
+
if (type === "react") {
|
|
2319
|
+
return this.parseHsPlusReactBlock(startToken);
|
|
2320
|
+
}
|
|
2321
|
+
if (["transform", "filter", "branch", "validate"].includes(type)) {
|
|
2322
|
+
const savedPos = this.pos;
|
|
2323
|
+
let blockName = "anonymous";
|
|
2324
|
+
if (this.check("IDENTIFIER") || this.check("STRING")) {
|
|
2325
|
+
blockName = this.advance().value;
|
|
2326
|
+
}
|
|
2327
|
+
if (this.check("LBRACE")) {
|
|
2328
|
+
return this.parsePipelineBlock(type, blockName, startToken);
|
|
2329
|
+
}
|
|
2330
|
+
this.pos = savedPos;
|
|
2331
|
+
}
|
|
2170
2332
|
if ([
|
|
2171
2333
|
"module",
|
|
2172
2334
|
"script",
|
|
@@ -2220,6 +2382,9 @@ var HoloScriptPlusParser = class {
|
|
|
2220
2382
|
if (type === "assert" || startToken.type === "ASSERT") {
|
|
2221
2383
|
return this.parseAssertNode();
|
|
2222
2384
|
}
|
|
2385
|
+
if (type === "timeline") {
|
|
2386
|
+
return this.parseTimelineNode(startToken);
|
|
2387
|
+
}
|
|
2223
2388
|
if (type === "environment") {
|
|
2224
2389
|
const envBody = this.parseEnvironmentBlock();
|
|
2225
2390
|
return {
|
|
@@ -2304,6 +2469,7 @@ var HoloScriptPlusParser = class {
|
|
|
2304
2469
|
const children = [];
|
|
2305
2470
|
const directives = [];
|
|
2306
2471
|
const traits = /* @__PURE__ */ new Map();
|
|
2472
|
+
let ambiguousPreBodyTrait = null;
|
|
2307
2473
|
if (templateRef) {
|
|
2308
2474
|
properties.__templateRef = templateRef;
|
|
2309
2475
|
}
|
|
@@ -2323,6 +2489,9 @@ var HoloScriptPlusParser = class {
|
|
|
2323
2489
|
traits.set(directive.name, directive.config);
|
|
2324
2490
|
this.hasVRTraits = true;
|
|
2325
2491
|
directives.push(directive);
|
|
2492
|
+
if (this.blockConfigDirectives.has(directive) && this.traitConfigLooksLikeNodeBody(directive.config)) {
|
|
2493
|
+
ambiguousPreBodyTrait = directive;
|
|
2494
|
+
}
|
|
2326
2495
|
} else {
|
|
2327
2496
|
directives.push(directive);
|
|
2328
2497
|
}
|
|
@@ -2373,6 +2542,13 @@ var HoloScriptPlusParser = class {
|
|
|
2373
2542
|
this.synchronizeProperty();
|
|
2374
2543
|
}
|
|
2375
2544
|
}
|
|
2545
|
+
if (!this.check("LBRACE") && ambiguousPreBodyTrait) {
|
|
2546
|
+
this.errorAt(
|
|
2547
|
+
this.blockConfigDirectiveLocations.get(ambiguousPreBodyTrait) || startToken,
|
|
2548
|
+
`Trait @${ambiguousPreBodyTrait.name} used a block that looks like an object body, but no object body follows. Use @${ambiguousPreBodyTrait.name}(...) for trait config, or add a separate { ... } object body.`,
|
|
2549
|
+
"HSP101"
|
|
2550
|
+
);
|
|
2551
|
+
}
|
|
2376
2552
|
if (this.check("LBRACE")) {
|
|
2377
2553
|
this.advance();
|
|
2378
2554
|
this.skipNewlines();
|
|
@@ -2417,7 +2593,7 @@ var HoloScriptPlusParser = class {
|
|
|
2417
2593
|
properties[key] = spreadNode;
|
|
2418
2594
|
} else {
|
|
2419
2595
|
const token = this.current();
|
|
2420
|
-
const isKeyToken = token.type === "IDENTIFIER" || token.type === "STRING" || token.type === "HASH" || token.type === "STATE" || token.type === "STATE_MACHINE" || token.type === "INITIAL" || token.type === "ON_ENTRY" || token.type === "ON_EXIT" || token.type === "TRANSITION";
|
|
2596
|
+
const isKeyToken = token.type === "IDENTIFIER" || token.type === "STRING" || token.type === "HASH" || token.type === "STATE" || token.type === "STATE_MACHINE" || token.type === "INITIAL" || token.type === "ON_ENTRY" || token.type === "ON_EXIT" || token.type === "ON_ERROR" || token.type === "TRANSITION";
|
|
2421
2597
|
if (isKeyToken) {
|
|
2422
2598
|
const saved = this.pos;
|
|
2423
2599
|
const name = this.advance().value;
|
|
@@ -2449,7 +2625,9 @@ var HoloScriptPlusParser = class {
|
|
|
2449
2625
|
"on_entry",
|
|
2450
2626
|
"on_exit",
|
|
2451
2627
|
"page",
|
|
2452
|
-
"include"
|
|
2628
|
+
"include",
|
|
2629
|
+
"brain",
|
|
2630
|
+
"react"
|
|
2453
2631
|
];
|
|
2454
2632
|
if (name === "transition" && this.check("STRING")) {
|
|
2455
2633
|
const event = this.advance().value;
|
|
@@ -2528,7 +2706,12 @@ var HoloScriptPlusParser = class {
|
|
|
2528
2706
|
}
|
|
2529
2707
|
if (this.check("COLON") || this.check("EQUALS")) {
|
|
2530
2708
|
this.advance();
|
|
2531
|
-
|
|
2709
|
+
const pipeNext = this.peek(1);
|
|
2710
|
+
if (this.check("PIPE") && (!pipeNext || pipeNext.type === "NEWLINE" || pipeNext.type === "EOF")) {
|
|
2711
|
+
properties[name] = this.parseBlockScalar(this.tokens[saved]);
|
|
2712
|
+
} else {
|
|
2713
|
+
properties[name] = this.parseValue();
|
|
2714
|
+
}
|
|
2532
2715
|
} else if (childNodeKeywords.includes(name) && (this.check("LBRACE") || this.check("STRING"))) {
|
|
2533
2716
|
this.pos = saved;
|
|
2534
2717
|
children.push(this.parseNode());
|
|
@@ -2585,15 +2768,24 @@ var HoloScriptPlusParser = class {
|
|
|
2585
2768
|
const isKeyword = ["STATE_MACHINE", "STATE", "ON_ENTRY", "ON_EXIT", "TRANSITION"].includes(
|
|
2586
2769
|
nameToken.type
|
|
2587
2770
|
);
|
|
2588
|
-
|
|
2771
|
+
let name;
|
|
2772
|
+
if (nameToken.type === "IDENTIFIER" || isKeyword) {
|
|
2773
|
+
this.advance();
|
|
2774
|
+
name = nameToken.value;
|
|
2775
|
+
} else if (nameToken.type === "NUMBER" && /^\d+[a-zA-Z]\w*$/.test(nameToken.value)) {
|
|
2776
|
+
this.advance();
|
|
2777
|
+
name = nameToken.value;
|
|
2778
|
+
const next = this.current();
|
|
2779
|
+
if (next.type === "IDENTIFIER" && next.line === nameToken.line && next.column === nameToken.column + nameToken.value.length) {
|
|
2780
|
+
name += this.advance().value;
|
|
2781
|
+
}
|
|
2782
|
+
} else {
|
|
2589
2783
|
this.error(
|
|
2590
2784
|
`Expected directive name, got ${nameToken.type}. Directives start with @ followed by name (e.g., @grabbable)`,
|
|
2591
2785
|
"HSP201"
|
|
2592
2786
|
);
|
|
2593
2787
|
return null;
|
|
2594
2788
|
}
|
|
2595
|
-
this.advance();
|
|
2596
|
-
const name = nameToken.value;
|
|
2597
2789
|
if (name === "version") {
|
|
2598
2790
|
this.expect("LPAREN", "Expected ( after @version");
|
|
2599
2791
|
const versionToken = this.expect("NUMBER", "Expected version number");
|
|
@@ -2613,18 +2805,147 @@ var HoloScriptPlusParser = class {
|
|
|
2613
2805
|
const body = this.check("LBRACE") ? this.parseCodeBlock() : "";
|
|
2614
2806
|
return { type: "migrate", fromVersion, body };
|
|
2615
2807
|
}
|
|
2808
|
+
if (name === "quest") {
|
|
2809
|
+
const config2 = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
|
|
2810
|
+
return { type: "quest", ...config2 };
|
|
2811
|
+
}
|
|
2812
|
+
if (name === "faction") {
|
|
2813
|
+
const config2 = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
|
|
2814
|
+
return { type: "faction", ...config2 };
|
|
2815
|
+
}
|
|
2816
|
+
if (name === "loot") {
|
|
2817
|
+
const config2 = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
|
|
2818
|
+
return { type: "loot", ...config2 };
|
|
2819
|
+
}
|
|
2820
|
+
if (name === "ability") {
|
|
2821
|
+
const config2 = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
|
|
2822
|
+
return { type: "ability", ...config2 };
|
|
2823
|
+
}
|
|
2824
|
+
if (name === "authority") {
|
|
2825
|
+
const config2 = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
|
|
2826
|
+
return { type: "authority", ...config2 };
|
|
2827
|
+
}
|
|
2828
|
+
if (name === "wallet_gated") {
|
|
2829
|
+
const config2 = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
|
|
2830
|
+
return { type: "wallet_gated", ...config2 };
|
|
2831
|
+
}
|
|
2832
|
+
if (name === "world_chunk") {
|
|
2833
|
+
const config2 = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
|
|
2834
|
+
return { type: "world_chunk", ...config2 };
|
|
2835
|
+
}
|
|
2836
|
+
if (name === "personality") {
|
|
2837
|
+
let value;
|
|
2838
|
+
if (this.check("IDENTIFIER")) {
|
|
2839
|
+
value = this.advance().value;
|
|
2840
|
+
} else if (this.check("STRING")) {
|
|
2841
|
+
value = this.advance().value;
|
|
2842
|
+
} else {
|
|
2843
|
+
value = "neutral";
|
|
2844
|
+
}
|
|
2845
|
+
return { type: "personality", value };
|
|
2846
|
+
}
|
|
2847
|
+
if (name === "faction_alignment") {
|
|
2848
|
+
let value;
|
|
2849
|
+
if (this.check("IDENTIFIER")) {
|
|
2850
|
+
value = this.advance().value;
|
|
2851
|
+
if (this.check("IDENTIFIER")) {
|
|
2852
|
+
value += "_" + this.advance().value;
|
|
2853
|
+
}
|
|
2854
|
+
} else if (this.check("STRING")) {
|
|
2855
|
+
value = this.advance().value;
|
|
2856
|
+
} else {
|
|
2857
|
+
value = "true_neutral";
|
|
2858
|
+
}
|
|
2859
|
+
return { type: "faction_alignment", value };
|
|
2860
|
+
}
|
|
2861
|
+
if (name === "memory_persistence") {
|
|
2862
|
+
let value = true;
|
|
2863
|
+
if (this.check("BOOLEAN")) {
|
|
2864
|
+
value = this.advance().value === "true";
|
|
2865
|
+
} else if (this.check("IDENTIFIER")) {
|
|
2866
|
+
const raw = this.advance().value;
|
|
2867
|
+
value = raw !== "false";
|
|
2868
|
+
}
|
|
2869
|
+
return { type: "memory_persistence", value };
|
|
2870
|
+
}
|
|
2871
|
+
if (name === "preferred_ability") {
|
|
2872
|
+
let abilityName;
|
|
2873
|
+
if (this.check("STRING")) {
|
|
2874
|
+
abilityName = this.advance().value;
|
|
2875
|
+
} else if (this.check("IDENTIFIER")) {
|
|
2876
|
+
abilityName = this.advance().value;
|
|
2877
|
+
} else {
|
|
2878
|
+
abilityName = "";
|
|
2879
|
+
}
|
|
2880
|
+
let when;
|
|
2881
|
+
if (this.check("AT")) {
|
|
2882
|
+
const saved = this.pos;
|
|
2883
|
+
this.advance();
|
|
2884
|
+
if (this.check("IDENTIFIER") && this.current().value === "when") {
|
|
2885
|
+
this.advance();
|
|
2886
|
+
if (this.check("LBRACE")) {
|
|
2887
|
+
when = this.parseCodeBlock();
|
|
2888
|
+
}
|
|
2889
|
+
} else {
|
|
2890
|
+
this.pos = saved;
|
|
2891
|
+
}
|
|
2892
|
+
}
|
|
2893
|
+
return { type: "preferred_ability", ability: abilityName, when };
|
|
2894
|
+
}
|
|
2895
|
+
if (name === "flee_threshold") {
|
|
2896
|
+
let value = 0.25;
|
|
2897
|
+
if (this.check("NUMBER")) {
|
|
2898
|
+
value = parseFloat(this.advance().value);
|
|
2899
|
+
}
|
|
2900
|
+
return { type: "flee_threshold", value };
|
|
2901
|
+
}
|
|
2902
|
+
if (name === "patrol_speed") {
|
|
2903
|
+
let value = 1;
|
|
2904
|
+
if (this.check("NUMBER")) {
|
|
2905
|
+
value = parseFloat(this.advance().value);
|
|
2906
|
+
} else if (this.check("IDENTIFIER")) {
|
|
2907
|
+
value = this.advance().value;
|
|
2908
|
+
}
|
|
2909
|
+
return { type: "patrol_speed", value };
|
|
2910
|
+
}
|
|
2911
|
+
if (name === "waypoints") {
|
|
2912
|
+
let points = [];
|
|
2913
|
+
if (this.check("LBRACKET")) {
|
|
2914
|
+
points = this.parseValue();
|
|
2915
|
+
} else if (this.check("LBRACE")) {
|
|
2916
|
+
points = this.parseBlockContent();
|
|
2917
|
+
}
|
|
2918
|
+
return { type: "waypoints", points };
|
|
2919
|
+
}
|
|
2616
2920
|
if (VR_TRAITS.includes(name)) {
|
|
2617
2921
|
if (!this.options.enableVRTraits) {
|
|
2618
2922
|
this.warn(`VR trait @${name} is disabled`);
|
|
2619
2923
|
return null;
|
|
2620
2924
|
}
|
|
2621
2925
|
let config2 = {};
|
|
2926
|
+
let configStyle2 = "none";
|
|
2622
2927
|
if (this.check("LPAREN")) {
|
|
2928
|
+
configStyle2 = "paren";
|
|
2623
2929
|
config2 = this.parseTraitConfig();
|
|
2624
2930
|
} else if (this.check("LBRACE")) {
|
|
2931
|
+
configStyle2 = "block";
|
|
2625
2932
|
config2 = this.parseBlockContent();
|
|
2933
|
+
} else if (this.check("COLON")) {
|
|
2934
|
+
configStyle2 = "colon";
|
|
2935
|
+
this.advance();
|
|
2936
|
+
if (this.check("LPAREN")) {
|
|
2937
|
+
config2 = this.parseTraitConfig();
|
|
2938
|
+
} else if (this.check("LBRACE")) {
|
|
2939
|
+
config2 = this.parseBlockContent();
|
|
2940
|
+
} else {
|
|
2941
|
+
config2 = { value: this.parseValue() };
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
const directive2 = { type: "trait", name, config: config2 };
|
|
2945
|
+
if (configStyle2 === "block") {
|
|
2946
|
+
this.markBlockConfigDirective(directive2, nameToken);
|
|
2626
2947
|
}
|
|
2627
|
-
return this.parseTraitSumTail(
|
|
2948
|
+
return this.parseTraitSumTail(directive2);
|
|
2628
2949
|
}
|
|
2629
2950
|
if (LIFECYCLE_HOOKS.includes(name)) {
|
|
2630
2951
|
const params = [];
|
|
@@ -2731,15 +3052,22 @@ var HoloScriptPlusParser = class {
|
|
|
2731
3052
|
this.warn("Expected 'from' after named import specifiers");
|
|
2732
3053
|
}
|
|
2733
3054
|
}
|
|
3055
|
+
let wildcardAlias;
|
|
2734
3056
|
if (this.check("ASTERISK") || this.check("IDENTIFIER") && this.current().value === "*") {
|
|
2735
3057
|
this.advance();
|
|
2736
3058
|
isWildcard = true;
|
|
2737
3059
|
if (this.check("IDENTIFIER") && this.current().value === "as") {
|
|
2738
3060
|
this.advance();
|
|
3061
|
+
if (this.check("IDENTIFIER") && this.current().value !== "from") {
|
|
3062
|
+
wildcardAlias = this.advance().value;
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
3065
|
+
if (this.check("IDENTIFIER") && this.current().value === "from") {
|
|
3066
|
+
this.advance();
|
|
2739
3067
|
}
|
|
2740
3068
|
}
|
|
2741
3069
|
const path = this.expect("STRING", "Expected import path string").value;
|
|
2742
|
-
let alias = path.split("/").pop()?.replace(/\.[^.]+$/, "") || "import";
|
|
3070
|
+
let alias = wildcardAlias || path.split("/").pop()?.replace(/\.[^.]+$/, "") || "import";
|
|
2743
3071
|
if (!namedImports && this.check("IDENTIFIER") && this.current().value === "as") {
|
|
2744
3072
|
this.advance();
|
|
2745
3073
|
alias = this.expect("IDENTIFIER", "Expected alias after as").value;
|
|
@@ -2949,9 +3277,12 @@ var HoloScriptPlusParser = class {
|
|
|
2949
3277
|
this.warn(`Unknown directive @${name}`);
|
|
2950
3278
|
}
|
|
2951
3279
|
let config = {};
|
|
3280
|
+
let configStyle = "none";
|
|
2952
3281
|
if (this.check("LPAREN")) {
|
|
3282
|
+
configStyle = "paren";
|
|
2953
3283
|
config = this.parseTraitConfig();
|
|
2954
3284
|
} else if (this.check("LBRACE")) {
|
|
3285
|
+
configStyle = "block";
|
|
2955
3286
|
config = this.parseBlockContent();
|
|
2956
3287
|
}
|
|
2957
3288
|
if (this.check("COLON")) {
|
|
@@ -2962,7 +3293,32 @@ var HoloScriptPlusParser = class {
|
|
|
2962
3293
|
config.body = this.parseCodeBlock();
|
|
2963
3294
|
}
|
|
2964
3295
|
}
|
|
2965
|
-
|
|
3296
|
+
const directive = { type: "trait", name, config };
|
|
3297
|
+
if (configStyle === "block") {
|
|
3298
|
+
this.markBlockConfigDirective(directive, nameToken);
|
|
3299
|
+
}
|
|
3300
|
+
return this.parseTraitSumTail(directive);
|
|
3301
|
+
}
|
|
3302
|
+
markBlockConfigDirective(directive, token) {
|
|
3303
|
+
this.blockConfigDirectives.add(directive);
|
|
3304
|
+
this.blockConfigDirectiveLocations.set(directive, token);
|
|
3305
|
+
}
|
|
3306
|
+
traitConfigLooksLikeNodeBody(config) {
|
|
3307
|
+
if (!config || typeof config !== "object") return false;
|
|
3308
|
+
const nodeBodyKeys = /* @__PURE__ */ new Set([
|
|
3309
|
+
"geometry",
|
|
3310
|
+
"position",
|
|
3311
|
+
"rotation",
|
|
3312
|
+
"scale",
|
|
3313
|
+
"size",
|
|
3314
|
+
"color",
|
|
3315
|
+
"material",
|
|
3316
|
+
"model",
|
|
3317
|
+
"mesh",
|
|
3318
|
+
"src",
|
|
3319
|
+
"url"
|
|
3320
|
+
]);
|
|
3321
|
+
return Object.keys(config).some((key) => nodeBodyKeys.has(key));
|
|
2966
3322
|
}
|
|
2967
3323
|
parseTraitSumTail(first) {
|
|
2968
3324
|
if (!this.check("PLUS")) {
|
|
@@ -3001,95 +3357,962 @@ var HoloScriptPlusParser = class {
|
|
|
3001
3357
|
this.expect("RPAREN", "Expected )");
|
|
3002
3358
|
return value;
|
|
3003
3359
|
}
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
this.expect("IDENTIFIER", "Expected to");
|
|
3008
|
-
const to = this.expect("IDENTIFIER", "Expected to name").value;
|
|
3009
|
-
return { from, to };
|
|
3010
|
-
}
|
|
3360
|
+
// ===========================================================================
|
|
3361
|
+
// Brain Declaration Parsing
|
|
3362
|
+
// ===========================================================================
|
|
3011
3363
|
/**
|
|
3012
|
-
* Parse
|
|
3364
|
+
* Parse a top-level `brain` declaration.
|
|
3365
|
+
*
|
|
3366
|
+
* Grammar:
|
|
3367
|
+
* brain <Name> [ : @<brainType> ] {
|
|
3368
|
+
* @personality <value>
|
|
3369
|
+
* @faction_alignment <value>
|
|
3370
|
+
* @memory_persistence true|false
|
|
3371
|
+
* @preferred_ability "<Name>" [ @when { <expr> } ]
|
|
3372
|
+
* @flee_threshold <number>
|
|
3373
|
+
* @patrol_speed <number|identifier>
|
|
3374
|
+
* @waypoints [...]
|
|
3375
|
+
* state <stateName> {
|
|
3376
|
+
* transition to <target> [ @when { <expr> } ]
|
|
3377
|
+
* <action statements ...>
|
|
3378
|
+
* }
|
|
3379
|
+
* }
|
|
3013
3380
|
*/
|
|
3014
|
-
|
|
3015
|
-
|
|
3381
|
+
parseBrainDeclaration() {
|
|
3382
|
+
this.advance();
|
|
3383
|
+
const name = this.check("IDENTIFIER") ? this.advance().value : "unnamed_brain";
|
|
3384
|
+
let brainType = "behavior_tree";
|
|
3385
|
+
if (this.check("COLON")) {
|
|
3386
|
+
this.advance();
|
|
3387
|
+
if (this.check("AT")) {
|
|
3388
|
+
this.advance();
|
|
3389
|
+
if (this.check("IDENTIFIER")) {
|
|
3390
|
+
const raw = this.advance().value;
|
|
3391
|
+
if (raw === "behavior_tree" || raw === "decision_tree" || raw === "neural" || raw === "scripted") {
|
|
3392
|
+
brainType = raw;
|
|
3393
|
+
}
|
|
3394
|
+
}
|
|
3395
|
+
}
|
|
3396
|
+
}
|
|
3397
|
+
const brain = {
|
|
3398
|
+
type: "brain",
|
|
3399
|
+
name,
|
|
3400
|
+
brainType,
|
|
3401
|
+
states: [],
|
|
3402
|
+
traits: {}
|
|
3403
|
+
};
|
|
3016
3404
|
if (!this.check("LBRACE")) {
|
|
3017
|
-
|
|
3405
|
+
this.warn(`brain "${name}" missing body block { }`);
|
|
3406
|
+
return brain;
|
|
3018
3407
|
}
|
|
3019
3408
|
this.advance();
|
|
3020
3409
|
this.skipNewlines();
|
|
3021
3410
|
while (!this.check("RBRACE") && !this.check("EOF")) {
|
|
3022
3411
|
this.skipNewlines();
|
|
3023
3412
|
if (this.check("RBRACE") || this.check("EOF")) break;
|
|
3024
|
-
this.
|
|
3025
|
-
if (this.check("RBRACE") || this.check("EOF")) break;
|
|
3026
|
-
const token = this.current();
|
|
3027
|
-
const isKeyToken = token.type === "IDENTIFIER" || token.type === "STRING" || token.type === "STATE" || token.type === "STATE_MACHINE" || token.type === "INITIAL" || token.type === "ON_ENTRY" || token.type === "ON_EXIT" || token.type === "TRANSITION";
|
|
3028
|
-
if (isKeyToken) {
|
|
3029
|
-
const next = this.peek(1);
|
|
3030
|
-
if (next.type === "COLON" || next.type === "EQUALS") {
|
|
3031
|
-
const key = this.advance().value;
|
|
3032
|
-
this.advance();
|
|
3033
|
-
content[key] = this.parseValue();
|
|
3034
|
-
} else if (next.type === "STRING" || next.type === "LBRACE" || next.type === "IDENTIFIER") {
|
|
3035
|
-
const node = this.parseNode();
|
|
3036
|
-
const type = node.type;
|
|
3037
|
-
const name = node.name || `unnamed_${type}_${Object.keys(content).length}`;
|
|
3038
|
-
content[name] = node;
|
|
3039
|
-
} else {
|
|
3040
|
-
const key = this.advance().value;
|
|
3041
|
-
content[key] = true;
|
|
3042
|
-
}
|
|
3043
|
-
} else if (this.check("SPREAD")) {
|
|
3413
|
+
if (this.check("AT")) {
|
|
3044
3414
|
this.advance();
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
} else if (this.check("AT")) {
|
|
3049
|
-
const directive = this.parseDirective();
|
|
3050
|
-
if (directive) {
|
|
3051
|
-
const dirKey = ("name" in directive ? directive.name : void 0) || directive.type;
|
|
3052
|
-
content[`@${dirKey}`] = directive;
|
|
3415
|
+
if (!this.check("IDENTIFIER")) {
|
|
3416
|
+
this.warn("Expected directive name after @");
|
|
3417
|
+
continue;
|
|
3053
3418
|
}
|
|
3054
|
-
|
|
3055
|
-
|
|
3419
|
+
const dirName = this.advance().value;
|
|
3420
|
+
if (dirName === "personality") {
|
|
3421
|
+
const val = this.check("IDENTIFIER") ? this.advance().value : this.check("STRING") ? this.advance().value : "neutral";
|
|
3422
|
+
brain.personality = val;
|
|
3423
|
+
} else if (dirName === "faction_alignment") {
|
|
3424
|
+
let val = this.check("IDENTIFIER") ? this.advance().value : this.check("STRING") ? this.advance().value : "true_neutral";
|
|
3425
|
+
if (this.check("IDENTIFIER")) val += "_" + this.advance().value;
|
|
3426
|
+
brain.factionAlignment = val;
|
|
3427
|
+
} else if (dirName === "memory_persistence") {
|
|
3428
|
+
const raw = this.check("BOOLEAN") ? this.advance().value : this.check("IDENTIFIER") ? this.advance().value : "true";
|
|
3429
|
+
brain.memoryPersistence = raw !== "false";
|
|
3430
|
+
} else if (dirName === "preferred_ability") {
|
|
3431
|
+
const abilityName = this.check("STRING") ? this.advance().value : this.check("IDENTIFIER") ? this.advance().value : "";
|
|
3432
|
+
let when;
|
|
3433
|
+
if (this.check("AT")) {
|
|
3434
|
+
const saved = this.pos;
|
|
3435
|
+
this.advance();
|
|
3436
|
+
if (this.check("IDENTIFIER") && this.current().value === "when") {
|
|
3437
|
+
this.advance();
|
|
3438
|
+
if (this.check("LBRACE")) when = this.parseCodeBlock();
|
|
3439
|
+
} else {
|
|
3440
|
+
this.pos = saved;
|
|
3441
|
+
}
|
|
3442
|
+
}
|
|
3443
|
+
brain.preferredAbility = { name: abilityName, when };
|
|
3444
|
+
} else if (dirName === "flee_threshold") {
|
|
3445
|
+
brain.fleeThreshold = this.check("NUMBER") ? parseFloat(this.advance().value) : 0.25;
|
|
3446
|
+
} else if (dirName === "patrol_speed") {
|
|
3447
|
+
brain.patrolSpeed = this.check("NUMBER") ? parseFloat(this.advance().value) : this.check("IDENTIFIER") ? this.advance().value : 1;
|
|
3448
|
+
} else if (dirName === "waypoints") {
|
|
3449
|
+
brain.waypoints = this.check("LBRACKET") ? this.parseValue() : [];
|
|
3450
|
+
} else if (dirName === "goal") {
|
|
3451
|
+
const cfg = this.check("LBRACE") ? this.parseBlockContent() : {};
|
|
3452
|
+
if (!brain.goals) brain.goals = [];
|
|
3453
|
+
brain.goals.push({
|
|
3454
|
+
name: typeof cfg.name === "string" ? cfg.name : String(cfg.name ?? `goal_${brain.goals.length}`),
|
|
3455
|
+
desiredState: cfg.desiredState && typeof cfg.desiredState === "object" ? cfg.desiredState : void 0,
|
|
3456
|
+
priority: typeof cfg.priority === "number" ? cfg.priority : void 0
|
|
3457
|
+
});
|
|
3458
|
+
} else if (dirName === "escalation") {
|
|
3459
|
+
const cfg = this.check("LBRACE") ? this.parseBlockContent() : {};
|
|
3460
|
+
if (!brain.escalations) brain.escalations = [];
|
|
3461
|
+
brain.escalations.push({
|
|
3462
|
+
on: typeof cfg.on === "string" ? cfg.on : String(cfg.on ?? ""),
|
|
3463
|
+
action: typeof cfg.action === "string" ? cfg.action : "notify"
|
|
3464
|
+
});
|
|
3465
|
+
} else if (dirName === "provider_policy") {
|
|
3466
|
+
const cfg = this.check("LBRACE") ? this.parseBlockContent() : {};
|
|
3467
|
+
brain.providerPolicy = {
|
|
3468
|
+
prefer: typeof cfg.prefer === "string" ? cfg.prefer : void 0,
|
|
3469
|
+
fallback: typeof cfg.fallback === "string" ? cfg.fallback : void 0,
|
|
3470
|
+
requires: typeof cfg.requires === "string" ? cfg.requires : void 0
|
|
3471
|
+
};
|
|
3472
|
+
} else if (dirName === "frame_declaration") {
|
|
3473
|
+
const cfg = this.check("LBRACE") ? this.parseBlockContent() : {};
|
|
3474
|
+
brain.frameDeclaration = coerceConfig(cfg);
|
|
3475
|
+
} else if (dirName === "behavior_tree") {
|
|
3476
|
+
const config = this.check("LBRACE") ? this.parseBlockContent() : {};
|
|
3477
|
+
brain.traits["behavior_tree"] = config;
|
|
3478
|
+
} else {
|
|
3479
|
+
const config = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
|
|
3480
|
+
brain.traits[dirName] = config;
|
|
3481
|
+
}
|
|
3482
|
+
this.skipNewlines();
|
|
3483
|
+
continue;
|
|
3484
|
+
}
|
|
3485
|
+
if (this.check("STATE") || this.check("IDENTIFIER") && this.current().value === "state") {
|
|
3056
3486
|
this.advance();
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3487
|
+
const stateName = this.check("IDENTIFIER") ? this.advance().value : "unnamed";
|
|
3488
|
+
const brainState = {
|
|
3489
|
+
name: stateName,
|
|
3490
|
+
transitions: [],
|
|
3491
|
+
actions: [],
|
|
3492
|
+
traits: {}
|
|
3493
|
+
};
|
|
3494
|
+
if (this.check("LBRACE")) {
|
|
3060
3495
|
this.advance();
|
|
3496
|
+
this.skipNewlines();
|
|
3497
|
+
while (!this.check("RBRACE") && !this.check("EOF")) {
|
|
3498
|
+
this.skipNewlines();
|
|
3499
|
+
if (this.check("RBRACE") || this.check("EOF")) break;
|
|
3500
|
+
if (this.check("TRANSITION") || this.check("IDENTIFIER") && this.current().value === "transition") {
|
|
3501
|
+
this.advance();
|
|
3502
|
+
let to = "";
|
|
3503
|
+
if (this.check("IDENTIFIER") && this.current().value === "to") {
|
|
3504
|
+
this.advance();
|
|
3505
|
+
}
|
|
3506
|
+
if (this.check("IDENTIFIER")) to = this.advance().value;
|
|
3507
|
+
else if (this.check("STRING")) to = this.advance().value;
|
|
3508
|
+
let when;
|
|
3509
|
+
if (this.check("AT")) {
|
|
3510
|
+
const saved = this.pos;
|
|
3511
|
+
this.advance();
|
|
3512
|
+
if (this.check("IDENTIFIER") && this.current().value === "when") {
|
|
3513
|
+
this.advance();
|
|
3514
|
+
if (this.check("LBRACE")) when = this.parseCodeBlock();
|
|
3515
|
+
} else {
|
|
3516
|
+
this.pos = saved;
|
|
3517
|
+
}
|
|
3518
|
+
}
|
|
3519
|
+
brainState.transitions.push({ to, when });
|
|
3520
|
+
} else if (this.check("AT")) {
|
|
3521
|
+
this.advance();
|
|
3522
|
+
const innerDir = this.check("IDENTIFIER") ? this.advance().value : "";
|
|
3523
|
+
const config = this.check("LBRACE") ? this.parseBlockContent() : this.check("LPAREN") ? this.parseTraitConfig() : {};
|
|
3524
|
+
brainState.traits[innerDir] = config;
|
|
3525
|
+
} else if (this.check("IDENTIFIER") && isCognitiveVerb(this.current().value)) {
|
|
3526
|
+
const saved = this.pos;
|
|
3527
|
+
const verb = this.advance().value;
|
|
3528
|
+
if (this.check("LBRACE")) {
|
|
3529
|
+
const config = this.parseBlockContent();
|
|
3530
|
+
if (!brainState.cognitiveActions) brainState.cognitiveActions = [];
|
|
3531
|
+
brainState.cognitiveActions.push({ kind: "cognitive", verb, config });
|
|
3532
|
+
} else {
|
|
3533
|
+
this.pos = saved;
|
|
3534
|
+
const parts = [this.advance().value];
|
|
3535
|
+
while (!this.check("NEWLINE") && !this.check("EOF") && !this.check("RBRACE")) {
|
|
3536
|
+
parts.push(this.advance().value);
|
|
3537
|
+
}
|
|
3538
|
+
brainState.actions.push(parts.join(" "));
|
|
3539
|
+
}
|
|
3540
|
+
} else if (this.check("IDENTIFIER") && this.tokens[this.pos + 1]?.type === "LBRACE" && nearestCognitiveVerb(this.current().value)) {
|
|
3541
|
+
const typo = this.current().value;
|
|
3542
|
+
const suggestion = nearestCognitiveVerb(typo);
|
|
3543
|
+
this.warn(`Unknown cognitive verb '${typo}' \u2014 did you mean '${suggestion}'?`);
|
|
3544
|
+
this.advance();
|
|
3545
|
+
this.parseBlockContent();
|
|
3546
|
+
brainState.actions.push(typo);
|
|
3547
|
+
} else if (this.check("IDENTIFIER")) {
|
|
3548
|
+
const parts = [this.advance().value];
|
|
3549
|
+
while (!this.check("NEWLINE") && !this.check("EOF") && !this.check("RBRACE")) {
|
|
3550
|
+
parts.push(this.advance().value);
|
|
3551
|
+
}
|
|
3552
|
+
brainState.actions.push(parts.join(" "));
|
|
3553
|
+
} else {
|
|
3554
|
+
this.advance();
|
|
3555
|
+
}
|
|
3556
|
+
this.skipNewlines();
|
|
3557
|
+
}
|
|
3558
|
+
this.expect("RBRACE", "Expected } to close state block");
|
|
3061
3559
|
}
|
|
3062
|
-
|
|
3063
|
-
this.
|
|
3560
|
+
brain.states.push(brainState);
|
|
3561
|
+
this.skipNewlines();
|
|
3562
|
+
continue;
|
|
3563
|
+
}
|
|
3564
|
+
if (this.check("IDENTIFIER")) {
|
|
3565
|
+
const parts = [this.advance().value];
|
|
3566
|
+
while (!this.check("NEWLINE") && !this.check("EOF") && !this.check("RBRACE")) {
|
|
3567
|
+
parts.push(this.advance().value);
|
|
3568
|
+
}
|
|
3569
|
+
brain.traits["_actions"] = [
|
|
3570
|
+
...brain.traits["_actions"] || [],
|
|
3571
|
+
parts.join(" ")
|
|
3572
|
+
];
|
|
3064
3573
|
} else {
|
|
3065
3574
|
this.advance();
|
|
3066
3575
|
}
|
|
3067
|
-
if (this.check("COMMA")) this.advance();
|
|
3068
3576
|
this.skipNewlines();
|
|
3069
3577
|
}
|
|
3070
|
-
this.expect("RBRACE", "Expected }");
|
|
3071
|
-
return
|
|
3578
|
+
this.expect("RBRACE", "Expected } to close brain declaration");
|
|
3579
|
+
return brain;
|
|
3072
3580
|
}
|
|
3073
3581
|
/**
|
|
3074
|
-
* Parse
|
|
3582
|
+
* Parse a .hs `connect` statement.
|
|
3583
|
+
* Syntax (full .hs format):
|
|
3584
|
+
* connect <source> -> <target>
|
|
3585
|
+
* where <source> and <target> are dotted member chains, optionally followed
|
|
3586
|
+
* by assignment for state connections:
|
|
3587
|
+
* connect alarm_bell.alarm_triggered -> guard_captain.state.alert_level = 3
|
|
3588
|
+
*
|
|
3589
|
+
* Strategy: consume the `connect` keyword, then collect all tokens up to
|
|
3590
|
+
* (but not including) the next NEWLINE / EOF as a raw string. This is
|
|
3591
|
+
* intentionally permissive — the connect statement has a rich surface syntax
|
|
3592
|
+
* (dotted paths, ARROW, assignments) that the generic property parser cannot
|
|
3593
|
+
* handle. Semantic validation of the wiring is a separate compilation phase.
|
|
3075
3594
|
*/
|
|
3076
|
-
|
|
3077
|
-
const
|
|
3078
|
-
|
|
3079
|
-
|
|
3595
|
+
parseHsConnectStatement() {
|
|
3596
|
+
const startToken = this.current();
|
|
3597
|
+
this.advance();
|
|
3598
|
+
const toks = [];
|
|
3599
|
+
while (!this.check("NEWLINE") && !this.check("EOF")) {
|
|
3600
|
+
toks.push(this.advance());
|
|
3080
3601
|
}
|
|
3602
|
+
const arrowIdx = toks.findIndex((t) => t.type === "ARROW");
|
|
3603
|
+
const fromToks = arrowIdx >= 0 ? toks.slice(0, arrowIdx) : toks;
|
|
3604
|
+
const toToks = arrowIdx >= 0 ? toks.slice(arrowIdx + 1) : [];
|
|
3605
|
+
return {
|
|
3606
|
+
type: "connection",
|
|
3607
|
+
properties: {
|
|
3608
|
+
from: this.joinTokensSmart(fromToks),
|
|
3609
|
+
to: this.joinTokensSmart(toToks),
|
|
3610
|
+
raw: this.joinTokensSmart(toks)
|
|
3611
|
+
},
|
|
3612
|
+
directives: [],
|
|
3613
|
+
children: [],
|
|
3614
|
+
traits: /* @__PURE__ */ new Map(),
|
|
3615
|
+
loc: {
|
|
3616
|
+
start: { line: startToken.line, column: startToken.column },
|
|
3617
|
+
end: { line: this.current().line, column: this.current().column }
|
|
3618
|
+
}
|
|
3619
|
+
};
|
|
3620
|
+
}
|
|
3621
|
+
/**
|
|
3622
|
+
* Parse a .hs `execute` statement.
|
|
3623
|
+
* Syntax:
|
|
3624
|
+
* execute <target>(<args>) [repeat forever | every <interval>]
|
|
3625
|
+
* Examples:
|
|
3626
|
+
* execute guard_captain.patrol() repeat forever
|
|
3627
|
+
* execute temp_sensor_A.read() every 1000ms
|
|
3628
|
+
*
|
|
3629
|
+
* Strategy: consume `execute` then collect all tokens to end of line.
|
|
3630
|
+
* The target is the leading member chain plus one balanced call-paren
|
|
3631
|
+
* group; everything after it is the schedule clause.
|
|
3632
|
+
*/
|
|
3633
|
+
parseHsExecuteStatement() {
|
|
3634
|
+
const startToken = this.current();
|
|
3081
3635
|
this.advance();
|
|
3082
|
-
|
|
3083
|
-
while (!this.check("
|
|
3084
|
-
this.
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3636
|
+
const toks = [];
|
|
3637
|
+
while (!this.check("NEWLINE") && !this.check("EOF")) {
|
|
3638
|
+
toks.push(this.advance());
|
|
3639
|
+
}
|
|
3640
|
+
let end = toks.length;
|
|
3641
|
+
let depth = 0;
|
|
3642
|
+
for (let i = 0; i < toks.length; i++) {
|
|
3643
|
+
const t = toks[i];
|
|
3644
|
+
if (t.type === "LPAREN") {
|
|
3645
|
+
depth++;
|
|
3646
|
+
} else if (t.type === "RPAREN") {
|
|
3647
|
+
depth--;
|
|
3648
|
+
if (depth === 0) {
|
|
3649
|
+
end = i + 1;
|
|
3650
|
+
break;
|
|
3651
|
+
}
|
|
3652
|
+
} else if (depth === 0 && t.type !== "IDENTIFIER" && t.type !== "DOT" && t.type !== "NUMBER") {
|
|
3653
|
+
end = i;
|
|
3654
|
+
break;
|
|
3655
|
+
}
|
|
3656
|
+
}
|
|
3657
|
+
const target = this.joinTokensSmart(toks.slice(0, end));
|
|
3658
|
+
const schedule = this.joinTokensSmart(toks.slice(end));
|
|
3659
|
+
return {
|
|
3660
|
+
type: "execute",
|
|
3661
|
+
properties: { target, schedule, raw: this.joinTokensSmart(toks) },
|
|
3662
|
+
directives: [],
|
|
3663
|
+
children: [],
|
|
3664
|
+
traits: /* @__PURE__ */ new Map(),
|
|
3665
|
+
loc: {
|
|
3666
|
+
start: { line: startToken.line, column: startToken.column },
|
|
3667
|
+
end: { line: this.current().line, column: this.current().column }
|
|
3668
|
+
}
|
|
3669
|
+
};
|
|
3670
|
+
}
|
|
3671
|
+
// ===========================================================================
|
|
3672
|
+
// Pipeline DSL block parsing (transform / filter / branch / validate)
|
|
3673
|
+
// ===========================================================================
|
|
3674
|
+
/**
|
|
3675
|
+
* Reassemble token values into readable source text: no spaces around
|
|
3676
|
+
* member/call/index punctuation, string literals re-quoted.
|
|
3677
|
+
*/
|
|
3678
|
+
joinTokensSmart(tokens) {
|
|
3679
|
+
const NO_SPACE_BEFORE = /* @__PURE__ */ new Set([
|
|
3680
|
+
"DOT",
|
|
3681
|
+
"COMMA",
|
|
3682
|
+
"LPAREN",
|
|
3683
|
+
"RPAREN",
|
|
3684
|
+
"LBRACKET",
|
|
3685
|
+
"RBRACKET",
|
|
3686
|
+
"OPTIONAL_DOT"
|
|
3687
|
+
]);
|
|
3688
|
+
const NO_SPACE_AFTER = /* @__PURE__ */ new Set(["DOT", "LPAREN", "LBRACKET", "OPTIONAL_DOT", "EXCLAMATION"]);
|
|
3689
|
+
let out = "";
|
|
3690
|
+
let prev = null;
|
|
3691
|
+
for (const t of tokens) {
|
|
3692
|
+
const text = t.type === "STRING" ? JSON.stringify(t.value) : t.value;
|
|
3693
|
+
if (prev && !NO_SPACE_BEFORE.has(t.type) && !NO_SPACE_AFTER.has(prev.type)) {
|
|
3694
|
+
out += " ";
|
|
3695
|
+
}
|
|
3696
|
+
out += text;
|
|
3697
|
+
prev = t;
|
|
3698
|
+
}
|
|
3699
|
+
return out;
|
|
3700
|
+
}
|
|
3701
|
+
/** Capture a dotted/indexed path: sku, a.b.c, results[0].id, entries[] */
|
|
3702
|
+
capturePipelinePath() {
|
|
3703
|
+
const toks = [];
|
|
3704
|
+
if (this.check("IDENTIFIER") || this.check("STRING") || this.check("UNDERSCORE")) {
|
|
3705
|
+
toks.push(this.advance());
|
|
3706
|
+
}
|
|
3707
|
+
for (; ; ) {
|
|
3708
|
+
if (this.check("DOT")) {
|
|
3709
|
+
toks.push(this.advance());
|
|
3710
|
+
if (this.check("IDENTIFIER") || this.check("NUMBER") || this.check("UNDERSCORE")) {
|
|
3711
|
+
toks.push(this.advance());
|
|
3712
|
+
}
|
|
3713
|
+
continue;
|
|
3714
|
+
}
|
|
3715
|
+
if (this.check("LBRACKET")) {
|
|
3716
|
+
let depth = 0;
|
|
3717
|
+
do {
|
|
3718
|
+
const t = this.advance();
|
|
3719
|
+
toks.push(t);
|
|
3720
|
+
if (t.type === "LBRACKET") depth++;
|
|
3721
|
+
else if (t.type === "RBRACKET") depth--;
|
|
3722
|
+
} while (depth > 0 && !this.check("EOF"));
|
|
3723
|
+
continue;
|
|
3724
|
+
}
|
|
3725
|
+
break;
|
|
3726
|
+
}
|
|
3727
|
+
return { raw: this.joinTokensSmart(toks), tokens: toks };
|
|
3728
|
+
}
|
|
3729
|
+
/** Capture a transform op call: trim() / multiply(100) / increment_if(a == b.c) */
|
|
3730
|
+
capturePipelineOp() {
|
|
3731
|
+
const toks = [];
|
|
3732
|
+
if (this.check("IDENTIFIER")) {
|
|
3733
|
+
toks.push(this.advance());
|
|
3734
|
+
}
|
|
3735
|
+
if (this.check("LPAREN")) {
|
|
3736
|
+
let depth = 0;
|
|
3737
|
+
do {
|
|
3738
|
+
const t = this.advance();
|
|
3739
|
+
toks.push(t);
|
|
3740
|
+
if (t.type === "LPAREN") depth++;
|
|
3741
|
+
else if (t.type === "RPAREN") depth--;
|
|
3742
|
+
} while (depth > 0 && !this.check("EOF"));
|
|
3743
|
+
}
|
|
3744
|
+
return this.joinTokensSmart(toks);
|
|
3745
|
+
}
|
|
3746
|
+
/** True when an ARROW appears before the end of the current statement line. */
|
|
3747
|
+
hasArrowBeforeEOL() {
|
|
3748
|
+
for (let look = this.pos; look < this.tokens.length; look++) {
|
|
3749
|
+
const t = this.tokens[look].type;
|
|
3750
|
+
if (t === "ARROW") return true;
|
|
3751
|
+
if (t === "NEWLINE" || t === "EOF" || t === "RBRACE" || t === "LBRACE") return false;
|
|
3752
|
+
}
|
|
3753
|
+
return false;
|
|
3754
|
+
}
|
|
3755
|
+
/**
|
|
3756
|
+
* Capture expression tokens to end of line, honoring `||` / `&&`
|
|
3757
|
+
* line continuations:
|
|
3758
|
+
* where: stock != previous.stock
|
|
3759
|
+
* || costCents != previous.costCents
|
|
3760
|
+
*/
|
|
3761
|
+
captureExpressionToEOL() {
|
|
3762
|
+
const toks = [];
|
|
3763
|
+
for (; ; ) {
|
|
3764
|
+
while (!this.check("NEWLINE") && !this.check("EOF") && !this.check("RBRACE")) {
|
|
3765
|
+
toks.push(this.advance());
|
|
3766
|
+
}
|
|
3767
|
+
if (this.check("NEWLINE")) {
|
|
3768
|
+
let look = this.pos;
|
|
3769
|
+
while (look < this.tokens.length && ["NEWLINE", "INDENT", "DEDENT"].includes(this.tokens[look].type)) {
|
|
3770
|
+
look++;
|
|
3771
|
+
}
|
|
3772
|
+
const next = this.tokens[look];
|
|
3773
|
+
if (next && (next.type === "OR" || next.type === "AND")) {
|
|
3774
|
+
this.pos = look;
|
|
3775
|
+
continue;
|
|
3776
|
+
}
|
|
3777
|
+
}
|
|
3778
|
+
break;
|
|
3779
|
+
}
|
|
3780
|
+
return toks;
|
|
3781
|
+
}
|
|
3782
|
+
/**
|
|
3783
|
+
* YAML-style block scalar property value:
|
|
3784
|
+
* prompt: |
|
|
3785
|
+
* Extract wisdom from this content.
|
|
3786
|
+
* Return JSON.
|
|
3787
|
+
* Captures the following lines from raw source while they are blank or
|
|
3788
|
+
* indented deeper than the key line, dedents, and skips their tokens.
|
|
3789
|
+
*/
|
|
3790
|
+
parseBlockScalar(keyToken) {
|
|
3791
|
+
this.advance();
|
|
3792
|
+
const keyIndent = keyToken.column - 1;
|
|
3793
|
+
const lines = this.source.split("\n");
|
|
3794
|
+
const collected = [];
|
|
3795
|
+
let lastLine = keyToken.line;
|
|
3796
|
+
for (let ln = keyToken.line + 1; ln <= lines.length; ln++) {
|
|
3797
|
+
const text = lines[ln - 1];
|
|
3798
|
+
if (text.trim() === "") {
|
|
3799
|
+
collected.push("");
|
|
3800
|
+
lastLine = ln;
|
|
3801
|
+
continue;
|
|
3802
|
+
}
|
|
3803
|
+
const indent = text.length - text.trimStart().length;
|
|
3804
|
+
if (indent <= keyIndent) break;
|
|
3805
|
+
collected.push(text);
|
|
3806
|
+
lastLine = ln;
|
|
3807
|
+
}
|
|
3808
|
+
while (!this.check("EOF") && this.current().line <= lastLine) {
|
|
3809
|
+
this.advance();
|
|
3810
|
+
}
|
|
3811
|
+
const nonBlank = collected.filter((l) => l.trim() !== "");
|
|
3812
|
+
const minIndent = nonBlank.length ? Math.min(...nonBlank.map((l) => l.length - l.trimStart().length)) : 0;
|
|
3813
|
+
return collected.map((l) => l.slice(minIndent)).join("\n").replace(/\s+$/, "");
|
|
3814
|
+
}
|
|
3815
|
+
/** Property value inside a pipeline DSL block. */
|
|
3816
|
+
parsePipelinePropertyValue(keyToken) {
|
|
3817
|
+
if (this.check("PIPE")) {
|
|
3818
|
+
const next = this.peek(1);
|
|
3819
|
+
if (!next || next.type === "NEWLINE" || next.type === "EOF") {
|
|
3820
|
+
return this.parseBlockScalar(keyToken);
|
|
3821
|
+
}
|
|
3822
|
+
}
|
|
3823
|
+
if (this.check("LBRACE") || this.check("LBRACKET")) {
|
|
3824
|
+
return this.parseValue();
|
|
3825
|
+
}
|
|
3826
|
+
const toks = this.captureExpressionToEOL();
|
|
3827
|
+
if (toks.length === 1) {
|
|
3828
|
+
const t = toks[0];
|
|
3829
|
+
if (t.type === "STRING") return t.value;
|
|
3830
|
+
if (t.type === "NUMBER") {
|
|
3831
|
+
const n = Number(t.value);
|
|
3832
|
+
return Number.isNaN(n) ? t.value : n;
|
|
3833
|
+
}
|
|
3834
|
+
if (t.value === "true") return true;
|
|
3835
|
+
if (t.value === "false") return false;
|
|
3836
|
+
return t.value;
|
|
3837
|
+
}
|
|
3838
|
+
return this.joinTokensSmart(toks);
|
|
3839
|
+
}
|
|
3840
|
+
/**
|
|
3841
|
+
* Body parser for pipeline DSL blocks. Handles, per statement:
|
|
3842
|
+
* key: value → property (incl. block scalars)
|
|
3843
|
+
* src.path[0] -> dst.path : op() : op2(...) → mapping child
|
|
3844
|
+
* when <cond> -> <target> → when child (branch)
|
|
3845
|
+
* default -> <target> → default child (branch)
|
|
3846
|
+
* field.path : rule, rule(...) → constraint child (validate /
|
|
3847
|
+
* dotted fields anywhere)
|
|
3848
|
+
* Statements are captured structurally with their raw text preserved;
|
|
3849
|
+
* semantic validation of the wiring is a separate compilation phase.
|
|
3850
|
+
*/
|
|
3851
|
+
parsePipelineBlock(kind, name, startToken) {
|
|
3852
|
+
this.expect("LBRACE", `Expected { after ${kind} ${name}`);
|
|
3853
|
+
const properties = {};
|
|
3854
|
+
const children = [];
|
|
3855
|
+
const directives = [];
|
|
3856
|
+
const traits = /* @__PURE__ */ new Map();
|
|
3857
|
+
const childLoc = (tok) => ({
|
|
3858
|
+
start: { line: tok.line, column: tok.column },
|
|
3859
|
+
end: { line: this.current().line, column: this.current().column }
|
|
3860
|
+
});
|
|
3861
|
+
while (!this.check("RBRACE") && !this.check("EOF")) {
|
|
3862
|
+
try {
|
|
3863
|
+
this.skipNewlines();
|
|
3864
|
+
if (this.check("RBRACE") || this.check("EOF")) break;
|
|
3865
|
+
if (this.check("AT")) {
|
|
3866
|
+
const directive = this.parseDirective();
|
|
3867
|
+
if (directive) {
|
|
3868
|
+
if (directive.type === "trait") {
|
|
3869
|
+
traits.set(directive.name, directive.config);
|
|
3870
|
+
this.hasVRTraits = true;
|
|
3871
|
+
}
|
|
3872
|
+
directives.push(directive);
|
|
3873
|
+
}
|
|
3874
|
+
} else if (kind === "branch" && this.check("IDENTIFIER") && this.current().value === "when") {
|
|
3875
|
+
const stmtStart = this.advance();
|
|
3876
|
+
const condToks = [];
|
|
3877
|
+
while (!this.check("ARROW") && !this.check("NEWLINE") && !this.check("EOF")) {
|
|
3878
|
+
condToks.push(this.advance());
|
|
3879
|
+
}
|
|
3880
|
+
let target = "";
|
|
3881
|
+
if (this.check("ARROW")) {
|
|
3882
|
+
this.advance();
|
|
3883
|
+
const targetToks = [];
|
|
3884
|
+
while (!this.check("NEWLINE") && !this.check("EOF") && !this.check("RBRACE")) {
|
|
3885
|
+
targetToks.push(this.advance());
|
|
3886
|
+
}
|
|
3887
|
+
target = this.joinTokensSmart(targetToks);
|
|
3888
|
+
}
|
|
3889
|
+
children.push({
|
|
3890
|
+
type: "when",
|
|
3891
|
+
condition: this.joinTokensSmart(condToks),
|
|
3892
|
+
target,
|
|
3893
|
+
loc: childLoc(stmtStart)
|
|
3894
|
+
});
|
|
3895
|
+
} else if (this.hasArrowBeforeEOL()) {
|
|
3896
|
+
const stmtStart = this.current();
|
|
3897
|
+
const lhsToks = [];
|
|
3898
|
+
while (!this.check("ARROW") && !this.check("NEWLINE") && !this.check("EOF")) {
|
|
3899
|
+
lhsToks.push(this.advance());
|
|
3900
|
+
}
|
|
3901
|
+
if (this.check("ARROW")) this.advance();
|
|
3902
|
+
const from = this.joinTokensSmart(lhsToks);
|
|
3903
|
+
if (kind === "branch") {
|
|
3904
|
+
const targetToks = [];
|
|
3905
|
+
while (!this.check("NEWLINE") && !this.check("EOF") && !this.check("RBRACE")) {
|
|
3906
|
+
targetToks.push(this.advance());
|
|
3907
|
+
}
|
|
3908
|
+
children.push({
|
|
3909
|
+
type: from === "default" ? "default" : "route",
|
|
3910
|
+
from,
|
|
3911
|
+
target: this.joinTokensSmart(targetToks),
|
|
3912
|
+
loc: childLoc(stmtStart)
|
|
3913
|
+
});
|
|
3914
|
+
} else {
|
|
3915
|
+
const to = this.capturePipelinePath();
|
|
3916
|
+
const ops = [];
|
|
3917
|
+
while (this.check("COLON")) {
|
|
3918
|
+
this.advance();
|
|
3919
|
+
ops.push(this.capturePipelineOp());
|
|
3920
|
+
}
|
|
3921
|
+
children.push({
|
|
3922
|
+
type: "mapping",
|
|
3923
|
+
from,
|
|
3924
|
+
to: to.raw,
|
|
3925
|
+
ops,
|
|
3926
|
+
loc: childLoc(stmtStart)
|
|
3927
|
+
});
|
|
3928
|
+
}
|
|
3929
|
+
} else if (this.check("IDENTIFIER") || this.check("STRING")) {
|
|
3930
|
+
const keyToken = this.current();
|
|
3931
|
+
const path = this.capturePipelinePath();
|
|
3932
|
+
if (this.check("COLON")) {
|
|
3933
|
+
this.advance();
|
|
3934
|
+
const pathIsDotted = path.tokens.some((t) => t.type === "DOT" || t.type === "LBRACKET");
|
|
3935
|
+
if (kind === "validate" || pathIsDotted) {
|
|
3936
|
+
const ruleToks = this.captureExpressionToEOL();
|
|
3937
|
+
children.push({
|
|
3938
|
+
type: "constraint",
|
|
3939
|
+
field: path.raw,
|
|
3940
|
+
rules: this.joinTokensSmart(ruleToks),
|
|
3941
|
+
loc: childLoc(keyToken)
|
|
3942
|
+
});
|
|
3943
|
+
} else {
|
|
3944
|
+
properties[path.raw] = this.parsePipelinePropertyValue(keyToken);
|
|
3945
|
+
}
|
|
3946
|
+
} else {
|
|
3947
|
+
properties[path.raw] = true;
|
|
3948
|
+
}
|
|
3949
|
+
} else if (this.check("COMMA")) {
|
|
3950
|
+
this.advance();
|
|
3951
|
+
} else {
|
|
3952
|
+
this.error(
|
|
3953
|
+
`Unexpected token ${this.current().type} "${this.current().value}" in ${kind} block`,
|
|
3954
|
+
"HSP001"
|
|
3955
|
+
);
|
|
3956
|
+
this.synchronizeProperty();
|
|
3957
|
+
}
|
|
3958
|
+
this.skipNewlines();
|
|
3959
|
+
} catch (e) {
|
|
3960
|
+
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
3961
|
+
if (errorMessage !== "ParseError") console.error(e);
|
|
3962
|
+
this.synchronizeProperty();
|
|
3963
|
+
}
|
|
3964
|
+
}
|
|
3965
|
+
this.expect("RBRACE", "Expected }");
|
|
3966
|
+
return {
|
|
3967
|
+
type: kind,
|
|
3968
|
+
name,
|
|
3969
|
+
id: name,
|
|
3970
|
+
properties,
|
|
3971
|
+
directives,
|
|
3972
|
+
children,
|
|
3973
|
+
traits,
|
|
3974
|
+
loc: {
|
|
3975
|
+
start: { line: startToken.line, column: startToken.column },
|
|
3976
|
+
end: { line: this.current().line, column: this.current().column }
|
|
3977
|
+
}
|
|
3978
|
+
};
|
|
3979
|
+
}
|
|
3980
|
+
/** @deprecated Use parseHsConnectStatement for .hs connect syntax */
|
|
3981
|
+
parseConnectionStatement() {
|
|
3982
|
+
this.expect("IDENTIFIER", "Expected connect");
|
|
3983
|
+
const from = this.expect("IDENTIFIER", "Expected from name").value;
|
|
3984
|
+
this.expect("IDENTIFIER", "Expected to");
|
|
3985
|
+
const to = this.expect("IDENTIFIER", "Expected to name").value;
|
|
3986
|
+
return { from, to };
|
|
3987
|
+
}
|
|
3988
|
+
/**
|
|
3989
|
+
* Map a reaction trigger to its routing bucket (mirrors the .hs parser's
|
|
3990
|
+
* reactionCategory; the movement-trigger list comes from the locomotion SSOT).
|
|
3991
|
+
*/
|
|
3992
|
+
hsplusReactionCategory(trigger) {
|
|
3993
|
+
if (isLocomotionReactionTrigger(trigger)) return "movement";
|
|
3994
|
+
switch (trigger) {
|
|
3995
|
+
case "on_interact":
|
|
3996
|
+
case "on_grab":
|
|
3997
|
+
case "on_release":
|
|
3998
|
+
case "on_use":
|
|
3999
|
+
case "on_hover":
|
|
4000
|
+
return "interaction";
|
|
4001
|
+
case "on_collision":
|
|
4002
|
+
case "on_collide":
|
|
4003
|
+
case "on_proximity":
|
|
4004
|
+
return "collision";
|
|
4005
|
+
case "on_spawn":
|
|
4006
|
+
case "on_death":
|
|
4007
|
+
case "on_enter":
|
|
4008
|
+
case "on_exit":
|
|
4009
|
+
case "on_tick":
|
|
4010
|
+
return "lifecycle";
|
|
4011
|
+
case "on_combat":
|
|
4012
|
+
case "on_cast":
|
|
4013
|
+
return "combat";
|
|
4014
|
+
case "on_signal":
|
|
4015
|
+
case "on_input":
|
|
4016
|
+
return "signal";
|
|
4017
|
+
default:
|
|
4018
|
+
return "custom";
|
|
4019
|
+
}
|
|
4020
|
+
}
|
|
4021
|
+
/**
|
|
4022
|
+
* Parse a declarative reaction block attached to an entity:
|
|
4023
|
+
* react {
|
|
4024
|
+
* on_grab(hand) => highlight()
|
|
4025
|
+
* on_proximity(player) => alert(player)
|
|
4026
|
+
* on_use => { open(); play_sound("creak") }
|
|
4027
|
+
* }
|
|
4028
|
+
* A leading `on` word is optional (`on collide(...)` == `on_collide(...)`).
|
|
4029
|
+
* Each entry becomes a `reaction` child node carrying trigger/params/body and
|
|
4030
|
+
* an inferred ReactionCategory. Body is captured raw (an expression or block).
|
|
4031
|
+
*/
|
|
4032
|
+
parseHsPlusReactBlock(startToken) {
|
|
4033
|
+
const startLoc = { line: startToken.line, column: startToken.column };
|
|
4034
|
+
const reactions = [];
|
|
4035
|
+
this.skipNewlines();
|
|
4036
|
+
if (this.check("LBRACE")) {
|
|
4037
|
+
this.advance();
|
|
4038
|
+
this.skipNewlines();
|
|
4039
|
+
while (!this.check("RBRACE") && !this.check("EOF")) {
|
|
4040
|
+
this.skipNewlines();
|
|
4041
|
+
if (this.check("RBRACE") || this.check("EOF")) break;
|
|
4042
|
+
let triggerPrefix = "";
|
|
4043
|
+
if (this.check("IDENTIFIER") && this.current().value === "on" && this.tokens[this.pos + 1]?.type === "IDENTIFIER") {
|
|
4044
|
+
this.advance();
|
|
4045
|
+
triggerPrefix = "on_";
|
|
4046
|
+
}
|
|
4047
|
+
if (!this.check("IDENTIFIER")) {
|
|
4048
|
+
this.advance();
|
|
4049
|
+
continue;
|
|
4050
|
+
}
|
|
4051
|
+
const trigger = triggerPrefix + this.advance().value;
|
|
4052
|
+
const params = [];
|
|
4053
|
+
if (this.check("LPAREN")) {
|
|
4054
|
+
this.advance();
|
|
4055
|
+
while (!this.check("RPAREN") && !this.check("EOF")) {
|
|
4056
|
+
if (this.check("IDENTIFIER")) params.push(this.advance().value);
|
|
4057
|
+
else this.advance();
|
|
4058
|
+
if (this.check("COMMA")) this.advance();
|
|
4059
|
+
}
|
|
4060
|
+
if (this.check("RPAREN")) this.advance();
|
|
4061
|
+
}
|
|
4062
|
+
if (this.check("ARROW")) this.advance();
|
|
4063
|
+
let body = "";
|
|
4064
|
+
if (this.check("LBRACE")) {
|
|
4065
|
+
body = this.parseRawBlock();
|
|
4066
|
+
} else {
|
|
4067
|
+
const parts = [];
|
|
4068
|
+
while (!this.check("NEWLINE") && !this.check("EOF") && !this.check("RBRACE")) {
|
|
4069
|
+
parts.push(this.advance().value);
|
|
4070
|
+
}
|
|
4071
|
+
body = parts.join(" ").trim();
|
|
4072
|
+
}
|
|
4073
|
+
reactions.push({
|
|
4074
|
+
type: "reaction",
|
|
4075
|
+
name: trigger,
|
|
4076
|
+
event: trigger,
|
|
4077
|
+
body,
|
|
4078
|
+
properties: {
|
|
4079
|
+
trigger,
|
|
4080
|
+
params,
|
|
4081
|
+
category: this.hsplusReactionCategory(trigger)
|
|
4082
|
+
}
|
|
4083
|
+
});
|
|
4084
|
+
this.skipNewlines();
|
|
4085
|
+
}
|
|
4086
|
+
if (this.check("RBRACE")) this.advance();
|
|
4087
|
+
}
|
|
4088
|
+
return {
|
|
4089
|
+
type: "react-block",
|
|
4090
|
+
name: "react",
|
|
4091
|
+
children: reactions,
|
|
4092
|
+
properties: { count: reactions.length },
|
|
4093
|
+
directives: [],
|
|
4094
|
+
traits: /* @__PURE__ */ new Map(),
|
|
4095
|
+
loc: {
|
|
4096
|
+
start: startLoc,
|
|
4097
|
+
end: { line: this.current().line, column: this.current().column }
|
|
4098
|
+
}
|
|
4099
|
+
};
|
|
4100
|
+
}
|
|
4101
|
+
/**
|
|
4102
|
+
* Parse a `timeline <name> { …properties, track-blocks, children }` node.
|
|
4103
|
+
* (Theatre.js harvest S1.) Produces the same shape as the canonical Rust
|
|
4104
|
+
* grammar: a `timeline` node whose `children` include structured `track`
|
|
4105
|
+
* nodes (`{ type: 'track', target, keyframes: [...] }`). Non-track lines are
|
|
4106
|
+
* handled the generic way: `key: value` → property, nested block keyword →
|
|
4107
|
+
* child node. The `timeline` keyword has already been consumed by the caller.
|
|
4108
|
+
*/
|
|
4109
|
+
parseTimelineNode(startToken) {
|
|
4110
|
+
let name;
|
|
4111
|
+
if (this.check("STRING") || this.check("IDENTIFIER")) {
|
|
4112
|
+
name = this.advance().value;
|
|
4113
|
+
}
|
|
4114
|
+
const properties = {};
|
|
4115
|
+
const children = [];
|
|
4116
|
+
const directives = [];
|
|
4117
|
+
const traits = /* @__PURE__ */ new Map();
|
|
4118
|
+
if (this.check("LBRACE")) {
|
|
4119
|
+
this.advance();
|
|
4120
|
+
this.skipNewlines();
|
|
4121
|
+
while (!this.check("RBRACE") && !this.check("EOF")) {
|
|
4122
|
+
this.skipNewlines();
|
|
4123
|
+
if (this.check("RBRACE") || this.check("EOF")) break;
|
|
4124
|
+
if (this.check("AT")) {
|
|
4125
|
+
const directive = this.parseDirective();
|
|
4126
|
+
if (directive) {
|
|
4127
|
+
if (directive.type === "trait") {
|
|
4128
|
+
traits.set(directive.name, directive.config);
|
|
4129
|
+
this.hasVRTraits = true;
|
|
4130
|
+
}
|
|
4131
|
+
directives.push(directive);
|
|
4132
|
+
}
|
|
4133
|
+
this.skipNewlines();
|
|
4134
|
+
continue;
|
|
4135
|
+
}
|
|
4136
|
+
const token = this.current();
|
|
4137
|
+
const next = this.peek(1);
|
|
4138
|
+
if (token.type === "IDENTIFIER" && token.value === "track" && (next.type === "STRING" || next.type === "IDENTIFIER") && this.peek(2).type === "LBRACE") {
|
|
4139
|
+
this.advance();
|
|
4140
|
+
children.push(this.parseTrackNode(token));
|
|
4141
|
+
if (this.check("COMMA")) this.advance();
|
|
4142
|
+
this.skipNewlines();
|
|
4143
|
+
continue;
|
|
4144
|
+
}
|
|
4145
|
+
if ((token.type === "IDENTIFIER" || token.type === "STRING") && (next.type === "COLON" || next.type === "EQUALS")) {
|
|
4146
|
+
const key = this.advance().value;
|
|
4147
|
+
this.advance();
|
|
4148
|
+
properties[key] = this.parseValue();
|
|
4149
|
+
if (this.check("COMMA")) this.advance();
|
|
4150
|
+
this.skipNewlines();
|
|
4151
|
+
continue;
|
|
4152
|
+
}
|
|
4153
|
+
if (token.type === "IDENTIFIER" || token.type === "STRING") {
|
|
4154
|
+
children.push(this.parseNode());
|
|
4155
|
+
if (this.check("COMMA")) this.advance();
|
|
4156
|
+
this.skipNewlines();
|
|
4157
|
+
continue;
|
|
4158
|
+
}
|
|
4159
|
+
this.advance();
|
|
4160
|
+
this.skipNewlines();
|
|
4161
|
+
}
|
|
4162
|
+
this.expect("RBRACE", "Expected } to close timeline block");
|
|
4163
|
+
}
|
|
4164
|
+
return {
|
|
4165
|
+
type: "timeline",
|
|
4166
|
+
name,
|
|
4167
|
+
id: name,
|
|
4168
|
+
properties,
|
|
4169
|
+
directives,
|
|
4170
|
+
children,
|
|
4171
|
+
traits,
|
|
4172
|
+
loc: {
|
|
4173
|
+
start: { line: startToken.line, column: startToken.column },
|
|
4174
|
+
end: { line: this.current().line, column: this.current().column }
|
|
4175
|
+
}
|
|
4176
|
+
};
|
|
4177
|
+
}
|
|
4178
|
+
/**
|
|
4179
|
+
* Parse a keyframe-track inside a timeline:
|
|
4180
|
+
* track "<target>" { key <time> { <value> } [easing <ease>] ; … }
|
|
4181
|
+
* Mirrors the Rust `TrackNode`/`KeyframeNode`. `;` is skipped by the lexer,
|
|
4182
|
+
* so keyframe separators are implicit. The `track` keyword has already been
|
|
4183
|
+
* consumed by the caller. Returns `{ type: 'track', target, keyframes }`.
|
|
4184
|
+
*/
|
|
4185
|
+
parseTrackNode(startToken) {
|
|
4186
|
+
const target = this.check("STRING") ? this.advance().value : this.expect("IDENTIFIER", "Expected track target name").value;
|
|
4187
|
+
const keyframes = [];
|
|
4188
|
+
this.expect("LBRACE", "Expected { to open track block");
|
|
4189
|
+
this.skipNewlines();
|
|
4190
|
+
while (!this.check("RBRACE") && !this.check("EOF")) {
|
|
4191
|
+
this.skipNewlines();
|
|
4192
|
+
if (this.check("RBRACE") || this.check("EOF")) break;
|
|
4193
|
+
if (this.check("COMMA")) {
|
|
4194
|
+
this.advance();
|
|
4195
|
+
continue;
|
|
4196
|
+
}
|
|
4197
|
+
if (this.check("IDENTIFIER") && this.current().value === "key") {
|
|
4198
|
+
this.advance();
|
|
4199
|
+
let timeSign = 1;
|
|
4200
|
+
if (this.check("MINUS")) {
|
|
4201
|
+
this.advance();
|
|
4202
|
+
timeSign = -1;
|
|
4203
|
+
}
|
|
4204
|
+
const timeTok = this.expect("NUMBER", "Expected numeric time after key");
|
|
4205
|
+
const time = timeSign * Number(timeTok.value);
|
|
4206
|
+
this.expect("LBRACE", "Expected { value block after key time");
|
|
4207
|
+
const value = this.parseValue();
|
|
4208
|
+
this.expect("RBRACE", "Expected } to close key value block");
|
|
4209
|
+
let easing;
|
|
4210
|
+
if (this.check("IDENTIFIER") && this.current().value === "easing") {
|
|
4211
|
+
this.advance();
|
|
4212
|
+
if (this.check("IDENTIFIER") || this.check("STRING")) {
|
|
4213
|
+
easing = this.advance().value;
|
|
4214
|
+
}
|
|
4215
|
+
}
|
|
4216
|
+
keyframes.push(easing === void 0 ? { time, value } : { time, value, easing });
|
|
4217
|
+
this.skipNewlines();
|
|
4218
|
+
continue;
|
|
4219
|
+
}
|
|
4220
|
+
this.advance();
|
|
4221
|
+
this.skipNewlines();
|
|
4222
|
+
}
|
|
4223
|
+
this.expect("RBRACE", "Expected } to close track block");
|
|
4224
|
+
return {
|
|
4225
|
+
type: "track",
|
|
4226
|
+
target,
|
|
4227
|
+
keyframes,
|
|
4228
|
+
loc: {
|
|
4229
|
+
start: { line: startToken.line, column: startToken.column },
|
|
4230
|
+
end: { line: this.current().line, column: this.current().column }
|
|
4231
|
+
}
|
|
4232
|
+
};
|
|
4233
|
+
}
|
|
4234
|
+
/**
|
|
4235
|
+
* Parse block content: { key: value, ... }
|
|
4236
|
+
*/
|
|
4237
|
+
parseBlockContent() {
|
|
4238
|
+
const content = {};
|
|
4239
|
+
if (!this.check("LBRACE")) {
|
|
4240
|
+
return content;
|
|
4241
|
+
}
|
|
4242
|
+
this.advance();
|
|
4243
|
+
this.skipNewlines();
|
|
4244
|
+
while (!this.check("RBRACE") && !this.check("EOF")) {
|
|
4245
|
+
this.skipNewlines();
|
|
4246
|
+
if (this.check("RBRACE") || this.check("EOF")) break;
|
|
4247
|
+
this.skipNewlines();
|
|
4248
|
+
if (this.check("RBRACE") || this.check("EOF")) break;
|
|
4249
|
+
const token = this.current();
|
|
4250
|
+
const isKeyToken = token.type === "IDENTIFIER" || token.type === "STRING" || token.type === "STATE" || token.type === "STATE_MACHINE" || token.type === "INITIAL" || token.type === "ON_ENTRY" || token.type === "ON_EXIT" || token.type === "TRANSITION";
|
|
4251
|
+
if (isKeyToken) {
|
|
4252
|
+
const next = this.peek(1);
|
|
4253
|
+
if (next.type === "COLON" || next.type === "EQUALS") {
|
|
4254
|
+
const key = this.advance().value;
|
|
4255
|
+
this.advance();
|
|
4256
|
+
content[key] = this.parseValue();
|
|
4257
|
+
} else if (next.type === "STRING" || next.type === "LBRACE" || next.type === "IDENTIFIER") {
|
|
4258
|
+
const node = this.parseNode();
|
|
4259
|
+
const type = node.type;
|
|
4260
|
+
const name = node.name || `unnamed_${type}_${Object.keys(content).length}`;
|
|
4261
|
+
content[name] = node;
|
|
4262
|
+
} else {
|
|
4263
|
+
const key = this.advance().value;
|
|
4264
|
+
content[key] = true;
|
|
4265
|
+
}
|
|
4266
|
+
} else if (this.check("SPREAD")) {
|
|
4267
|
+
this.advance();
|
|
4268
|
+
const val = this.parseValue();
|
|
4269
|
+
const spreadKey = `__spread_${Object.keys(content).length}`;
|
|
4270
|
+
content[spreadKey] = { type: "spread", argument: val };
|
|
4271
|
+
} else if (this.check("AT")) {
|
|
4272
|
+
const directive = this.parseDirective();
|
|
4273
|
+
if (directive) {
|
|
4274
|
+
const dirKey = ("name" in directive ? directive.name : void 0) || directive.type;
|
|
4275
|
+
content[`@${dirKey}`] = directive;
|
|
4276
|
+
}
|
|
4277
|
+
} else if (this.check("LBRACE")) {
|
|
4278
|
+
let depth = 1;
|
|
4279
|
+
this.advance();
|
|
4280
|
+
while (depth > 0 && !this.check("EOF")) {
|
|
4281
|
+
if (this.check("LBRACE")) depth++;
|
|
4282
|
+
if (this.check("RBRACE")) depth--;
|
|
4283
|
+
this.advance();
|
|
4284
|
+
}
|
|
4285
|
+
} else if (this.check("LPAREN")) {
|
|
4286
|
+
this.skipParens();
|
|
4287
|
+
} else {
|
|
4288
|
+
this.advance();
|
|
4289
|
+
}
|
|
4290
|
+
if (this.check("COMMA")) this.advance();
|
|
4291
|
+
this.skipNewlines();
|
|
4292
|
+
}
|
|
4293
|
+
this.expect("RBRACE", "Expected }");
|
|
4294
|
+
return content;
|
|
4295
|
+
}
|
|
4296
|
+
/**
|
|
4297
|
+
* Parse bindings block: { bind(expr) -> target, ... }
|
|
4298
|
+
*/
|
|
4299
|
+
parseBindingsBlock() {
|
|
4300
|
+
const bindings = [];
|
|
4301
|
+
if (!this.check("LBRACE")) {
|
|
4302
|
+
return bindings;
|
|
4303
|
+
}
|
|
4304
|
+
this.advance();
|
|
4305
|
+
this.skipNewlines();
|
|
4306
|
+
while (!this.check("RBRACE") && !this.check("EOF")) {
|
|
4307
|
+
this.skipNewlines();
|
|
4308
|
+
if (this.check("RBRACE") || this.check("EOF")) break;
|
|
4309
|
+
if (this.check("IDENTIFIER") && this.current().value === "bind") {
|
|
4310
|
+
this.advance();
|
|
4311
|
+
if (this.check("LPAREN")) {
|
|
4312
|
+
this.advance();
|
|
4313
|
+
let source = "";
|
|
4314
|
+
let parenDepth = 1;
|
|
4315
|
+
while (parenDepth > 0 && !this.check("EOF")) {
|
|
3093
4316
|
if (this.check("LPAREN")) parenDepth++;
|
|
3094
4317
|
if (this.check("RPAREN")) {
|
|
3095
4318
|
parenDepth--;
|
|
@@ -3194,7 +4417,8 @@ var HoloScriptPlusParser = class {
|
|
|
3194
4417
|
"camera",
|
|
3195
4418
|
"timeline",
|
|
3196
4419
|
"page",
|
|
3197
|
-
"include"
|
|
4420
|
+
"include",
|
|
4421
|
+
"react"
|
|
3198
4422
|
];
|
|
3199
4423
|
while (!this.check("RBRACE") && !this.check("EOF")) {
|
|
3200
4424
|
const currentDirectives = [];
|
|
@@ -3713,7 +4937,9 @@ var HoloScriptPlusParser = class {
|
|
|
3713
4937
|
if (startToken.type === "STATE_MACHINE") {
|
|
3714
4938
|
this.advance();
|
|
3715
4939
|
}
|
|
3716
|
-
const name = this.
|
|
4940
|
+
const name = this.parseStateMachineIdentifier("Expected state machine name");
|
|
4941
|
+
const inputs = [];
|
|
4942
|
+
const listeners = [];
|
|
3717
4943
|
const states = [];
|
|
3718
4944
|
const transitions = [];
|
|
3719
4945
|
let initialState = "";
|
|
@@ -3726,7 +4952,13 @@ var HoloScriptPlusParser = class {
|
|
|
3726
4952
|
if (current.type === "INITIAL" || current.value === "initial") {
|
|
3727
4953
|
this.advance();
|
|
3728
4954
|
this.expect("COLON", "Expected : after initial");
|
|
3729
|
-
initialState = this.
|
|
4955
|
+
initialState = this.parseStateMachineIdentifier("Expected initial state name");
|
|
4956
|
+
} else if (current.value === "input") {
|
|
4957
|
+
inputs.push(this.parseStateMachineInputDeclaration());
|
|
4958
|
+
} else if (current.value === "listen") {
|
|
4959
|
+
listeners.push(this.parseStateMachineListenerDeclaration());
|
|
4960
|
+
} else if (this.isStateMachineTransitionShorthandStart()) {
|
|
4961
|
+
transitions.push(this.parseStateMachineTransitionShorthand());
|
|
3730
4962
|
} else if (current.type === "STATE" || current.value === "state") {
|
|
3731
4963
|
states.push(this.parseStateNode());
|
|
3732
4964
|
} else if (current.type === "TRANSITION" || current.value === "transitions") {
|
|
@@ -3741,6 +4973,8 @@ var HoloScriptPlusParser = class {
|
|
|
3741
4973
|
type: "state-machine",
|
|
3742
4974
|
name,
|
|
3743
4975
|
initialState,
|
|
4976
|
+
inputs,
|
|
4977
|
+
listeners,
|
|
3744
4978
|
states,
|
|
3745
4979
|
transitions,
|
|
3746
4980
|
loc: {
|
|
@@ -3751,9 +4985,10 @@ var HoloScriptPlusParser = class {
|
|
|
3751
4985
|
}
|
|
3752
4986
|
parseStateNode() {
|
|
3753
4987
|
this.advance();
|
|
3754
|
-
const name = this.
|
|
4988
|
+
const name = this.parseStateMachineIdentifier("Expected state name");
|
|
3755
4989
|
let onEntry;
|
|
3756
4990
|
let onExit;
|
|
4991
|
+
const metadata = {};
|
|
3757
4992
|
this.expect("LBRACE", "Expected { after state name");
|
|
3758
4993
|
this.skipNewlines();
|
|
3759
4994
|
while (!this.check("RBRACE") && !this.check("EOF")) {
|
|
@@ -3766,19 +5001,39 @@ var HoloScriptPlusParser = class {
|
|
|
3766
5001
|
} else if (current.type === "ON_EXIT" || current.value === "on_exit") {
|
|
3767
5002
|
this.advance();
|
|
3768
5003
|
onExit = this.parseCodeBlock();
|
|
5004
|
+
} else if (this.isStateMachineStateMetadataKey(current.value) && this.peek(1).type === "COLON") {
|
|
5005
|
+
const key = this.advance().value;
|
|
5006
|
+
this.expect("COLON", `Expected : after ${key}`);
|
|
5007
|
+
metadata[key] = this.parseValue();
|
|
3769
5008
|
} else {
|
|
3770
5009
|
this.advance();
|
|
3771
5010
|
}
|
|
3772
5011
|
this.skipNewlines();
|
|
3773
5012
|
}
|
|
3774
5013
|
this.expect("RBRACE", "Expected }");
|
|
3775
|
-
return { name, onEntry, onExit };
|
|
5014
|
+
return { name, onEntry, onExit, ...metadata };
|
|
5015
|
+
}
|
|
5016
|
+
isStateMachineStateMetadataKey(key) {
|
|
5017
|
+
return key === "clip" || key === "clips" || key === "parameter" || key === "parameters" || key === "thresholds" || key === "blendType" || key === "blend_type" || key === "blend" || key === "blendMode" || key === "blend_mode" || key === "mask" || key === "baseline";
|
|
3776
5018
|
}
|
|
3777
5019
|
parseOnErrorNode() {
|
|
3778
5020
|
const startToken = this.previous();
|
|
5021
|
+
const params = [];
|
|
5022
|
+
if (this.check("LPAREN")) {
|
|
5023
|
+
this.advance();
|
|
5024
|
+
while (!this.check("RPAREN") && !this.check("EOF") && !this.check("LBRACE")) {
|
|
5025
|
+
if (this.check("IDENTIFIER")) {
|
|
5026
|
+
params.push(this.advance().value);
|
|
5027
|
+
} else {
|
|
5028
|
+
this.advance();
|
|
5029
|
+
}
|
|
5030
|
+
}
|
|
5031
|
+
if (this.check("RPAREN")) this.advance();
|
|
5032
|
+
}
|
|
3779
5033
|
const body = this.parseControlFlowBody();
|
|
3780
5034
|
return {
|
|
3781
5035
|
type: "on_error",
|
|
5036
|
+
params,
|
|
3782
5037
|
body,
|
|
3783
5038
|
loc: {
|
|
3784
5039
|
start: { line: startToken.line, column: startToken.column },
|
|
@@ -3813,17 +5068,153 @@ var HoloScriptPlusParser = class {
|
|
|
3813
5068
|
while (!this.check("RBRACE") && !this.check("EOF")) {
|
|
3814
5069
|
this.skipNewlines();
|
|
3815
5070
|
if (this.check("RBRACE") || this.check("EOF")) break;
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
5071
|
+
if (this.isStateMachineTransitionShorthandStart()) {
|
|
5072
|
+
transitions.push(this.parseStateMachineTransitionShorthand());
|
|
5073
|
+
} else {
|
|
5074
|
+
const from = this.parseStateMachineIdentifier("Expected source state");
|
|
5075
|
+
this.expect("ARROW", "Expected ->");
|
|
5076
|
+
const to = this.parseStateMachineIdentifier("Expected target state");
|
|
5077
|
+
this.expect("COLON", "Expected :");
|
|
5078
|
+
const event = this.parseStateMachineIdentifier("Expected event name");
|
|
5079
|
+
transitions.push({ from, to, event });
|
|
5080
|
+
}
|
|
3822
5081
|
this.skipNewlines();
|
|
3823
5082
|
}
|
|
3824
5083
|
this.expect("RBRACE", "Expected }");
|
|
3825
5084
|
return transitions;
|
|
3826
5085
|
}
|
|
5086
|
+
parseStateMachineInputDeclaration() {
|
|
5087
|
+
this.advance();
|
|
5088
|
+
const name = this.parseStateMachineIdentifier("Expected input name");
|
|
5089
|
+
this.expect("COLON", "Expected : after input name");
|
|
5090
|
+
const rawType = this.parseStateMachineIdentifier("Expected input type");
|
|
5091
|
+
const inputType = rawType === "number" ? "float" : rawType === "boolean" ? "bool" : rawType;
|
|
5092
|
+
let defaultValue;
|
|
5093
|
+
if (this.check("EQUALS")) {
|
|
5094
|
+
this.advance();
|
|
5095
|
+
defaultValue = this.parseValue();
|
|
5096
|
+
}
|
|
5097
|
+
return {
|
|
5098
|
+
type: "animation-input",
|
|
5099
|
+
name,
|
|
5100
|
+
inputType,
|
|
5101
|
+
rawType,
|
|
5102
|
+
default: defaultValue
|
|
5103
|
+
};
|
|
5104
|
+
}
|
|
5105
|
+
parseStateMachineListenerDeclaration() {
|
|
5106
|
+
this.advance();
|
|
5107
|
+
const event = this.parseStateMachineDottedIdentifier("Expected listener event");
|
|
5108
|
+
this.expect("ARROW", "Expected -> after listener event");
|
|
5109
|
+
if (this.current().value === "fire") {
|
|
5110
|
+
this.advance();
|
|
5111
|
+
return {
|
|
5112
|
+
type: "animation-listener",
|
|
5113
|
+
event,
|
|
5114
|
+
action: "fire",
|
|
5115
|
+
parameter: this.parseStateMachineDottedIdentifier("Expected trigger input")
|
|
5116
|
+
};
|
|
5117
|
+
}
|
|
5118
|
+
if (this.current().value === "reset") {
|
|
5119
|
+
this.advance();
|
|
5120
|
+
return {
|
|
5121
|
+
type: "animation-listener",
|
|
5122
|
+
event,
|
|
5123
|
+
action: "reset",
|
|
5124
|
+
parameter: this.parseStateMachineDottedIdentifier("Expected trigger input")
|
|
5125
|
+
};
|
|
5126
|
+
}
|
|
5127
|
+
const parameter = this.parseStateMachineDottedIdentifier("Expected animation input");
|
|
5128
|
+
this.expect("EQUALS", "Expected = in listener binding");
|
|
5129
|
+
const parsedValue = this.parseValue();
|
|
5130
|
+
const listener = {
|
|
5131
|
+
type: "animation-listener",
|
|
5132
|
+
event,
|
|
5133
|
+
action: "set",
|
|
5134
|
+
parameter
|
|
5135
|
+
};
|
|
5136
|
+
if (parsedValue && typeof parsedValue === "object" && "__ref" in parsedValue) {
|
|
5137
|
+
const ref = parsedValue.__ref;
|
|
5138
|
+
if (typeof ref === "string" && (ref === "event" || ref.startsWith("event."))) {
|
|
5139
|
+
listener.source = ref;
|
|
5140
|
+
} else if (typeof ref === "string") {
|
|
5141
|
+
listener.value = ref;
|
|
5142
|
+
} else {
|
|
5143
|
+
listener.value = String(ref ?? "");
|
|
5144
|
+
}
|
|
5145
|
+
} else if (typeof parsedValue === "number" || typeof parsedValue === "boolean" || typeof parsedValue === "string") {
|
|
5146
|
+
listener.value = parsedValue;
|
|
5147
|
+
} else {
|
|
5148
|
+
listener.value = String(parsedValue ?? "");
|
|
5149
|
+
}
|
|
5150
|
+
return listener;
|
|
5151
|
+
}
|
|
5152
|
+
isStateMachineTransitionShorthandStart() {
|
|
5153
|
+
return this.isStateMachineIdentifierToken(0) && this.peek(1).type === "ARROW";
|
|
5154
|
+
}
|
|
5155
|
+
parseStateMachineTransitionShorthand() {
|
|
5156
|
+
const fromRaw = this.parseStateMachineIdentifier("Expected source state");
|
|
5157
|
+
const from = fromRaw.toLowerCase() === "any" ? "any" : fromRaw;
|
|
5158
|
+
this.expect("ARROW", "Expected ->");
|
|
5159
|
+
const to = this.parseStateMachineIdentifier("Expected target state");
|
|
5160
|
+
const transition = { from, to };
|
|
5161
|
+
while (!this.check("NEWLINE") && !this.check("RBRACE") && !this.check("COMMA") && !this.check("EOF")) {
|
|
5162
|
+
if (!this.isStateMachineIdentifierToken(0)) break;
|
|
5163
|
+
const clause = this.current().value.toLowerCase();
|
|
5164
|
+
this.advance();
|
|
5165
|
+
if (clause === "when") {
|
|
5166
|
+
transition.when = this.parseExpression();
|
|
5167
|
+
} else if (clause === "on") {
|
|
5168
|
+
transition.event = this.parseStateMachineIdentifier("Expected trigger input");
|
|
5169
|
+
} else if (clause === "over" || clause === "duration") {
|
|
5170
|
+
transition.duration = this.parseValue();
|
|
5171
|
+
} else if (clause === "easing") {
|
|
5172
|
+
transition.easing = this.parseStateMachineIdentifier("Expected easing name");
|
|
5173
|
+
} else if (clause === "exittime" || clause === "exit_time") {
|
|
5174
|
+
transition.exitTime = this.parseValue();
|
|
5175
|
+
transition.hasExitTime = true;
|
|
5176
|
+
} else if (clause === "pausewhenexiting" || clause === "pause_when_exiting") {
|
|
5177
|
+
transition.pauseWhenExiting = this.parseOptionalStateMachineBoolean();
|
|
5178
|
+
} else if (clause === "priority") {
|
|
5179
|
+
transition.priority = this.parseValue();
|
|
5180
|
+
} else if (clause === "cantransitiontoself" || clause === "can_transition_to_self") {
|
|
5181
|
+
transition.canTransitionToSelf = this.parseOptionalStateMachineBoolean();
|
|
5182
|
+
} else {
|
|
5183
|
+
break;
|
|
5184
|
+
}
|
|
5185
|
+
}
|
|
5186
|
+
return transition;
|
|
5187
|
+
}
|
|
5188
|
+
parseOptionalStateMachineBoolean() {
|
|
5189
|
+
if (this.check("COLON")) this.advance();
|
|
5190
|
+
if (this.check("BOOLEAN")) return this.advance().value === "true";
|
|
5191
|
+
if (this.check("IDENTIFIER")) {
|
|
5192
|
+
const value = this.current().value.toLowerCase();
|
|
5193
|
+
if (value === "true" || value === "false") {
|
|
5194
|
+
this.advance();
|
|
5195
|
+
return value === "true";
|
|
5196
|
+
}
|
|
5197
|
+
}
|
|
5198
|
+
return true;
|
|
5199
|
+
}
|
|
5200
|
+
parseStateMachineIdentifier(message) {
|
|
5201
|
+
if (this.check("IDENTIFIER") || this.check("STRING")) {
|
|
5202
|
+
return this.advance().value;
|
|
5203
|
+
}
|
|
5204
|
+
return this.expect("IDENTIFIER", message).value;
|
|
5205
|
+
}
|
|
5206
|
+
parseStateMachineDottedIdentifier(message) {
|
|
5207
|
+
let value = this.parseStateMachineIdentifier(message);
|
|
5208
|
+
while (this.check("DOT")) {
|
|
5209
|
+
this.advance();
|
|
5210
|
+
value += `.${this.parseStateMachineIdentifier("Expected property name after dot")}`;
|
|
5211
|
+
}
|
|
5212
|
+
return value;
|
|
5213
|
+
}
|
|
5214
|
+
isStateMachineIdentifierToken(offset) {
|
|
5215
|
+
const token = this.peek(offset);
|
|
5216
|
+
return token.type === "IDENTIFIER" || token.type === "STRING";
|
|
5217
|
+
}
|
|
3827
5218
|
parseControlFlowBody() {
|
|
3828
5219
|
const nodes = [];
|
|
3829
5220
|
if (this.check("LBRACE")) {
|
|
@@ -3867,41 +5258,10 @@ var HoloScriptPlusParser = class {
|
|
|
3867
5258
|
return nodes;
|
|
3868
5259
|
}
|
|
3869
5260
|
parseCodeBlock() {
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
if (this.check("LBRACE")) {
|
|
3873
|
-
this.advance();
|
|
3874
|
-
braceDepth = 1;
|
|
3875
|
-
try {
|
|
3876
|
-
while (braceDepth > 0 && !this.check("EOF")) {
|
|
3877
|
-
const token = this.advance();
|
|
3878
|
-
if (token.type === "LBRACE") {
|
|
3879
|
-
braceDepth++;
|
|
3880
|
-
code += "{";
|
|
3881
|
-
} else if (token.type === "RBRACE") {
|
|
3882
|
-
braceDepth--;
|
|
3883
|
-
if (braceDepth > 0) {
|
|
3884
|
-
code += "}";
|
|
3885
|
-
}
|
|
3886
|
-
} else if (token.type === "STRING") {
|
|
3887
|
-
code += `"${token.value}"`;
|
|
3888
|
-
code += " ";
|
|
3889
|
-
} else {
|
|
3890
|
-
code += token.value;
|
|
3891
|
-
if (token.type === "NEWLINE") {
|
|
3892
|
-
code += "\n";
|
|
3893
|
-
} else {
|
|
3894
|
-
code += " ";
|
|
3895
|
-
}
|
|
3896
|
-
}
|
|
3897
|
-
}
|
|
3898
|
-
} catch (e) {
|
|
3899
|
-
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
3900
|
-
if (errorMessage !== "ParseError") console.error(e);
|
|
3901
|
-
this.synchronize();
|
|
3902
|
-
}
|
|
5261
|
+
if (!this.check("LBRACE")) {
|
|
5262
|
+
return "";
|
|
3903
5263
|
}
|
|
3904
|
-
return
|
|
5264
|
+
return this.parseRawBlock();
|
|
3905
5265
|
}
|
|
3906
5266
|
parseInlineExpression() {
|
|
3907
5267
|
let expr = "";
|
|
@@ -4153,6 +5513,9 @@ var HoloScriptPlusParser = class {
|
|
|
4153
5513
|
}
|
|
4154
5514
|
return this.parseParenExpression();
|
|
4155
5515
|
}
|
|
5516
|
+
if (token.type === "ARROW" && token.value === "->") {
|
|
5517
|
+
return this.parseTransitionShorthand();
|
|
5518
|
+
}
|
|
4156
5519
|
if (token.type === "MATCH") {
|
|
4157
5520
|
return this.parseMatchExpression();
|
|
4158
5521
|
}
|
|
@@ -4208,6 +5571,36 @@ var HoloScriptPlusParser = class {
|
|
|
4208
5571
|
err.message = "ParseError";
|
|
4209
5572
|
throw err;
|
|
4210
5573
|
}
|
|
5574
|
+
/**
|
|
5575
|
+
* Parse a state-machine transition shorthand value:
|
|
5576
|
+
* -> "target"
|
|
5577
|
+
* -> "target" action(callback_name)
|
|
5578
|
+
* -> "target" guard(state.credits >= 10) action(begin)
|
|
5579
|
+
* Used as the value of on_<event> keys inside @state_machine states config.
|
|
5580
|
+
* Modifiers (action / guard) may appear in any order, each at most once
|
|
5581
|
+
* meaningfully (last one wins, matching general object semantics).
|
|
5582
|
+
*/
|
|
5583
|
+
parseTransitionShorthand() {
|
|
5584
|
+
this.advance();
|
|
5585
|
+
let target = "";
|
|
5586
|
+
if (this.check("STRING") || this.check("IDENTIFIER")) {
|
|
5587
|
+
target = this.advance().value;
|
|
5588
|
+
} else {
|
|
5589
|
+
this.error(
|
|
5590
|
+
`Expected target state after -> in transition. Got ${this.current().type} "${this.current().value}"`,
|
|
5591
|
+
"HSP300"
|
|
5592
|
+
);
|
|
5593
|
+
}
|
|
5594
|
+
const transition = { type: "transition", target };
|
|
5595
|
+
while (this.check("IDENTIFIER") && (this.current().value === "action" || this.current().value === "guard") && this.peek(1).type === "LPAREN") {
|
|
5596
|
+
const kind = this.advance().value;
|
|
5597
|
+
this.advance();
|
|
5598
|
+
const arg = this.parseExpression();
|
|
5599
|
+
this.expect("RPAREN", `Expected ) after ${kind} argument in transition`);
|
|
5600
|
+
transition[kind] = arg;
|
|
5601
|
+
}
|
|
5602
|
+
return transition;
|
|
5603
|
+
}
|
|
4211
5604
|
parseParenExpression() {
|
|
4212
5605
|
this.expect("LPAREN", "Expected (");
|
|
4213
5606
|
const items = [];
|
|
@@ -4592,6 +5985,14 @@ var HoloScriptPlusParser = class {
|
|
|
4592
5985
|
})
|
|
4593
5986
|
);
|
|
4594
5987
|
}
|
|
5988
|
+
errorAt(token, message, code = "HSP001") {
|
|
5989
|
+
this.errors.push(
|
|
5990
|
+
createRichError(code, message, token.line, token.column, {
|
|
5991
|
+
source: this.source,
|
|
5992
|
+
severity: "error"
|
|
5993
|
+
})
|
|
5994
|
+
);
|
|
5995
|
+
}
|
|
4595
5996
|
errorWithSuggestion(message, suggestion, code = "HSP001") {
|
|
4596
5997
|
const token = this.current();
|
|
4597
5998
|
this.errors.push(
|
|
@@ -4846,5 +6247,5 @@ function parse(source, options) {
|
|
|
4846
6247
|
}
|
|
4847
6248
|
|
|
4848
6249
|
export { ChunkBasedIncrementalParser, HSPLUS_ERROR_CODES, HoloScriptPlusParser, ParseCache, createKeywordError, createParser, createRichError, createTraitError, findSimilarKeyword, findSimilarTrait, formatRichError, formatRichErrors, getErrorCodeDocumentation, getSourceContext, globalParseCache, parse, parseIncrementalChunks };
|
|
4849
|
-
//# sourceMappingURL=chunk-
|
|
4850
|
-
//# sourceMappingURL=chunk-
|
|
6250
|
+
//# sourceMappingURL=chunk-DBH3D2MU.js.map
|
|
6251
|
+
//# sourceMappingURL=chunk-DBH3D2MU.js.map
|