redscript-mc 1.2.9 → 1.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -33
- package/README.zh.md +35 -33
- package/demo.gif +0 -0
- package/dist/__tests__/mc-integration.test.js +85 -0
- package/dist/ast/types.d.ts +84 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lexer/index.d.ts +1 -1
- package/dist/lexer/index.js +2 -0
- package/dist/lowering/index.d.ts +3 -0
- package/dist/lowering/index.js +119 -11
- package/dist/optimizer/dce.js +6 -0
- package/dist/parser/index.d.ts +4 -0
- package/dist/parser/index.js +171 -18
- package/package.json +1 -1
- package/src/__tests__/fixtures/array-test.mcrs +30 -0
- package/src/__tests__/fixtures/break-continue-test.mcrs +46 -0
- package/src/__tests__/fixtures/enum-test.mcrs +37 -0
- package/src/__tests__/fixtures/foreach-at-test.mcrs +33 -0
- package/src/__tests__/fixtures/match-range-test.mcrs +45 -0
- package/src/__tests__/fixtures/struct-test.mcrs +34 -0
- package/src/__tests__/mc-integration.test.ts +97 -0
- package/src/ast/types.ts +24 -1
- package/src/index.ts +1 -1
- package/src/lexer/index.ts +3 -1
- package/src/lowering/index.ts +123 -11
- package/src/optimizer/dce.ts +6 -0
- package/src/parser/index.ts +159 -18
- package/test-datapacks/README.md +67 -0
- package/test-datapacks/test_control_flow/data/minecraft/tags/function/load.json +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/__load.mcfunction +41 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/run_control_flow_tests.mcfunction +21 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/else_7.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/else_8.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/for_body_1.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/for_check_0.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/for_continue_2.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/for_exit_2.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/for_exit_3.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/merge_5.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/merge_6.mcfunction +2 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/merge_8.mcfunction +1 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/merge_9.mcfunction +1 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/then_3.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/then_4.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/then_6.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break/then_7.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_break.mcfunction +4 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/else_1.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/else_10.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/else_4.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/else_7.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/merge_11.mcfunction +1 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/merge_2.mcfunction +9 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/merge_5.mcfunction +7 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/merge_8.mcfunction +13 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/then_0.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/then_3.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/then_6.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions/then_9.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_complex_conditions.mcfunction +12 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/else_7.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/else_8.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/for_body_1.mcfunction +7 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/for_check_0.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/for_continue_2.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/for_exit_2.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/for_exit_3.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/merge_5.mcfunction +8 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/merge_6.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/merge_8.mcfunction +1 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/merge_9.mcfunction +1 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/then_3.mcfunction +2 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/then_4.mcfunction +2 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/then_6.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue/then_7.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_continue.mcfunction +4 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/else_13.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/else_16.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/else_4.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/else_5.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_body_1.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_body_10.mcfunction +8 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_body_12.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_body_7.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_body_8.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_check_0.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_check_11.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_check_6.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_check_7.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_check_9.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_continue_13.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_continue_2.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_continue_9.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_exit_10.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_exit_11.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_exit_14.mcfunction +2 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_exit_2.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_exit_3.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/for_exit_8.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/merge_14.mcfunction +1 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/merge_17.mcfunction +1 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/merge_5.mcfunction +4 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/merge_6.mcfunction +4 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/then_12.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/then_15.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/then_3.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop/then_4.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_for_loop.mcfunction +4 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_foreach_at/foreach_0.mcfunction +2 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_foreach_at.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_foreach_selector/else_1.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_foreach_selector/foreach_0.mcfunction +4 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_foreach_selector/merge_2.mcfunction +2 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_foreach_selector/then_0.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_foreach_selector.mcfunction +11 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/else_1.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/else_13.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/else_16.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/else_4.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/merge_11.mcfunction +2 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/merge_14.mcfunction +1 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/merge_17.mcfunction +2 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/merge_2.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/merge_5.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/merge_8.mcfunction +6 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/then_0.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/then_12.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/then_15.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/then_3.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/then_6.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else/then_9.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_if_else.mcfunction +6 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_0.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_1.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_2.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_3.mcfunction +2 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_4.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_5.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_6.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_7.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_8.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match/match_9.mcfunction +2 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_match.mcfunction +15 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/else_13.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/else_4.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/loop_body_1.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/loop_body_7.mcfunction +8 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/loop_check_0.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/loop_check_6.mcfunction +4 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/loop_exit_2.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/loop_exit_8.mcfunction +5 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/merge_11.mcfunction +2 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/merge_14.mcfunction +1 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/merge_5.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/then_12.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/then_3.mcfunction +3 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop/then_9.mcfunction +2 -0
- package/test-datapacks/test_control_flow/data/test_control_flow/function/test_while_loop.mcfunction +3 -0
- package/test-datapacks/test_control_flow/pack.mcmeta +6 -0
- package/test-datapacks/test_control_flow.mcrs +242 -0
- package/test-datapacks/test_decorators/data/minecraft/tags/function/load.json +5 -0
- package/test-datapacks/test_decorators/data/minecraft/tags/function/tick.json +5 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/__load.mcfunction +20 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/__tick.mcfunction +3 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/every_second/merge_2.mcfunction +9 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/every_second/merge_5.mcfunction +1 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/every_second/then_0.mcfunction +1 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/every_second/then_3.mcfunction +4 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/every_second/tick_body.mcfunction +6 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/every_second/tick_skip.mcfunction +1 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/every_second.mcfunction +5 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/on_load.mcfunction +2 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/on_test_trigger.mcfunction +2 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/on_tick/merge_2.mcfunction +10 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/on_tick/merge_5.mcfunction +5 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/on_tick/merge_8.mcfunction +1 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/on_tick/then_0.mcfunction +1 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/on_tick/then_3.mcfunction +3 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/on_tick/then_6.mcfunction +4 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/on_tick.mcfunction +5 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/run_decorator_tests.mcfunction +7 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/setup_trigger_test.mcfunction +4 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/start_slow_tick_test.mcfunction +4 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/start_tick_test.mcfunction +4 -0
- package/test-datapacks/test_decorators/data/test_decorators/function/stop_tick_test.mcfunction +3 -0
- package/test-datapacks/test_decorators/pack.mcmeta +6 -0
- package/test-datapacks/test_decorators.mcrs +81 -0
- package/test-datapacks/test_events/data/minecraft/tags/function/load.json +5 -0
- package/test-datapacks/test_events/data/test_events/advancements/on_death_on_player_death.json +10 -0
- package/test-datapacks/test_events/data/test_events/function/__load.mcfunction +3 -0
- package/test-datapacks/test_events/data/test_events/function/on_player_death.mcfunction +3 -0
- package/test-datapacks/test_events/data/test_events/function/run_event_tests.mcfunction +5 -0
- package/test-datapacks/test_events/data/test_events/function/setup_events.mcfunction +3 -0
- package/test-datapacks/test_events/data/test_events/function/spawn_test_entity.mcfunction +3 -0
- package/test-datapacks/test_events/data/test_events/function/test_advancement_event.mcfunction +4 -0
- package/test-datapacks/test_events/pack.mcmeta +6 -0
- package/test-datapacks/test_events.mcrs +37 -0
- package/test-datapacks/test_fstrings/data/minecraft/tags/function/load.json +5 -0
- package/test-datapacks/test_fstrings/data/test_fstrings/function/__load.mcfunction +10 -0
- package/test-datapacks/test_fstrings/data/test_fstrings/function/run_fstring_tests.mcfunction +15 -0
- package/test-datapacks/test_fstrings/data/test_fstrings/function/test_actionbar_fstring.mcfunction +4 -0
- package/test-datapacks/test_fstrings/data/test_fstrings/function/test_announce.mcfunction +3 -0
- package/test-datapacks/test_fstrings/data/test_fstrings/function/test_multi_var_fstring.mcfunction +9 -0
- package/test-datapacks/test_fstrings/data/test_fstrings/function/test_say_fstring.mcfunction +4 -0
- package/test-datapacks/test_fstrings/data/test_fstrings/function/test_tell.mcfunction +3 -0
- package/test-datapacks/test_fstrings/data/test_fstrings/function/test_title_fstring.mcfunction +4 -0
- package/test-datapacks/test_fstrings/pack.mcmeta +6 -0
- package/test-datapacks/test_fstrings.mcrs +58 -0
- package/test-datapacks/test_timers/data/minecraft/tags/function/load.json +5 -0
- package/test-datapacks/test_timers/data/test_timers/function/__interval_0.mcfunction +3 -0
- package/test-datapacks/test_timers/data/test_timers/function/__interval_body_0.mcfunction +5 -0
- package/test-datapacks/test_timers/data/test_timers/function/__load.mcfunction +5 -0
- package/test-datapacks/test_timers/data/test_timers/function/__timeout_0.mcfunction +2 -0
- package/test-datapacks/test_timers/data/test_timers/function/run_timer_tests.mcfunction +5 -0
- package/test-datapacks/test_timers/data/test_timers/function/test_set_interval.mcfunction +5 -0
- package/test-datapacks/test_timers/data/test_timers/function/test_set_timeout.mcfunction +3 -0
- package/test-datapacks/test_timers/pack.mcmeta +6 -0
- package/test-datapacks/test_timers.mcrs +35 -0
package/dist/lowering/index.js
CHANGED
|
@@ -209,6 +209,8 @@ class Lowering {
|
|
|
209
209
|
this.floatVars = new Set();
|
|
210
210
|
// World object counter for unique tags
|
|
211
211
|
this.worldObjCounter = 0;
|
|
212
|
+
// Loop context stack for break/continue
|
|
213
|
+
this.loopStack = [];
|
|
212
214
|
this.namespace = namespace;
|
|
213
215
|
this.sourceRanges = sourceRanges;
|
|
214
216
|
LoweringBuilder.resetTempCounter();
|
|
@@ -462,6 +464,12 @@ class Lowering {
|
|
|
462
464
|
case 'return':
|
|
463
465
|
this.lowerReturnStmt(stmt);
|
|
464
466
|
break;
|
|
467
|
+
case 'break':
|
|
468
|
+
this.lowerBreakStmt();
|
|
469
|
+
break;
|
|
470
|
+
case 'continue':
|
|
471
|
+
this.lowerContinueStmt();
|
|
472
|
+
break;
|
|
465
473
|
case 'if':
|
|
466
474
|
this.lowerIfStmt(stmt);
|
|
467
475
|
break;
|
|
@@ -599,6 +607,20 @@ class Lowering {
|
|
|
599
607
|
this.builder.emitReturn();
|
|
600
608
|
}
|
|
601
609
|
}
|
|
610
|
+
lowerBreakStmt() {
|
|
611
|
+
if (this.loopStack.length === 0) {
|
|
612
|
+
throw new diagnostics_1.DiagnosticError('LoweringError', 'break statement outside of loop', { line: 1, col: 1 });
|
|
613
|
+
}
|
|
614
|
+
const loop = this.loopStack[this.loopStack.length - 1];
|
|
615
|
+
this.builder.emitJump(loop.breakLabel);
|
|
616
|
+
}
|
|
617
|
+
lowerContinueStmt() {
|
|
618
|
+
if (this.loopStack.length === 0) {
|
|
619
|
+
throw new diagnostics_1.DiagnosticError('LoweringError', 'continue statement outside of loop', { line: 1, col: 1 });
|
|
620
|
+
}
|
|
621
|
+
const loop = this.loopStack[this.loopStack.length - 1];
|
|
622
|
+
this.builder.emitJump(loop.continueLabel);
|
|
623
|
+
}
|
|
602
624
|
lowerIfStmt(stmt) {
|
|
603
625
|
if (stmt.cond.kind === 'is_check') {
|
|
604
626
|
this.lowerIsCheckIfStmt(stmt);
|
|
@@ -671,12 +693,16 @@ class Lowering {
|
|
|
671
693
|
const condVar = this.lowerExpr(stmt.cond);
|
|
672
694
|
const condName = this.operandToVar(condVar);
|
|
673
695
|
this.builder.emitJumpIf(condName, bodyLabel, exitLabel);
|
|
696
|
+
// Push loop context for break/continue (while has no step, so continue goes to check)
|
|
697
|
+
this.loopStack.push({ breakLabel: exitLabel, continueLabel: checkLabel });
|
|
674
698
|
// Body block
|
|
675
699
|
this.builder.startBlock(bodyLabel);
|
|
676
700
|
this.lowerBlock(stmt.body);
|
|
677
701
|
if (!this.builder.isBlockSealed()) {
|
|
678
702
|
this.builder.emitJump(checkLabel);
|
|
679
703
|
}
|
|
704
|
+
// Pop loop context
|
|
705
|
+
this.loopStack.pop();
|
|
680
706
|
// Exit block
|
|
681
707
|
this.builder.startBlock(exitLabel);
|
|
682
708
|
}
|
|
@@ -688,6 +714,7 @@ class Lowering {
|
|
|
688
714
|
}
|
|
689
715
|
const checkLabel = this.builder.freshLabel('for_check');
|
|
690
716
|
const bodyLabel = this.builder.freshLabel('for_body');
|
|
717
|
+
const continueLabel = this.builder.freshLabel('for_continue');
|
|
691
718
|
const exitLabel = this.builder.freshLabel('for_exit');
|
|
692
719
|
this.builder.emitJump(checkLabel);
|
|
693
720
|
// Check block
|
|
@@ -695,14 +722,20 @@ class Lowering {
|
|
|
695
722
|
const condVar = this.lowerExpr(stmt.cond);
|
|
696
723
|
const condName = this.operandToVar(condVar);
|
|
697
724
|
this.builder.emitJumpIf(condName, bodyLabel, exitLabel);
|
|
725
|
+
// Push loop context for break/continue
|
|
726
|
+
this.loopStack.push({ breakLabel: exitLabel, continueLabel });
|
|
698
727
|
// Body block
|
|
699
728
|
this.builder.startBlock(bodyLabel);
|
|
700
729
|
this.lowerBlock(stmt.body);
|
|
701
|
-
// Step expression
|
|
702
|
-
this.lowerExpr(stmt.step);
|
|
703
730
|
if (!this.builder.isBlockSealed()) {
|
|
704
|
-
this.builder.emitJump(
|
|
731
|
+
this.builder.emitJump(continueLabel);
|
|
705
732
|
}
|
|
733
|
+
// Continue block (step + loop back)
|
|
734
|
+
this.builder.startBlock(continueLabel);
|
|
735
|
+
this.lowerExpr(stmt.step);
|
|
736
|
+
this.builder.emitJump(checkLabel);
|
|
737
|
+
// Pop loop context
|
|
738
|
+
this.loopStack.pop();
|
|
706
739
|
// Exit block
|
|
707
740
|
this.builder.startBlock(exitLabel);
|
|
708
741
|
}
|
|
@@ -794,12 +827,32 @@ class Lowering {
|
|
|
794
827
|
defaultArm = arm;
|
|
795
828
|
continue;
|
|
796
829
|
}
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
830
|
+
// Handle range patterns specially
|
|
831
|
+
let matchCondition;
|
|
832
|
+
if (arm.pattern.kind === 'range_lit') {
|
|
833
|
+
const range = arm.pattern.range;
|
|
834
|
+
if (range.min !== undefined && range.max !== undefined) {
|
|
835
|
+
matchCondition = `${range.min}..${range.max}`;
|
|
836
|
+
}
|
|
837
|
+
else if (range.min !== undefined) {
|
|
838
|
+
matchCondition = `${range.min}..`;
|
|
839
|
+
}
|
|
840
|
+
else if (range.max !== undefined) {
|
|
841
|
+
matchCondition = `..${range.max}`;
|
|
842
|
+
}
|
|
843
|
+
else {
|
|
844
|
+
matchCondition = '0..'; // Match any
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
else {
|
|
848
|
+
const patternValue = this.lowerExpr(arm.pattern);
|
|
849
|
+
if (patternValue.kind !== 'const') {
|
|
850
|
+
throw new Error('Match patterns must lower to compile-time constants');
|
|
851
|
+
}
|
|
852
|
+
matchCondition = String(patternValue.value);
|
|
800
853
|
}
|
|
801
854
|
const subFnName = `${this.currentFn}/match_${this.foreachCounter++}`;
|
|
802
|
-
this.builder.emitRaw(`execute if score ${matchedVar} rs matches ..0 if score ${subject} rs matches ${
|
|
855
|
+
this.builder.emitRaw(`execute if score ${matchedVar} rs matches ..0 if score ${subject} rs matches ${matchCondition} run function ${this.namespace}:${subFnName}`);
|
|
803
856
|
this.emitMatchArmSubFunction(subFnName, matchedVar, arm.body, true);
|
|
804
857
|
}
|
|
805
858
|
if (defaultArm) {
|
|
@@ -953,18 +1006,52 @@ class Lowering {
|
|
|
953
1006
|
const parts = ['execute'];
|
|
954
1007
|
for (const sub of stmt.subcommands) {
|
|
955
1008
|
switch (sub.kind) {
|
|
1009
|
+
// Context modifiers
|
|
956
1010
|
case 'as':
|
|
957
1011
|
parts.push(`as ${this.selectorToString(sub.selector)}`);
|
|
958
1012
|
break;
|
|
959
1013
|
case 'at':
|
|
960
1014
|
parts.push(`at ${this.selectorToString(sub.selector)}`);
|
|
961
1015
|
break;
|
|
1016
|
+
case 'positioned':
|
|
1017
|
+
parts.push(`positioned ${sub.x} ${sub.y} ${sub.z}`);
|
|
1018
|
+
break;
|
|
1019
|
+
case 'positioned_as':
|
|
1020
|
+
parts.push(`positioned as ${this.selectorToString(sub.selector)}`);
|
|
1021
|
+
break;
|
|
1022
|
+
case 'rotated':
|
|
1023
|
+
parts.push(`rotated ${sub.yaw} ${sub.pitch}`);
|
|
1024
|
+
break;
|
|
1025
|
+
case 'rotated_as':
|
|
1026
|
+
parts.push(`rotated as ${this.selectorToString(sub.selector)}`);
|
|
1027
|
+
break;
|
|
1028
|
+
case 'facing':
|
|
1029
|
+
parts.push(`facing ${sub.x} ${sub.y} ${sub.z}`);
|
|
1030
|
+
break;
|
|
1031
|
+
case 'facing_entity':
|
|
1032
|
+
parts.push(`facing entity ${this.selectorToString(sub.selector)} ${sub.anchor}`);
|
|
1033
|
+
break;
|
|
1034
|
+
case 'anchored':
|
|
1035
|
+
parts.push(`anchored ${sub.anchor}`);
|
|
1036
|
+
break;
|
|
1037
|
+
case 'align':
|
|
1038
|
+
parts.push(`align ${sub.axes}`);
|
|
1039
|
+
break;
|
|
1040
|
+
case 'in':
|
|
1041
|
+
parts.push(`in ${sub.dimension}`);
|
|
1042
|
+
break;
|
|
1043
|
+
case 'on':
|
|
1044
|
+
parts.push(`on ${sub.relation}`);
|
|
1045
|
+
break;
|
|
1046
|
+
case 'summon':
|
|
1047
|
+
parts.push(`summon ${sub.entity}`);
|
|
1048
|
+
break;
|
|
1049
|
+
// Conditions
|
|
962
1050
|
case 'if_entity':
|
|
963
1051
|
if (sub.selector) {
|
|
964
1052
|
parts.push(`if entity ${this.selectorToString(sub.selector)}`);
|
|
965
1053
|
}
|
|
966
1054
|
else if (sub.varName) {
|
|
967
|
-
// Variable with filters - substitute with @s and apply filters
|
|
968
1055
|
const sel = { kind: '@s', filters: sub.filters };
|
|
969
1056
|
parts.push(`if entity ${this.selectorToString(sel)}`);
|
|
970
1057
|
}
|
|
@@ -974,13 +1061,34 @@ class Lowering {
|
|
|
974
1061
|
parts.push(`unless entity ${this.selectorToString(sub.selector)}`);
|
|
975
1062
|
}
|
|
976
1063
|
else if (sub.varName) {
|
|
977
|
-
// Variable with filters - substitute with @s and apply filters
|
|
978
1064
|
const sel = { kind: '@s', filters: sub.filters };
|
|
979
1065
|
parts.push(`unless entity ${this.selectorToString(sel)}`);
|
|
980
1066
|
}
|
|
981
1067
|
break;
|
|
982
|
-
case '
|
|
983
|
-
parts.push(`
|
|
1068
|
+
case 'if_block':
|
|
1069
|
+
parts.push(`if block ${sub.pos[0]} ${sub.pos[1]} ${sub.pos[2]} ${sub.block}`);
|
|
1070
|
+
break;
|
|
1071
|
+
case 'unless_block':
|
|
1072
|
+
parts.push(`unless block ${sub.pos[0]} ${sub.pos[1]} ${sub.pos[2]} ${sub.block}`);
|
|
1073
|
+
break;
|
|
1074
|
+
case 'if_score':
|
|
1075
|
+
parts.push(`if score ${sub.target} ${sub.targetObj} ${sub.op} ${sub.source} ${sub.sourceObj}`);
|
|
1076
|
+
break;
|
|
1077
|
+
case 'unless_score':
|
|
1078
|
+
parts.push(`unless score ${sub.target} ${sub.targetObj} ${sub.op} ${sub.source} ${sub.sourceObj}`);
|
|
1079
|
+
break;
|
|
1080
|
+
case 'if_score_range':
|
|
1081
|
+
parts.push(`if score ${sub.target} ${sub.targetObj} matches ${sub.range}`);
|
|
1082
|
+
break;
|
|
1083
|
+
case 'unless_score_range':
|
|
1084
|
+
parts.push(`unless score ${sub.target} ${sub.targetObj} matches ${sub.range}`);
|
|
1085
|
+
break;
|
|
1086
|
+
// Store
|
|
1087
|
+
case 'store_result':
|
|
1088
|
+
parts.push(`store result score ${sub.target} ${sub.targetObj}`);
|
|
1089
|
+
break;
|
|
1090
|
+
case 'store_success':
|
|
1091
|
+
parts.push(`store success score ${sub.target} ${sub.targetObj}`);
|
|
984
1092
|
break;
|
|
985
1093
|
}
|
|
986
1094
|
}
|
package/dist/optimizer/dce.js
CHANGED
|
@@ -241,6 +241,8 @@ class DeadCodeEliminator {
|
|
|
241
241
|
this.collectNestedStmtRefs(stmt, scope);
|
|
242
242
|
break;
|
|
243
243
|
case 'raw':
|
|
244
|
+
case 'break':
|
|
245
|
+
case 'continue':
|
|
244
246
|
break;
|
|
245
247
|
}
|
|
246
248
|
}
|
|
@@ -508,6 +510,10 @@ class DeadCodeEliminator {
|
|
|
508
510
|
return [copySpan({ ...stmt, body: this.transformBlock(stmt.body, scope) }, stmt)];
|
|
509
511
|
case 'raw':
|
|
510
512
|
return [stmt];
|
|
513
|
+
case 'break':
|
|
514
|
+
return [stmt];
|
|
515
|
+
case 'continue':
|
|
516
|
+
return [stmt];
|
|
511
517
|
}
|
|
512
518
|
}
|
|
513
519
|
transformExpr(expr, scope) {
|
package/dist/parser/index.d.ts
CHANGED
|
@@ -45,6 +45,10 @@ export declare class Parser {
|
|
|
45
45
|
private parseAsStmt;
|
|
46
46
|
private parseAtStmt;
|
|
47
47
|
private parseExecuteStmt;
|
|
48
|
+
private parseExecuteCondition;
|
|
49
|
+
private parseCoordToken;
|
|
50
|
+
private parseBlockId;
|
|
51
|
+
private checkIdent;
|
|
48
52
|
private parseExprStmt;
|
|
49
53
|
private parseExpr;
|
|
50
54
|
private parseAssignment;
|
package/dist/parser/index.js
CHANGED
|
@@ -397,6 +397,18 @@ class Parser {
|
|
|
397
397
|
if (this.check('return')) {
|
|
398
398
|
return this.parseReturnStmt();
|
|
399
399
|
}
|
|
400
|
+
// Break statement
|
|
401
|
+
if (this.check('break')) {
|
|
402
|
+
const token = this.advance();
|
|
403
|
+
this.match(';');
|
|
404
|
+
return this.withLoc({ kind: 'break' }, token);
|
|
405
|
+
}
|
|
406
|
+
// Continue statement
|
|
407
|
+
if (this.check('continue')) {
|
|
408
|
+
const token = this.advance();
|
|
409
|
+
this.match(';');
|
|
410
|
+
return this.withLoc({ kind: 'continue' }, token);
|
|
411
|
+
}
|
|
400
412
|
// If statement
|
|
401
413
|
if (this.check('if')) {
|
|
402
414
|
return this.parseIfStmt();
|
|
@@ -534,11 +546,11 @@ class Parser {
|
|
|
534
546
|
this.expect('in');
|
|
535
547
|
const iterable = this.parseExpr();
|
|
536
548
|
this.expect(')');
|
|
537
|
-
// Parse optional execute context modifiers (at, positioned, rotated, facing, etc.)
|
|
549
|
+
// Parse optional execute context modifiers (as, at, positioned, rotated, facing, etc.)
|
|
538
550
|
let executeContext;
|
|
539
|
-
// Check for
|
|
540
|
-
const execIdentKeywords = ['positioned', 'rotated', 'facing', 'anchored', 'align'];
|
|
541
|
-
if (this.check('at') || this.check('in') || (this.check('ident') && execIdentKeywords.includes(this.peek().value))) {
|
|
551
|
+
// Check for execute subcommand keywords
|
|
552
|
+
const execIdentKeywords = ['positioned', 'rotated', 'facing', 'anchored', 'align', 'on', 'summon'];
|
|
553
|
+
if (this.check('as') || this.check('at') || this.check('in') || (this.check('ident') && execIdentKeywords.includes(this.peek().value))) {
|
|
542
554
|
// Collect everything until we hit '{'
|
|
543
555
|
let context = '';
|
|
544
556
|
while (!this.check('{') && !this.check('eof')) {
|
|
@@ -603,34 +615,175 @@ class Parser {
|
|
|
603
615
|
const selector = this.parseSelector();
|
|
604
616
|
subcommands.push({ kind: 'at', selector });
|
|
605
617
|
}
|
|
606
|
-
else if (this.
|
|
607
|
-
|
|
608
|
-
if (this.
|
|
609
|
-
this.
|
|
618
|
+
else if (this.checkIdent('positioned')) {
|
|
619
|
+
this.advance();
|
|
620
|
+
if (this.match('as')) {
|
|
621
|
+
const selector = this.parseSelector();
|
|
622
|
+
subcommands.push({ kind: 'positioned_as', selector });
|
|
623
|
+
}
|
|
624
|
+
else {
|
|
625
|
+
const x = this.parseCoordToken();
|
|
626
|
+
const y = this.parseCoordToken();
|
|
627
|
+
const z = this.parseCoordToken();
|
|
628
|
+
subcommands.push({ kind: 'positioned', x, y, z });
|
|
610
629
|
}
|
|
611
|
-
const selectorOrVar = this.parseSelectorOrVarSelector();
|
|
612
|
-
subcommands.push({ kind: 'if_entity', ...selectorOrVar });
|
|
613
630
|
}
|
|
614
|
-
else if (this.
|
|
615
|
-
|
|
616
|
-
if (this.
|
|
617
|
-
this.
|
|
631
|
+
else if (this.checkIdent('rotated')) {
|
|
632
|
+
this.advance();
|
|
633
|
+
if (this.match('as')) {
|
|
634
|
+
const selector = this.parseSelector();
|
|
635
|
+
subcommands.push({ kind: 'rotated_as', selector });
|
|
636
|
+
}
|
|
637
|
+
else {
|
|
638
|
+
const yaw = this.parseCoordToken();
|
|
639
|
+
const pitch = this.parseCoordToken();
|
|
640
|
+
subcommands.push({ kind: 'rotated', yaw, pitch });
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
else if (this.checkIdent('facing')) {
|
|
644
|
+
this.advance();
|
|
645
|
+
if (this.checkIdent('entity')) {
|
|
646
|
+
this.advance();
|
|
647
|
+
const selector = this.parseSelector();
|
|
648
|
+
const anchor = this.checkIdent('eyes') || this.checkIdent('feet') ? this.advance().value : 'feet';
|
|
649
|
+
subcommands.push({ kind: 'facing_entity', selector, anchor });
|
|
650
|
+
}
|
|
651
|
+
else {
|
|
652
|
+
const x = this.parseCoordToken();
|
|
653
|
+
const y = this.parseCoordToken();
|
|
654
|
+
const z = this.parseCoordToken();
|
|
655
|
+
subcommands.push({ kind: 'facing', x, y, z });
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
else if (this.checkIdent('anchored')) {
|
|
659
|
+
this.advance();
|
|
660
|
+
const anchor = this.advance().value;
|
|
661
|
+
subcommands.push({ kind: 'anchored', anchor });
|
|
662
|
+
}
|
|
663
|
+
else if (this.checkIdent('align')) {
|
|
664
|
+
this.advance();
|
|
665
|
+
const axes = this.advance().value;
|
|
666
|
+
subcommands.push({ kind: 'align', axes });
|
|
667
|
+
}
|
|
668
|
+
else if (this.checkIdent('on')) {
|
|
669
|
+
this.advance();
|
|
670
|
+
const relation = this.advance().value;
|
|
671
|
+
subcommands.push({ kind: 'on', relation });
|
|
672
|
+
}
|
|
673
|
+
else if (this.checkIdent('summon')) {
|
|
674
|
+
this.advance();
|
|
675
|
+
const entity = this.advance().value;
|
|
676
|
+
subcommands.push({ kind: 'summon', entity });
|
|
677
|
+
}
|
|
678
|
+
else if (this.checkIdent('store')) {
|
|
679
|
+
this.advance();
|
|
680
|
+
const storeType = this.advance().value; // 'result' or 'success'
|
|
681
|
+
if (this.checkIdent('score')) {
|
|
682
|
+
this.advance();
|
|
683
|
+
const target = this.advance().value;
|
|
684
|
+
const targetObj = this.advance().value;
|
|
685
|
+
if (storeType === 'result') {
|
|
686
|
+
subcommands.push({ kind: 'store_result', target, targetObj });
|
|
687
|
+
}
|
|
688
|
+
else {
|
|
689
|
+
subcommands.push({ kind: 'store_success', target, targetObj });
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
else {
|
|
693
|
+
this.error('store currently only supports score target');
|
|
618
694
|
}
|
|
619
|
-
|
|
620
|
-
|
|
695
|
+
}
|
|
696
|
+
else if (this.match('if')) {
|
|
697
|
+
this.parseExecuteCondition(subcommands, 'if');
|
|
698
|
+
}
|
|
699
|
+
else if (this.match('unless')) {
|
|
700
|
+
this.parseExecuteCondition(subcommands, 'unless');
|
|
621
701
|
}
|
|
622
702
|
else if (this.match('in')) {
|
|
623
|
-
|
|
703
|
+
// Dimension can be namespaced: minecraft:the_nether
|
|
704
|
+
let dim = this.advance().value;
|
|
705
|
+
if (this.match(':')) {
|
|
706
|
+
dim += ':' + this.advance().value;
|
|
707
|
+
}
|
|
624
708
|
subcommands.push({ kind: 'in', dimension: dim });
|
|
625
709
|
}
|
|
626
710
|
else {
|
|
627
|
-
this.error(`Unexpected token in execute statement: ${this.peek().kind}`);
|
|
711
|
+
this.error(`Unexpected token in execute statement: ${this.peek().kind} (${this.peek().value})`);
|
|
628
712
|
}
|
|
629
713
|
}
|
|
630
714
|
this.expect('run');
|
|
631
715
|
const body = this.parseBlock();
|
|
632
716
|
return this.withLoc({ kind: 'execute', subcommands, body }, executeToken);
|
|
633
717
|
}
|
|
718
|
+
parseExecuteCondition(subcommands, type) {
|
|
719
|
+
if (this.checkIdent('entity') || this.check('selector')) {
|
|
720
|
+
if (this.checkIdent('entity'))
|
|
721
|
+
this.advance();
|
|
722
|
+
const selectorOrVar = this.parseSelectorOrVarSelector();
|
|
723
|
+
subcommands.push({ kind: type === 'if' ? 'if_entity' : 'unless_entity', ...selectorOrVar });
|
|
724
|
+
}
|
|
725
|
+
else if (this.checkIdent('block')) {
|
|
726
|
+
this.advance();
|
|
727
|
+
const x = this.parseCoordToken();
|
|
728
|
+
const y = this.parseCoordToken();
|
|
729
|
+
const z = this.parseCoordToken();
|
|
730
|
+
const block = this.parseBlockId();
|
|
731
|
+
subcommands.push({ kind: type === 'if' ? 'if_block' : 'unless_block', pos: [x, y, z], block });
|
|
732
|
+
}
|
|
733
|
+
else if (this.checkIdent('score')) {
|
|
734
|
+
this.advance();
|
|
735
|
+
const target = this.advance().value;
|
|
736
|
+
const targetObj = this.advance().value;
|
|
737
|
+
// Check for range or comparison
|
|
738
|
+
if (this.checkIdent('matches')) {
|
|
739
|
+
this.advance();
|
|
740
|
+
const range = this.advance().value;
|
|
741
|
+
subcommands.push({ kind: type === 'if' ? 'if_score_range' : 'unless_score_range', target, targetObj, range });
|
|
742
|
+
}
|
|
743
|
+
else {
|
|
744
|
+
const op = this.advance().value; // <, <=, =, >=, >
|
|
745
|
+
const source = this.advance().value;
|
|
746
|
+
const sourceObj = this.advance().value;
|
|
747
|
+
subcommands.push({
|
|
748
|
+
kind: type === 'if' ? 'if_score' : 'unless_score',
|
|
749
|
+
target, targetObj, op, source, sourceObj
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
else {
|
|
754
|
+
this.error(`Unknown condition type after ${type}`);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
parseCoordToken() {
|
|
758
|
+
// Handle ~, ^, numbers, relative coords like ~5, ^-3
|
|
759
|
+
const token = this.peek();
|
|
760
|
+
if (token.kind === 'rel_coord' || token.kind === 'local_coord' ||
|
|
761
|
+
token.kind === 'int_lit' || token.kind === 'float_lit' ||
|
|
762
|
+
token.kind === '-' || token.kind === 'ident') {
|
|
763
|
+
return this.advance().value;
|
|
764
|
+
}
|
|
765
|
+
this.error(`Expected coordinate, got ${token.kind}`);
|
|
766
|
+
return '~';
|
|
767
|
+
}
|
|
768
|
+
parseBlockId() {
|
|
769
|
+
// Parse block ID like minecraft:stone or stone
|
|
770
|
+
let id = this.advance().value;
|
|
771
|
+
if (this.match(':')) {
|
|
772
|
+
id += ':' + this.advance().value;
|
|
773
|
+
}
|
|
774
|
+
// Handle block states [facing=north]
|
|
775
|
+
if (this.check('[')) {
|
|
776
|
+
id += this.advance().value; // [
|
|
777
|
+
while (!this.check(']') && !this.check('eof')) {
|
|
778
|
+
id += this.advance().value;
|
|
779
|
+
}
|
|
780
|
+
id += this.advance().value; // ]
|
|
781
|
+
}
|
|
782
|
+
return id;
|
|
783
|
+
}
|
|
784
|
+
checkIdent(value) {
|
|
785
|
+
return this.check('ident') && this.peek().value === value;
|
|
786
|
+
}
|
|
634
787
|
parseExprStmt() {
|
|
635
788
|
const expr = this.parseExpr();
|
|
636
789
|
this.expect(';');
|
package/package.json
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Array operations test
|
|
2
|
+
|
|
3
|
+
@keep fn test_array() {
|
|
4
|
+
// Array initialization
|
|
5
|
+
let nums: int[] = [10, 20, 30, 40, 50];
|
|
6
|
+
|
|
7
|
+
// Array access
|
|
8
|
+
scoreboard_set("#arr_0", #rs, nums[0]);
|
|
9
|
+
scoreboard_set("#arr_2", #rs, nums[2]);
|
|
10
|
+
scoreboard_set("#arr_4", #rs, nums[4]);
|
|
11
|
+
|
|
12
|
+
// Array length via .len property
|
|
13
|
+
scoreboard_set("#arr_len", #rs, nums.len);
|
|
14
|
+
|
|
15
|
+
// Sum via foreach
|
|
16
|
+
let sum: int = 0;
|
|
17
|
+
foreach (n in nums) {
|
|
18
|
+
sum = sum + n;
|
|
19
|
+
}
|
|
20
|
+
scoreboard_set("#arr_sum", #rs, sum);
|
|
21
|
+
|
|
22
|
+
// Push operation
|
|
23
|
+
let arr2: int[] = [1, 2, 3];
|
|
24
|
+
arr2.push(4);
|
|
25
|
+
scoreboard_set("#arr_push", #rs, arr2.len);
|
|
26
|
+
|
|
27
|
+
// Pop operation
|
|
28
|
+
let popped: int = arr2.pop();
|
|
29
|
+
scoreboard_set("#arr_pop", #rs, popped);
|
|
30
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Break and continue statements test
|
|
2
|
+
|
|
3
|
+
@keep fn test_break_continue() {
|
|
4
|
+
// Test break - should stop at i=5
|
|
5
|
+
let break_at: int = -1;
|
|
6
|
+
for (let i: int = 0; i < 10; i = i + 1) {
|
|
7
|
+
if (i == 5) {
|
|
8
|
+
break_at = i;
|
|
9
|
+
break;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
scoreboard_set("#break_at", #rs, break_at);
|
|
13
|
+
|
|
14
|
+
// Test continue - sum only even numbers
|
|
15
|
+
let sum_evens: int = 0;
|
|
16
|
+
for (let i: int = 0; i < 10; i = i + 1) {
|
|
17
|
+
if (i % 2 != 0) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
sum_evens = sum_evens + i;
|
|
21
|
+
}
|
|
22
|
+
// 0+2+4+6+8 = 20
|
|
23
|
+
scoreboard_set("#sum_evens", #rs, sum_evens);
|
|
24
|
+
|
|
25
|
+
// While with break
|
|
26
|
+
let count: int = 0;
|
|
27
|
+
while (true) {
|
|
28
|
+
count = count + 1;
|
|
29
|
+
if (count >= 7) {
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
scoreboard_set("#while_break", #rs, count);
|
|
34
|
+
|
|
35
|
+
// Nested loop break (breaks inner only)
|
|
36
|
+
let outer_count: int = 0;
|
|
37
|
+
for (let a: int = 0; a < 3; a = a + 1) {
|
|
38
|
+
for (let b: int = 0; b < 10; b = b + 1) {
|
|
39
|
+
if (b == 2) {
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
outer_count = outer_count + 1;
|
|
44
|
+
}
|
|
45
|
+
scoreboard_set("#nested_break", #rs, outer_count);
|
|
46
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Enum definition and matching test
|
|
2
|
+
|
|
3
|
+
enum GamePhase {
|
|
4
|
+
Lobby, // 0
|
|
5
|
+
Starting, // 1
|
|
6
|
+
Playing, // 2
|
|
7
|
+
Ended // 3
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
enum Rank {
|
|
11
|
+
Bronze = 1,
|
|
12
|
+
Silver = 2,
|
|
13
|
+
Gold = 3,
|
|
14
|
+
Diamond = 10
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@keep fn test_enum() {
|
|
18
|
+
// Basic enum value (use . not ::)
|
|
19
|
+
let phase: int = GamePhase.Playing;
|
|
20
|
+
scoreboard_set("#enum_phase", #rs, phase);
|
|
21
|
+
|
|
22
|
+
// Match on enum
|
|
23
|
+
match (phase) {
|
|
24
|
+
GamePhase.Lobby => { scoreboard_set("#enum_match", #rs, 0); }
|
|
25
|
+
GamePhase.Playing => { scoreboard_set("#enum_match", #rs, 2); }
|
|
26
|
+
_ => { scoreboard_set("#enum_match", #rs, -1); }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Custom values
|
|
30
|
+
let rank: int = Rank.Diamond;
|
|
31
|
+
scoreboard_set("#enum_rank", #rs, rank);
|
|
32
|
+
|
|
33
|
+
// Comparison
|
|
34
|
+
if (rank > Rank.Gold) {
|
|
35
|
+
scoreboard_set("#enum_high", #rs, 1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Foreach with execute context modifiers test
|
|
2
|
+
|
|
3
|
+
@load fn setup() {
|
|
4
|
+
scoreboard_add("rs");
|
|
5
|
+
scoreboard_set("#foreach_count", #rs, 0);
|
|
6
|
+
scoreboard_set("#foreach_at_count", #rs, 0);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
@keep fn test_foreach_at() {
|
|
10
|
+
// Spawn test entities
|
|
11
|
+
raw("summon minecraft:armor_stand ~ ~ ~ {Tags:[\"test_foreach\"],NoGravity:1b}");
|
|
12
|
+
raw("summon minecraft:armor_stand ~2 ~ ~ {Tags:[\"test_foreach\"],NoGravity:1b}");
|
|
13
|
+
raw("summon minecraft:armor_stand ~4 ~ ~ {Tags:[\"test_foreach\"],NoGravity:1b}");
|
|
14
|
+
|
|
15
|
+
// Basic foreach
|
|
16
|
+
let count: int = 0;
|
|
17
|
+
foreach (e in @e[type=armor_stand,tag=test_foreach]) {
|
|
18
|
+
count = count + 1;
|
|
19
|
+
}
|
|
20
|
+
scoreboard_set("#foreach_count", #rs, count);
|
|
21
|
+
|
|
22
|
+
// Foreach with at @s (execute at entity position)
|
|
23
|
+
let at_count: int = 0;
|
|
24
|
+
foreach (e in @e[type=armor_stand,tag=test_foreach]) at @s {
|
|
25
|
+
// This runs at each entity's position
|
|
26
|
+
at_count = at_count + 1;
|
|
27
|
+
raw("particle minecraft:heart ~ ~1 ~ 0 0 0 0 1");
|
|
28
|
+
}
|
|
29
|
+
scoreboard_set("#foreach_at_count", #rs, at_count);
|
|
30
|
+
|
|
31
|
+
// Cleanup
|
|
32
|
+
raw("kill @e[type=armor_stand,tag=test_foreach]");
|
|
33
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Match with range patterns test
|
|
2
|
+
|
|
3
|
+
@keep fn test_match_range() {
|
|
4
|
+
// Test score grading
|
|
5
|
+
let score: int = 85;
|
|
6
|
+
let grade: int = 0;
|
|
7
|
+
|
|
8
|
+
match (score) {
|
|
9
|
+
0..59 => { grade = 1; } // F
|
|
10
|
+
60..69 => { grade = 2; } // D
|
|
11
|
+
70..79 => { grade = 3; } // C
|
|
12
|
+
80..89 => { grade = 4; } // B
|
|
13
|
+
90..100 => { grade = 5; } // A
|
|
14
|
+
_ => { grade = 0; }
|
|
15
|
+
}
|
|
16
|
+
scoreboard_set("#grade", #rs, grade);
|
|
17
|
+
|
|
18
|
+
// Test boundary values
|
|
19
|
+
let val1: int = 59;
|
|
20
|
+
let result1: int = 0;
|
|
21
|
+
match (val1) {
|
|
22
|
+
0..59 => { result1 = 1; }
|
|
23
|
+
60..100 => { result1 = 2; }
|
|
24
|
+
_ => { result1 = 0; }
|
|
25
|
+
}
|
|
26
|
+
scoreboard_set("#boundary_59", #rs, result1);
|
|
27
|
+
|
|
28
|
+
let val2: int = 60;
|
|
29
|
+
let result2: int = 0;
|
|
30
|
+
match (val2) {
|
|
31
|
+
0..59 => { result2 = 1; }
|
|
32
|
+
60..100 => { result2 = 2; }
|
|
33
|
+
_ => { result2 = 0; }
|
|
34
|
+
}
|
|
35
|
+
scoreboard_set("#boundary_60", #rs, result2);
|
|
36
|
+
|
|
37
|
+
// Open-ended ranges
|
|
38
|
+
let neg: int = -5;
|
|
39
|
+
let neg_result: int = 0;
|
|
40
|
+
match (neg) {
|
|
41
|
+
..0 => { neg_result = 1; }
|
|
42
|
+
0.. => { neg_result = 2; }
|
|
43
|
+
}
|
|
44
|
+
scoreboard_set("#neg_range", #rs, neg_result);
|
|
45
|
+
}
|