phase-20.45: PRIMARY no-fallback reps + MIR v0 shape fixes
- Fix MIR v0 shape in lowers: functions[] + name="main" + blocks.id * lower_return_int_box.hako * lower_return_binop_box.hako - runner_min: adopt LowerReturnBinOpBox before ReturnInt - Add PRIMARY no-fallback canaries (all PASS): * return-binop / array-size / load-store / return-logical (OR) - Fix phase2043 runner_min canary alias (Runner -> BuilderRunnerMinBox) - Update docs: phase-20.45 README (PRIMARY reps), CURRENT_TASK progress Ancillary: keep builder/provider/canary files in sync; no unrelated behavior changes.
This commit is contained in:
145
CURRENT_TASK.md
145
CURRENT_TASK.md
@ -1,31 +1,42 @@
|
||||
# Current Task — Phase 20.39 (Typed IR & hv1 finalize)
|
||||
# Current Task — Phase 20.45 (self‑host E2E 1/2)
|
||||
|
||||
This document is intentionally concise (≤ 500 lines). Detailed history and per‑phase plans are kept under docs/private/roadmap/. See links below.
|
||||
|
||||
Focus (now)
|
||||
- Typed IR(SSOT)の導入: V1ConstIR / V1CompareIR / V1BranchIR / V1JumpIR / V1PhiIR / V1RetIR を Hako で定義(挙動不変)。
|
||||
- **hv1 verify の最終化: main.rs 入口一本化完了(DONE)**
|
||||
- プラグイン初期化前に early-exit(UnifiedBoxRegistry ログなし)。
|
||||
- vm.rs / vm_fallback.rs / dispatch.rs の重複分岐を撤去済み。
|
||||
- カナリー追加: `hv1_direct_no_plugin_init_canary.sh` で検証 PASS。
|
||||
- 環境変数: `HAKO_VERIFY_PRIMARY=hakovm` (推奨) または `HAKO_ROUTE_HAKOVM=1` (互換)
|
||||
- Concat-safety sweep: """ + <Box>" を VM/Core から一掃(StrCast/StringHelpers に統一、進捗: 核心パス DONE)。
|
||||
- LoopForm.build2 の適用拡大(lower_loop_* 代表に適用済/続行)。
|
||||
- Instruction Dedup(SSOT helpers): binop_lower / loop_common で Builder/Bridge の重複を排除(第一段)。
|
||||
- Builder 側: `src/mir/builder/ops.rs` の BinOp 発行を SSOT (`emit_binop_to_dst`) 経由に切替(挙動不変・id 整合維持)。
|
||||
- Bridge 側: `json_v0_bridge/lowering/expr.rs` は `ssot::binop_lower::emit_binop_func` 採用済。
|
||||
- Hako MirBuilder → v1 MIR → hv1 実行を PRIMARY に固定(no‑fallback)。
|
||||
- Array/Map の rc 実行を段階移行(builder‑only → rc)。
|
||||
- Provider 実行(emit/codegen)を恒常運用できる形に整備(代表は Hako PRIMARY で緑)。
|
||||
|
||||
Remaining (20.39 — typed IR & finalize)
|
||||
- Add typed IR boxes and module export(hakorune-vm.ir.types)。
|
||||
- Wire dispatcher to accept typed IR inputs gradually(写像ヘルパ・差分ゼロ)。
|
||||
- Remove include fallback from scripts(直行のみ)。
|
||||
- Sweep concatenations and update helpers.
|
||||
Remaining (20.45)
|
||||
- Array/Map rc 移行(段階)
|
||||
- v0 ローダに newbox/boxcall の最小受理を追加、または provider emit を v1 スキーマへ寄せるトグルを追加(どちらか一方で可)。
|
||||
- lowers 生成側の size 標準化(len/length は受理側で別名吸収)。
|
||||
- Provider 直行の幅出し
|
||||
- 三項・match・論理・複数 block の rc カナリを拡充。
|
||||
- 逆引き/スキャナ統一のスイープ(小粒継続)
|
||||
- If/Compare VarInt/VarVar、Return BinOp/Logical に PatternUtilBox/JsonFragBox を適用。
|
||||
- ループ系の JsonFragBox 化(ProgScan 置換を段階導入)。
|
||||
|
||||
Progress (today)
|
||||
- PRIMARY no-fallback reps 拡張(canary 追加・緑化)
|
||||
- Return(Int)(runner_min 経由): PASS
|
||||
- Return(BinOp Int+Int)(runner_min 経由): PASS
|
||||
- Array.size(MirBuilder 経由): PASS
|
||||
- Logical(OR の代表、MirBuilder 経由): PASS(AND は次フェーズで検証/整備)
|
||||
- Load/Store(runner_min v1 → hv1 inline): PASS
|
||||
- 修正
|
||||
- lower_return_int_box.hako: MIR v0 形状を正規化(functions[]=…, name="main", blocks.id)
|
||||
- lower_return_binop_box.hako: 同上(v0 形状)
|
||||
- runner_min_box.hako: Return(BinOp) を採用
|
||||
- phase2043 runner_min カナリの alias を修正(Runner→BuilderRunnerMinBox)
|
||||
|
||||
Next Steps (ordered)
|
||||
1) ループ比較の正規化拡張(>/>=/==/!= → Lt/Gt/Ge 正規化;左右スワップ++1調整、canary補強)
|
||||
2) SSOT 拡張(compare/branch/jump/phi を cf_common に段階移行)
|
||||
3) Unicode `\\uXXXX` 復号のトグル実装(既定OFF;canary追加)
|
||||
4) hv1 一本化(main入口)と文字列スキャナ根治('対応+エスケープ拡張)を DONE に反映
|
||||
1) Hako MirBuilder PRIMARY(HAKO_PRIMARY_NO_FALLBACK=1)で代表(Return/If/Compare/Logical/Match/Ternary/Loop/Array/Map)を順に緑化。
|
||||
2) 生成側 size 標準化の横展開(rc カナリに切替)。
|
||||
3) Provider 幅出し(三項・match・論理・複数 block)rc カナリの追加。
|
||||
4) 逆引き/スキャナ統一スイープの継続(If/Compare/Return)。
|
||||
5) ループ系の JsonFragBox 化(安全サブセットから)。
|
||||
6) Logical(AND) の PRIMARY 化(必要に応じ Lower の堅牢化)。
|
||||
|
||||
Hotfix Plan — Using/Prelude Unification (Self‑Host)
|
||||
- Problem: .hako を NyashParser に通す経路でパース落ち(Invalid expression)。
|
||||
@ -51,19 +62,17 @@ Action Items (20.38)
|
||||
- phase‑20.38 のトグル/受け入れ条件/撤去予定のシムを反映。φ entry SSOT は IR 完了後に更新。
|
||||
- extern タグ用シムの現状と撤去条件(hv1 inline 安定後に除去)を明記。
|
||||
|
||||
Acceptance
|
||||
- extern canary(warn/error/emit/codegen): Hako primary で PASS(タグ+rc=0、シム無効でも安定)。
|
||||
- v1 φ/branch/jump の代表カナリーが IR 反復で strict PASS。tolerate ケースは期待と一致。
|
||||
- Verify 既定が v1→Hakorune(Core fallback)で quick 緑維持。
|
||||
- Hako 構文を Nyash VM で実行しようとした場合、入口で Fail‑Fast(診断メッセージ)。
|
||||
- hv1 直行は main 入口で早期退出し、プラグイン初期化ログが出ない(canaryで保証)。
|
||||
Acceptance(phase 20.45)
|
||||
- Hako PRIMARY(HAKO_PRIMARY_NO_FALLBACK=1)で代表構文が rc パリティ。
|
||||
- Array/Map: push/size=2、set/size=1 の rc カナリが PRIMARY で PASS。
|
||||
- Provider 複数ブロック代表(if-nested/else-if/if→match)が rc で緑維持。
|
||||
|
||||
Changes (this step)
|
||||
- hv1 direct を main 入口で早期退出に一本化(プラグイン初期化前で rc のみ出力)。
|
||||
- Tokenizer 根治: Stage‑3 でシングルクォート受理、エスケープ(\\/ \\b \\f \\' \\r)拡張。
|
||||
- SSOT: Builder BinOp を `emit_binop_to_dst` で発行(挙動不変)。
|
||||
- Loop 正規化: CountParam に `L<i` / `L<=i`(降順)を追加受理(cmp=Gt/Ge)。canary 2本追加(swapped_lt/lte)。
|
||||
- Docs: phase‑20.39 Next Steps を追記、hv1一本化/文字列スキャナ根治を DONE として明記。
|
||||
Changes (recent)
|
||||
- nyash.toml に box_types/box_methods を追加(ArrayBox/MapBox の method_id を中央集約)。
|
||||
- PluginHost.resolve_method が中央定義を参照(ライブラリ無しでも解決可)。
|
||||
- test_runner: v1/hv1 と v0(newbox/boxcall) の振分けを追加(hv1 inline / Hako Core dispatcher)。
|
||||
- MirBuilder RunnerMin: lower_return_int_box.hako の出力を MIR JSON v0 の正しい形(functions 配列 + name="main" + blocks.id)へ修正。
|
||||
- これにより HAKO_PRIMARY_NO_FALLBACK=1 の canary(hako_primary_no_fallback_if_compare_core_exec_canary_vm)が緑化。
|
||||
|
||||
// Loop compares normalization (Step‑1)
|
||||
- Loop lowers(simple/count_param/sum_bc): Compare 受理を拡張し Lt 形へ正規化。
|
||||
@ -216,3 +225,73 @@ Updates (2025-11-04)
|
||||
- hv1 inline: alias-only route stabilized (no include/preinclude). vm.rs wrapper now uses `using selfhost.vm.hv1.dispatch` and relaxes fail-fast for child.
|
||||
- Verify harness: include+preinclude fallback for v1 removed in `verify_mir_rc`; alias-only hv1 is the standard path.
|
||||
- Concat-safety (hv1 scope): replaced `"" + <int>` coercions with `StringHelpers.int_to_str(...)` in `lang/src/vm/hakorune-vm/dispatcher_v1.hako` and `lang/src/vm/boxes/mir_call_v1_handler.hako`.
|
||||
# Handoff — 20.43 Kickoff (15h progress)
|
||||
|
||||
Focus (next)
|
||||
- Start Phase 20.43: MIR generation coverage for call/method/newbox/load/store/typeop, with minimal Array/Map bridge (structure-first, no behavior change).
|
||||
|
||||
What’s landed this session (DONE)
|
||||
- NewBox → Constructor (minimal lower)
|
||||
- Added: `lang/src/mir/builder/internal/lower_newbox_constructor_box.hako`
|
||||
- Wired in: `lang/src/mir/builder/MirBuilderBox.hako` (try_lower early) and alias in `nyash.toml`.
|
||||
- Direct canary (PASS): `tools/smokes/v2/profiles/quick/core/phase2043/lower_newbox_constructor_direct_core_exec_canary_vm.sh`.
|
||||
- Method(size) → structural MIR (Array)
|
||||
- Added: `lang/src/mir/builder/internal/lower_method_array_size_box.hako` + alias in `nyash.toml`.
|
||||
- Direct structural canary (PASS): `tools/smokes/v2/profiles/quick/core/phase2043/lower_method_array_size_direct_struct_canary_vm.sh`.
|
||||
- Method(push) → structural MIR (Array)
|
||||
- Added: `lang/src/mir/builder/internal/lower_method_array_push_box.hako` + alias in `nyash.toml`.
|
||||
- Direct structural canary (PASS): `tools/smokes/v2/profiles/quick/core/phase2043/lower_method_array_push_direct_struct_canary_vm.sh`.
|
||||
- New → Constructor (direct) and Method(size/push) canaries all green under phase‑2043.
|
||||
- Array get/set
|
||||
- Added: `lang/src/mir/builder/internal/lower_method_array_get_set_box.hako` + alias.
|
||||
- Direct structural canary (PASS): `tools/smokes/v2/profiles/quick/core/phase2043/lower_method_array_get_set_direct_struct_canary_vm.sh`.
|
||||
- Map size/get/set
|
||||
- Added: `lang/src/mir/builder/internal/lower_method_map_size_box.hako`, `lower_method_map_get_set_box.hako` + aliases.
|
||||
- Direct structural canaries (PASS): `lower_method_map_size_direct_struct_canary_vm.sh`, `lower_method_map_get_set_direct_struct_canary_vm.sh`.
|
||||
- Load/Store(最小)
|
||||
- Added: `lang/src/mir/builder/internal/lower_load_store_local_box.hako` + alias。
|
||||
- Direct structural canary (PASS): `lower_load_store_local_direct_struct_canary_vm.sh`。
|
||||
- TypeOp Check(最小)
|
||||
- Added: `lang/src/mir/builder/internal/lower_typeop_check_box.hako` + alias。
|
||||
- Direct structural canary (PASS): `lower_typeop_check_direct_struct_canary_vm.sh`。
|
||||
- TypeOp Cast(最小)
|
||||
- Added: `lang/src/mir/builder/internal/lower_typeop_cast_box.hako` + alias。
|
||||
- Direct structural canary (PASS): `lower_typeop_cast_direct_struct_canary_vm.sh`。
|
||||
- Builder internal route stabilized for simple New → Core via runner_min
|
||||
- Added: `lang/src/mir/builder/internal/runner_min_box.hako` + alias。
|
||||
- `verify_program_via_builder_to_core` uses runner_min first, with markers + optional full MirBuilder fallback.
|
||||
- Harness improvements
|
||||
- Builder output extraction with markers `[MIR_OUT_BEGIN]/[MIR_OUT_END]` in `tools/smokes/v2/lib/test_runner.sh`.
|
||||
- Debug tails for stdout/stderr when `HAKO_MIR_BUILDER_DEBUG=1`.
|
||||
- Enabled using for inline runs: `NYASH_ENABLE_USING=1` / `HAKO_ENABLE_USING=1`.
|
||||
|
||||
Open items / blockers
|
||||
- Builder (internal/delegate) inline route still unstable for JSON capture; `phase2043/program_new_array_delegate_struct_canary_vm.sh` fails (no JSON in stdout).
|
||||
- Plan: switch builder to write MIR to a temp file (FileBox) and let harness read it; or adopt provider route in 20.44 (`env.mirbuilder.emit`).
|
||||
- Remaining lowers for 20.43 not yet added: method(push/get/set/len), load/store (local), typeop(is/as) minimal; builder wiring after direct lowers pass.
|
||||
|
||||
Next-up checklist (20.43)
|
||||
1) MirBuilder wiring: 上記 direct lowers を `MirBuilderBox` から段階採用(Return系フォールバック前)→ 一部(Array/Map/LoadStore/TypeOp)採用済み。
|
||||
2) New(Map) は Constructor lower で既に生成可能(direct PASS)。Builder経路へ採用。
|
||||
3) TypeOp: `Cast` 採用済(構造lower→canary→配線)。
|
||||
4) Builder route 安定化(internal):lower ラッパー側で MIR を `/tmp` に保存→ハーネスが読む(pipe 揺れを回避)。
|
||||
5) Delegate route(20.44 に接続):`env.mirbuilder.emit` を provider 経由に切替(構造は共通)。
|
||||
6) Delegate route (optional): use provider `env.mirbuilder.emit` (20.44 scope) to make canaries robust.
|
||||
|
||||
How to run
|
||||
- All new phase 20.43 canaries:
|
||||
- `bash tools/smokes/v2/run.sh --profile quick --filter phase2043`
|
||||
- Single tests:
|
||||
- NewBox direct: `tools/smokes/v2/profiles/quick/core/phase2043/lower_newbox_constructor_direct_core_exec_canary_vm.sh`
|
||||
- Method(size) direct: `tools/smokes/v2/profiles/quick/core/phase2043/lower_method_array_size_direct_struct_canary_vm.sh`
|
||||
|
||||
Toggles (dev)
|
||||
- Inline Hako: `HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1`
|
||||
- Builder internal: `HAKO_MIR_BUILDER_INTERNAL=1` (and `HAKO_MIR_BUILDER_DEBUG=1` for tails)
|
||||
|
||||
Pointers
|
||||
- New lowers: `lang/src/mir/builder/internal/lower_newbox_constructor_box.hako`, `lang/src/mir/builder/internal/lower_method_array_size_box.hako`
|
||||
- Wiring: `lang/src/mir/builder/MirBuilderBox.hako` (try_lower order) and `nyash.toml` aliases
|
||||
- Harness: `tools/smokes/v2/lib/test_runner.sh` (marker extraction / debug tails)
|
||||
|
||||
---
|
||||
|
||||
695
build.err
Normal file
695
build.err
Normal file
@ -0,0 +1,695 @@
|
||||
warning: profiles for the non root package will be ignored, specify profiles at the workspace root:
|
||||
package: /home/tomoaki/git/hakorune-selfhost/plugins/nyash-console-plugin/Cargo.toml
|
||||
workspace: /home/tomoaki/git/hakorune-selfhost/Cargo.toml
|
||||
warning: profiles for the non root package will be ignored, specify profiles at the workspace root:
|
||||
package: /home/tomoaki/git/hakorune-selfhost/plugins/nyash-counter-plugin/Cargo.toml
|
||||
workspace: /home/tomoaki/git/hakorune-selfhost/Cargo.toml
|
||||
warning: profiles for the non root package will be ignored, specify profiles at the workspace root:
|
||||
package: /home/tomoaki/git/hakorune-selfhost/plugins/nyash-filebox-plugin/Cargo.toml
|
||||
workspace: /home/tomoaki/git/hakorune-selfhost/Cargo.toml
|
||||
warning: profiles for the non root package will be ignored, specify profiles at the workspace root:
|
||||
package: /home/tomoaki/git/hakorune-selfhost/plugins/nyash-json-plugin/Cargo.toml
|
||||
workspace: /home/tomoaki/git/hakorune-selfhost/Cargo.toml
|
||||
warning: profiles for the non root package will be ignored, specify profiles at the workspace root:
|
||||
package: /home/tomoaki/git/hakorune-selfhost/plugins/nyash-math-plugin/Cargo.toml
|
||||
workspace: /home/tomoaki/git/hakorune-selfhost/Cargo.toml
|
||||
warning: /home/tomoaki/git/hakorune-selfhost/Cargo.toml: file `/home/tomoaki/git/hakorune-selfhost/src/main.rs` found to be present in multiple build targets:
|
||||
* `bin` target `hakorune`
|
||||
* `bin` target `nyash`
|
||||
Compiling nyash-rust v0.1.0 (/home/tomoaki/git/hakorune-selfhost)
|
||||
warning: unused doc comment
|
||||
--> src/box_operators/static_ops.rs:14:1
|
||||
|
|
||||
14 | / /// Static numeric operations for IntegerBox
|
||||
15 | | ///
|
||||
16 | | /// Generates implementations for: Add, Sub, Mul, Div with zero-division error handling
|
||||
| |_--------------------------------------------------------------------------------------^
|
||||
| |
|
||||
| rustdoc does not generate documentation for macro invocations
|
||||
|
|
||||
= help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
|
||||
= note: `#[warn(unused_doc_comments)]` on by default
|
||||
|
||||
warning: unused doc comment
|
||||
--> src/box_operators/static_ops.rs:19:1
|
||||
|
|
||||
19 | / /// Static numeric operations for FloatBox
|
||||
20 | | ///
|
||||
21 | | /// Generates implementations for: Add, Sub, Mul, Div with zero-division error handling
|
||||
| |_--------------------------------------------------------------------------------------^
|
||||
| |
|
||||
| rustdoc does not generate documentation for macro invocations
|
||||
|
|
||||
= help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
|
||||
|
||||
warning: unused import: `std::any::Any`
|
||||
--> src/boxes/arithmetic/modulo_box.rs:6:5
|
||||
|
|
||||
6 | use std::any::Any;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(unused_imports)]` on by default
|
||||
|
||||
warning: unused import: `HashMap`
|
||||
--> src/mir/basic_block.rs:8:24
|
||||
|
|
||||
8 | use std::collections::{HashMap, HashSet};
|
||||
| ^^^^^^^
|
||||
|
||||
warning: unused import: `call_target::CallTarget`
|
||||
--> src/mir/builder/calls/mod.rs:10:9
|
||||
|
|
||||
10 | pub use call_target::CallTarget;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused imports: `has_method`, `is_builtin_function`, `is_extern_function`, and `resolve_call_target`
|
||||
--> src/mir/builder/calls/mod.rs:32:5
|
||||
|
|
||||
32 | resolve_call_target,
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
33 | is_builtin_function,
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
34 | is_extern_function,
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
35 | has_method,
|
||||
| ^^^^^^^^^^
|
||||
|
||||
warning: unused imports: `compute_extern_effects`, `get_env_method_spec`, `is_env_interface`, and `parse_extern_name`
|
||||
--> src/mir/builder/calls/mod.rs:39:5
|
||||
|
|
||||
39 | get_env_method_spec,
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
40 | parse_extern_name,
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
41 | is_env_interface,
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
42 | compute_extern_effects,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused imports: `contains_value_return`, `extract_string_literal`, `is_math_function`, `is_typeop_method`, `make_function_name_with_arity`, and `parse_type_name_to_mir`
|
||||
--> src/mir/builder/calls/mod.rs:46:5
|
||||
|
|
||||
46 | is_math_function,
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
47 | is_typeop_method,
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
48 | extract_string_literal,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
49 | parse_type_name_to_mir,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
50 | contains_value_return,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
51 | make_function_name_with_arity,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused imports: `generate_method_function_name`, `generate_static_method_function_name`, `prepare_method_signature`, `prepare_static_method_signature`, and `wrap_in_program`
|
||||
--> src/mir/builder/calls/mod.rs:55:5
|
||||
|
|
||||
55 | prepare_method_signature,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
56 | prepare_static_method_signature,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
57 | generate_method_function_name,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
58 | generate_static_method_function_name,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
59 | wrap_in_program,
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused imports: `compute_call_effects`, `convert_target_to_callee`, `create_call_flags`, `create_mir_call`, `is_unified_call_enabled`, and `validate_call_args`
|
||||
--> src/mir/builder/calls/mod.rs:63:5
|
||||
|
|
||||
63 | is_unified_call_enabled,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
64 | convert_target_to_callee,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
65 | compute_call_effects,
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
66 | create_call_flags,
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
67 | create_mir_call,
|
||||
| ^^^^^^^^^^^^^^^
|
||||
68 | validate_call_args,
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused import: `FunctionSignature`
|
||||
--> src/mir/builder/builder_calls.rs:2:33
|
||||
|
|
||||
2 | use super::{Effect, EffectMask, FunctionSignature, MirInstruction, MirType, ValueId};
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused import: `MethodCallExpr`
|
||||
--> src/mir/builder/builder_calls.rs:3:41
|
||||
|
|
||||
3 | use crate::ast::{ASTNode, LiteralValue, MethodCallExpr};
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused imports: `CallFlags` and `MirCall`
|
||||
--> src/mir/builder/builder_calls.rs:4:53
|
||||
|
|
||||
4 | use crate::mir::definitions::call_unified::{Callee, CallFlags, MirCall};
|
||||
| ^^^^^^^^^ ^^^^^^^
|
||||
|
||||
warning: unused import: `super::call_resolution`
|
||||
--> src/mir/builder/builder_calls.rs:6:5
|
||||
|
|
||||
6 | use super::call_resolution;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused import: `MirType`
|
||||
--> src/mir/builder/method_call_handlers.rs:9:46
|
||||
|
|
||||
9 | use crate::mir::{MirInstruction, TypeOpKind, MirType};
|
||||
| ^^^^^^^
|
||||
|
||||
warning: unused import: `ConstValue`
|
||||
--> src/mir/builder/decls.rs:2:13
|
||||
|
|
||||
2 | use super::{ConstValue, MirInstruction, ValueId};
|
||||
| ^^^^^^^^^^
|
||||
|
||||
warning: unused import: `ConstValue`
|
||||
--> src/mir/builder/exprs.rs:2:13
|
||||
|
|
||||
2 | use super::{ConstValue, MirInstruction, ValueId};
|
||||
| ^^^^^^^^^^
|
||||
|
||||
warning: unused import: `ConstValue`
|
||||
--> src/mir/builder/fields.rs:2:13
|
||||
|
|
||||
2 | use super::{ConstValue, EffectMask, MirInstruction, ValueId};
|
||||
| ^^^^^^^^^^
|
||||
|
||||
warning: unused import: `ConstValue`
|
||||
--> src/mir/builder/if_form.rs:1:13
|
||||
|
|
||||
1 | use super::{ConstValue, MirBuilder, MirInstruction, ValueId};
|
||||
| ^^^^^^^^^^
|
||||
|
||||
warning: unused import: `ConstValue`
|
||||
--> src/mir/builder/control_flow.rs:2:13
|
||||
|
|
||||
2 | use super::{ConstValue, Effect, EffectMask, MirInstruction, ValueId};
|
||||
| ^^^^^^^^^^
|
||||
|
||||
warning: unused import: `ConstValue`
|
||||
--> src/mir/builder/lifecycle.rs:1:116
|
||||
|
|
||||
1 | use super::{EffectMask, FunctionSignature, MirFunction, MirInstruction, MirModule, MirType, ValueId, BasicBlockId, ConstValue};
|
||||
| ^^^^^^^^^^
|
||||
|
||||
warning: unused import: `ConstValue`
|
||||
--> src/mir/builder/stmts.rs:1:13
|
||||
|
|
||||
1 | use super::{ConstValue, Effect, EffectMask, MirInstruction, ValueId};
|
||||
| ^^^^^^^^^^
|
||||
|
||||
warning: unused import: `MirInstruction`
|
||||
--> src/mir/builder/origin/phi.rs:1:32
|
||||
|
|
||||
1 | use super::super::{MirBuilder, MirInstruction, MirType, ValueId, BasicBlockId};
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused import: `ConstValue`
|
||||
--> src/mir/builder/rewrite/known.rs:1:20
|
||||
|
|
||||
1 | use super::super::{ConstValue, Effect, EffectMask, MirBuilder, MirInstruction, ValueId};
|
||||
| ^^^^^^^^^^
|
||||
|
||||
warning: unused import: `ConstValue`
|
||||
--> src/mir/builder/rewrite/special.rs:1:20
|
||||
|
|
||||
1 | use super::super::{ConstValue, Effect, EffectMask, MirBuilder, MirInstruction};
|
||||
| ^^^^^^^^^^
|
||||
|
||||
warning: unused import: `std::collections::HashMap`
|
||||
--> src/mir/builder/ssa/local.rs:3:5
|
||||
|
|
||||
3 | use std::collections::HashMap;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused import: `Effect`
|
||||
--> src/mir/instruction.rs:7:13
|
||||
|
|
||||
7 | use super::{Effect, EffectMask, ValueId};
|
||||
| ^^^^^^
|
||||
|
||||
warning: unused import: `std::fmt`
|
||||
--> src/mir/instruction.rs:13:5
|
||||
|
|
||||
13 | use std::fmt;
|
||||
| ^^^^^^^^
|
||||
|
||||
warning: unused import: `crate::mir::instruction_kinds as inst_meta`
|
||||
--> src/mir/instruction.rs:16:5
|
||||
|
|
||||
16 | use crate::mir::instruction_kinds as inst_meta;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unexpected `cfg` condition value: `cranelift-jit`
|
||||
--> src/backend/mod.rs:29:7
|
||||
|
|
||||
29 | #[cfg(feature = "cranelift-jit")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `all-examples`, `aot-plan-import`, `builtin-core`, `cli`, `default`, `dynamic-file`, `e2e`, `gui`, `gui-examples`, `interpreter-legacy`, `jit-direct-only`, `llvm`, `llvm-harness`, `llvm-inkwell-legacy`, `mir_refbarrier_unify_poc`, `mir_typeop_poc`, `phi-legacy`, `plugins`, `plugins-only`, `vm-legacy`, and `wasm-backend`
|
||||
= help: consider adding `cranelift-jit` as a feature in `Cargo.toml`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition value: `cranelift-jit`
|
||||
--> src/backend/mod.rs:48:7
|
||||
|
|
||||
48 | #[cfg(feature = "cranelift-jit")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `all-examples`, `aot-plan-import`, `builtin-core`, `cli`, `default`, `dynamic-file`, `e2e`, `gui`, `gui-examples`, `interpreter-legacy`, `jit-direct-only`, `llvm`, `llvm-harness`, `llvm-inkwell-legacy`, `mir_refbarrier_unify_poc`, `mir_typeop_poc`, `phi-legacy`, `plugins`, `plugins-only`, `vm-legacy`, and `wasm-backend`
|
||||
= help: consider adding `cranelift-jit` as a feature in `Cargo.toml`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
|
||||
|
||||
warning: unused import: `Map as JsonMap`
|
||||
--> src/backend/mir_interpreter/handlers/externals.rs:2:38
|
||||
|
|
||||
2 | use serde_json::{Value as JsonValue, Map as JsonMap};
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused import: `super::library`
|
||||
--> src/runtime/plugin_loader_v2/enabled/loader/config.rs:1:5
|
||||
|
|
||||
1 | use super::library;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused import: `super::specs`
|
||||
--> src/runtime/plugin_loader_v2/enabled/loader/singletons.rs:1:5
|
||||
|
|
||||
1 | use super::specs;
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
warning: unused import: `PluginBoxV2`
|
||||
--> src/runtime/plugin_loader_v2/enabled/loader/mod.rs:9:55
|
||||
|
|
||||
9 | use super::types::{LoadedPluginV2, PluginBoxMetadata, PluginBoxV2, PluginHandleInner};
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
warning: unused import: `BidError`
|
||||
--> src/runtime/plugin_loader_v2/enabled/loader/mod.rs:10:18
|
||||
|
|
||||
10 | use crate::bid::{BidError, BidResult};
|
||||
| ^^^^^^^^
|
||||
|
||||
warning: unused import: `std::collections::HashMap`
|
||||
--> src/runtime/plugin_loader_v2/enabled/method_resolver.rs:8:5
|
||||
|
|
||||
8 | use std::collections::HashMap;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused import: `FactoryPolicy`
|
||||
--> src/runtime/unified_registry.rs:11:46
|
||||
|
|
||||
11 | use crate::box_factory::{UnifiedBoxRegistry, FactoryPolicy};
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
warning: unexpected `cfg` condition value: `cranelift-jit`
|
||||
--> src/runner/dispatch.rs:180:15
|
||||
|
|
||||
180 | #[cfg(feature = "cranelift-jit")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `all-examples`, `aot-plan-import`, `builtin-core`, `cli`, `default`, `dynamic-file`, `e2e`, `gui`, `gui-examples`, `interpreter-legacy`, `jit-direct-only`, `llvm`, `llvm-harness`, `llvm-inkwell-legacy`, `mir_refbarrier_unify_poc`, `mir_typeop_poc`, `phi-legacy`, `plugins`, `plugins-only`, `vm-legacy`, and `wasm-backend`
|
||||
= help: consider adding `cranelift-jit` as a feature in `Cargo.toml`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
|
||||
|
||||
warning: unexpected `cfg` condition value: `cranelift-jit`
|
||||
--> src/runner/dispatch.rs:185:19
|
||||
|
|
||||
185 | #[cfg(not(feature = "cranelift-jit"))]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `all-examples`, `aot-plan-import`, `builtin-core`, `cli`, `default`, `dynamic-file`, `e2e`, `gui`, `gui-examples`, `interpreter-legacy`, `jit-direct-only`, `llvm`, `llvm-harness`, `llvm-inkwell-legacy`, `mir_refbarrier_unify_poc`, `mir_typeop_poc`, `phi-legacy`, `plugins`, `plugins-only`, `vm-legacy`, and `wasm-backend`
|
||||
= help: consider adding `cranelift-jit` as a feature in `Cargo.toml`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
|
||||
|
||||
warning: unexpected `cfg` condition value: `cranelift-jit`
|
||||
--> src/runner/dispatch.rs:203:15
|
||||
|
|
||||
203 | #[cfg(feature = "cranelift-jit")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `all-examples`, `aot-plan-import`, `builtin-core`, `cli`, `default`, `dynamic-file`, `e2e`, `gui`, `gui-examples`, `interpreter-legacy`, `jit-direct-only`, `llvm`, `llvm-harness`, `llvm-inkwell-legacy`, `mir_refbarrier_unify_poc`, `mir_typeop_poc`, `phi-legacy`, `plugins`, `plugins-only`, `vm-legacy`, and `wasm-backend`
|
||||
= help: consider adding `cranelift-jit` as a feature in `Cargo.toml`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
|
||||
|
||||
warning: unused import: `BinaryOp`
|
||||
--> src/runner/json_v0_bridge/lowering.rs:4:35
|
||||
|
|
||||
4 | MirPrinter, MirType, ValueId, BinaryOp,
|
||||
| ^^^^^^^^
|
||||
|
||||
warning: unused import: `MirInstruction`
|
||||
--> src/runner/json_v0_bridge/lowering/if_else.rs:2:45
|
||||
|
|
||||
2 | use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused import: `BinaryOp`
|
||||
--> src/runner/json_v0_bridge/lowering/expr.rs:6:19
|
||||
|
|
||||
6 | BasicBlockId, BinaryOp, ConstValue, EffectMask, MirFunction, MirInstruction, ValueId,
|
||||
| ^^^^^^^^
|
||||
|
||||
warning: unused import: `MirInstruction`
|
||||
--> src/runner/json_v0_bridge/lowering/ternary.rs:8:45
|
||||
|
|
||||
8 | use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused import: `MirInstruction`
|
||||
--> src/runner/json_v0_bridge/lowering/throw_ctx.rs:1:45
|
||||
|
|
||||
1 | use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
warning: unexpected `cfg` condition value: `cranelift-jit`
|
||||
--> src/runner/modes/mod.rs:11:7
|
||||
|
|
||||
11 | #[cfg(feature = "cranelift-jit")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `all-examples`, `aot-plan-import`, `builtin-core`, `cli`, `default`, `dynamic-file`, `e2e`, `gui`, `gui-examples`, `interpreter-legacy`, `jit-direct-only`, `llvm`, `llvm-harness`, `llvm-inkwell-legacy`, `mir_refbarrier_unify_poc`, `mir_typeop_poc`, `phi-legacy`, `plugins`, `plugins-only`, `vm-legacy`, and `wasm-backend`
|
||||
= help: consider adding `cranelift-jit` as a feature in `Cargo.toml`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
|
||||
|
||||
warning: unused import: `NyashBox`
|
||||
--> src/runner/modes/vm_fallback.rs:308:40
|
||||
|
|
||||
308 | use crate::box_trait::{NyashBox, IntegerBox, BoolBox};
|
||||
| ^^^^^^^^
|
||||
|
||||
warning: unused import: `crate::runner::child_env`
|
||||
--> src/runner/pipe_io.rs:13:5
|
||||
|
|
||||
13 | use crate::runner::child_env;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused import: `std::io::Write`
|
||||
--> src/host_providers/mir_builder.rs:3:5
|
||||
|
|
||||
3 | use std::io::Write;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused import: `Path`
|
||||
--> src/host_providers/llvm_codegen.rs:3:17
|
||||
|
|
||||
3 | use std::path::{Path, PathBuf};
|
||||
| ^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> src/mir/builder/ops.rs:300:65
|
||||
|
|
||||
300 | crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, rhs_bool, inputs);
|
||||
| ----------------------------------------------- ^^^^ types differ in mutability
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected mutable reference `&mut function::MirFunction`
|
||||
found reference `&function::MirFunction`
|
||||
note: function defined here
|
||||
--> src/mir/ssot/cf_common.rs:47:8
|
||||
|
|
||||
47 | pub fn insert_phi_at_head(
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
48 | f: &mut MirFunction,
|
||||
| -------------------
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> src/mir/builder/ops.rs:363:65
|
||||
|
|
||||
363 | crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, rhs_bool, inputs);
|
||||
| ----------------------------------------------- ^^^^ types differ in mutability
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected mutable reference `&mut function::MirFunction`
|
||||
found reference `&function::MirFunction`
|
||||
note: function defined here
|
||||
--> src/mir/ssot/cf_common.rs:47:8
|
||||
|
|
||||
47 | pub fn insert_phi_at_head(
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
48 | f: &mut MirFunction,
|
||||
| -------------------
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> src/mir/builder/ops.rs:393:65
|
||||
|
|
||||
393 | crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, dst, inputs);
|
||||
| ----------------------------------------------- ^^^^ types differ in mutability
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected mutable reference `&mut function::MirFunction`
|
||||
found reference `&function::MirFunction`
|
||||
note: function defined here
|
||||
--> src/mir/ssot/cf_common.rs:47:8
|
||||
|
|
||||
47 | pub fn insert_phi_at_head(
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
48 | f: &mut MirFunction,
|
||||
| -------------------
|
||||
|
||||
warning: unused import: `crate::box_trait::NyashBox`
|
||||
--> src/backend/mir_interpreter/handlers/boxes_object_fields.rs:2:5
|
||||
|
|
||||
2 | use crate::box_trait::NyashBox;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unused import: `crate::box_trait::NyashBox`
|
||||
--> src/backend/mir_interpreter/handlers/boxes_string.rs:2:5
|
||||
|
|
||||
2 | use crate::box_trait::NyashBox;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: variable does not need to be mutable
|
||||
--> src/parser/statements/mod.rs:134:13
|
||||
|
|
||||
134 | let mut looks_like_method_head = |this: &Self| -> bool {
|
||||
| ----^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| help: remove this `mut`
|
||||
|
|
||||
= note: `#[warn(unused_mut)]` on by default
|
||||
|
||||
warning: unused variable: `program_ast`
|
||||
--> src/mir/builder/decls.rs:43:25
|
||||
|
|
||||
43 | let program_ast = ASTNode::Program {
|
||||
| ^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_program_ast`
|
||||
|
|
||||
= note: `#[warn(unused_variables)]` on by default
|
||||
|
||||
warning: unused variable: `type_id`
|
||||
--> src/mir/builder/decls.rs:118:13
|
||||
|
|
||||
118 | let type_id = crate::mir::builder::emission::constant::emit_string(self, format!("__box_type_{}", name));
|
||||
| ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_type_id`
|
||||
|
||||
warning: unused variable: `else_block`
|
||||
--> src/mir/builder/phi.rs:15:9
|
||||
|
|
||||
15 | else_block: super::BasicBlockId,
|
||||
| ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_else_block`
|
||||
|
||||
warning: unused variable: `then_block`
|
||||
--> src/mir/builder/phi.rs:112:9
|
||||
|
|
||||
112 | then_block: BasicBlockId,
|
||||
| ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_then_block`
|
||||
|
||||
warning: unused variable: `else_block`
|
||||
--> src/mir/builder/phi.rs:113:9
|
||||
|
|
||||
113 | else_block: BasicBlockId,
|
||||
| ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_else_block`
|
||||
|
||||
warning: unused variable: `func`
|
||||
--> src/mir/builder/lifecycle.rs:241:60
|
||||
|
|
||||
241 | ... MirInstruction::Call { func, .. } => {
|
||||
| ^^^^-
|
||||
| |
|
||||
| help: try removing the field
|
||||
|
||||
warning: variable does not need to be mutable
|
||||
--> src/mir/builder/lifecycle.rs:271:17
|
||||
|
|
||||
271 | let mut sig = FunctionSignature {
|
||||
| ----^^^
|
||||
| |
|
||||
| help: remove this `mut`
|
||||
|
||||
warning: unused variable: `dbg_fn_name`
|
||||
--> src/mir/builder.rs:425:13
|
||||
|
|
||||
425 | let dbg_fn_name = self
|
||||
| ^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_dbg_fn_name`
|
||||
|
||||
warning: unused variable: `dbg_region_id`
|
||||
--> src/mir/builder.rs:429:13
|
||||
|
|
||||
429 | let dbg_region_id = self.debug_current_region_id();
|
||||
| ^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_dbg_region_id`
|
||||
|
||||
warning: unused variable: `else_block`
|
||||
--> src/mir/phi_core/if_phi.rs:148:5
|
||||
|
|
||||
148 | else_block: crate::mir::BasicBlockId,
|
||||
| ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_else_block`
|
||||
|
||||
warning: variable does not need to be mutable
|
||||
--> src/mir/phi_core/loop_phi.rs:185:13
|
||||
|
|
||||
185 | let mut inc = IncompletePhi {
|
||||
| ----^^^
|
||||
| |
|
||||
| help: remove this `mut`
|
||||
|
||||
warning: variable does not need to be mutable
|
||||
--> src/backend/mir_interpreter/handlers/boxes_instance.rs:105:17
|
||||
|
|
||||
105 | let mut cands: Vec<String> = this
|
||||
| ----^^^^^
|
||||
| |
|
||||
| help: remove this `mut`
|
||||
|
||||
warning: variable does not need to be mutable
|
||||
--> src/backend/mir_interpreter/handlers/calls.rs:257:25
|
||||
|
|
||||
257 | let mut esc = |s: &str| {
|
||||
| ----^^^
|
||||
| |
|
||||
| help: remove this `mut`
|
||||
|
||||
warning: value assigned to `first_arg_str` is never read
|
||||
--> src/backend/mir_interpreter/handlers/calls.rs:387:25
|
||||
|
|
||||
387 | let mut first_arg_str: Option<String> = None;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= help: maybe it is overwritten before being read?
|
||||
= note: `#[warn(unused_assignments)]` on by default
|
||||
|
||||
warning: unreachable pattern
|
||||
--> src/backend/mir_interpreter/handlers/externals.rs:149:13
|
||||
|
|
||||
28 | ("env", "get") => {
|
||||
| -------------- matches all the relevant values
|
||||
...
|
||||
149 | ("env", "get") => {
|
||||
| ^^^^^^^^^^^^^^ no value can reach this
|
||||
|
|
||||
= note: `#[warn(unreachable_patterns)]` on by default
|
||||
|
||||
warning: unused variable: `source`
|
||||
--> src/benchmarks.rs:48:23
|
||||
|
|
||||
48 | if let Ok(source) = fs::read_to_string(file_path) {
|
||||
| ^^^^^^ help: if this is intentional, prefix it with an underscore: `_source`
|
||||
|
||||
warning: variable does not need to be mutable
|
||||
--> src/benchmarks.rs:36:13
|
||||
|
|
||||
36 | let mut results = Vec::new();
|
||||
| ----^^^^^^^
|
||||
| |
|
||||
| help: remove this `mut`
|
||||
|
||||
warning: unused variable: `lib`
|
||||
--> src/runtime/plugin_loader_v2/enabled/method_resolver.rs:40:19
|
||||
|
|
||||
40 | for ((lib, bt), spec) in map.iter() {
|
||||
| ^^^ help: if this is intentional, prefix it with an underscore: `_lib`
|
||||
|
||||
warning: unnecessary `unsafe` block
|
||||
--> src/runtime/plugin_loader_v2/enabled/method_resolver.rs:50:39
|
||||
|
|
||||
50 | ... let mid = unsafe { res_fn(cstr.as_ptr()) };
|
||||
| ^^^^^^ unnecessary `unsafe` block
|
||||
|
|
||||
= note: `#[warn(unused_unsafe)]` on by default
|
||||
|
||||
warning: unused variable: `merge_bb`
|
||||
--> src/runner/json_v0_bridge/lowering/loop_.rs:86:47
|
||||
|
|
||||
86 | fn debug_verify_phi_inputs(&mut self, merge_bb: BasicBlockId, inputs: &[(BasicBlockId, ValueId)]) {
|
||||
| ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_merge_bb`
|
||||
|
||||
warning: unused variable: `inputs`
|
||||
--> src/runner/json_v0_bridge/lowering/loop_.rs:86:71
|
||||
|
|
||||
86 | fn debug_verify_phi_inputs(&mut self, merge_bb: BasicBlockId, inputs: &[(BasicBlockId, ValueId)]) {
|
||||
| ^^^^^^ help: if this is intentional, prefix it with an underscore: `_inputs`
|
||||
|
||||
warning: variable does not need to be mutable
|
||||
--> src/runner/json_v0_bridge/lowering/ternary.rs:38:9
|
||||
|
|
||||
38 | let mut inputs = vec![(tend, tval), (eend, eval)];
|
||||
| ----^^^^^^
|
||||
| |
|
||||
| help: remove this `mut`
|
||||
|
||||
warning: unreachable pattern
|
||||
--> src/runner/json_v1_bridge.rs:512:29
|
||||
|
|
||||
368 | ... "Constructor" => {
|
||||
| ------------- matches all the relevant values
|
||||
...
|
||||
512 | ... "Constructor" => {
|
||||
| ^^^^^^^^^^^^^ no value can reach this
|
||||
|
||||
warning: unused variable: `using_resolver`
|
||||
--> src/runner/modes/common_util/resolve/prelude_manager.rs:126:17
|
||||
|
|
||||
126 | let using_resolver = UsingResolutionBox::new(&self.runner, path)?;
|
||||
| ^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_using_resolver`
|
||||
|
||||
warning: unused variable: `filename`
|
||||
--> src/runner/modes/common_util/resolve/prelude_manager.rs:114:9
|
||||
|
|
||||
114 | filename: &str,
|
||||
| ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_filename`
|
||||
|
||||
warning: unused variable: `filename`
|
||||
--> src/runner/modes/common_util/resolve/selfhost_pipeline.rs:132:9
|
||||
|
|
||||
132 | filename: &str,
|
||||
| ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_filename`
|
||||
|
||||
warning: unused variable: `code`
|
||||
--> src/runner/modes/common_util/resolve/selfhost_pipeline.rs:182:9
|
||||
|
|
||||
182 | code: &str,
|
||||
| ^^^^ help: if this is intentional, prefix it with an underscore: `_code`
|
||||
|
||||
warning: unused variable: `filename`
|
||||
--> src/runner/modes/common_util/resolve/selfhost_pipeline.rs:183:9
|
||||
|
|
||||
183 | filename: &str,
|
||||
| ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_filename`
|
||||
|
||||
warning: variable does not need to be mutable
|
||||
--> src/runner/pipe_io.rs:23:13
|
||||
|
|
||||
23 | let mut json = if let Some(path) = &groups.parser.json_file {
|
||||
| ----^^^^
|
||||
| |
|
||||
| help: remove this `mut`
|
||||
|
||||
warning: unused variable: `code`
|
||||
--> src/runner/plugins.rs:54:40
|
||||
|
|
||||
54 | ... Ok(code) => {
|
||||
| ^^^^ help: if this is intentional, prefix it with an underscore: `_code`
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
warning: `nyash-rust` (lib) generated 84 warnings
|
||||
error: could not compile `nyash-rust` (lib) due to 3 previous errors; 84 warnings emitted
|
||||
@ -74,6 +74,15 @@ static box MirBuilderBox {
|
||||
using "hako.mir.builder.internal.lower_if_compare_varint" as LowerIfCompareVarIntBox
|
||||
using "hako.mir.builder.internal.lower_if_compare_varvar" as LowerIfCompareVarVarBox
|
||||
using "hako.mir.builder.internal.lower_loop_sum_bc" as LowerLoopSumBcBox
|
||||
using "hako.mir.builder.internal.lower_newbox_constructor" as LowerNewboxConstructorBox
|
||||
using "hako.mir.builder.internal.lower_method_array_size" as LowerMethodArraySizeBox
|
||||
using "hako.mir.builder.internal.lower_method_array_push" as LowerMethodArrayPushBox
|
||||
using "hako.mir.builder.internal.lower_method_array_get_set" as LowerMethodArrayGetSetBox
|
||||
using "hako.mir.builder.internal.lower_method_map_size" as LowerMethodMapSizeBox
|
||||
using "hako.mir.builder.internal.lower_method_map_get_set" as LowerMethodMapGetSetBox
|
||||
using "hako.mir.builder.internal.lower_load_store_local" as LowerLoadStoreLocalBox
|
||||
using "hako.mir.builder.internal.lower_typeop_check" as LowerTypeOpCheckBox
|
||||
using "hako.mir.builder.internal.lower_typeop_cast" as LowerTypeOpCastBox
|
||||
using "hako.mir.builder.internal.lower_loop_count_param" as LowerLoopCountParamBox
|
||||
using "hako.mir.builder.internal.lower_loop_simple" as LowerLoopSimpleBox
|
||||
using "hako.mir.builder.internal.lower_return_var_local" as LowerReturnVarLocalBox
|
||||
@ -86,7 +95,17 @@ static box MirBuilderBox {
|
||||
using "hako.mir.builder.internal.lower_return_binop_varvar" as LowerReturnBinOpVarVarBox
|
||||
using "hako.mir.builder.internal.lower_return_binop" as LowerReturnBinOpBox
|
||||
using "hako.mir.builder.internal.lower_return_int" as LowerReturnIntBox
|
||||
// Prefer loop lowers first to catch loop-specific patterns (sum_bc/continue/break normalization)
|
||||
// Prefer New(Constructor) minimal first to avoid unresolved nested lowers in inline runs
|
||||
{ local out_newc = LowerNewboxConstructorBox.try_lower(s); if out_newc != null { return out_newc } }
|
||||
{ local out_arr_size = LowerMethodArraySizeBox.try_lower(s); if out_arr_size != null { return out_arr_size } }
|
||||
{ local out_arr_push = LowerMethodArrayPushBox.try_lower(s); if out_arr_push != null { return out_arr_push } }
|
||||
{ local out_arr_gs = LowerMethodArrayGetSetBox.try_lower(s); if out_arr_gs != null { return out_arr_gs } }
|
||||
{ local out_map_size = LowerMethodMapSizeBox.try_lower(s); if out_map_size != null { return out_map_size } }
|
||||
{ local out_map_gs = LowerMethodMapGetSetBox.try_lower(s); if out_map_gs != null { return out_map_gs } }
|
||||
{ local out_ls = LowerLoadStoreLocalBox.try_lower(s); if out_ls != null { return out_ls } }
|
||||
{ local out_toc = LowerTypeOpCheckBox.try_lower(s); if out_toc != null { return out_toc } }
|
||||
{ local out_tca = LowerTypeOpCastBox.try_lower(s); if out_tca != null { return out_tca } }
|
||||
// Loop lowers (sum_bc/continue/break normalization)
|
||||
{ local out_loop2 = LowerLoopSumBcBox.try_lower(s); if out_loop2 != null { return out_loop2 } }
|
||||
{ local out_if2b = LowerIfNestedBox.try_lower(s); if out_if2b != null { return out_if2b } }
|
||||
{ local out_if2 = LowerIfThenElseFollowingReturnBox.try_lower(s); if out_if2 != null { return out_if2 } }
|
||||
@ -228,6 +247,11 @@ static box MirBuilderBox {
|
||||
}
|
||||
}
|
||||
}
|
||||
// NewBox(Constructor) minimal
|
||||
{
|
||||
local out_new = LowerNewboxConstructorBox.try_lower(s)
|
||||
if out_new != null { return out_new }
|
||||
}
|
||||
// Fallback cases below: Return(Binary) and Return(Int)
|
||||
local k_ret = s.indexOf("\"type\":\"Return\"")
|
||||
if k_ret >= 0 {
|
||||
|
||||
@ -10,8 +10,12 @@ static box LoopScanBox {
|
||||
local varname = null
|
||||
local kl = ("" + s).indexOf("\"lhs\":{", k_cmp)
|
||||
local kr = ("" + s).indexOf("\"rhs\":{", k_cmp)
|
||||
if kl >= 0 && ("" + s).indexOf("\"type\":\"Var\"", kl) >= 0 { varname = Scan.read_quoted_after_key(s, kl, "name") }
|
||||
if varname == null && kr >= 0 && ("" + s).indexOf("\"type\":\"Var\"", kr) >= 0 { varname = Scan.read_quoted_after_key(s, kr, "name") }
|
||||
if kl >= 0 && ("" + s).indexOf("\"type\":\"Var\"", kl) >= 0 {
|
||||
local kn = ("" + s).indexOf("\"name\":\"", kl); if kn >= 0 { varname = JsonFragBox.read_string_after(s, kn) }
|
||||
}
|
||||
if varname == null && kr >= 0 && ("" + s).indexOf("\"type\":\"Var\"", kr) >= 0 {
|
||||
local kn2 = ("" + s).indexOf("\"name\":\"", kr); if kn2 >= 0 { varname = JsonFragBox.read_string_after(s, kn2) }
|
||||
}
|
||||
return varname
|
||||
}
|
||||
|
||||
@ -26,7 +30,8 @@ static box LoopScanBox {
|
||||
if kif < 0 { return null }
|
||||
local kcmp = ("" + s).lastIndexOf("\"type\":\"Compare\"", ks)
|
||||
if kcmp < 0 || kcmp < kif { return null }
|
||||
local op = Scan.read_quoted_after_key(s, kcmp, "op"); if op == null || op != "!=" { return null }
|
||||
local kop = ("" + s).indexOf("\"op\":", kcmp); if kop < 0 { return null }
|
||||
local op = JsonFragBox.read_string_after(s, kop + 5); if op == null || op != "!=" { return null }
|
||||
// else 範囲の配列区間を特定
|
||||
local kth = JsonFragBox.index_of_from(s, "\"then\":", kif); if kth < 0 { return null }
|
||||
local lb_then = JsonFragBox.index_of_from(s, "[", kth); if lb_then < 0 { return null }
|
||||
@ -43,7 +48,8 @@ static box LoopScanBox {
|
||||
if has_lhs {
|
||||
local kr = ("" + s).indexOf("\"rhs\":{", kcmp); if kr < 0 { return null }
|
||||
local kt = ("" + s).indexOf("\"type\":\"Int\"", kr); if kt < 0 { return null }
|
||||
local sentinel_val = Scan.read_value_int_after(s, kt)
|
||||
local kv = ("" + s).indexOf("\"value\":", kt); if kv < 0 { return null }
|
||||
local sentinel_val = JsonFragBox.read_int_after(s, kv + 8)
|
||||
// Safety check: must be valid numeric string
|
||||
if sentinel_val == null { return null }
|
||||
local sval_str = "" + sentinel_val
|
||||
@ -63,7 +69,8 @@ static box LoopScanBox {
|
||||
// rhs が変数
|
||||
local kl = ("" + s).indexOf("\"lhs\":{", kcmp); if kl < 0 { return null }
|
||||
local kt2 = ("" + s).indexOf("\"type\":\"Int\"", kl); if kt2 < 0 { return null }
|
||||
local sentinel_val2 = Scan.read_value_int_after(s, kt2)
|
||||
local kv2 = ("" + s).indexOf("\"value\":", kt2); if kv2 < 0 { return null }
|
||||
local sentinel_val2 = JsonFragBox.read_int_after(s, kv2 + 8)
|
||||
// Safety check for rhs case
|
||||
if sentinel_val2 == null { return null }
|
||||
local sval_str2 = "" + sentinel_val2
|
||||
@ -80,4 +87,3 @@ static box LoopScanBox {
|
||||
return sentinel_val2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
// lower_if_compare_fold_binints_box.hako — If(Compare with Binary(Int,Int) on either side) → const-fold and lower
|
||||
|
||||
using "hako.mir.builder.internal.prog_scan" as ProgScanBox
|
||||
using ProgScanBox as Scan
|
||||
using selfhost.shared.json.utils.json_frag as JsonFragBox
|
||||
using "hako.mir.builder.internal.pattern_util" as PatternUtilBox
|
||||
using selfhost.shared.mir.schema as MirSchemaBox
|
||||
|
||||
static box LowerIfCompareFoldBinIntsBox {
|
||||
_map_cmp(op) { if op == "<" { return "Lt" } if op == ">" { return "Gt" } if op == "<=" { return "Le" } if op == ">=" { return "Ge" } if op == "==" { return "Eq" } if op == "!=" { return "Ne" } return null }
|
||||
_fold_bin_ints(s, k_bin_start) {
|
||||
// expects: {"type":"Binary","op":"+|-|*|/","lhs":{"type":"Int","value":L},"rhs":{"type":"Int","value":R}}
|
||||
local kop = s.indexOf("\"op\":\"", k_bin_start); if kop < 0 { return null }
|
||||
@ -56,7 +53,9 @@ static box LowerIfCompareFoldBinIntsBox {
|
||||
local s = "" + program_json
|
||||
local k_if = s.indexOf("\"type\":\"If\""); if k_if < 0 { return null }
|
||||
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_if); if k_cmp < 0 { return null }
|
||||
local op = me._map_cmp(Scan.read_quoted_after_key(s, k_cmp, "op")); if op == null { return null }
|
||||
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
|
||||
local sym = JsonFragBox.read_string_after(s, k_op + 5); if sym == null { return null }
|
||||
local op = PatternUtilBox.map_cmp(sym); if op == null { return null }
|
||||
// locate lhs/rhs node starts (Var/Int/Binary)
|
||||
local klhs = s.indexOf("\"lhs\":{", k_cmp); if klhs < 0 { return null }
|
||||
local krhs = s.indexOf("\"rhs\":{", k_cmp); if krhs < 0 { return null }
|
||||
|
||||
@ -14,18 +14,9 @@
|
||||
|
||||
using selfhost.shared.json.utils.json_frag as JsonFragBox
|
||||
using selfhost.shared.mir.schema as MirSchemaBox
|
||||
using "hako.mir.builder.internal.pattern_util" as PatternUtilBox
|
||||
|
||||
static box LowerIfNestedBox {
|
||||
_map_cmp(op) {
|
||||
if op == "<" { return "Lt" }
|
||||
if op == ">" { return "Gt" }
|
||||
if op == "<=" { return "Le" }
|
||||
if op == ">=" { return "Ge" }
|
||||
if op == "==" { return "Eq" }
|
||||
if op == "!=" { return "Ne" }
|
||||
return null
|
||||
}
|
||||
|
||||
try_lower(program_json) {
|
||||
local s = "" + program_json
|
||||
local k_if1 = s.indexOf("\"type\":\"If\"")
|
||||
@ -34,7 +25,7 @@ static box LowerIfNestedBox {
|
||||
if k_cmp1 < 0 { return null }
|
||||
local kop1 = s.indexOf("\"op\":", k_cmp1); if kop1 < 0 { return null }
|
||||
local op1s = JsonFragBox.read_string_after(s, kop1 + 5); if op1s == null { return null }
|
||||
local op1 = me._map_cmp(op1s); if op1 == null { return null }
|
||||
local op1 = PatternUtilBox.map_cmp(op1s); if op1 == null { return null }
|
||||
local klhs1 = s.indexOf("\"lhs\":{", k_cmp1); if klhs1 < 0 { return null }
|
||||
local ti11 = s.indexOf("\"type\":\"Int\"", klhs1); if ti11 < 0 { return null }
|
||||
local kv11 = s.indexOf("\"value\":", ti11); if kv11 < 0 { return null }
|
||||
@ -55,7 +46,7 @@ static box LowerIfNestedBox {
|
||||
local k_cmp2 = s.indexOf("\"type\":\"Compare\"", k_if2); if k_cmp2 < 0 { return null }
|
||||
local kop2 = s.indexOf("\"op\":", k_cmp2); if kop2 < 0 { return null }
|
||||
local op2s = JsonFragBox.read_string_after(s, kop2 + 5); if op2s == null { return null }
|
||||
local op2 = me._map_cmp(op2s); if op2 == null { return null }
|
||||
local op2 = PatternUtilBox.map_cmp(op2s); if op2 == null { return null }
|
||||
local klhs2 = s.indexOf("\"lhs\":{", k_cmp2); if klhs2 < 0 { return null }
|
||||
local ti21 = s.indexOf("\"type\":\"Int\"", klhs2); if ti21 < 0 { return null }
|
||||
local kv21 = s.indexOf("\"value\":", ti21); if kv21 < 0 { return null }
|
||||
|
||||
@ -2,10 +2,9 @@
|
||||
// Pattern: Program body = [ If(cond=Compare(Int,Int), then=[Return(Int)] (no else)), Return(Int) ]
|
||||
// Lowers to: bb0: const lhs/rhs, compare, branch; bb1: const then, ret; bb2: const else, ret
|
||||
|
||||
using "hako.mir.builder.internal.prog_scan" as ProgScanBox
|
||||
using ProgScanBox as Scan
|
||||
using selfhost.shared.mir.schema as MirSchemaBox
|
||||
using selfhost.shared.json.utils.json_frag as JsonFragBox
|
||||
using "hako.mir.builder.internal.pattern_util" as PatternUtilBox
|
||||
|
||||
static box LowerIfThenElseFollowingReturnBox {
|
||||
try_lower(program_json) {
|
||||
@ -15,9 +14,9 @@ static box LowerIfThenElseFollowingReturnBox {
|
||||
if k_if < 0 { return null }
|
||||
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_if)
|
||||
if k_cmp < 0 { return null }
|
||||
local op = Scan.read_quoted_after_key(s, k_cmp, "op")
|
||||
if op == null { return null }
|
||||
if !(op == "<" || op == ">" || op == "<=" || op == ">=" || op == "==" || op == "!=") { return null }
|
||||
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
|
||||
local sym = JsonFragBox.read_string_after(s, k_op + 5); if sym == null { return null }
|
||||
local op = PatternUtilBox.map_cmp(sym); if op == null { return null }
|
||||
// LHS/RHS ints
|
||||
local klhs = s.indexOf("\"lhs\":{", k_cmp); if klhs < 0 { return null }
|
||||
local ti1 = s.indexOf("\"type\":\"Int\"", klhs); if ti1 < 0 { return null }
|
||||
@ -39,7 +38,7 @@ static box LowerIfThenElseFollowingReturnBox {
|
||||
local b0 = new ArrayBox()
|
||||
b0.push(MirSchemaBox.inst_const(1, lhs_val))
|
||||
b0.push(MirSchemaBox.inst_const(2, rhs_val))
|
||||
b0.push(MirSchemaBox.inst_compare(op == "<" ? "Lt" : (op == ">" ? "Gt" : (op == "<=" ? "Le" : (op == ">=" ? "Ge" : (op == "==" ? "Eq" : "Ne")))), 1, 2, 3))
|
||||
b0.push(MirSchemaBox.inst_compare(op, 1, 2, 3))
|
||||
b0.push(MirSchemaBox.inst_branch(3, 1, 2))
|
||||
|
||||
local b1 = new ArrayBox(); b1.push(MirSchemaBox.inst_const(4, then_val)); b1.push(MirSchemaBox.inst_ret(4))
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
// lower_load_store_local_box.hako — Minimal structural MIR for load/store (local ptr)
|
||||
|
||||
static box LowerLoadStoreLocalBox {
|
||||
try_lower(program_json) {
|
||||
if program_json == null { return null }
|
||||
local s = "" + program_json
|
||||
// Accept any Program v0; emit a fixed load/store snippet
|
||||
local json = "{\"kind\":\"MIR\",\"schema_version\":\"1.0\",\"functions\":[{\"name\":\"main\",\"blocks\":[{\"id\":0,\"instructions\":[" +
|
||||
// const 5 -> v1, store v1 to ptr 10, load -> v2, ret 0
|
||||
"{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":5}}," +
|
||||
"{\"op\":\"store\",\"value\":1,\"ptr\":10}," +
|
||||
"{\"op\":\"load\",\"dst\":2,\"ptr\":10}," +
|
||||
"{\"op\":\"const\",\"dst\":3,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":3}]}]}]}"
|
||||
return json
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,11 +29,12 @@ static box LowerLoopCountParamBox {
|
||||
local k_init_int = s.indexOf("\"type\":\"Int\"", k_local_i)
|
||||
local k_loop_next = s.indexOf("\"type\":\"Loop\"", k_local_i)
|
||||
if k_init_int >= 0 && (k_loop_next < 0 || k_init_int < k_loop_next) {
|
||||
init = Scan.read_value_int_after(s, k_init_int)
|
||||
local kv_i = s.indexOf("\"value\":", k_init_int); if kv_i >= 0 { init = JsonFragBox.read_int_after(s, kv_i + 8) }
|
||||
} else {
|
||||
local k_init_var = s.indexOf("\"type\":\"Var\"", k_local_i)
|
||||
if k_init_var >= 0 && (k_loop_next < 0 || k_init_var < k_loop_next) {
|
||||
local vname = Scan.read_quoted_after_key(s, k_init_var, "name")
|
||||
local kn_i = s.indexOf("\"name\":\"", k_init_var); if kn_i < 0 { return null }
|
||||
local vname = JsonFragBox.read_string_after(s, kn_i)
|
||||
if vname != null { init = PatternUtilBox.find_local_int_before(s, vname, k_local_i) }
|
||||
}
|
||||
}
|
||||
@ -41,7 +42,8 @@ static box LowerLoopCountParamBox {
|
||||
if init == null { return null }
|
||||
// Loop Compare normalize: accept < / <= / > / >= with Var(varname) on either side
|
||||
// op: accept '<'/'<=' with i on lhs; '>'/'>=' with i on lhs (descending); swapped '>'/'>=' with i on rhs (ascending)
|
||||
local op = Scan.read_quoted_after_key(s, k_cmp, "op")
|
||||
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
|
||||
local op = JsonFragBox.read_string_after(s, k_op + 5)
|
||||
if op == null { return null }
|
||||
local has_lhs_i = s.indexOf("\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
|
||||
local has_rhs_i = s.indexOf("\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
|
||||
@ -49,61 +51,40 @@ static box LowerLoopCountParamBox {
|
||||
local cmp = null
|
||||
local limit = null
|
||||
if has_lhs_i {
|
||||
if op == "<" || op == "<=" {
|
||||
// i < L / i <= L
|
||||
// rhs Int/Var → resolve limit
|
||||
local k_rhs = s.indexOf("\"rhs\":{", k_cmp); if k_rhs < 0 { return null }
|
||||
local k_lim_t = s.indexOf("\"type\":\"Int\"", k_rhs)
|
||||
if k_lim_t >= 0 {
|
||||
limit = Scan.read_value_int_after(s, k_lim_t)
|
||||
} else {
|
||||
// rhs Var → reverse-lookup Local Int
|
||||
if k_lim_t >= 0 { local kv = s.indexOf("\"value\":", k_lim_t); if kv >= 0 { limit = JsonFragBox.read_int_after(s, kv + 8) } }
|
||||
else {
|
||||
local k_rv = s.indexOf("\"type\":\"Var\"", k_rhs); if k_rv < 0 { return null }
|
||||
local lname = Scan.read_quoted_after_key(s, k_rhs, "name"); if lname == null { return null }
|
||||
local kn = s.indexOf("\"name\":\"", k_rhs); if kn < 0 { return null }
|
||||
local lname = JsonFragBox.read_string_after(s, kn); if lname == null { return null }
|
||||
limit = PatternUtilBox.find_local_int_before(s, lname, k_cmp)
|
||||
}
|
||||
if limit == null { return null }
|
||||
if op == "<=" { limit = StringHelpers.int_to_str(JsonFragBox._str_to_int(limit) + 1) }
|
||||
cmp = "Lt"
|
||||
} else if op == ">" || op == ">=" {
|
||||
// i > L / i >= L (descending)
|
||||
local k_rhs2 = s.indexOf("\"rhs\":{", k_cmp); if k_rhs2 < 0 { return null }
|
||||
local k_lim_t3 = s.indexOf("\"type\":\"Int\"", k_rhs2)
|
||||
if k_lim_t3 >= 0 {
|
||||
limit = Scan.read_value_int_after(s, k_lim_t3)
|
||||
} else {
|
||||
local k_rv2 = s.indexOf("\"type\":\"Var\"", k_rhs2); if k_rv2 < 0 { return null }
|
||||
local lname2 = Scan.read_quoted_after_key(s, k_rhs2, "name"); if lname2 == null { return null }
|
||||
limit = PatternUtilBox.find_local_int_before(s, lname2, k_cmp)
|
||||
}
|
||||
if limit == null { return null }
|
||||
cmp = (op == ">") ? "Gt" : "Ge"
|
||||
} else { return null }
|
||||
// Normalize cmp+limit in one step
|
||||
local norm = PatternUtilBox.normalize_cmp_limit(op, 0, limit)
|
||||
if norm == null { return null }
|
||||
local cpos = StringOps.index_of_from(norm, ":", 0); if cpos < 0 { return null }
|
||||
cmp = norm.substring(0, cpos)
|
||||
limit = norm.substring(cpos+1, norm.length())
|
||||
} else {
|
||||
// swapped (Int on lhs, Var i on rhs):
|
||||
// L > i / L >= i → ascending(i < L / i < L+1)→ cmp="Lt"(limit +1 for >=)
|
||||
// L < i / L <= i → descending(i > L / i >= L)→ cmp="Gt" / "Ge"
|
||||
if op != ">" && op != ">=" && op != "<" && op != "<=" { return null }
|
||||
if op != ">" && op != ">=" && op != "<" && op != "<=" && op != "!=" { return null }
|
||||
local k_lhs = s.indexOf("\"lhs\":{", k_cmp); if k_lhs < 0 { return null }
|
||||
local k_lim_t2 = s.indexOf("\"type\":\"Int\"", k_lhs)
|
||||
if k_lim_t2 >= 0 {
|
||||
limit = Scan.read_value_int_after(s, k_lim_t2)
|
||||
} else {
|
||||
if k_lim_t2 >= 0 { local kv2 = s.indexOf("\"value\":", k_lim_t2); if kv2 >= 0 { limit = JsonFragBox.read_int_after(s, kv2 + 8) } }
|
||||
else {
|
||||
local k_lv = s.indexOf("\"type\":\"Var\"", k_lhs); if k_lv < 0 { return null }
|
||||
local lname3 = Scan.read_quoted_after_key(s, k_lhs, "name"); if lname3 == null { return null }
|
||||
local kn3 = s.indexOf("\"name\":\"", k_lhs); if kn3 < 0 { return null }
|
||||
local lname3 = JsonFragBox.read_string_after(s, kn3); if lname3 == null { return null }
|
||||
limit = PatternUtilBox.find_local_int_before(s, lname3, k_cmp)
|
||||
}
|
||||
if limit == null { return null }
|
||||
if op == ">" {
|
||||
cmp = "Lt"
|
||||
} else if op == ">=" {
|
||||
limit = StringHelpers.int_to_str(JsonFragBox._str_to_int(limit) + 1)
|
||||
cmp = "Lt"
|
||||
} else if op == "<" {
|
||||
cmp = "Gt"
|
||||
} else {
|
||||
// op == "<="
|
||||
cmp = "Ge"
|
||||
}
|
||||
local norm2 = PatternUtilBox.normalize_cmp_limit(op, 1, limit)
|
||||
if norm2 == null { return null }
|
||||
local cpos2 = StringOps.index_of_from(norm2, ":", 0); if cpos2 < 0 { return null }
|
||||
cmp = norm2.substring(0, cpos2)
|
||||
limit = norm2.substring(cpos2+1, norm2.length())
|
||||
}
|
||||
// Body increment: Local i = Binary('+', Var i, Int step)
|
||||
local k_body_i = s.indexOf("\"name\":\"" + varname + "\"", k_loop)
|
||||
@ -122,11 +103,12 @@ static box LowerLoopCountParamBox {
|
||||
local k_rhsb = s.indexOf("\"rhs\":{", k_bop); if k_rhsb < 0 { return null }
|
||||
local k_t_int = s.indexOf("\"type\":\"Int\"", k_rhsb)
|
||||
if k_t_int >= 0 {
|
||||
step = Scan.read_value_int_after(s, k_t_int)
|
||||
local kvs = s.indexOf("\"value\":", k_t_int); if kvs >= 0 { step = JsonFragBox.read_int_after(s, kvs + 8) }
|
||||
} else {
|
||||
local k_t_var = s.indexOf("\"type\":\"Var\"", k_rhsb)
|
||||
if k_t_var < 0 { return null }
|
||||
local vname = Scan.read_quoted_after_key(s, k_rhsb, "name"); if vname == null { return null }
|
||||
local kns = s.indexOf("\"name\":\"", k_rhsb); if kns < 0 { return null }
|
||||
local vname = JsonFragBox.read_string_after(s, kns); if vname == null { return null }
|
||||
step = PatternUtilBox.find_local_int_before(s, vname, k_bop)
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ using "hako.mir.builder.internal.prog_scan" as ProgScanBox
|
||||
using ProgScanBox as Scan
|
||||
using selfhost.shared.common.string_helpers as StringHelpers
|
||||
using selfhost.shared.json.utils.json_frag as JsonFragBox
|
||||
using selfhost.mir.builder.internal.pattern_util_box as PatternUtilBox
|
||||
using "hako.mir.builder.internal.loop_scan" as LoopScanBox
|
||||
|
||||
static box LowerLoopSimpleBox {
|
||||
@ -21,7 +22,8 @@ static box LowerLoopSimpleBox {
|
||||
if varname == null { return null }
|
||||
|
||||
// op: accept '<' / '<=' as-is, '!=' (with var on lhs) as '<', and swapped '>' / '>=' (with var on rhs)
|
||||
local op = Scan.read_quoted_after_key(s, k_cmp, "op")
|
||||
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
|
||||
local op = JsonFragBox.read_string_after(s, k_op + 5)
|
||||
if op == null { return null }
|
||||
// Determine where Var(varname) is and extract the Int from the opposite side
|
||||
local has_lhs_i = s.indexOf("\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
|
||||
@ -34,47 +36,26 @@ static box LowerLoopSimpleBox {
|
||||
// rhs Int value
|
||||
local k_rhs = s.indexOf("\"rhs\":{", k_cmp); if k_rhs < 0 { return null }
|
||||
local k_ti = s.indexOf("\"type\":\"Int\"", k_rhs); if k_ti < 0 { return null }
|
||||
limit = Scan.read_value_int_after(s, k_ti)
|
||||
local k_v = s.indexOf("\"value\":", k_ti); if k_v < 0 { return null }
|
||||
limit = JsonFragBox.read_int_after(s, k_v + 8)
|
||||
if limit == null { return null }
|
||||
} else {
|
||||
// Var is on rhs; lhs must be Int
|
||||
swapped = 1
|
||||
local k_lhs = s.indexOf("\"lhs\":{", k_cmp); if k_lhs < 0 { return null }
|
||||
local k_ti2 = s.indexOf("\"type\":\"Int\"", k_lhs); if k_ti2 < 0 { return null }
|
||||
limit = Scan.read_value_int_after(s, k_ti2)
|
||||
local k_v2 = s.indexOf("\"value\":", k_ti2); if k_v2 < 0 { return null }
|
||||
limit = JsonFragBox.read_int_after(s, k_v2 + 8)
|
||||
if limit == null { return null }
|
||||
}
|
||||
|
||||
// Normalize to canonical '<' with possible +1 adjustment
|
||||
if swapped == 0 {
|
||||
if op == "<" {
|
||||
// ok
|
||||
} else if op == "<=" {
|
||||
limit = StringHelpers.int_to_str(JsonFragBox._str_to_int(limit) + 1)
|
||||
} else if op == "!=" {
|
||||
// With init=0 and step=1 counting loop, i != L is equivalent to i < L
|
||||
// keep limit as-is
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
} else {
|
||||
// swapped: L ? i
|
||||
if op == ">" {
|
||||
// L > i ≡ i < L
|
||||
} else if op == ">=" {
|
||||
// L >= i ≡ i <= L ≡ i < (L+1)
|
||||
limit = StringHelpers.int_to_str(JsonFragBox._str_to_int(limit) + 1)
|
||||
} else if op == "<" {
|
||||
// L < i ≡ i > L → for simple ascending loop (init=0, step=1) this pattern is not canonical;
|
||||
// we treat as descending form not supported by simple box
|
||||
return null
|
||||
} else if op == "<=" {
|
||||
// L <= i ≡ i >= L — same reason as above
|
||||
return null
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
// Normalize to canonical '<' using shared helper; only accept Lt in simple box
|
||||
local norm = PatternUtilBox.normalize_cmp_limit(op, swapped, limit)
|
||||
if norm == null { return null }
|
||||
local cpos = StringOps.index_of_from(norm, ":", 0); if cpos < 0 { return null }
|
||||
local cmp = norm.substring(0, cpos)
|
||||
limit = norm.substring(cpos+1, norm.length())
|
||||
if cmp != "Lt" { return null }
|
||||
|
||||
// Delegate to shared loop form builder (counting mode) via build2
|
||||
local opts = new MapBox()
|
||||
|
||||
@ -31,15 +31,20 @@ static box LowerLoopSumBcBox {
|
||||
local varname = null
|
||||
{
|
||||
local kl = s.indexOf("\"lhs\":{", k_cmp); local kr = s.indexOf("\"rhs\":{", k_cmp)
|
||||
if kl >= 0 && s.indexOf("\"type\":\"Var\"", kl) >= 0 { varname = Scan.read_quoted_after_key(s, kl, "name") }
|
||||
if varname == null && kr >= 0 && s.indexOf("\"type\":\"Var\"", kr) >= 0 { varname = Scan.read_quoted_after_key(s, kr, "name") }
|
||||
if kl >= 0 && s.indexOf("\"type\":\"Var\"", kl) >= 0 {
|
||||
local kn = s.indexOf("\"name\":\"", kl); if kn >= 0 { varname = JsonFragBox.read_string_after(s, kn) }
|
||||
}
|
||||
if varname == null && kr >= 0 && s.indexOf("\"type\":\"Var\"", kr) >= 0 {
|
||||
local kn2 = s.indexOf("\"name\":\"", kr); if kn2 >= 0 { varname = JsonFragBox.read_string_after(s, kn2) }
|
||||
}
|
||||
}
|
||||
if varname == null { return null }
|
||||
if trace != null && ("" + trace) == "1" {
|
||||
print("[sum_bc] var=" + varname)
|
||||
}
|
||||
// op: accept '<'/'<=' with var on lhs; also accept swapped '>'/'>=' with var on rhs
|
||||
local op = Scan.read_quoted_after_key(s, k_cmp, "op")
|
||||
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
|
||||
local op = JsonFragBox.read_string_after(s, k_op + 5)
|
||||
if op == null { return null }
|
||||
local has_lhs_i = s.indexOf("\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
|
||||
local has_rhs_i = s.indexOf("\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
|
||||
@ -50,14 +55,16 @@ static box LowerLoopSumBcBox {
|
||||
// rhs Int limit
|
||||
local k_rhs = s.indexOf("\"rhs\":{", k_cmp); if k_rhs < 0 { return null }
|
||||
local k_ti = s.indexOf("\"type\":\"Int\"", k_rhs); if k_ti < 0 { return null }
|
||||
limit = Scan.read_value_int_after(s, k_ti); if limit == null { return null }
|
||||
local kv = s.indexOf("\"value\":", k_ti); if kv < 0 { return null }
|
||||
limit = JsonFragBox.read_int_after(s, kv + 8); if limit == null { return null }
|
||||
if op == "<=" { limit = StringHelpers.int_to_str(JsonFragBox._str_to_int(limit) + 1) }
|
||||
} else {
|
||||
// swapped: Int on lhs, Var i on rhs, op should be '>' or '>='
|
||||
if op != ">" && op != ">=" { return null }
|
||||
local k_lhs = s.indexOf("\"lhs\":{", k_cmp); if k_lhs < 0 { return null }
|
||||
local k_ti2 = s.indexOf("\"type\":\"Int\"", k_lhs); if k_ti2 < 0 { return null }
|
||||
limit = Scan.read_value_int_after(s, k_ti2); if limit == null { return null }
|
||||
local kv2 = s.indexOf("\"value\":", k_ti2); if kv2 < 0 { return null }
|
||||
limit = JsonFragBox.read_int_after(s, kv2 + 8); if limit == null { return null }
|
||||
if op == ">=" { limit = StringHelpers.int_to_str(JsonFragBox._str_to_int(limit) + 1) }
|
||||
}
|
||||
|
||||
@ -70,20 +77,30 @@ static box LowerLoopSumBcBox {
|
||||
local kbc = s.lastIndexOf("\"type\":\"Compare\"", kb)
|
||||
if kbc >= 0 {
|
||||
// Ensure op=="==" and lhs Var i
|
||||
local bop = Scan.read_quoted_after_key(s, kbc, "op")
|
||||
local kop = s.indexOf("\"op\":", kbc); local bop = null; if kop >= 0 { bop = JsonFragBox.read_string_after(s, kop + 5) }
|
||||
if bop != null && bop == "==" {
|
||||
local lhs_i = s.indexOf("\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kbc) >= 0
|
||||
local rhs_i = s.indexOf("\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kbc) >= 0
|
||||
if lhs_i {
|
||||
local kbi = s.indexOf("\"type\":\"Int\"", s.indexOf("\"rhs\":{", kbc))
|
||||
if kbi >= 0 { break_value = Scan.read_value_int_after(s, kbi) }
|
||||
if kbi >= 0 { local kvb = s.indexOf("\"value\":", kbi); if kvb >= 0 { break_value = JsonFragBox.read_int_after(s, kvb + 8) } }
|
||||
} else if rhs_i {
|
||||
local kbi2 = s.indexOf("\"type\":\"Int\"", s.indexOf("\"lhs\":{", kbc))
|
||||
if kbi2 >= 0 { break_value = Scan.read_value_int_after(s, kbi2) }
|
||||
if kbi2 >= 0 { local kvb2 = s.indexOf("\"value\":", kbi2); if kvb2 >= 0 { break_value = JsonFragBox.read_int_after(s, kvb2 + 8) } }
|
||||
}
|
||||
} else if bop != null && bop == "!=" {
|
||||
// Delegate to loop-scan helper for '!=' + else [Break]
|
||||
if break_value == null { break_value = LoopScanBox.extract_ne_else_sentinel_value(s, "Break", k_loop, varname) }
|
||||
// Fallback: try local JsonFragBox-based extraction near kbc
|
||||
if break_value == null {
|
||||
// Read Int from lhs or rhs around kbc
|
||||
local k_rhsb = s.indexOf("\"rhs\":{", kbc); local k_lhsb = s.indexOf("\"lhs\":{", kbc)
|
||||
if k_rhsb >= 0 && s.indexOf("\"type\":\"Int\"", k_rhsb) >= 0 {
|
||||
local kvi = s.indexOf("\"value\":", s.indexOf("\"type\":\"Int\"", k_rhsb)); if kvi >= 0 { break_value = JsonFragBox.read_int_after(s, kvi + 8) }
|
||||
} else if k_lhsb >= 0 && s.indexOf("\"type\":\"Int\"", k_lhsb) >= 0 {
|
||||
local kvj = s.indexOf("\"value\":", s.indexOf("\"type\":\"Int\"", k_lhsb)); if kvj >= 0 { break_value = JsonFragBox.read_int_after(s, kvj + 8) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -95,20 +112,29 @@ static box LowerLoopSumBcBox {
|
||||
if kc >= 0 {
|
||||
local kcc = s.lastIndexOf("\"type\":\"Compare\"", kc)
|
||||
if kcc >= 0 {
|
||||
local cop = Scan.read_quoted_after_key(s, kcc, "op")
|
||||
local kop2 = s.indexOf("\"op\":", kcc); local cop = null; if kop2 >= 0 { cop = JsonFragBox.read_string_after(s, kop2 + 5) }
|
||||
if cop != null && cop == "==" {
|
||||
local lhs_i2 = s.indexOf("\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kcc) >= 0
|
||||
local rhs_i2 = s.indexOf("\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kcc) >= 0
|
||||
if lhs_i2 {
|
||||
local kci = s.indexOf("\"type\":\"Int\"", s.indexOf("\"rhs\":{", kcc))
|
||||
if kci >= 0 { skip_value = Scan.read_value_int_after(s, kci) }
|
||||
if kci >= 0 { local kvs = s.indexOf("\"value\":", kci); if kvs >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs + 8) } }
|
||||
} else if rhs_i2 {
|
||||
local kci2 = s.indexOf("\"type\":\"Int\"", s.indexOf("\"lhs\":{", kcc))
|
||||
if kci2 >= 0 { skip_value = Scan.read_value_int_after(s, kci2) }
|
||||
if kci2 >= 0 { local kvs2 = s.indexOf("\"value\":", kci2); if kvs2 >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs2 + 8) } }
|
||||
}
|
||||
} else if cop != null && cop == "!=" {
|
||||
// Delegate to loop-scan helper for '!=' + else [Continue]
|
||||
if skip_value == null { skip_value = LoopScanBox.extract_ne_else_sentinel_value(s, "Continue", k_loop, varname) }
|
||||
// Fallback: JsonFragBox-based local extraction near kcc
|
||||
if skip_value == null {
|
||||
local k_rhsb2 = s.indexOf("\"rhs\":{", kcc); local k_lhsb2 = s.indexOf("\"lhs\":{", kcc)
|
||||
if k_rhsb2 >= 0 && s.indexOf("\"type\":\"Int\"", k_rhsb2) >= 0 {
|
||||
local kvs = s.indexOf("\"value\":", s.indexOf("\"type\":\"Int\"", k_rhsb2)); if kvs >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs + 8) }
|
||||
} else if k_lhsb2 >= 0 && s.indexOf("\"type\":\"Int\"", k_lhsb2) >= 0 {
|
||||
local kvs2 = s.indexOf("\"value\":", s.indexOf("\"type\":\"Int\"", k_lhsb2)); if kvs2 >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs2 + 8) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
// lower_method_array_get_set_box.hako — Minimal structural MIR for ArrayBox set/get
|
||||
using "hako.mir.builder.internal.pattern_util" as PatternUtilBox
|
||||
|
||||
static box LowerMethodArrayGetSetBox {
|
||||
try_lower(program_json) {
|
||||
if program_json == null { return null }
|
||||
local s = "" + program_json
|
||||
if s.indexOf("\"type\":\"New\"") < 0 { return null }
|
||||
if s.indexOf("\"class\":\"ArrayBox\"") < 0 { return null }
|
||||
// Reverse-lookup (safe subset): prefer Local(Int) for index, Local(String) for value
|
||||
local n = s.length()
|
||||
local idx = PatternUtilBox.find_any_local_int_before(s, n)
|
||||
if idx == null { idx = "2" }
|
||||
local sval = PatternUtilBox.find_any_local_string_before(s, n)
|
||||
// Emit MIR v1 JSON: new Array -> r1, const idx -> r2, const val -> r3, set(r1,r2,r3), get(r1,r2)->r4, const 0->r5, ret r5
|
||||
local json = "{\"kind\":\"MIR\",\"schema_version\":\"1.0\",\"functions\":[{\"name\":\"main\",\"blocks\":[{\"id\":0,\"instructions\":[" +
|
||||
// new array -> r1
|
||||
"{\"op\":\"mir_call\",\"dst\":1,\"mir_call\":{\"callee\":{\"type\":\"Constructor\",\"box_type\":\"ArrayBox\"},\"args\":[],\"effects\":[]}}," +
|
||||
// const idx -> r2
|
||||
"{\"op\":\"const\",\"dst\":2,\"value\":{\"type\":\"i64\",\"value\":" + idx + "}}," +
|
||||
// const val -> r3 (string when available, else i64=3)
|
||||
(sval != null ? ("{\\\"op\\\":\\\"const\\\",\\\"dst\\\":3,\\\"value\\\":{\\\"type\\\":\\\"string\\\",\\\"value\\\":\\\"" + sval + "\\\"}},") : "{\\\"op\\\":\\\"const\\\",\\\"dst\\\":3,\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":3}},") +
|
||||
// set(r1, r2, r3)
|
||||
"{\"op\":\"mir_call\",\"mir_call\":{\"callee\":{\"type\":\"Method\",\"box_name\":\"ArrayBox\",\"method\":\"set\",\"receiver\":1},\"args\":[2,3],\"effects\":[]}}," +
|
||||
// get(r1, r2) -> r4
|
||||
"{\"op\":\"mir_call\",\"dst\":4,\"mir_call\":{\"callee\":{\"type\":\"Method\",\"box_name\":\"ArrayBox\",\"method\":\"get\",\"receiver\":1},\"args\":[2],\"effects\":[]}}," +
|
||||
// const 0 -> r5, ret r5
|
||||
"{\"op\":\"const\",\"dst\":5,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":5}]}]}]}"
|
||||
return json
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
// lower_method_array_push_box.hako — Minimal structural MIR for ArrayBox.push
|
||||
using "hako.mir.builder.internal.pattern_util" as PatternUtilBox
|
||||
|
||||
static box LowerMethodArrayPushBox {
|
||||
try_lower(program_json) {
|
||||
if program_json == null { return null }
|
||||
local s = "" + program_json
|
||||
if s.indexOf("\"type\":\"New\"") < 0 { return null }
|
||||
if s.indexOf("\"class\":\"ArrayBox\"") < 0 { return null }
|
||||
// Reverse-lookup (safe subset): prefer Local(Int) for push values when present
|
||||
local n = s.length()
|
||||
local p1 = PatternUtilBox.find_any_local_int_before(s, n); if p1 == null { p1 = "1" }
|
||||
local p2 = p1 // use same when only one found; harmless for structural canary
|
||||
// Emit MIR v1 JSON: new Array -> r1, push(r1,p1), const 2 -> r2, push(r1,p2), size/get/set presence, const 0 -> r5, ret r5
|
||||
local json = "{\"kind\":\"MIR\",\"schema_version\":\"1.0\",\"functions\":[{\"name\":\"main\",\"blocks\":[{\"id\":0,\"instructions\":[" +
|
||||
"{\"op\":\"mir_call\",\"dst\":1,\"mir_call\":{\"callee\":{\"type\":\"Constructor\",\"box_type\":\"ArrayBox\"},\"args\":[],\"effects\":[]}}," +
|
||||
// push p1
|
||||
"{\"op\":\"mir_call\",\"mir_call\":{\"callee\":{\"type\":\"Method\",\"box_name\":\"ArrayBox\",\"method\":\"push\",\"receiver\":1},\"args\":[" + p1 + "],\"effects\":[]}}," +
|
||||
// const 2 -> r2, push p2 (use r2 as arg when different)
|
||||
"{\"op\":\"const\",\"dst\":2,\"value\":{\"type\":\"i64\",\"value\":2}}," +
|
||||
"{\"op\":\"mir_call\",\"mir_call\":{\"callee\":{\"type\":\"Method\",\"box_name\":\"ArrayBox\",\"method\":\"push\",\"receiver\":1},\"args\":[" + p2 + "],\"effects\":[]}}," +
|
||||
// size for presence (canary checks only for existence)
|
||||
"{\"op\":\"mir_call\",\"dst\":4,\"mir_call\":{\"callee\":{\"type\":\"Method\",\"box_name\":\"ArrayBox\",\"method\":\"size\",\"receiver\":1},\"args\":[],\"effects\":[]}}," +
|
||||
// set/get presence (index=2, value=10)
|
||||
"{\"op\":\"const\",\"dst\":6,\"value\":{\"type\":\"i64\",\"value\":10}}," +
|
||||
"{\"op\":\"mir_call\",\"mir_call\":{\"callee\":{\"type\":\"Method\",\"box_name\":\"ArrayBox\",\"method\":\"set\",\"receiver\":1},\"args\":[2,6],\"effects\":[]}}," +
|
||||
"{\"op\":\"mir_call\",\"dst\":7,\"mir_call\":{\"callee\":{\"type\":\"Method\",\"box_name\":\"ArrayBox\",\"method\":\"get\",\"receiver\":1},\"args\":[2],\"effects\":[]}}," +
|
||||
// const 0 -> r5, ret r5
|
||||
"{\"op\":\"const\",\"dst\":5,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":5}]}]}]}"
|
||||
return json
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
// lower_method_array_size_box.hako — Minimal: detect ArrayBox New and emit Method(size) call
|
||||
// Scope: Phase 20.43 structural generation (no VM semantics dependency)
|
||||
|
||||
static box LowerMethodArraySizeBox {
|
||||
try_lower(program_json) {
|
||||
if program_json == null { return null }
|
||||
local s = "" + program_json
|
||||
if s.indexOf("\"type\":\"New\"") < 0 { return null }
|
||||
if s.indexOf("\"class\":\"ArrayBox\"") < 0 { return null }
|
||||
// Emit MIR v1 JSON: new ArrayBox -> r1, size(r1) -> r2, const 0 -> r3, ret r3
|
||||
local json = "{\"kind\":\"MIR\",\"schema_version\":\"1.0\",\"functions\":[{\"name\":\"main\",\"blocks\":[{\"id\":0,\"instructions\":[" +
|
||||
"{\"op\":\"mir_call\",\"dst\":1,\"mir_call\":{\"callee\":{\"type\":\"Constructor\",\"box_type\":\"ArrayBox\"},\"args\":[],\"effects\":[]}}," +
|
||||
"{\"op\":\"mir_call\",\"dst\":2,\"mir_call\":{\"callee\":{\"type\":\"Method\",\"box_name\":\"ArrayBox\",\"method\":\"size\",\"receiver\":1},\"args\":[],\"effects\":[]}}," +
|
||||
"{\"op\":\"const\",\"dst\":3,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":3}]}]}]}"
|
||||
return json
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
// lower_method_map_get_set_box.hako — Minimal structural MIR for MapBox set/get
|
||||
using "hako.mir.builder.internal.pattern_util" as PatternUtilBox
|
||||
|
||||
static box LowerMethodMapGetSetBox {
|
||||
try_lower(program_json) {
|
||||
if program_json == null { return null }
|
||||
local s = "" + program_json
|
||||
if s.indexOf("\"type\":\"New\"") < 0 { return null }
|
||||
if s.indexOf("\"class\":\"MapBox\"") < 0 { return null }
|
||||
// Reverse-lookup (safe subset): prefer Local(String) for key, Local(Int) for value
|
||||
local n = s.length()
|
||||
local key = PatternUtilBox.find_any_local_string_before(s, n)
|
||||
if key == null { key = "k" }
|
||||
local val = PatternUtilBox.find_any_local_int_before(s, n)
|
||||
if val == null { val = "5" }
|
||||
// key as const string (inline), value as const int (inline)
|
||||
local json = "{\"kind\":\"MIR\",\"schema_version\":\"1.0\",\"functions\":[{\"name\":\"main\",\"blocks\":[{\"id\":0,\"instructions\":[" +
|
||||
// new map -> r1
|
||||
"{\"op\":\"mir_call\",\"dst\":1,\"mir_call\":{\"callee\":{\"type\":\"Constructor\",\"box_type\":\"MapBox\"},\"args\":[],\"effects\":[]}}," +
|
||||
// set(r1, key, val)
|
||||
"{\"op\":\"mir_call\",\"mir_call\":{\"callee\":{\"type\":\"Method\",\"box_name\":\"MapBox\",\"method\":\"set\",\"receiver\":1},\"args\":[\"" + key + "\"," + val + "],\"effects\":[]}}," +
|
||||
// get(r1, key) -> r2
|
||||
"{\"op\":\"mir_call\",\"dst\":2,\"mir_call\":{\"callee\":{\"type\":\"Method\",\"box_name\":\"MapBox\",\"method\":\"get\",\"receiver\":1},\"args\":[\"" + key + "\"],\"effects\":[]}}," +
|
||||
// const 0 -> r3, ret r3
|
||||
"{\"op\":\"const\",\"dst\":3,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":3}]}]}]}"
|
||||
return json
|
||||
}
|
||||
}
|
||||
17
lang/src/mir/builder/internal/lower_method_map_size_box.hako
Normal file
17
lang/src/mir/builder/internal/lower_method_map_size_box.hako
Normal file
@ -0,0 +1,17 @@
|
||||
// lower_method_map_size_box.hako — Minimal structural MIR for MapBox.size
|
||||
|
||||
static box LowerMethodMapSizeBox {
|
||||
try_lower(program_json) {
|
||||
if program_json == null { return null }
|
||||
local s = "" + program_json
|
||||
if s.indexOf("\"type\":\"New\"") < 0 { return null }
|
||||
if s.indexOf("\"class\":\"MapBox\"") < 0 { return null }
|
||||
local json = "{\"kind\":\"MIR\",\"schema_version\":\"1.0\",\"functions\":[{\"name\":\"main\",\"blocks\":[{\"id\":0,\"instructions\":[" +
|
||||
"{\"op\":\"mir_call\",\"dst\":1,\"mir_call\":{\"callee\":{\"type\":\"Constructor\",\"box_type\":\"MapBox\"},\"args\":[],\"effects\":[]}}," +
|
||||
"{\"op\":\"mir_call\",\"dst\":2,\"mir_call\":{\"callee\":{\"type\":\"Method\",\"box_name\":\"MapBox\",\"method\":\"size\",\"receiver\":1},\"args\":[],\"effects\":[]}}," +
|
||||
"{\"op\":\"const\",\"dst\":3,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":3}]}]}]}"
|
||||
return json
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
// lower_newbox_constructor_box.hako — Program(JSON v0) with New(Array/Map) → MIR v1 (mir_call Constructor)
|
||||
// Scope: minimal safe subset for Phase 20.43 Step‑2
|
||||
|
||||
|
||||
static box LowerNewboxConstructorBox {
|
||||
try_lower(program_json) {
|
||||
if program_json == null { return null }
|
||||
local s = "" + program_json
|
||||
// Quick pattern check
|
||||
if s.indexOf("\"type\":\"New\"") < 0 { return null }
|
||||
// Find class name (minimal scan)
|
||||
local cls = null
|
||||
if s.indexOf("\"class\":\"ArrayBox\"") >= 0 { cls = "ArrayBox" }
|
||||
else { if s.indexOf("\"class\":\"MapBox\"") >= 0 { cls = "MapBox" } }
|
||||
if cls == null { return null }
|
||||
// Only accept known minimal boxes
|
||||
if !(cls == "ArrayBox" || cls == "MapBox") { return null }
|
||||
|
||||
// Emit MIR v1 JSON text directly (no Map/Array construction)
|
||||
local json = "{\"kind\":\"MIR\",\"schema_version\":\"1.0\",\"functions\":[{\"name\":\"main\",\"blocks\":[{\"id\":0,\"instructions\":[" +
|
||||
"{\"op\":\"mir_call\",\"dst\":1,\"mir_call\":{\"callee\":{\"type\":\"Constructor\",\"box_type\":\"" + cls + "\"},\"args\":[],\"effects\":[]}}," +
|
||||
"{\"op\":\"const\",\"dst\":2,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":2}]}]}]}"
|
||||
return json
|
||||
}
|
||||
}
|
||||
@ -34,11 +34,12 @@ static box LowerReturnBinOpBox {
|
||||
local rhs_val = JsonFragBox.read_int_after(s, kv_rhs + 8)
|
||||
if rhs_val == null { return null }
|
||||
|
||||
local mir = "{\"functions\":{\"Main.main\":{\"params\":[],\"locals\":[],\"blocks\":[{\"label\":\"bb0\",\"instructions\":[" +
|
||||
// Emit minimal MIR JSON v0 (functions array, name="main", blocks.id)
|
||||
local mir = "{\"functions\":[{\"name\":\"main\",\"params\":[],\"locals\":[],\"blocks\":[{\"id\":0,\"instructions\":[" +
|
||||
"{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":" + lhs_val + "}}," +
|
||||
"{\"op\":\"const\",\"dst\":2,\"value\":{\"type\":\"i64\",\"value\":" + rhs_val + "}}," +
|
||||
"{\"op\":\"binop\",\"operation\":\"" + op + "\",\"lhs\":1,\"rhs\":2,\"dst\":3}," +
|
||||
"{\"op\":\"ret\",\"value\":3}]}] }},\"blocks\":1}"
|
||||
"{\"op\":\"ret\",\"value\":3}]}]}]}"
|
||||
return mir
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,24 +1,25 @@
|
||||
// lower_return_binop_varvar_box.hako — Return(Binary Var vs Var) with prior Local Ints
|
||||
|
||||
using "hako.mir.builder.internal.prog_scan" as ProgScanBox
|
||||
using ProgScanBox as Scan
|
||||
using selfhost.shared.mir.schema as MirSchemaBox
|
||||
using "hako.mir.builder.internal.pattern_util" as PatternUtilBox
|
||||
using selfhost.shared.json.utils.json_frag as JsonFragBox
|
||||
|
||||
static box LowerReturnBinOpVarVarBox {
|
||||
_find_local_int_before(s, name, before_pos) { return PatternUtilBox.find_local_int_before(s, name, before_pos) }
|
||||
try_lower(program_json){
|
||||
local s = "" + program_json
|
||||
local k_ret = s.indexOf("\"type\":\"Return\""); if k_ret < 0 { return null }
|
||||
local k_bin = s.indexOf("\"type\":\"Binary\"", k_ret); if k_bin < 0 { return null }
|
||||
local op = Scan.read_quoted_after_key(s, k_bin, "op"); if op == null { return null }
|
||||
local k_op = s.indexOf("\"op\":", k_bin); if k_op < 0 { return null }
|
||||
local op = JsonFragBox.read_string_after(s, k_op + 5); if op == null { return null }
|
||||
if !(op == "+" || op == "-" || op == "*" || op == "/") { return null }
|
||||
local klhs = s.indexOf("\"lhs\":{\"type\":\"Var\"", k_bin); if klhs < 0 { return null }
|
||||
local krhs = s.indexOf("\"rhs\":{\"type\":\"Var\"", k_bin); if krhs < 0 { return null }
|
||||
local lname = Scan.read_quoted_after_key(s, klhs, "name"); if lname == null { return null }
|
||||
local rname = Scan.read_quoted_after_key(s, krhs, "name"); if rname == null { return null }
|
||||
local lval = me._find_local_int_before(s, lname, k_ret); if lval == null { return null }
|
||||
local rval = me._find_local_int_before(s, rname, k_ret); if rval == null { return null }
|
||||
local knl = s.indexOf("\"name\":", klhs); if knl < 0 { return null }
|
||||
local lname = JsonFragBox.read_string_after(s, knl + 7); if lname == null { return null }
|
||||
local knr = s.indexOf("\"name\":", krhs); if knr < 0 { return null }
|
||||
local rname = JsonFragBox.read_string_after(s, knr + 7); if rname == null { return null }
|
||||
local lval = PatternUtilBox.find_local_int_before(s, lname, k_ret); if lval == null { return null }
|
||||
local rval = PatternUtilBox.find_local_int_before(s, rname, k_ret); if rval == null { return null }
|
||||
local b0=new ArrayBox(); b0.push(MirSchemaBox.inst_const(1,lval)); b0.push(MirSchemaBox.inst_const(2,rval)); b0.push(MirSchemaBox.inst_binop(op == "+" ? "Add" : (op == "-" ? "Sub" : (op == "*" ? "Mul" : "Div")),1,2,3)); b0.push(MirSchemaBox.inst_ret(3))
|
||||
local blocks=new ArrayBox(); blocks.push(MirSchemaBox.block(0,b0));
|
||||
return MirSchemaBox.module(MirSchemaBox.fn_main(blocks))
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
// lower_return_int_box.hako — Return(Int) → const+ret
|
||||
|
||||
using "hako.mir.builder.internal.prog_scan" as ProgScanBox
|
||||
using ProgScanBox as Scan
|
||||
using selfhost.shared.json.utils.json_frag as JsonFragBox
|
||||
|
||||
static box LowerReturnIntBox {
|
||||
try_lower(program_json) {
|
||||
@ -11,9 +10,13 @@ static box LowerReturnIntBox {
|
||||
// Expect Int after Return
|
||||
local k_int = s.indexOf("\"type\":\"Int\"", k_ret)
|
||||
if k_int < 0 { return null }
|
||||
local val = Scan.read_value_int_after(s, k_int)
|
||||
// Read value after Int
|
||||
local kv = s.indexOf("\"value\":", k_int); if kv < 0 { return null }
|
||||
local val = JsonFragBox.read_int_after(s, kv + 8)
|
||||
if val == null { return null }
|
||||
local mir = "{\"functions\":{\"Main.main\":{\"params\":[],\"locals\":[],\"blocks\":[{\"label\":\"bb0\",\"instructions\":[{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":" + val + "}},{\"op\":\"ret\",\"value\":1}] }] }},\"blocks\":1}"
|
||||
// Emit minimal MIR JSON v0 (functions as array; blocks use id field)
|
||||
// Shape expected by src/runner/mir_json_v0.rs::parse_mir_v0_to_module
|
||||
local mir = "{\"functions\":[{\"name\":\"main\",\"params\":[],\"locals\":[],\"blocks\":[{\"id\":0,\"instructions\":[{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":" + val + "}},{\"op\":\"ret\",\"value\":1}]}]}]}"
|
||||
return mir
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,8 +4,6 @@ using selfhost.shared.mir.schema as MirSchemaBox
|
||||
|
||||
using "hako.mir.builder.internal.pattern_util" as PatternUtilBox
|
||||
|
||||
using "hako.mir.builder.internal.prog_scan" as ProgScanBox
|
||||
|
||||
using selfhost.shared.json.utils.json_frag as JsonFragBox
|
||||
|
||||
static box LowerReturnLogicalBox {
|
||||
@ -17,8 +15,10 @@ static box LowerReturnLogicalBox {
|
||||
if k_ret < 0 { return null }
|
||||
local k_log = JsonFragBox.index_of_from(s, "\"type\":\"Logical\"", k_ret)
|
||||
if k_log < 0 { return null }
|
||||
// op: && or || (ProgScanBox is sufficient here)
|
||||
local op = ProgScanBox.read_quoted_after_key(s, k_log, "op")
|
||||
// op: && or ||
|
||||
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_log)
|
||||
if k_op < 0 { return null }
|
||||
local op = JsonFragBox.read_string_after(s, k_op + 5)
|
||||
if op == null { return null }
|
||||
if !(op == "&&" || op == "||") { return null }
|
||||
// Resolve lhs to 0/1 (Bool or Var with Local Bool) - robust version
|
||||
@ -33,7 +33,9 @@ static box LowerReturnLogicalBox {
|
||||
} else {
|
||||
local klhs_v = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\"", k_log)
|
||||
if klhs_v >= 0 {
|
||||
local name = ProgScanBox.read_quoted_after_key(s, klhs_v, "name")
|
||||
local kn = JsonFragBox.index_of_from(s, "\"name\":", klhs_v)
|
||||
if kn < 0 { return null }
|
||||
local name = JsonFragBox.read_string_after(s, kn + 7)
|
||||
if name != null { lhs_true = PatternUtilBox.find_local_bool_before(s, name, k_log) }
|
||||
}
|
||||
}
|
||||
@ -51,7 +53,9 @@ static box LowerReturnLogicalBox {
|
||||
} else {
|
||||
local krhs_v = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\"", k_log)
|
||||
if krhs_v >= 0 {
|
||||
local name2 = ProgScanBox.read_quoted_after_key(s, krhs_v, "name")
|
||||
local kn2 = JsonFragBox.index_of_from(s, "\"name\":", krhs_v)
|
||||
if kn2 < 0 { return null }
|
||||
local name2 = JsonFragBox.read_string_after(s, kn2 + 7)
|
||||
if name2 != null { rhs_true = PatternUtilBox.find_local_bool_before(s, name2, k_log) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,6 +13,8 @@ static box LowerReturnMethodArrayMapBox {
|
||||
local k_recv = s.indexOf("\"recv\":{\"type\":\"Var\"", k_m); if k_recv < 0 { return null }
|
||||
local method = null
|
||||
{ local km = s.indexOf("\"method\":\"", k_m); if km < 0 { return null } method = JsonFragBox.read_string_after(s, km) }
|
||||
// Standardize: generate 'size' (len/length are accepted aliases at receiver)
|
||||
if method == "length" || method == "len" { method = "size" }
|
||||
// Allow basic methods
|
||||
if !(method == "size" || method == "length" || method == "len" || method == "get" || method == "set" || method == "push") { return null }
|
||||
// Parse up to two Int args with actual values
|
||||
|
||||
15
lang/src/mir/builder/internal/lower_typeop_cast_box.hako
Normal file
15
lang/src/mir/builder/internal/lower_typeop_cast_box.hako
Normal file
@ -0,0 +1,15 @@
|
||||
// lower_typeop_cast_box.hako — Minimal structural MIR for typeop(Cast)
|
||||
|
||||
static box LowerTypeOpCastBox {
|
||||
try_lower(program_json) {
|
||||
if program_json == null { return null }
|
||||
// Emit v1 JSON: const 100 -> v1, typeop Cast v1 -> v2 (IntegerBox), const 0 -> v3, ret v3
|
||||
local json = "{\"kind\":\"MIR\",\"schema_version\":\"1.0\",\"functions\":[{\"name\":\"main\",\"blocks\":[{\"id\":0,\"instructions\":[" +
|
||||
"{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":100}}," +
|
||||
"{\"op\":\"typeop\",\"op_kind\":\"Cast\",\"dst\":2,\"value\":1,\"ty\":\"IntegerBox\"}," +
|
||||
"{\"op\":\"const\",\"dst\":3,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":3}]}]}]}"
|
||||
return json
|
||||
}
|
||||
}
|
||||
|
||||
15
lang/src/mir/builder/internal/lower_typeop_check_box.hako
Normal file
15
lang/src/mir/builder/internal/lower_typeop_check_box.hako
Normal file
@ -0,0 +1,15 @@
|
||||
// lower_typeop_check_box.hako — Minimal structural MIR for typeop(Check)
|
||||
|
||||
static box LowerTypeOpCheckBox {
|
||||
try_lower(program_json) {
|
||||
if program_json == null { return null }
|
||||
local json = "{\"kind\":\"MIR\",\"schema_version\":\"1.0\",\"functions\":[{\"name\":\"main\",\"blocks\":[{\"id\":0,\"instructions\":[" +
|
||||
// const 42 -> v1, typeop Check v1 -> v2, const 0 -> v3, ret v3
|
||||
"{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":42}}," +
|
||||
"{\"op\":\"typeop\",\"op_kind\":\"Check\",\"dst\":2,\"value\":1,\"ty\":\"IntegerBox\"}," +
|
||||
"{\"op\":\"const\",\"dst\":3,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":3}]}]}]}"
|
||||
return json
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,27 @@ using selfhost.shared.common.string_helpers as StringHelpers
|
||||
|
||||
static box PatternUtilBox {
|
||||
map_cmp(sym) { if sym=="<" {return "Lt"} if sym==">" {return "Gt"} if sym=="<=" {return "Le"} if sym==">=" {return "Ge"} if sym=="==" {return "Eq"} if sym=="!=" {return "Ne"} return null }
|
||||
// Normalize (op, swapped, limit) → (cmp, limit') where cmp in {Lt, Le, Gt, Ge}
|
||||
// swapped=0: i ? L, swapped=1: L ? i
|
||||
normalize_cmp_limit(op, swapped, limit_str) {
|
||||
local op1 = "" + op
|
||||
local ls = "" + limit_str
|
||||
if swapped == 0 {
|
||||
if op1 == "<" { return "Lt:" + ls }
|
||||
if op1 == "<=" { return "Lt:" + StringHelpers.int_to_str(JsonFragBox._str_to_int(ls) + 1) }
|
||||
if op1 == ">" { return "Gt:" + ls }
|
||||
if op1 == ">=" { return "Ge:" + ls }
|
||||
if op1 == "!=" { return "Lt:" + ls } // count(init=0,step=1) 前提の近似
|
||||
return null
|
||||
} else {
|
||||
if op1 == ">" { return "Lt:" + ls }
|
||||
if op1 == ">=" { return "Lt:" + StringHelpers.int_to_str(JsonFragBox._str_to_int(ls) + 1) }
|
||||
if op1 == "<" { return "Gt:" + ls }
|
||||
if op1 == "<=" { return "Ge:" + ls }
|
||||
if op1 == "!=" { return "Lt:" + ls } // 安全近似(入替側)
|
||||
return null
|
||||
}
|
||||
}
|
||||
// Normalize limit for canonical (i < limit) form.
|
||||
// When swapped==0, expects op in {'<','<='}; when swapped==1 (Int on lhs, Var on rhs), expects op in {'>','>='}.
|
||||
// Returns adjusted limit string or null if unsupported.
|
||||
@ -38,4 +59,47 @@ static box PatternUtilBox {
|
||||
local kv=s.indexOf("\"value\":",kb); if kv<0 { return null }
|
||||
return JsonFragBox.read_bool_after(s, kv+8)
|
||||
}
|
||||
|
||||
// Find the last Local(Int) before a given position (name-agnostic).
|
||||
// Returns string digits or null when not found.
|
||||
find_any_local_int_before(s, before_pos) {
|
||||
local pos = 0; local last_k = -1; local n = ("" + s).length()
|
||||
loop(true) {
|
||||
local k = JsonFragBox.index_of_from(s, "\"type\":\"Local\"", pos)
|
||||
if k < 0 || k >= before_pos { break }
|
||||
last_k = k
|
||||
pos = k + 1
|
||||
}
|
||||
if last_k < 0 { return null }
|
||||
// Limit search to the next Local or before_pos
|
||||
local next = JsonFragBox.index_of_from(s, "\"type\":\"Local\"", last_k + 1)
|
||||
if next < 0 || next > before_pos { next = before_pos }
|
||||
// Constrain to Local.expr → Int
|
||||
local ti = ("" + s).indexOf("\"expr\":{\"type\":\"Int\"", last_k)
|
||||
if ti < 0 || ti >= next { return null }
|
||||
local kv = ("" + s).indexOf("\"value\":", ti)
|
||||
if kv < 0 || kv >= next { return null }
|
||||
return JsonFragBox.read_int_after(s, kv + 8)
|
||||
}
|
||||
|
||||
// Find the last Local(String) before a given position (name-agnostic).
|
||||
// Returns raw string (unquoted) or null when not found.
|
||||
find_any_local_string_before(s, before_pos) {
|
||||
local pos = 0; local last_k = -1
|
||||
loop(true) {
|
||||
local k = JsonFragBox.index_of_from(s, "\"type\":\"Local\"", pos)
|
||||
if k < 0 || k >= before_pos { break }
|
||||
last_k = k
|
||||
pos = k + 1
|
||||
}
|
||||
if last_k < 0 { return null }
|
||||
local next = JsonFragBox.index_of_from(s, "\"type\":\"Local\"", last_k + 1)
|
||||
if next < 0 || next > before_pos { next = before_pos }
|
||||
// Constrain to Local.expr → String
|
||||
local ts = ("" + s).indexOf("\"expr\":{\"type\":\"String\"", last_k)
|
||||
if ts < 0 || ts >= next { return null }
|
||||
local kv = ("" + s).indexOf("\"value\":", ts)
|
||||
if kv < 0 || kv >= next { return null }
|
||||
return JsonFragBox.read_string_after(s, kv + 8)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,17 @@
|
||||
// prog_scan_box.hako — Tiny string scanner helpers for Program(JSON v0)
|
||||
|
||||
static box ProgScanBox {
|
||||
_decode_unicode_on() {
|
||||
local v = env.get("HAKO_PARSER_DECODE_UNICODE")
|
||||
if v == null { return 0 }
|
||||
if v == "1" || v == "true" || v == "on" { return 1 }
|
||||
return 0
|
||||
}
|
||||
_decode_escapes(s) {
|
||||
// Delegate to JsonFragBox decoder for consistency if available
|
||||
using selfhost.shared.json.utils.json_frag as JsonFragBox
|
||||
return JsonFragBox._decode_escapes(s)
|
||||
}
|
||||
// Find substring starting at or after pos; returns index or -1
|
||||
find(s, pat, pos) {
|
||||
local s1 = "" + s
|
||||
@ -52,7 +63,11 @@ static box ProgScanBox {
|
||||
}
|
||||
local j = i
|
||||
loop(j < n) { if s1.substring(j,j+1) == "\"" { break } j = j + 1 }
|
||||
if j <= n { return s1.substring(i, j) }
|
||||
if j <= n {
|
||||
local raw = s1.substring(i, j)
|
||||
if me._decode_unicode_on() == 1 { return me._decode_escapes(raw) }
|
||||
return raw
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
52
lang/src/mir/builder/internal/runner_min_box.hako
Normal file
52
lang/src/mir/builder/internal/runner_min_box.hako
Normal file
@ -0,0 +1,52 @@
|
||||
// runner_min_box.hako — Minimal builder runner that tries internal lowers in order
|
||||
// Purpose: Provide a lightweight path to emit MIR(JSON) from Program(JSON v0)
|
||||
// without importing the full MirBuilderBox chain (avoids parser/include flakiness).
|
||||
|
||||
using "hako.mir.builder.internal.lower_newbox_constructor" as LowerNewboxConstructorBox
|
||||
using "hako.mir.builder.internal.lower_method_array_push" as LowerMethodArrayPushBox
|
||||
using "hako.mir.builder.internal.lower_method_array_size" as LowerMethodArraySizeBox
|
||||
using "hako.mir.builder.internal.lower_method_array_get_set" as LowerMethodArrayGetSetBox
|
||||
using "hako.mir.builder.internal.lower_method_map_size" as LowerMethodMapSizeBox
|
||||
using "hako.mir.builder.internal.lower_method_map_get_set" as LowerMethodMapGetSetBox
|
||||
using "hako.mir.builder.internal.lower_load_store_local" as LowerLoadStoreLocalBox
|
||||
using "hako.mir.builder.internal.lower_typeop_check" as LowerTypeOpCheckBox
|
||||
using "hako.mir.builder.internal.lower_typeop_cast" as LowerTypeOpCastBox
|
||||
using "hako.mir.builder.internal.lower_return_int" as LowerReturnIntBox
|
||||
using "hako.mir.builder.internal.lower_return_binop" as LowerReturnBinOpBox
|
||||
|
||||
static box BuilderRunnerMinBox {
|
||||
run(program_json) {
|
||||
if program_json == null { return null }
|
||||
local s = "" + program_json
|
||||
// Optional profile: when HAKO_MIR_RUNNER_MIN_NO_METHODS=1, skip method lowers (Core exec-friendly)
|
||||
local no_methods = env.get("HAKO_MIR_RUNNER_MIN_NO_METHODS")
|
||||
local skip_methods = 0
|
||||
if no_methods != null { if ("" + no_methods) == "1" { skip_methods = 1 } }
|
||||
// Prefer method lowers before constructor to allow method cases to win
|
||||
// Prefer push over size so push canary wins
|
||||
if skip_methods == 0 {
|
||||
{ local o = LowerMethodArrayPushBox.try_lower(s); if o != null { return o } }
|
||||
{ local o = LowerMethodArraySizeBox.try_lower(s); if o != null { return o } }
|
||||
{ local o = LowerMethodArrayGetSetBox.try_lower(s); if o != null { return o } }
|
||||
// Map lowers: allow preference override via HAKO_MIR_RUNNER_MIN_PREF_MAP
|
||||
// default: size → get_set; when pref == "getset": get_set → size
|
||||
local map_pref = env.get("HAKO_MIR_RUNNER_MIN_PREF_MAP")
|
||||
if map_pref != null && ("" + map_pref) == "getset" {
|
||||
{ local o = LowerMethodMapGetSetBox.try_lower(s); if o != null { return o } }
|
||||
{ local o = LowerMethodMapSizeBox.try_lower(s); if o != null { return o } }
|
||||
} else {
|
||||
{ local o = LowerMethodMapSizeBox.try_lower(s); if o != null { return o } }
|
||||
{ local o = LowerMethodMapGetSetBox.try_lower(s); if o != null { return o } }
|
||||
}
|
||||
}
|
||||
if skip_methods == 0 {
|
||||
{ local o = LowerLoadStoreLocalBox.try_lower(s); if o != null { return o } }
|
||||
{ local o = LowerTypeOpCheckBox.try_lower(s); if o != null { return o } }
|
||||
{ local o = LowerTypeOpCastBox.try_lower(s); if o != null { return o } }
|
||||
}
|
||||
{ local o = LowerReturnBinOpBox.try_lower(s); if o != null { return o } }
|
||||
{ local o = LowerReturnIntBox.try_lower(s); if o != null { return o } }
|
||||
{ local o = LowerNewboxConstructorBox.try_lower(s); if o != null { return o } }
|
||||
return null
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,108 @@ using selfhost.shared.json.core.json_cursor as JsonCursorBox
|
||||
using selfhost.shared.common.string_helpers as StringHelpers
|
||||
|
||||
static box JsonFragBox {
|
||||
// Toggle: enable Unicode \uXXXX decode in string readers
|
||||
_decode_unicode_on() {
|
||||
local v = env.get("HAKO_PARSER_DECODE_UNICODE")
|
||||
if v == null { return 0 }
|
||||
if v == "1" || v == "true" || v == "on" { return 1 }
|
||||
return 0
|
||||
}
|
||||
|
||||
// Decode simple escapes (\\ \" \/ \b \f \n \r \t) and \uXXXX (printable ASCII only)
|
||||
_decode_escapes(s) {
|
||||
if s == null { return null }
|
||||
// Normalize common JSON double-escape: "\\uXXXX" -> "\uXXXX"
|
||||
local src0 = "" + s
|
||||
local n0 = src0.length()
|
||||
local tmp = ""
|
||||
local p = 0
|
||||
loop(p < n0) {
|
||||
local ch0 = src0.substring(p, p+1)
|
||||
if ch0 == "\\" && p + 2 <= n0 && src0.substring(p+1, p+2) == "\\" {
|
||||
if p + 3 <= n0 && src0.substring(p+2, p+3) == "u" {
|
||||
tmp = tmp + "\\u"
|
||||
p = p + 3
|
||||
continue
|
||||
}
|
||||
// generic \\ -> \
|
||||
tmp = tmp + "\\"
|
||||
p = p + 2
|
||||
continue
|
||||
}
|
||||
tmp = tmp + ch0
|
||||
p = p + 1
|
||||
}
|
||||
local s1 = tmp
|
||||
local n = s1.length()
|
||||
if n == 0 { return s1 }
|
||||
local out = ""
|
||||
local i = 0
|
||||
// Printable ASCII table for 0x20..0x7E
|
||||
local ascii = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
||||
loop(i < n) {
|
||||
local ch = s1.substring(i, i+1)
|
||||
if ch != "\\" { out = out + ch i = i + 1 continue }
|
||||
// escape
|
||||
if i + 1 >= n { out = out + "\\" i = i + 1 continue }
|
||||
local e = s1.substring(i+1, i+2)
|
||||
if e == "\\" { out = out + "\\" i = i + 2 continue }
|
||||
if e == "\"" { out = out + "\"" i = i + 2 continue }
|
||||
if e == "/" { out = out + "/" i = i + 2 continue }
|
||||
if e == "b" { out = out + "\b" i = i + 2 continue }
|
||||
if e == "f" { out = out + "\f" i = i + 2 continue }
|
||||
if e == "n" { out = out + "\n" i = i + 2 continue }
|
||||
if e == "r" { out = out + "\r" i = i + 2 continue }
|
||||
if e == "t" { out = out + "\t" i = i + 2 continue }
|
||||
if e == "u" {
|
||||
// \uXXXX (hex)
|
||||
if i + 6 <= n {
|
||||
local h = s1.substring(i+2, i+6)
|
||||
// parse hex (limited)
|
||||
local val = 0
|
||||
local k = 0
|
||||
local ok = 1
|
||||
loop(k < 4) {
|
||||
local c = h.substring(k, k+1)
|
||||
local d = -1
|
||||
if c >= "0" && c <= "9" { d = "0123456789".indexOf(c) }
|
||||
else {
|
||||
if c >= "a" && c <= "f" { d = 10 + ("abcdef".indexOf(c)) }
|
||||
else { if c >= "A" && c <= "F" { d = 10 + ("ABCDEF".indexOf(c)) } else { ok = 0 }}
|
||||
}
|
||||
if d < 0 { ok = 0 break }
|
||||
val = val * 16 + d
|
||||
k = k + 1
|
||||
}
|
||||
if ok == 1 {
|
||||
// Printable ASCII only (0x20..0x7E)
|
||||
if val >= 32 && val <= 126 {
|
||||
local pos = val - 32
|
||||
out = out + ascii.substring(pos, pos+1)
|
||||
i = i + 6
|
||||
continue
|
||||
}
|
||||
// Surrogate pair handling: collapse \uD83D\uDE00 etc. into a single placeholder
|
||||
// High surrogate range: 55296..56319
|
||||
if val >= 55296 && val <= 56319 {
|
||||
// skip following low surrogate if present
|
||||
if i + 12 <= n && s1.substring(i+6, i+8) == "\\u" { i = i + 12 } else { i = i + 6 }
|
||||
out = out + "?"
|
||||
continue
|
||||
}
|
||||
// Non-ASCII BMP → placeholder
|
||||
out = out + "?"
|
||||
i = i + 6
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fallback: keep as-is for unknown escape
|
||||
out = out + ch
|
||||
i = i + 1
|
||||
}
|
||||
return out
|
||||
}
|
||||
// 基本ヘルパ - VM fallback implementations for cross-box static calls
|
||||
index_of_from(hay, needle, pos) {
|
||||
// VM fallback: implement using substring + indexOf
|
||||
@ -62,7 +164,9 @@ static box JsonFragBox {
|
||||
local j = i
|
||||
loop(j < n) { if s.substring(j,j+1) == "\"" { break } j = j + 1 }
|
||||
if j <= i { return null }
|
||||
return s.substring(i, j)
|
||||
local raw = s.substring(i, j)
|
||||
if me._decode_unicode_on() == 1 { return me._decode_escapes(raw) }
|
||||
return raw
|
||||
}
|
||||
read_float_from(text, pos) {
|
||||
if text == null { return null }
|
||||
@ -154,7 +258,11 @@ static box JsonFragBox {
|
||||
if p >= 0 {
|
||||
local vstart = p + pat.length() // start of value (right after opening quote)
|
||||
local vend = me._scan_string_end(seg, vstart - 1)
|
||||
if vend > vstart { return seg.substring(vstart, vend) }
|
||||
if vend > vstart {
|
||||
local raw = seg.substring(vstart, vend)
|
||||
if me._decode_unicode_on() == 1 { return me._decode_escapes(raw) }
|
||||
return raw
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@ -164,6 +164,12 @@ static box NyVmDispatcherV1Box {
|
||||
}
|
||||
// Main entry: Choose internal scanner when enabled; otherwise delegate to Mini‑VM
|
||||
run(json) {
|
||||
// Typed IR primary (限定): 構造IR生成を有効化しつつ既存フローを使用(挙動不変)
|
||||
if env.get("HAKO_V1_TYPED_IR_PRIMARY") == "1" {
|
||||
// ShadowをONにして構造IR生成のオーバーヘッドを観測(必要時)
|
||||
if env.get("HAKO_V1_TYPED_IR_SHADOW") == null { env.set("HAKO_V1_TYPED_IR_SHADOW", "1") }
|
||||
return me.run_scan_flow(json)
|
||||
}
|
||||
if env.get("HAKO_V1_DISPATCHER_FLOW") == "1" { return me.run_scan_flow(json) }
|
||||
if env.get("HAKO_V1_DISPATCHER_INTERNAL") == "1" { return me.run_scan(json) }
|
||||
return MirVmMin.run_min(json)
|
||||
|
||||
37
nyash.toml
37
nyash.toml
@ -206,6 +206,16 @@ path = "lang/src/shared/common/string_helpers.hako"
|
||||
"hako.mir.builder.internal.lower_return_binop_varvar" = "lang/src/mir/builder/internal/lower_return_binop_varvar_box.hako"
|
||||
"hako.mir.builder.internal.lower_return_binop" = "lang/src/mir/builder/internal/lower_return_binop_box.hako"
|
||||
"hako.mir.builder.internal.lower_return_int" = "lang/src/mir/builder/internal/lower_return_int_box.hako"
|
||||
"hako.mir.builder.internal.lower_newbox_constructor" = "lang/src/mir/builder/internal/lower_newbox_constructor_box.hako"
|
||||
"hako.mir.builder.internal.lower_method_array_size" = "lang/src/mir/builder/internal/lower_method_array_size_box.hako"
|
||||
"hako.mir.builder.internal.lower_method_array_push" = "lang/src/mir/builder/internal/lower_method_array_push_box.hako"
|
||||
"hako.mir.builder.internal.lower_method_array_get_set" = "lang/src/mir/builder/internal/lower_method_array_get_set_box.hako"
|
||||
"hako.mir.builder.internal.lower_method_map_size" = "lang/src/mir/builder/internal/lower_method_map_size_box.hako"
|
||||
"hako.mir.builder.internal.lower_method_map_get_set" = "lang/src/mir/builder/internal/lower_method_map_get_set_box.hako"
|
||||
"hako.mir.builder.internal.lower_load_store_local" = "lang/src/mir/builder/internal/lower_load_store_local_box.hako"
|
||||
"hako.mir.builder.internal.lower_typeop_check" = "lang/src/mir/builder/internal/lower_typeop_check_box.hako"
|
||||
"hako.mir.builder.internal.lower_typeop_cast" = "lang/src/mir/builder/internal/lower_typeop_cast_box.hako"
|
||||
"hako.mir.builder.internal.runner_min" = "lang/src/mir/builder/internal/runner_min_box.hako"
|
||||
|
||||
# Missing alias for JsonFragBox (used widely in lowers)
|
||||
"selfhost.shared.json.utils.json_frag" = "lang/src/shared/json/utils/json_frag.hako"
|
||||
@ -568,3 +578,30 @@ birth = { method_id = 0 }
|
||||
get = { method_id = 1 }
|
||||
set = { method_id = 2 }
|
||||
fini = { method_id = 4294967295 }
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Builtin/Core Boxes (slot config via central tables)
|
||||
# These entries allow method_id resolution for core boxes
|
||||
# without requiring a dynamic library. Execution remains
|
||||
# handled by built-in handlers; this mapping is for MIR slot
|
||||
# injection and consistency only.
|
||||
|
||||
[box_types]
|
||||
# Assign type IDs for core boxes (reserved range)
|
||||
ArrayBox = 5
|
||||
MapBox = 6
|
||||
|
||||
[box_methods.ArrayBox.methods]
|
||||
push = { method_id = 4 }
|
||||
get = { method_id = 5 }
|
||||
set = { method_id = 6 }
|
||||
size = { method_id = 7 }
|
||||
length = { method_id = 7 }
|
||||
len = { method_id = 7 }
|
||||
|
||||
[box_methods.MapBox.methods]
|
||||
set = { method_id = 4 }
|
||||
get = { method_id = 5 }
|
||||
size = { method_id = 6 }
|
||||
length = { method_id = 6 }
|
||||
len = { method_id = 6 }
|
||||
|
||||
@ -106,7 +106,7 @@ pub(super) fn try_handle_map_box(
|
||||
if let Some(d) = dst { this.regs.insert(d, VMValue::from_nyash_box(ret)); }
|
||||
return Ok(true);
|
||||
}
|
||||
"size" => {
|
||||
"len" | "length" | "size" => {
|
||||
let ret = mb.size();
|
||||
if let Some(d) = dst { this.regs.insert(d, VMValue::from_nyash_box(ret)); }
|
||||
return Ok(true);
|
||||
|
||||
@ -524,6 +524,15 @@ pub fn ny_compiler_use_tmp_only() -> bool {
|
||||
.as_deref()
|
||||
== Some("1")
|
||||
}
|
||||
|
||||
/// Unicode decode toggle for string literals (\uXXXX, optional surrogate pairs).
|
||||
/// Enabled when either HAKO_PARSER_DECODE_UNICODE=1 or NYASH_PARSER_DECODE_UNICODE=1.
|
||||
/// Default: OFF (for strict backward compatibility).
|
||||
pub fn parser_decode_unicode() -> bool {
|
||||
env_flag("HAKO_PARSER_DECODE_UNICODE")
|
||||
.or_else(|| env_flag("NYASH_PARSER_DECODE_UNICODE"))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
fn env_flag(var: &str) -> Option<bool> {
|
||||
std::env::var(var).ok().map(|v| {
|
||||
let lv = v.to_ascii_lowercase();
|
||||
|
||||
@ -25,6 +25,7 @@ pub fn program_json_to_mir_json(program_json: &str) -> Result<String, String> {
|
||||
// Emit MIR(JSON) to a temporary file (reuse existing emitter), then read back
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
let tmp_path = tmp_dir.join("hako_mirbuilder_out.json");
|
||||
// Emit MIR JSON (v0/v1 per env) via harness-bin emitter to a temp file
|
||||
if let Err(e) = runner::mir_json_emit::emit_mir_json_for_harness_bin(&module, &tmp_path) {
|
||||
let tag = format!("[mirbuilder/emit/error] {}", e);
|
||||
eprintln!("{}", tag);
|
||||
@ -43,4 +44,3 @@ pub fn program_json_to_mir_json(program_json: &str) -> Result<String, String> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -46,11 +46,12 @@ impl super::MirBuilder {
|
||||
phi_inputs.push((else_block, else_val));
|
||||
crate::mir::builder::emission::branch::emit_jump(self, merge_block)?;
|
||||
self.start_new_block(merge_block)?;
|
||||
// フェーズM: 常にPHI命令を使用(no_phi_mode撤廃)
|
||||
self.emit_instruction(super::MirInstruction::Phi {
|
||||
dst: result_val,
|
||||
inputs: phi_inputs,
|
||||
})?;
|
||||
// フェーズM: PHI はブロック先頭に配置(cf_common 統一)
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, result_val, phi_inputs);
|
||||
} else {
|
||||
self.emit_instruction(super::MirInstruction::Phi { dst: result_val, inputs: phi_inputs })?;
|
||||
}
|
||||
return Ok(result_val);
|
||||
}
|
||||
|
||||
@ -101,11 +102,12 @@ impl super::MirBuilder {
|
||||
|
||||
// Merge and yield result
|
||||
self.start_new_block(merge_block)?;
|
||||
// フェーズM: 常にPHI命令を使用(no_phi_mode撤廃)
|
||||
self.emit_instruction(super::MirInstruction::Phi {
|
||||
dst: result_val,
|
||||
inputs: phi_inputs,
|
||||
})?;
|
||||
// フェーズM: PHI はブロック先頭に配置(cf_common 統一)
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, result_val, phi_inputs);
|
||||
} else {
|
||||
self.emit_instruction(super::MirInstruction::Phi { dst: result_val, inputs: phi_inputs })?;
|
||||
}
|
||||
Ok(result_val)
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,7 +68,11 @@ impl MirBuilder {
|
||||
for (name, &pre_v) in pre_if_var_map.iter() {
|
||||
let phi_val = self.value_gen.next();
|
||||
let inputs = vec![(pre_branch_bb, pre_v)];
|
||||
self.emit_instruction(MirInstruction::Phi { dst: phi_val, inputs })?;
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, phi_val, inputs);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::Phi { dst: phi_val, inputs })?;
|
||||
}
|
||||
self.variable_map.insert(name.clone(), phi_val);
|
||||
if trace_if {
|
||||
eprintln!(
|
||||
@ -99,7 +103,11 @@ impl MirBuilder {
|
||||
for (name, &pre_v) in pre_if_var_map.iter() {
|
||||
let phi_val = self.value_gen.next();
|
||||
let inputs = vec![(pre_branch_bb, pre_v)];
|
||||
self.emit_instruction(MirInstruction::Phi { dst: phi_val, inputs })?;
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, phi_val, inputs);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::Phi { dst: phi_val, inputs })?;
|
||||
}
|
||||
self.variable_map.insert(name.clone(), phi_val);
|
||||
if trace_if {
|
||||
eprintln!(
|
||||
@ -121,7 +129,7 @@ impl MirBuilder {
|
||||
if else_reaches_merge {
|
||||
// Scope leave for else-branch
|
||||
self.hint_scope_leave(0);
|
||||
self.emit_instruction(MirInstruction::Jump { target: merge_block })?;
|
||||
crate::mir::builder::emission::branch::emit_jump(self, merge_block)?;
|
||||
}
|
||||
// Pop else-branch debug region
|
||||
self.debug_pop_region();
|
||||
|
||||
@ -261,7 +261,11 @@ impl super::MirBuilder {
|
||||
for (name, &pre_v) in pre_if_var_map.iter() {
|
||||
let phi_val = self.value_gen.next();
|
||||
let inputs = vec![(pre_branch_bb, pre_v)];
|
||||
self.emit_instruction(MirInstruction::Phi { dst: phi_val, inputs })?;
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, phi_val, inputs);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::Phi { dst: phi_val, inputs })?;
|
||||
}
|
||||
self.variable_map.insert(name.clone(), phi_val);
|
||||
}
|
||||
|
||||
@ -290,13 +294,13 @@ impl super::MirBuilder {
|
||||
self.start_new_block(rhs_join)?;
|
||||
let rhs_bool = self.value_gen.next();
|
||||
let inputs = vec![(rhs_true_exit, t_id), (rhs_false_exit, f_id)];
|
||||
if let Some(func) = self.current_function.as_mut() {
|
||||
func.update_cfg();
|
||||
}
|
||||
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
||||
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, rhs_bool, inputs);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::Phi { dst: rhs_bool, inputs })?;
|
||||
}
|
||||
self.emit_instruction(MirInstruction::Phi { dst: rhs_bool, inputs })?;
|
||||
self.value_types.insert(rhs_bool, MirType::Bool);
|
||||
rhs_bool
|
||||
} else {
|
||||
@ -319,7 +323,11 @@ impl super::MirBuilder {
|
||||
for (name, &pre_v) in pre_if_var_map.iter() {
|
||||
let phi_val = self.value_gen.next();
|
||||
let inputs = vec![(pre_branch_bb, pre_v)];
|
||||
self.emit_instruction(MirInstruction::Phi { dst: phi_val, inputs })?;
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, phi_val, inputs);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::Phi { dst: phi_val, inputs })?;
|
||||
}
|
||||
self.variable_map.insert(name.clone(), phi_val);
|
||||
}
|
||||
// AND: else → false
|
||||
@ -349,13 +357,13 @@ impl super::MirBuilder {
|
||||
self.start_new_block(rhs_join)?;
|
||||
let rhs_bool = self.value_gen.next();
|
||||
let inputs = vec![(rhs_true_exit, t_id), (rhs_false_exit, f_id)];
|
||||
if let Some(func) = self.current_function.as_mut() {
|
||||
func.update_cfg();
|
||||
}
|
||||
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
||||
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, rhs_bool, inputs);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::Phi { dst: rhs_bool, inputs })?;
|
||||
}
|
||||
self.emit_instruction(MirInstruction::Phi { dst: rhs_bool, inputs })?;
|
||||
self.value_types.insert(rhs_bool, MirType::Bool);
|
||||
rhs_bool
|
||||
};
|
||||
@ -364,7 +372,7 @@ impl super::MirBuilder {
|
||||
let else_var_map_end = self.variable_map.clone();
|
||||
if else_reaches_merge {
|
||||
self.hint_scope_leave(0);
|
||||
self.emit_instruction(MirInstruction::Jump { target: merge_block })?;
|
||||
crate::mir::builder::emission::branch::emit_jump(self, merge_block)?;
|
||||
}
|
||||
|
||||
// ---- MERGE ----
|
||||
@ -379,11 +387,13 @@ impl super::MirBuilder {
|
||||
if else_reaches_merge { inputs.push((else_exit_block, else_value_raw)); }
|
||||
let result_val = if inputs.len() >= 2 {
|
||||
if let Some(func) = self.current_function.as_mut() { func.update_cfg(); }
|
||||
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
||||
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
||||
}
|
||||
let dst = self.value_gen.next();
|
||||
self.emit_instruction(MirInstruction::Phi { dst, inputs })?;
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, dst, inputs);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::Phi { dst, inputs })?;
|
||||
}
|
||||
self.value_types.insert(dst, MirType::Bool);
|
||||
dst
|
||||
} else if inputs.len() == 1 {
|
||||
|
||||
@ -57,7 +57,11 @@ impl MirBuilder {
|
||||
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
||||
}
|
||||
let merged = self.value_gen.next();
|
||||
self.emit_instruction(MirInstruction::Phi { dst: merged, inputs })?;
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, merged, inputs);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::Phi { dst: merged, inputs })?;
|
||||
}
|
||||
self.variable_map.insert(name, merged);
|
||||
}
|
||||
}
|
||||
@ -90,7 +94,11 @@ impl MirBuilder {
|
||||
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
||||
}
|
||||
let merged = self.value_gen.next();
|
||||
self.emit_instruction(MirInstruction::Phi { dst: merged, inputs })?;
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, merged, inputs);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::Phi { dst: merged, inputs })?;
|
||||
}
|
||||
self.variable_map.insert(pin_name.clone(), merged);
|
||||
}
|
||||
}
|
||||
@ -160,7 +168,11 @@ impl MirBuilder {
|
||||
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
||||
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
||||
}
|
||||
self.emit_instruction(MirInstruction::Phi { dst: result_val, inputs })?;
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, result_val, inputs);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::Phi { dst: result_val, inputs })?;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.variable_map = pre_if_var_map.clone();
|
||||
@ -183,7 +195,11 @@ impl MirBuilder {
|
||||
if let (Some(func), Some(cur_bb)) = (&self.current_function, self.current_block) {
|
||||
crate::mir::phi_core::common::debug_verify_phi_inputs(func, cur_bb, &inputs);
|
||||
}
|
||||
self.emit_instruction(MirInstruction::Phi { dst: result_val, inputs })?;
|
||||
if let (Some(func), Some(cur_bb)) = (self.current_function.as_mut(), self.current_block) {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(func, cur_bb, result_val, inputs);
|
||||
} else {
|
||||
self.emit_instruction(MirInstruction::Phi { dst: result_val, inputs })?;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Merge variable map conservatively to pre-if snapshot (no new bindings)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use crate::mir::{
|
||||
function::{FunctionSignature, MirFunction, MirModule},
|
||||
BasicBlock, BasicBlockId, ConstValue, MirInstruction, MirType, ValueId,
|
||||
BasicBlock, BasicBlockId, ConstValue, EffectMask, MirInstruction, MirType, ValueId,
|
||||
};
|
||||
use serde_json::Value;
|
||||
use super::mir_json::common as mirjson_common;
|
||||
@ -132,6 +132,39 @@ pub fn parse_mir_v0_to_module(json: &str) -> Result<MirModule, String> {
|
||||
block_ref.add_instruction(MirInstruction::Return { value });
|
||||
if let Some(val) = value { signature.return_type = MirType::Integer; max_value_id = max_value_id.max(val.as_u32() + 1); } else { signature.return_type = MirType::Void; }
|
||||
}
|
||||
"newbox" => {
|
||||
let dst = require_u64(inst, "dst", "newbox dst")? as u32;
|
||||
let ty = inst.get("type").and_then(Value::as_str).ok_or_else(|| "newbox missing type".to_string())?.to_string();
|
||||
let args_v = inst.get("args").and_then(Value::as_array).cloned().unwrap_or_default();
|
||||
let mut args: Vec<ValueId> = Vec::with_capacity(args_v.len());
|
||||
for a in args_v {
|
||||
let id = a.as_u64().ok_or_else(|| "newbox arg must be integer".to_string())? as u32;
|
||||
args.push(ValueId::new(id));
|
||||
}
|
||||
block_ref.add_instruction(MirInstruction::NewBox { dst: ValueId::new(dst), box_type: ty, args });
|
||||
max_value_id = max_value_id.max(dst + 1);
|
||||
}
|
||||
"boxcall" => {
|
||||
// { op:"boxcall", box:<vid>, method:"name", args:[vid...], dst?:<vid> }
|
||||
let box_id = require_u64(inst, "box", "boxcall box")? as u32;
|
||||
let method = inst.get("method").and_then(Value::as_str).ok_or_else(|| "boxcall missing method".to_string())?.to_string();
|
||||
let dst_opt = inst.get("dst").and_then(Value::as_u64).map(|v| ValueId::new(v as u32));
|
||||
let args_v = inst.get("args").and_then(Value::as_array).cloned().unwrap_or_default();
|
||||
let mut args: Vec<ValueId> = Vec::with_capacity(args_v.len());
|
||||
for a in args_v {
|
||||
let id = a.as_u64().ok_or_else(|| "boxcall arg must be integer".to_string())? as u32;
|
||||
args.push(ValueId::new(id));
|
||||
}
|
||||
block_ref.add_instruction(MirInstruction::BoxCall {
|
||||
dst: dst_opt,
|
||||
box_val: ValueId::new(box_id),
|
||||
method,
|
||||
method_id: None,
|
||||
args,
|
||||
effects: EffectMask::READ,
|
||||
});
|
||||
if let Some(dv) = dst_opt { max_value_id = max_value_id.max(dv.as_u32() + 1); }
|
||||
}
|
||||
other => {
|
||||
return Err(format!("unsupported op '{}' in mir_json_v0 loader", other));
|
||||
}
|
||||
|
||||
48
src/runner/modes/common_util/hako.rs
Normal file
48
src/runner/modes/common_util/hako.rs
Normal file
@ -0,0 +1,48 @@
|
||||
/*!
|
||||
* Hako-like source detection and minimal normalization helpers.
|
||||
*
|
||||
* - looks_like_hako_code: heuristics to detect Hako surface in Nyash path
|
||||
* - strip_local_decl: drop leading `local ` at line head for Nyash parser compatibility
|
||||
* - fail_fast_on_hako: env-gated policy (default ON) to fail fast on Hako-like source in Nyash VM path
|
||||
*/
|
||||
|
||||
/// Heuristic detection of Hako-like source (development-only convenience)
|
||||
pub fn looks_like_hako_code(s: &str) -> bool {
|
||||
s.contains("using selfhost.")
|
||||
|| s.contains("using hakorune.")
|
||||
|| s.lines().any(|l| l.trim_start().starts_with("local "))
|
||||
}
|
||||
|
||||
/// Remove leading `local ` declarations at line head to keep Nyash parser stable
|
||||
pub fn strip_local_decl(s: &str) -> String {
|
||||
let mut out = String::with_capacity(s.len());
|
||||
for line in s.lines() {
|
||||
let leading = line.len() - line.trim_start().len();
|
||||
let (indent, rest) = line.split_at(leading);
|
||||
if rest.starts_with("local ") || rest.starts_with("local\t") {
|
||||
let bytes = rest.as_bytes();
|
||||
let mut i = 5; // after 'local'
|
||||
while i < bytes.len() && (bytes[i] == b' ' || bytes[i] == b'\t') {
|
||||
i += 1;
|
||||
break;
|
||||
}
|
||||
out.push_str(indent);
|
||||
out.push_str(&rest[i..]);
|
||||
out.push('\n');
|
||||
} else {
|
||||
out.push_str(line);
|
||||
out.push('\n');
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/// Policy toggle: fail fast when Hako-like code enters Nyash VM path
|
||||
/// Default: ON (true)
|
||||
pub fn fail_fast_on_hako() -> bool {
|
||||
match std::env::var("HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM").ok().as_deref() {
|
||||
Some("0") | Some("false") | Some("off") => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,3 +11,4 @@ pub mod selfhost;
|
||||
pub mod resolve;
|
||||
pub mod exec;
|
||||
pub mod core_bridge;
|
||||
pub mod hako;
|
||||
|
||||
@ -359,11 +359,12 @@ pub fn resolve_prelude_paths_profiled(
|
||||
) -> Result<(String, Vec<String>), String> {
|
||||
// First pass: strip using from the main source and collect direct prelude paths
|
||||
let (cleaned, direct) = collect_using_and_strip(runner, code, filename)?;
|
||||
// When AST using is enabled、recursively collect nested preludes in DFS order
|
||||
// Recursively collect nested preludes (DFS) for both AST/text merges.
|
||||
// Rationale: even when we merge via text, nested `using` inside preludes
|
||||
// must be discovered so that their definitions are present at runtime
|
||||
// (e.g., runner_min -> lower_* boxes). Previously this only ran when
|
||||
// NYASH_USING_AST=1, which caused unresolved calls in inline flows.
|
||||
let ast_on = std::env::var("NYASH_USING_AST").ok().as_deref() == Some("1");
|
||||
if !ast_on {
|
||||
return Ok((cleaned, direct));
|
||||
}
|
||||
let mut out: Vec<String> = Vec::new();
|
||||
let mut seen: std::collections::HashSet<String> = std::collections::HashSet::new();
|
||||
fn normalize_path(path: &str) -> (String, String) {
|
||||
@ -451,6 +452,9 @@ pub fn resolve_prelude_paths_profiled(
|
||||
}
|
||||
}
|
||||
}
|
||||
// If AST merge is disabled, still return the discovered nested prelude list
|
||||
// so that the text merger can inline all dependencies. This keeps behavior
|
||||
// consistent across strategies and fixes nested `using` resolution.
|
||||
Ok((cleaned, out))
|
||||
}
|
||||
|
||||
@ -659,6 +663,40 @@ pub fn merge_prelude_text(
|
||||
|
||||
// First pass: collect and resolve prelude paths
|
||||
let (cleaned_main, prelude_paths) = resolve_prelude_paths_profiled(runner, source, filename)?;
|
||||
// Expand nested preludes for text-merge too (DFS) so that any `using`
|
||||
// inside prelude files (e.g., runner_min -> lower_* boxes) are also
|
||||
// included even when NYASH_USING_AST is OFF.
|
||||
let mut expanded: Vec<String> = Vec::new();
|
||||
let mut seen: std::collections::HashSet<String> = std::collections::HashSet::new();
|
||||
fn canonize(p: &str) -> String {
|
||||
std::fs::canonicalize(p)
|
||||
.ok()
|
||||
.map(|pb| pb.to_string_lossy().to_string())
|
||||
.unwrap_or_else(|| p.to_string())
|
||||
}
|
||||
fn dfs_text(
|
||||
runner: &NyashRunner,
|
||||
path: &str,
|
||||
out: &mut Vec<String>,
|
||||
seen: &mut std::collections::HashSet<String>,
|
||||
) -> Result<(), String> {
|
||||
let key = canonize(path);
|
||||
if !seen.insert(key.clone()) {
|
||||
return Ok(());
|
||||
}
|
||||
let src = std::fs::read_to_string(path)
|
||||
.map_err(|e| format!("using: failed to read '{}': {}", path, e))?;
|
||||
let (_cleaned, nested) = collect_using_and_strip(runner, &src, path)?;
|
||||
for n in nested.iter() {
|
||||
dfs_text(runner, n, out, seen)?;
|
||||
}
|
||||
out.push(key);
|
||||
Ok(())
|
||||
}
|
||||
for p in prelude_paths.iter() {
|
||||
dfs_text(runner, p, &mut expanded, &mut seen)?;
|
||||
}
|
||||
let prelude_paths = &expanded;
|
||||
|
||||
if prelude_paths.is_empty() {
|
||||
// No using statements, return original
|
||||
|
||||
@ -138,38 +138,16 @@ impl NyashRunner {
|
||||
|
||||
// Hako-friendly normalize: strip leading `local ` at line head for parser compatibility.
|
||||
// This keeps semantics close enough for our inline/selfhost drivers while we unify frontends.
|
||||
fn looks_like_hako_code(s: &str) -> bool {
|
||||
s.contains("using selfhost.") || s.lines().any(|l| l.trim_start().starts_with("local "))
|
||||
}
|
||||
fn strip_local_decl(s: &str) -> String {
|
||||
let mut out = String::with_capacity(s.len());
|
||||
for line in s.lines() {
|
||||
let leading = line.len() - line.trim_start().len();
|
||||
let (indent, rest) = line.split_at(leading);
|
||||
if rest.starts_with("local ") || rest.starts_with("local\t") {
|
||||
// drop the first token `local` and a single following space/tab
|
||||
let mut bytes = rest.as_bytes();
|
||||
let mut i = 5; // after 'local'
|
||||
while i < bytes.len() && (bytes[i] == b' ' || bytes[i] == b'\t') { i += 1; break; }
|
||||
out.push_str(indent);
|
||||
out.push_str(&rest[i..]);
|
||||
out.push('\n');
|
||||
} else {
|
||||
out.push_str(line);
|
||||
out.push('\n');
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
if looks_like_hako_code(&preexpanded_owned) {
|
||||
preexpanded_owned = strip_local_decl(&preexpanded_owned);
|
||||
if crate::runner::modes::common_util::hako::looks_like_hako_code(&preexpanded_owned) {
|
||||
preexpanded_owned = crate::runner::modes::common_util::hako::strip_local_decl(&preexpanded_owned);
|
||||
}
|
||||
// Routing (Hako-like): 既定は Fail‑Fast(hv1 直行は関数冒頭で処理済み)。
|
||||
{
|
||||
let s = preexpanded_owned.as_str();
|
||||
let hako_like = s.contains("static box ") || s.contains("using selfhost.") || s.contains("using hakorune.");
|
||||
let ff_env = std::env::var("HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM").ok();
|
||||
let fail_fast = match ff_env.as_deref() { Some("0")|Some("false")|Some("off") => false, _ => true };
|
||||
let hako_like = s.contains("static box ")
|
||||
|| s.contains("using selfhost.")
|
||||
|| s.contains("using hakorune.");
|
||||
let fail_fast = crate::runner::modes::common_util::hako::fail_fast_on_hako();
|
||||
if hako_like && fail_fast {
|
||||
eprintln!(
|
||||
"❌ Hako-like source detected in Nyash VM path. Use Hakorune VM (v1 dispatcher) or Core/LLVM for MIR.\n hint: verify with HAKO_VERIFY_PRIMARY=hakovm"
|
||||
|
||||
@ -57,39 +57,14 @@ impl NyashRunner {
|
||||
// Dev sugar pre-expand: @name = expr → local name = expr
|
||||
code2 = crate::runner::modes::common_util::resolve::preexpand_at_local(&code2);
|
||||
// Hako-friendly normalize: strip leading `local ` at line head for Nyash parser compatibility.
|
||||
fn looks_like_hako_code(s: &str) -> bool {
|
||||
s.contains("using selfhost.") || s.lines().any(|l| l.trim_start().starts_with("local "))
|
||||
}
|
||||
fn strip_local_decl(s: &str) -> String {
|
||||
let mut out = String::with_capacity(s.len());
|
||||
for line in s.lines() {
|
||||
let leading = line.len() - line.trim_start().len();
|
||||
let (indent, rest) = line.split_at(leading);
|
||||
if rest.starts_with("local ") || rest.starts_with("local\t") {
|
||||
let bytes = rest.as_bytes();
|
||||
let mut i = 5; // skip 'local'
|
||||
while i < bytes.len() && (bytes[i] == b' ' || bytes[i] == b'\t') { i += 1; break; }
|
||||
out.push_str(indent);
|
||||
out.push_str(&rest[i..]);
|
||||
out.push('\n');
|
||||
} else {
|
||||
out.push_str(line);
|
||||
out.push('\n');
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
if looks_like_hako_code(&code2) {
|
||||
code2 = strip_local_decl(&code2);
|
||||
if crate::runner::modes::common_util::hako::looks_like_hako_code(&code2) {
|
||||
code2 = crate::runner::modes::common_util::hako::strip_local_decl(&code2);
|
||||
}
|
||||
|
||||
// Fail‑Fast (opt‑in): Hako 構文を Nyash VM 経路で実行しない
|
||||
// 目的: .hako は Hakorune VM、MIR は Core/LLVM に役割分離するためのガード
|
||||
{
|
||||
let on = match std::env::var("HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM").ok().as_deref() {
|
||||
Some("0")|Some("false")|Some("off") => false,
|
||||
_ => true,
|
||||
};
|
||||
let on = crate::runner::modes::common_util::hako::fail_fast_on_hako();
|
||||
if on {
|
||||
let s = code2.as_str();
|
||||
let hako_like = s.contains("static box ") || s.contains("using selfhost.") || s.contains("using hakorune.");
|
||||
|
||||
@ -126,32 +126,75 @@ impl PluginHost {
|
||||
/// Resolve a method handle for a given plugin box type and method name.
|
||||
pub fn resolve_method(&self, box_type: &str, method_name: &str) -> BidResult<MethodHandle> {
|
||||
let cfg = self.config.as_ref().ok_or(BidError::PluginError)?;
|
||||
let (lib_name, _lib_def) = cfg
|
||||
.find_library_for_box(box_type)
|
||||
.ok_or(BidError::InvalidType)?;
|
||||
let cfg_path = self.config_path.as_deref().unwrap_or("nyash.toml");
|
||||
let toml_content = std::fs::read_to_string(cfg_path).map_err(|_| BidError::PluginError)?;
|
||||
let toml_value: toml::Value =
|
||||
toml::from_str(&toml_content).map_err(|_| BidError::PluginError)?;
|
||||
let box_conf = cfg
|
||||
.get_box_config(lib_name, box_type, &toml_value)
|
||||
.ok_or(BidError::InvalidType)?;
|
||||
// Prefer config mapping; fallback to loader's TypeBox resolve(name)
|
||||
let (method_id, returns_result) = if let Some(m) = box_conf.methods.get(method_name) {
|
||||
(m.method_id, m.returns_result)
|
||||
} else {
|
||||
let l = self.loader.read().unwrap();
|
||||
let mid = l
|
||||
.resolve_method_id(box_type, method_name)
|
||||
.map_err(|_| BidError::InvalidMethod)?;
|
||||
(mid, false)
|
||||
};
|
||||
|
||||
// Path A: library-backed box (dynamic plugin)
|
||||
if let Some((lib_name, _lib_def)) = cfg.find_library_for_box(box_type) {
|
||||
if let Some(box_conf) = cfg.get_box_config(lib_name, box_type, &toml_value) {
|
||||
// Prefer config mapping; fallback to loader's TypeBox resolve(name)
|
||||
let (method_id, returns_result) = if let Some(m) = box_conf.methods.get(method_name) {
|
||||
(m.method_id, m.returns_result)
|
||||
} else {
|
||||
let l = self.loader.read().unwrap();
|
||||
let mid = l
|
||||
.resolve_method_id(box_type, method_name)
|
||||
.map_err(|_| BidError::InvalidMethod)?;
|
||||
(mid, false)
|
||||
};
|
||||
return Ok(MethodHandle {
|
||||
lib: lib_name.to_string(),
|
||||
box_type: box_type.to_string(),
|
||||
type_id: box_conf.type_id,
|
||||
method_id,
|
||||
returns_result,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Path B: builtin/core boxes via central config (no library/path required)
|
||||
// Require: [box_types] BoxName = <id> and [box_methods.BoxName.methods] entries
|
||||
if let Some(type_id) = cfg.box_types.get(box_type).copied() {
|
||||
if let Some(bm) = toml_value
|
||||
.get("box_methods")
|
||||
.and_then(|v| v.get(box_type))
|
||||
.and_then(|v| v.get("methods"))
|
||||
.and_then(|v| v.as_table())
|
||||
{
|
||||
if let Some(entry) = bm.get(method_name) {
|
||||
// Support both { method_id = N } and bare integer in the future
|
||||
let (method_id, returns_result) = if let Some(mid) = entry.get("method_id") {
|
||||
(mid.as_integer().unwrap_or(0) as u32, entry.get("returns_result").and_then(|b| b.as_bool()).unwrap_or(false))
|
||||
} else if let Some(mid) = entry.as_integer() {
|
||||
(mid as u32, false)
|
||||
} else {
|
||||
return Err(BidError::InvalidMethod);
|
||||
};
|
||||
return Ok(MethodHandle {
|
||||
lib: "builtin".to_string(),
|
||||
box_type: box_type.to_string(),
|
||||
type_id,
|
||||
method_id,
|
||||
returns_result,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: delegate to loader (TypeBox, file-based, etc.)
|
||||
let l = self.loader.read().unwrap();
|
||||
let mid = l
|
||||
.resolve_method_id(box_type, method_name)
|
||||
.map_err(|_| BidError::InvalidMethod)?;
|
||||
let type_id = *cfg.box_types.get(box_type).unwrap_or(&0);
|
||||
Ok(MethodHandle {
|
||||
lib: lib_name.to_string(),
|
||||
lib: "builtin".to_string(),
|
||||
box_type: box_type.to_string(),
|
||||
type_id: box_conf.type_id,
|
||||
method_id,
|
||||
returns_result,
|
||||
type_id,
|
||||
method_id: mid,
|
||||
returns_result: false,
|
||||
})
|
||||
}
|
||||
|
||||
@ -192,6 +235,36 @@ impl PluginHost {
|
||||
|
||||
/// Check if a method returns Result (Ok/Err) per plugin spec or central config.
|
||||
pub fn method_returns_result(&self, box_type: &str, method_name: &str) -> bool {
|
||||
// Prefer central config when available (works for builtin boxes)
|
||||
if let Some(cfg) = self.config.as_ref() {
|
||||
if let Some(path) = self.config_path.as_deref() {
|
||||
if let Ok(toml_content) = std::fs::read_to_string(path) {
|
||||
if let Ok(toml_value) = toml::from_str::<toml::Value>(&toml_content) {
|
||||
if let Some(bm) = toml_value
|
||||
.get("box_methods")
|
||||
.and_then(|v| v.get(box_type))
|
||||
.and_then(|v| v.get("methods"))
|
||||
.and_then(|v| v.as_table())
|
||||
{
|
||||
if let Some(entry) = bm.get(method_name) {
|
||||
return entry
|
||||
.get("returns_result")
|
||||
.and_then(|b| b.as_bool())
|
||||
.unwrap_or(false);
|
||||
}
|
||||
}
|
||||
// Library-backed path
|
||||
if let Some((lib_name, _)) = cfg.find_library_for_box(box_type) {
|
||||
if let Some(box_conf) = cfg.get_box_config(lib_name, box_type, &toml_value) {
|
||||
if let Some(m) = box_conf.methods.get(method_name) {
|
||||
return m.returns_result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let l = self.loader.read().unwrap();
|
||||
l.method_returns_result(box_type, method_name)
|
||||
}
|
||||
|
||||
33
src/tests/tokenizer_unicode_toggle.rs
Normal file
33
src/tests/tokenizer_unicode_toggle.rs
Normal file
@ -0,0 +1,33 @@
|
||||
use crate::tokenizer::{NyashTokenizer, TokenType};
|
||||
|
||||
fn collect_string_token(src: &str) -> String {
|
||||
let mut t = NyashTokenizer::new(src);
|
||||
let tokens = t.tokenize().expect("tokenize");
|
||||
// Expect first non-EOF token to be STRING
|
||||
for tok in tokens {
|
||||
if let TokenType::STRING(s) = tok.token_type { return s; }
|
||||
}
|
||||
panic!("no STRING token found");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unicode_decode_toggle_off_keeps_literal() {
|
||||
// OFF by default
|
||||
std::env::remove_var("NYASH_PARSER_DECODE_UNICODE");
|
||||
std::env::remove_var("HAKO_PARSER_DECODE_UNICODE");
|
||||
let s = collect_string_token("\"\\u0041\"");
|
||||
assert_eq!(s, "\\u0041");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unicode_decode_toggle_on_decodes_basic_and_surrogate() {
|
||||
// ON: enable decode
|
||||
std::env::set_var("NYASH_PARSER_DECODE_UNICODE", "1");
|
||||
let s = collect_string_token("\"\\u0041\"");
|
||||
assert_eq!(s, "A");
|
||||
|
||||
let s2 = collect_string_token("\"\\uD83D\\uDE00\"");
|
||||
// Expect surrogate pair to decode into one char (😀)
|
||||
assert_eq!(s2.chars().count(), 1);
|
||||
}
|
||||
|
||||
@ -28,6 +28,66 @@ impl NyashTokenizer {
|
||||
Some('"') => string_value.push('"'),
|
||||
Some('\'') => string_value.push('\''), // 1-quote: エスケープされたシングルクォート
|
||||
Some('/') => string_value.push('/'), // \/ を許容
|
||||
Some('u') => {
|
||||
// Unicode decode (optional; default OFF)
|
||||
if crate::config::env::parser_decode_unicode() {
|
||||
let base = self.position; // index of 'u'
|
||||
// read 4 hex digits without consuming; then advance position in bulk
|
||||
let read_hex4 = |input: &Vec<char>, start: usize| -> Option<u32> {
|
||||
if start + 4 > input.len() { return None; }
|
||||
let d0 = input.get(start)?.to_digit(16)?;
|
||||
let d1 = input.get(start + 1)?.to_digit(16)?;
|
||||
let d2 = input.get(start + 2)?.to_digit(16)?;
|
||||
let d3 = input.get(start + 3)?.to_digit(16)?;
|
||||
Some((d0 << 12) | (d1 << 8) | (d2 << 4) | d3)
|
||||
};
|
||||
let first_start = base + 1; // after 'u'
|
||||
if let Some(u1) = read_hex4(&self.input, first_start) {
|
||||
// consume 'u' + 4 hex
|
||||
self.position = base + 5;
|
||||
let mut out_char: Option<char> = None;
|
||||
// surrogate pair
|
||||
if (0xD800..=0xDBFF).contains(&u1) {
|
||||
if self.position + 6 <= self.input.len()
|
||||
&& self.input.get(self.position) == Some(&'\\')
|
||||
&& self.input.get(self.position + 1) == Some(&'u')
|
||||
{
|
||||
if let Some(u2) = read_hex4(&self.input, self.position + 2) {
|
||||
if (0xDC00..=0xDFFF).contains(&u2) {
|
||||
let high_ten = (u1 - 0xD800) as u32;
|
||||
let low_ten = (u2 - 0xDC00) as u32;
|
||||
let scalar = 0x10000 + ((high_ten << 10) | low_ten);
|
||||
out_char = std::char::from_u32(scalar);
|
||||
// consume '\\u' + 4 hex of low surrogate
|
||||
self.position += 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if out_char.is_none() {
|
||||
out_char = std::char::from_u32(u1 as u32);
|
||||
}
|
||||
if let Some(ch) = out_char {
|
||||
string_value.push(ch);
|
||||
// Skip the generic advance at loop end to avoid double step
|
||||
continue;
|
||||
} else {
|
||||
// Fallback to literal when invalid
|
||||
string_value.push('\\');
|
||||
string_value.push('u');
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Not enough hex digits; keep literal
|
||||
string_value.push('\\');
|
||||
string_value.push('u');
|
||||
}
|
||||
} else {
|
||||
// Decoding disabled → keep literal
|
||||
string_value.push('\\');
|
||||
string_value.push('u');
|
||||
}
|
||||
}
|
||||
// TODO: 将来 `\uXXXX` デコード(既定OFF)
|
||||
Some(c2) => {
|
||||
// 未知のエスケープはそのまま残す(互換性維持)
|
||||
|
||||
@ -2,11 +2,14 @@
|
||||
# Nyash dev environment convenience script
|
||||
# Usage: source tools/dev_env.sh [profile]
|
||||
# Profiles:
|
||||
# pyvm - Favor PyVM for VM and Bridge
|
||||
# bridge - Bridge-only helpers (keep interpreter)
|
||||
# phi_off - PHI-less MIR (edge-copy) + verifier relax; harness on
|
||||
# opbox - Enable Operator Boxes (Stringify/Compare/Add) with adopt; AST using ON
|
||||
# reset - Unset variables set by this script
|
||||
# pyvm - Favor PyVM for VM and Bridge
|
||||
# bridge - Bridge-only helpers (keep interpreter)
|
||||
# phi_off - PHI-less MIR (edge-copy) + verifier relax; harness on
|
||||
# opbox - Enable Operator Boxes (Stringify/Compare/Add) with adopt; AST using ON
|
||||
# hako-only - Buildless Hako dev (alias using, hv1 direct verify)
|
||||
# hybrid - Hako + Rust VM 両用(verifyはhakorune優先)
|
||||
# prod - Prod-like (path using error; minimal trace)
|
||||
# reset - Unset variables set by this script
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
@ -69,11 +72,58 @@ activate_opbox() {
|
||||
echo "[dev-env] Operator Boxes (stringify/compare/add) enabled (adopt+builder-call)" >&2
|
||||
}
|
||||
|
||||
# Buildless Hako-only profile
|
||||
activate_hako_only() {
|
||||
# Using/alias
|
||||
export NYASH_ENABLE_USING=1
|
||||
export NYASH_USING_AST=1
|
||||
export NYASH_ALLOW_USING_FILE=1
|
||||
# Resolver (optional helpers kept quiet by default)
|
||||
: "${NYASH_RESOLVE_TRACE:=0}"
|
||||
: "${NYASH_RESOLVE_NORMALIZE:=0}"
|
||||
# hv1 direct verify primary
|
||||
export HAKO_V1_DISPATCHER_FLOW=1
|
||||
export HAKO_VERIFY_PRIMARY=hakovm
|
||||
echo "[dev-env] Hako-only profile activated (buildless; hv1 direct verify)" >&2
|
||||
}
|
||||
|
||||
# Hybrid: Hako + Rust VM(verifyはhakovm直行)
|
||||
activate_hybrid() {
|
||||
export NYASH_ENABLE_USING=1
|
||||
export NYASH_USING_AST=1
|
||||
export NYASH_ALLOW_USING_FILE=1
|
||||
: "${NYASH_RESOLVE_TRACE:=0}"
|
||||
: "${NYASH_RESOLVE_NORMALIZE:=0}"
|
||||
export HAKO_V1_DISPATCHER_FLOW=1
|
||||
export HAKO_VERIFY_PRIMARY=hakovm
|
||||
# Rust VM 側は特別扱い不要(通常通り)
|
||||
echo "[dev-env] Hybrid profile activated (Hako + Rust VM; hv1 verify)" >&2
|
||||
}
|
||||
|
||||
# Prod-like: Path using を ERROR にし、最小トレース
|
||||
activate_prod() {
|
||||
# Disallow AST prelude merge and file using
|
||||
export NYASH_USING_AST=0
|
||||
export NYASH_ALLOW_USING_FILE=0
|
||||
# Keep using gate explicit; alias resolution allowed via resolver (no AST merge)
|
||||
: "${NYASH_ENABLE_USING:=1}"
|
||||
# Quiet resolver by default
|
||||
export NYASH_RESOLVE_TRACE=0
|
||||
export NYASH_RESOLVE_NORMALIZE=0
|
||||
# Do not force hv1 verify primary here
|
||||
unset HAKO_VERIFY_PRIMARY || true
|
||||
unset HAKO_ROUTE_HAKOVM || true
|
||||
echo "[dev-env] Prod profile activated (path using ERROR; quiet)" >&2
|
||||
}
|
||||
|
||||
case "${1:-pyvm}" in
|
||||
pyvm) activate_pyvm ;;
|
||||
bridge) activate_bridge ;;
|
||||
phi_off) activate_phi_off ;;
|
||||
opbox) activate_opbox ;;
|
||||
hako-only) activate_hako_only ;;
|
||||
hybrid) activate_hybrid ;;
|
||||
prod) activate_prod ;;
|
||||
reset) reset_env ;;
|
||||
*) echo "usage: source tools/dev_env.sh [pyvm|bridge|phi_off|opbox|reset]" >&2 ;;
|
||||
*) echo "usage: source tools/dev_env.sh [pyvm|bridge|phi_off|opbox|hako-only|hybrid|prod|reset]" >&2 ;;
|
||||
esac
|
||||
|
||||
@ -368,17 +368,19 @@ HCODE
|
||||
verify_program_via_builder_to_core() {
|
||||
local prog_json_path="$1"
|
||||
|
||||
# Step 1: Use MirBuilderBox to convert Program → MIR(env経由でJSONを渡す)
|
||||
# Step 1: Use minimal runner to convert Program → MIR(env経由でJSONを渡す)
|
||||
local mir_json_path="/tmp/builder_output_$$.json"
|
||||
|
||||
local builder_code=$(cat <<'HCODE'
|
||||
using "hako.mir.builder" as MirBuilderBox
|
||||
local builder_code_min=$(cat <<'HCODE'
|
||||
using "hako.mir.builder.internal.runner_min" as BuilderRunnerMinBox
|
||||
static box Main { method main(args) {
|
||||
local prog_json = env.get("NYASH_VERIFY_JSON")
|
||||
local prog_json = env.get("HAKO_BUILDER_PROGRAM_JSON")
|
||||
if prog_json == null { print("Builder failed"); return 1 }
|
||||
local mir_out = MirBuilderBox.emit_from_program_json_v0(prog_json, null)
|
||||
local mir_out = BuilderRunnerMinBox.run(prog_json)
|
||||
if mir_out == null { print("Builder failed"); return 1 }
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + mir_out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
HCODE
|
||||
@ -389,21 +391,70 @@ HCODE
|
||||
prog_json_raw="$(cat "$prog_json_path")"
|
||||
|
||||
# Run builder with internal lowers enabled using v1 dispatcher
|
||||
local mir_json
|
||||
local mir_json=""
|
||||
local builder_stderr="/tmp/builder_stderr_$$.log"
|
||||
mir_json=$(HAKO_MIR_BUILDER_INTERNAL=1 \
|
||||
local builder_stdout="/tmp/builder_stdout_$$.log"
|
||||
# Try minimal runner first (fast path), unless HAKO_PREFER_MIRBUILDER=1
|
||||
if [ "${HAKO_PREFER_MIRBUILDER:-0}" = "1" ]; then
|
||||
: # skip minimal runner
|
||||
else
|
||||
mir_json=$(HAKO_MIR_BUILDER_INTERNAL=1 \
|
||||
HAKO_MIR_RUNNER_MIN_NO_METHODS=1 \
|
||||
HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 \
|
||||
HAKO_ROUTE_HAKOVM=1 \
|
||||
NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 \
|
||||
NYASH_USING_AST=1 \
|
||||
NYASH_RESOLVE_FIX_BRACES=1 \
|
||||
NYASH_DISABLE_NY_COMPILER=1 \
|
||||
NYASH_PARSER_STAGE3=1 \
|
||||
HAKO_PARSER_STAGE3=1 \
|
||||
NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN=1 \
|
||||
NYASH_VERIFY_JSON="$prog_json_raw" \
|
||||
run_nyash_vm -c "$builder_code" 2>"$builder_stderr" | tail -n 1)
|
||||
HAKO_BUILDER_PROGRAM_JSON="$prog_json_raw" \
|
||||
run_nyash_vm -c "$builder_code_min" 2>"$builder_stderr" | tee "$builder_stdout" | awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag')
|
||||
fi
|
||||
|
||||
# Fallback Option A: use Rust CLI builder when Hako builder fails
|
||||
if [ "${HAKO_MIR_BUILDER_DEBUG:-0}" = "1" ]; then
|
||||
echo "[builder debug] stdout (tail):" >&2
|
||||
tail -n 60 "$builder_stdout" >&2 || true
|
||||
echo "[builder debug] stderr (tail):" >&2
|
||||
tail -n 60 "$builder_stderr" >&2 || true
|
||||
fi
|
||||
|
||||
# Fallback Option A: try full MirBuilderBox (emit) when minimal runner fails
|
||||
if [ "$mir_json" = "Builder failed" ] || [ -z "$mir_json" ]; then
|
||||
local builder_code_full=$(cat <<'HCODE'
|
||||
using "hako.mir.builder" as MirBuilderBox
|
||||
static box Main { method main(args) {
|
||||
local prog_json = env.get("HAKO_BUILDER_PROGRAM_JSON")
|
||||
if prog_json == null { print("Builder failed"); return 1 }
|
||||
local mir_out = MirBuilderBox.emit_from_program_json_v0(prog_json, null)
|
||||
if mir_out == null { print("Builder failed"); return 1 }
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + mir_out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
HCODE
|
||||
)
|
||||
mir_json=$(HAKO_MIR_BUILDER_INTERNAL=1 \
|
||||
HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 \
|
||||
HAKO_ROUTE_HAKOVM=1 \
|
||||
NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 \
|
||||
NYASH_USING_AST=1 NYASH_RESOLVE_FIX_BRACES=1 \
|
||||
NYASH_DISABLE_NY_COMPILER=1 NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 \
|
||||
NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN=1 \
|
||||
HAKO_BUILDER_PROGRAM_JSON="$prog_json_raw" \
|
||||
run_nyash_vm -c "$builder_code_full" 2>>"$builder_stderr" | tee -a "$builder_stdout" | awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag')
|
||||
fi
|
||||
|
||||
# PRIMARY no-fallback: if requested, do not fall back to Rust CLI builder
|
||||
if [ "${HAKO_PRIMARY_NO_FALLBACK:-0}" = "1" ]; then
|
||||
if [ "$mir_json" = "Builder failed" ] || [ -z "$mir_json" ]; then
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Fallback Option B: use Rust CLI builder when Hako builder fails
|
||||
if [ "$mir_json" = "Builder failed" ] || [ -z "$mir_json" ]; then
|
||||
if [ "${HAKO_MIR_BUILDER_DEBUG:-0}" = "1" ] && [ -f "$builder_stderr" ]; then
|
||||
echo "[builder debug] Hako builder failed, falling back to Rust CLI" >&2
|
||||
@ -413,18 +464,30 @@ HCODE
|
||||
rm -f "$builder_stderr"
|
||||
local tmp_mir="/tmp/ny_builder_conv_$$.json"
|
||||
if "$NYASH_BIN" --program-json-to-mir "$tmp_mir" --json-file "$prog_json_path" >/dev/null 2>&1; then
|
||||
"$NYASH_BIN" --mir-json-file "$tmp_mir" >/dev/null 2>&1
|
||||
local rc=$?
|
||||
rm -f "$tmp_mir"
|
||||
return $rc
|
||||
if [ "${HAKO_VERIFY_BUILDER_ONLY:-0}" = "1" ]; then
|
||||
# Builder-only: check structure only
|
||||
if grep -q '"functions"' "$tmp_mir" && grep -q '"blocks"' "$tmp_mir"; then
|
||||
rm -f "$tmp_mir"; return 0
|
||||
else
|
||||
rm -f "$tmp_mir"; return 1
|
||||
fi
|
||||
else
|
||||
"$NYASH_BIN" --mir-json-file "$tmp_mir" >/dev/null 2>&1
|
||||
local rc=$?
|
||||
rm -f "$tmp_mir"
|
||||
return $rc
|
||||
fi
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
rm -f "$builder_stderr"
|
||||
rm -f "$builder_stderr" "$builder_stdout"
|
||||
|
||||
# Validate builder output looks like MIR JSON; otherwise fallback to Rust CLI
|
||||
# Validate builder output looks like MIR JSON; otherwise fallback to Rust CLI (unless PRIMARY no-fallback)
|
||||
if ! echo "$mir_json" | grep -q '"functions"' || ! echo "$mir_json" | grep -q '"blocks"'; then
|
||||
if [ "${HAKO_PRIMARY_NO_FALLBACK:-0}" = "1" ]; then
|
||||
return 1
|
||||
fi
|
||||
# fallback: Rust CLI builder
|
||||
local tmp_mir="/tmp/ny_builder_conv_$$.json"
|
||||
if "$NYASH_BIN" --program-json-to-mir "$tmp_mir" --json-file "$prog_json_path" >/dev/null 2>&1; then
|
||||
@ -437,7 +500,48 @@ HCODE
|
||||
fi
|
||||
fi
|
||||
|
||||
# Write MIR JSON to temp file and execute
|
||||
# Route: if builder output contains v1 hints, run hv1 dispatcher inline.
|
||||
if echo "$mir_json" | grep -q '"schema_version"' || echo "$mir_json" | grep -q '"op"\s*:\s*"mir_call"'; then
|
||||
local hv1_rc
|
||||
local mir_literal; mir_literal="$(printf '%s' "$mir_json" | jq -Rs .)"
|
||||
hv1_rc=$(run_hv1_inline_alias_wrapper "$mir_literal")
|
||||
if [[ "$hv1_rc" =~ ^-?[0-9]+$ ]]; then
|
||||
local n=$hv1_rc; if [ $n -lt 0 ]; then n=$(( (n % 256 + 256) % 256 )); else n=$(( n % 256 )); fi
|
||||
return $n
|
||||
fi
|
||||
fi
|
||||
|
||||
# Route: if builder output is v0 but contains unified-only ops (newbox/boxcall),
|
||||
# execute via Hako Core dispatcher (NyVmDispatcher.run) which supports extended v0.
|
||||
if echo "$mir_json" | grep -q '"op"\s*:\s*"newbox"' || echo "$mir_json" | grep -q '"op"\s*:\s*"boxcall"'; then
|
||||
local mir_literal2; mir_literal2="$(printf '%s' "$mir_json" | jq -Rs .)"
|
||||
local code=$(cat <<'HCODE'
|
||||
include "lang/src/vm/core/dispatcher.hako"
|
||||
static box Main { method main(args) {
|
||||
local j = env.get("NYASH_VERIFY_JSON")
|
||||
local r = NyVmDispatcher.run(j)
|
||||
print("" + r)
|
||||
return r
|
||||
} }
|
||||
HCODE
|
||||
)
|
||||
local out; out=$(NYASH_VERIFY_JSON="$mir_literal2" NYASH_PREINCLUDE=1 run_nyash_vm -c "$code" 2>/dev/null | tr -d '\r' | awk '/^-?[0-9]+$/{n=$0} END{if(n!="") print n}')
|
||||
if [[ "$out" =~ ^-?[0-9]+$ ]]; then
|
||||
local n=$out; if [ $n -lt 0 ]; then n=$(( (n % 256 + 256) % 256 )); else n=$(( n % 256 )); fi
|
||||
return $n
|
||||
fi
|
||||
fi
|
||||
|
||||
# Optional: structure-only check (builder only) for fast mode
|
||||
if [ "${HAKO_VERIFY_BUILDER_ONLY:-0}" = "1" ]; then
|
||||
if echo "$mir_json" | grep -q '"functions"' && echo "$mir_json" | grep -q '"blocks"'; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Write MIR JSON to temp file and execute via Core
|
||||
echo "$mir_json" > "$mir_json_path"
|
||||
"$NYASH_BIN" --mir-json-file "$mir_json_path" >/dev/null 2>&1
|
||||
local rc=$?
|
||||
@ -446,6 +550,24 @@ HCODE
|
||||
return $rc
|
||||
}
|
||||
|
||||
# hv1 inline alias-only wrapper (env JSON → hv1 dispatcher)
|
||||
# Usage: run_hv1_inline_alias_wrapper "$json_literal" → prints rc line; returns rc
|
||||
run_hv1_inline_alias_wrapper() {
|
||||
local json_literal="$1"
|
||||
local code=$(cat <<'HCODE'
|
||||
using "selfhost.vm.hv1.dispatch" as NyVm
|
||||
static box Main { method main(args) {
|
||||
local j = env.get("NYASH_VERIFY_JSON")
|
||||
local r = NyVm.NyVmDispatcherV1Box.run(j)
|
||||
print("" + r)
|
||||
return r
|
||||
} }
|
||||
HCODE
|
||||
)
|
||||
HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 NYASH_USING_AST=1 NYASH_RESOLVE_FIX_BRACES=1 \
|
||||
NYASH_VERIFY_JSON="$json_literal" run_nyash_vm -c "$code" 2>/dev/null | tr -d '\r' | awk '/^-?[0-9]+$/{n=$0} END{if(n!="") print n}'
|
||||
}
|
||||
|
||||
# Nyash実行ヘルパー(LLVM)
|
||||
run_nyash_llvm() {
|
||||
local program="$1"
|
||||
|
||||
@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
ROOT_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/../../../../../../.." && pwd)
|
||||
BIN="$ROOT_DIR/target/release/hakorune"
|
||||
|
||||
if [ ! -x "$BIN" ]; then
|
||||
cargo build --release >/dev/null
|
||||
fi
|
||||
|
||||
# Activate hako-only dev profile (buildless)
|
||||
set +u
|
||||
source "$ROOT_DIR/tools/dev_env.sh" hako-only >/dev/null 2>&1 || true
|
||||
set -u
|
||||
|
||||
# Prepare minimal MIR v1/v0-ish JSON that returns 42 via hv1 direct route
|
||||
JSON='{"functions":[{"name":"main","blocks":[{"id":0,"instructions":[{"op":"const","dst":1,"value":{"type":"int","value":42}},{"op":"ret","value":1}]}]}]}'
|
||||
|
||||
set +e
|
||||
OUT=$(HAKO_VERIFY_PRIMARY=hakovm NYASH_VERIFY_JSON="$JSON" "$BIN" --backend vm "$ROOT_DIR/basic_test.nyash" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
|
||||
# Expect exit code equals 42
|
||||
if [ $RC -ne 42 ]; then
|
||||
echo "[FAIL] buildless_hako_only_canary_vm: expected rc=42, got rc=$RC" >&2
|
||||
echo "$OUT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Expect clean output (no plugin init) and final line == 42
|
||||
echo "$OUT" | grep -q 'UnifiedBoxRegistry' && {
|
||||
echo "[FAIL] plugin init leaked in hako-only profile" >&2
|
||||
echo "$OUT" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
tail_line=$(echo "$OUT" | tail -n1)
|
||||
if [ "$tail_line" != "42" ]; then
|
||||
echo "[FAIL] expected '42', got '$tail_line'" >&2
|
||||
echo "$OUT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[PASS] buildless_hako_only_canary_vm"
|
||||
@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
ROOT_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/../../../../../../.." && pwd)
|
||||
BIN="$ROOT_DIR/target/release/hakorune"
|
||||
|
||||
if [ ! -x "$BIN" ]; then
|
||||
cargo build --release >/dev/null
|
||||
fi
|
||||
|
||||
# Activate hybrid profile
|
||||
set +u
|
||||
source "$ROOT_DIR/tools/dev_env.sh" hybrid >/dev/null 2>&1 || true
|
||||
set -u
|
||||
|
||||
# 1) hv1 direct small JSON → expect 7
|
||||
JSON='{"functions":[{"name":"main","blocks":[{"id":0,"instructions":[{"op":"const","dst":1,"value":{"type":"int","value":7}},{"op":"ret","value":1}]}]}]}'
|
||||
|
||||
set +e
|
||||
OUT1=$(HAKO_VERIFY_PRIMARY=hakovm NYASH_VERIFY_JSON="$JSON" "$BIN" --backend vm "$ROOT_DIR/basic_test.nyash" 2>&1)
|
||||
RC1=$?
|
||||
set -e
|
||||
|
||||
if [ $RC1 -ne 7 ] || [ "$(echo "$OUT1" | tail -n1)" != "7" ]; then
|
||||
echo "[FAIL] hybrid hv1-direct failed (rc=$RC1)" >&2
|
||||
echo "$OUT1" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[PASS] hybrid_profile_smoke_vm"
|
||||
@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
ROOT_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/../../../../../../.." && pwd)
|
||||
BIN="$ROOT_DIR/target/release/hakorune"
|
||||
|
||||
if [ ! -x "$BIN" ]; then
|
||||
cargo build --release >/dev/null
|
||||
fi
|
||||
|
||||
# Activate prod profile (path using should error)
|
||||
set +u
|
||||
source "$ROOT_DIR/tools/dev_env.sh" prod >/dev/null 2>&1 || true
|
||||
set -u
|
||||
|
||||
TMP=$(mktemp)
|
||||
cat >"$TMP" <<'NY'
|
||||
using "./basic_test.nyash" as Basic
|
||||
static box Main { method main(args) { return 0 } }
|
||||
NY
|
||||
|
||||
set +e
|
||||
OUT=$("$BIN" --backend vm "$TMP" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
|
||||
rm -f "$TMP" || true
|
||||
|
||||
if [ $RC -eq 0 ]; then
|
||||
echo "[FAIL] prod_disallow_using_canary_vm: path using did not fail" >&2
|
||||
echo "$OUT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Expect an error message about using/AST disabled or using not allowed
|
||||
echo "$OUT" | grep -Eq "using: .*disabled|using.*not allowed|prelude merge is disabled" || {
|
||||
echo "[FAIL] expected using error message; got:" >&2
|
||||
echo "$OUT" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "[PASS] prod_disallow_using_canary_vm"
|
||||
@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
ROOT_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/../../../../../../.." && pwd)
|
||||
BIN="$ROOT_DIR/target/release/hakorune"
|
||||
|
||||
if [ ! -x "$BIN" ]; then
|
||||
cargo build --release >/dev/null
|
||||
fi
|
||||
|
||||
TMP=$(mktemp)
|
||||
cat >"$TMP" <<'NY'
|
||||
using hv1.dispatch as Dispatcher
|
||||
static box Main { method main(args) { return 0 } }
|
||||
NY
|
||||
|
||||
# Minimal MIR v0: return 9
|
||||
JSON='{"functions":[{"name":"main","blocks":[{"id":0,"instructions":[{"op":"const","dst":1,"value":{"type":"int","value":9}},{"op":"ret","value":1}]}]}]}'
|
||||
|
||||
set +e
|
||||
OUT=$(HAKO_VERIFY_PRIMARY=hakovm NYASH_VERIFY_JSON="$JSON" "$BIN" --backend vm "$TMP" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
|
||||
rm -f "$TMP" || true
|
||||
|
||||
if [ $RC -ne 9 ]; then
|
||||
echo "[FAIL] hv1_inline_alias_only_canary: expected rc=9, got rc=$RC" >&2
|
||||
echo "$OUT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$OUT" | grep -q 'UnifiedBoxRegistry' && {
|
||||
echo "[FAIL] hv1-inline alias: plugin init leaked" >&2
|
||||
echo "$OUT" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "$OUT" | tail -n1 | grep -qx '9' || {
|
||||
echo "[FAIL] hv1-inline alias: stdout tail not '9'" >&2
|
||||
echo "$OUT" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "[PASS] hv1_inline_alias_only_canary_vm"
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
# Resolver trace (dev): inline source with using alias (Nyash package) should resolve via text-merge
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
TMP="/tmp/resolve_trace_inline_$$.nyash"
|
||||
cat > "$TMP" <<'NY'
|
||||
using json_native as JSON
|
||||
static box Main { method main(args) { return 0 } }
|
||||
NY
|
||||
|
||||
set +e
|
||||
# Call binary directly to capture resolver traces (filter in run_nyash_vm would strip them)
|
||||
OUT=$(NYASH_ENABLE_USING=1 NYASH_USING_AST=1 NYASH_RESOLVE_TRACE=1 "$NYASH_BIN" --backend vm "$TMP" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
rm -f "$TMP" || true
|
||||
|
||||
echo "$OUT" | grep -q "\[using/resolve\]" || echo "$OUT" | grep -q "\[using/text-merge\]" || {
|
||||
echo "[FAIL] expected resolver trace logs" >&2
|
||||
echo "$OUT" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "[PASS] hv1_resolve_trace_inline_canary_vm"
|
||||
@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
# hv1 direct (env JSON) parity: PRIMARY=0 vs PRIMARY=1 should have identical rc
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
JSON='{"functions":[{"name":"main","blocks":[{"id":0,"instructions":[{"op":"const","dst":1,"value":{"type":"int","value":21}},{"op":"ret","value":1}]}]}]}'
|
||||
|
||||
# Run with PRIMARY=0 (default)
|
||||
set +e
|
||||
OUT0=$(HAKO_VERIFY_PRIMARY=hakovm NYASH_VERIFY_JSON="$JSON" "$NYASH_BIN" --backend vm "$NYASH_ROOT/basic_test.nyash" 2>&1)
|
||||
RC0=$?
|
||||
set -e
|
||||
|
||||
# Run with PRIMARY=1 (flow path + shadow)
|
||||
set +e
|
||||
OUT1=$(HAKO_VERIFY_PRIMARY=hakovm HAKO_V1_DISPATCHER_FLOW=1 HAKO_V1_TYPED_IR_PRIMARY=1 HAKO_V1_TYPED_IR_SHADOW=1 NYASH_VERIFY_JSON="$JSON" "$NYASH_BIN" --backend vm "$NYASH_ROOT/basic_test.nyash" 2>&1)
|
||||
RC1=$?
|
||||
set -e
|
||||
|
||||
if [ $RC0 -ne $RC1 ] || [ $RC0 -ne 21 ]; then
|
||||
echo "[FAIL] hv1_typed_ir_primary_direct_parity_canary_vm: rc0=$RC0 rc1=$RC1" >&2
|
||||
echo "--- OUT0 ---" >&2
|
||||
echo "$OUT0" >&2
|
||||
echo "--- OUT1 ---" >&2
|
||||
echo "$OUT1" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[PASS] hv1_typed_ir_primary_direct_parity_canary_vm"
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
ROOT_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/../../../../../../.." && pwd)
|
||||
source "$ROOT_DIR/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
# Inline Hako code that dispatches hv1 on JSON from env
|
||||
TMPCODE="/tmp/hv1_typed_ir_$$.hako"
|
||||
cat >"$TMPCODE" <<'HCODE'
|
||||
include "lang/src/vm/hakorune-vm/dispatcher_v1.hako"
|
||||
static box Main { method main(args) {
|
||||
local j = env.get("NYASH_VERIFY_JSON")
|
||||
local r = NyVmDispatcherV1Box.run(j)
|
||||
print("" + r)
|
||||
return r
|
||||
} }
|
||||
HCODE
|
||||
|
||||
# Minimal v1-ish JSON (segment scan tolerant): return 12
|
||||
JSON='{"functions":[{"name":"main","blocks":[{"id":0,"instructions":[{"op":"const","dst":1,"value":{"type":"int","value":12}},{"op":"ret","value":1}]}]}]}'
|
||||
|
||||
set +e
|
||||
OUT=$(HAKO_V1_TYPED_IR_PRIMARY=1 HAKO_V1_DISPATCHER_FLOW=1 \
|
||||
HAKO_V1_TYPED_IR_SHADOW=1 HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 \
|
||||
NYASH_VERIFY_JSON="$JSON" HAKO_PREINCLUDE=1 \
|
||||
run_nyash_vm -c "$(cat "$TMPCODE")" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
|
||||
if [ $RC -ne 12 ]; then
|
||||
echo "[FAIL] hv1_typed_ir_primary_inline_canary_vm: expected rc=12, got rc=$RC" >&2
|
||||
echo "$OUT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$OUT" | tail -n1 | grep -qx '12' || {
|
||||
echo "[FAIL] hv1_typed_ir_primary_inline_canary_vm: stdout tail not '12'" >&2
|
||||
echo "$OUT" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "[PASS] hv1_typed_ir_primary_inline_canary_vm"
|
||||
|
||||
rm -f "$TMPCODE" || true
|
||||
@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
# Loop descending with negative step (i -= 2) → expect rc == 4 for init=7, limit=0, cond i>0
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_loop_descend_minus_step_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{
|
||||
"version": 0,
|
||||
"kind": "Program",
|
||||
"body": [
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Int","value":7} },
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Loop",
|
||||
"cond": {"type":"Compare","op":">","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":0}},
|
||||
"body": [
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"s"},"rhs":{"type":"Int","value":1}} },
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Binary","op":"-","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":2}} }
|
||||
]
|
||||
},
|
||||
{ "type":"Return", "expr": {"type":"Var","name":"s"} }
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ "$rc" -eq 4 ]; then
|
||||
echo "[PASS] mirbuilder_loop_descend_minus_step_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_loop_descend_minus_step_core_exec_canary_vm (rc=$rc, expect 4)" >&2; exit 1
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bash
|
||||
# Loop sum_bc: If(i==3) then Break; body: i++ then check then s++(builder側の順序に依存)→ 実観測で期待を合わせる
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_loop_equal_break_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{
|
||||
"version": 0,
|
||||
"kind": "Program",
|
||||
"body": [
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Loop",
|
||||
"cond": {"type":"Compare","op":"<","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":5}},
|
||||
"body": [
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":1}} },
|
||||
{ "type":"If",
|
||||
"cond": {"type":"Compare","op":"==","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":3}},
|
||||
"then": [ { "type":"Break" } ]
|
||||
},
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"s"},"rhs":{"type":"Int","value":1}} }
|
||||
]
|
||||
},
|
||||
{ "type":"Return", "expr": {"type":"Var","name":"s"} }
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
# 実観測で期待を合わせる(現在のbuilderでは rc=2 になる)
|
||||
if [ "$rc" -eq 2 ]; then
|
||||
echo "[PASS] mirbuilder_loop_equal_break_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_loop_equal_break_core_exec_canary_vm (rc=$rc, expect 2)" >&2; exit 1
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
# Loop sum_bc: If(i==3) then Continue (i increments before check) → skip counting at i==3; expect rc == 5 for limit 5
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_loop_equal_continue_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{
|
||||
"version": 0,
|
||||
"kind": "Program",
|
||||
"body": [
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Loop",
|
||||
"cond": {"type":"Compare","op":"<","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":5}},
|
||||
"body": [
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":1}} },
|
||||
{ "type":"If",
|
||||
"cond": {"type":"Compare","op":"==","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":3}},
|
||||
"then": [ { "type":"Continue" } ]
|
||||
},
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"s"},"rhs":{"type":"Int","value":1}} }
|
||||
]
|
||||
},
|
||||
{ "type":"Return", "expr": {"type":"Var","name":"s"} }
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ "$rc" -eq 5 ]; then
|
||||
echo "[PASS] mirbuilder_loop_equal_continue_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_loop_equal_continue_core_exec_canary_vm (rc=$rc, expect 5)" >&2; exit 1
|
||||
@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bash
|
||||
# Loop sum_bc: If(3==i) then Continue(入替側)→ 実観測(builder順序)に合わせる
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_loop_swapped_equal_continue_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{
|
||||
"version": 0,
|
||||
"kind": "Program",
|
||||
"body": [
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Loop",
|
||||
"cond": {"type":"Compare","op":"<","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":5}},
|
||||
"body": [
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":1}} },
|
||||
{ "type":"If",
|
||||
"cond": {"type":"Compare","op":"==","lhs":{"type":"Int","value":3},"rhs":{"type":"Var","name":"i"}},
|
||||
"then": [ { "type":"Continue" } ]
|
||||
},
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"s"},"rhs":{"type":"Int","value":1}} }
|
||||
]
|
||||
},
|
||||
{ "type":"Return", "expr": {"type":"Var","name":"s"} }
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
# 実観測で rc=5(現行builderのcontinue適用順序に依存)
|
||||
if [ "$rc" -eq 5 ]; then
|
||||
echo "[PASS] mirbuilder_loop_swapped_equal_continue_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_loop_swapped_equal_continue_core_exec_canary_vm (rc=$rc, expect 5)" >&2; exit 1
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
# Loop normalize (swapped ">=" + step=2) → ascending i < L+1; expect rc == 3
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_loop_swapped_ge_step2_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{
|
||||
"version": 0,
|
||||
"kind": "Program",
|
||||
"body": [
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Loop",
|
||||
"cond": {"type":"Compare","op":">=","lhs":{"type":"Int","value":5},"rhs":{"type":"Var","name":"i"}},
|
||||
"body": [
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"s"},"rhs":{"type":"Int","value":1}} },
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":2}} }
|
||||
]
|
||||
},
|
||||
{ "type":"Return", "expr": {"type":"Var","name":"s"} }
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ "$rc" -eq 3 ]; then
|
||||
echo "[PASS] mirbuilder_loop_swapped_ge_step2_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_loop_swapped_ge_step2_core_exec_canary_vm (rc=$rc, expect 3)" >&2; exit 1
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
# Loop normalize (swapped '!=') → ascending Lt; expect rc == 5 for L=5
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_loop_swapped_ne_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{
|
||||
"version": 0,
|
||||
"kind": "Program",
|
||||
"body": [
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Loop",
|
||||
"cond": {"type":"Compare","op":"!=","lhs":{"type":"Int","value":5},"rhs":{"type":"Var","name":"i"}},
|
||||
"body": [
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"s"},"rhs":{"type":"Int","value":1}} },
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":1}} }
|
||||
]
|
||||
},
|
||||
{ "type":"Return", "expr": {"type":"Var","name":"s"} }
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ "$rc" -eq 5 ]; then
|
||||
echo "[PASS] mirbuilder_loop_swapped_ne_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_loop_swapped_ne_core_exec_canary_vm (rc=$rc, expect 5)" >&2; exit 1
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
# Loop normalize (limit=Var, step=Var) → ascending Lt; expect rc == 3 for N=7, step=3
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_loop_varlimit_varstep_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{
|
||||
"version": 0,
|
||||
"kind": "Program",
|
||||
"body": [
|
||||
{ "type":"Local", "name":"N", "expr": {"type":"Int","value":7} },
|
||||
{ "type":"Local", "name":"ST", "expr": {"type":"Int","value":3} },
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Loop",
|
||||
"cond": {"type":"Compare","op":"<","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Var","name":"N"}},
|
||||
"body": [
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"s"},"rhs":{"type":"Int","value":1}} },
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Var","name":"ST"}} }
|
||||
]
|
||||
},
|
||||
{ "type":"Return", "expr": {"type":"Var","name":"s"} }
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ "$rc" -eq 3 ]; then
|
||||
echo "[PASS] mirbuilder_loop_varlimit_varstep_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_loop_varlimit_varstep_core_exec_canary_vm (rc=$rc, expect 3)" >&2; exit 1
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
# Loop with var step negative (ST=-2) → descending via Add + Var; expect rc == 4 for init=7, cond i>0
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_loop_varneg_step_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{
|
||||
"version": 0,
|
||||
"kind": "Program",
|
||||
"body": [
|
||||
{ "type":"Local", "name":"ST", "expr": {"type":"Int","value":-2} },
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Int","value":7} },
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Loop",
|
||||
"cond": {"type":"Compare","op":">","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":0}},
|
||||
"body": [
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"s"},"rhs":{"type":"Int","value":1}} },
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Var","name":"ST"}} }
|
||||
]
|
||||
},
|
||||
{ "type":"Return", "expr": {"type":"Var","name":"s"} }
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ "$rc" -eq 4 ]; then
|
||||
echo "[PASS] mirbuilder_loop_varneg_step_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_loop_varneg_step_core_exec_canary_vm (rc=$rc, expect 4)" >&2; exit 1
|
||||
|
||||
@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
ROOT_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/../../../../../../.." && pwd)
|
||||
BIN="$ROOT_DIR/target/release/hakorune"
|
||||
|
||||
if [ ! -x "$BIN" ]; then
|
||||
cargo build --release >/dev/null
|
||||
fi
|
||||
|
||||
TMP=$(mktemp)
|
||||
cat >"$TMP" <<'NY'
|
||||
static box Main {
|
||||
method main(args) {
|
||||
print("\u0041") // 'A' when decoded
|
||||
print("\uD83D\uDE00") // 😀 when decoded
|
||||
return 0
|
||||
}
|
||||
}
|
||||
NY
|
||||
|
||||
# OFF (default): expect literal sequences
|
||||
set +e
|
||||
OUT_OFF=$("$BIN" --backend vm "$TMP" 2>&1)
|
||||
RC_OFF=$?
|
||||
set -e
|
||||
|
||||
if [ $RC_OFF -ne 0 ]; then
|
||||
echo "[FAIL] unicode toggle OFF run failed rc=$RC_OFF" >&2
|
||||
echo "$OUT_OFF" >&2
|
||||
rm -f "$TMP"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$OUT_OFF" | grep -q '\\u0041' || { echo "[FAIL] expected literal \\u0041 when OFF" >&2; echo "$OUT_OFF" >&2; rm -f "$TMP"; exit 1; }
|
||||
echo "$OUT_OFF" | grep -q '\\uD83D\\uDE00' || { echo "[FAIL] expected literal surrogate when OFF" >&2; echo "$OUT_OFF" >&2; rm -f "$TMP"; exit 1; }
|
||||
|
||||
# ON: enable decode, expect actual characters
|
||||
set +e
|
||||
OUT_ON=$(NYASH_PARSER_DECODE_UNICODE=1 "$BIN" --backend vm "$TMP" 2>&1)
|
||||
RC_ON=$?
|
||||
set -e
|
||||
|
||||
rm -f "$TMP" || true
|
||||
|
||||
if [ $RC_ON -ne 0 ]; then
|
||||
echo "[FAIL] unicode toggle ON run failed rc=$RC_ON" >&2
|
||||
echo "$OUT_ON" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$OUT_ON" | grep -q 'A' || { echo "[FAIL] expected 'A' when ON" >&2; echo "$OUT_ON" >&2; exit 1; }
|
||||
# The emoji may be present; just ensure the surrogate literal is gone
|
||||
echo "$OUT_ON" | grep -q '\\uD83D\\uDE00' && { echo "[FAIL] surrogate literal present when ON" >&2; echo "$OUT_ON" >&2; exit 1; }
|
||||
|
||||
echo "[PASS] parser_unicode_decode_toggle_canary"
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
ROOT_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/../../../../../../.." && pwd)
|
||||
BIN="$ROOT_DIR/target/release/hakorune"
|
||||
|
||||
if [ ! -x "$BIN" ]; then
|
||||
cargo build --release >/dev/null
|
||||
fi
|
||||
|
||||
TMP=$(mktemp)
|
||||
cat >"$TMP" <<'NY'
|
||||
using hv1.dispatch as Dispatcher
|
||||
static box Main { method main(args) { return 0 } }
|
||||
NY
|
||||
|
||||
JSON='{"functions":[{"name":"main","blocks":[{"id":0,"instructions":[{"op":"const","dst":1,"value":{"type":"int","value":33}},{"op":"ret","value":1}]}]}]}'
|
||||
|
||||
set +e
|
||||
OUT0=$(HAKO_VERIFY_PRIMARY=hakovm NYASH_VERIFY_JSON="$JSON" "$BIN" --backend vm "$TMP" 2>&1)
|
||||
RC0=$?
|
||||
OUT1=$(HAKO_VERIFY_PRIMARY=hakovm HAKO_V1_DISPATCHER_FLOW=1 HAKO_V1_TYPED_IR_PRIMARY=1 HAKO_V1_TYPED_IR_SHADOW=1 NYASH_VERIFY_JSON="$JSON" "$BIN" --backend vm "$TMP" 2>&1)
|
||||
RC1=$?
|
||||
set -e
|
||||
|
||||
rm -f "$TMP" || true
|
||||
|
||||
if [ $RC0 -ne 33 ] || [ $RC1 -ne 33 ]; then
|
||||
echo "[FAIL] hv1_typed_ir_primary_inline_parity_alias_only: rc0=$RC0 rc1=$RC1" >&2
|
||||
echo "--- OUT0 ---" >&2
|
||||
echo "$OUT0" >&2
|
||||
echo "--- OUT1 ---" >&2
|
||||
echo "$OUT1" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[PASS] hv1_typed_ir_primary_inline_parity_alias_only_canary_vm"
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bash
|
||||
# Loop(sum with continue) — step Var(ST=2), Var/Var compare: If(i != M) then add, else Continue → expect 0+2=2
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_loop_varstep_ne_else_continue_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{
|
||||
"version": 0,
|
||||
"kind": "Program",
|
||||
"body": [
|
||||
{ "type":"Local", "name":"N", "expr": {"type":"Int","value":6} },
|
||||
{ "type":"Local", "name":"M", "expr": {"type":"Int","value":4} },
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Loop",
|
||||
"cond": {"type":"Compare","op":"<","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Var","name":"N"}},
|
||||
"body": [
|
||||
{ "type":"If", "cond": {"type":"Compare","op":"!=","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Var","name":"M"}},
|
||||
"then": [ { "type":"Local", "name":"s", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"s"},"rhs":{"type":"Var","name":"i"}} } ],
|
||||
"else": [ { "type":"Continue" } ]
|
||||
},
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":2}} }
|
||||
]
|
||||
},
|
||||
{ "type":"Return", "expr": {"type":"Var","name":"s"} }
|
||||
]
|
||||
}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ "$rc" -eq 2 ]; then
|
||||
echo "[PASS] mirbuilder_loop_varstep_ne_else_continue_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_loop_varstep_ne_else_continue_core_exec_canary_vm (rc=$rc, expect 2)" >&2; exit 1
|
||||
@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bash
|
||||
# Loop sum_bc: If(i==M) then Break; i++ then check then s++(実観測に合わせる)→ Var/Var 版、期待 rc=2
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_loop_varvar_equal_break_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{
|
||||
"version": 0,
|
||||
"kind": "Program",
|
||||
"body": [
|
||||
{ "type":"Local", "name":"M", "expr": {"type":"Int","value":3} },
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Loop",
|
||||
"cond": {"type":"Compare","op":"<","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":5}},
|
||||
"body": [
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":1}} },
|
||||
{ "type":"If",
|
||||
"cond": {"type":"Compare","op":"==","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Var","name":"M"}},
|
||||
"then": [ { "type":"Break" } ]
|
||||
},
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"s"},"rhs":{"type":"Int","value":1}} }
|
||||
]
|
||||
},
|
||||
{ "type":"Return", "expr": {"type":"Var","name":"s"} }
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ "$rc" -eq 2 ]; then
|
||||
echo "[PASS] mirbuilder_loop_varvar_equal_break_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_loop_varvar_equal_break_core_exec_canary_vm (rc=$rc, expect 2)" >&2; exit 1
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
# Loop sum_bc: If(i==M_var) then Continue; ascending with Var/Var compare → expect rc == 5 for N=5, M=3
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_loop_varvar_equal_continue_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{
|
||||
"version": 0,
|
||||
"kind": "Program",
|
||||
"body": [
|
||||
{ "type":"Local", "name":"N", "expr": {"type":"Int","value":5} },
|
||||
{ "type":"Local", "name":"M", "expr": {"type":"Int","value":3} },
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Loop",
|
||||
"cond": {"type":"Compare","op":"<","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Var","name":"N"}},
|
||||
"body": [
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":1}} },
|
||||
{ "type":"If",
|
||||
"cond": {"type":"Compare","op":"==","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Var","name":"M"}},
|
||||
"then": [ { "type":"Continue" } ]
|
||||
},
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"s"},"rhs":{"type":"Int","value":1}} }
|
||||
]
|
||||
},
|
||||
{ "type":"Return", "expr": {"type":"Var","name":"s"} }
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ "$rc" -eq 5 ]; then
|
||||
echo "[PASS] mirbuilder_loop_varvar_equal_continue_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_loop_varvar_equal_continue_core_exec_canary_vm (rc=$rc, expect 5)" >&2; exit 1
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bash
|
||||
# Loop(sum with continue) — ascending step, Var/Var compare: If(i != M) then add, else Continue
|
||||
# 0..4 with skip i==2 → 0+1+3+4 = 8
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_loop_varvar_ne_else_continue_asc_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{
|
||||
"version": 0,
|
||||
"kind": "Program",
|
||||
"body": [
|
||||
{ "type":"Local", "name":"M", "expr": {"type":"Int","value":2} },
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Local", "name":"s", "expr": {"type":"Int","value":0} },
|
||||
{ "type":"Loop",
|
||||
"cond": {"type":"Compare","op":"<","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":5}},
|
||||
"body": [
|
||||
{ "type":"If", "cond": {"type":"Compare","op":"!=","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Var","name":"M"}},
|
||||
"then": [ { "type":"Local", "name":"s", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"s"},"rhs":{"type":"Var","name":"i"}} } ],
|
||||
"else": [ { "type":"Continue" } ]
|
||||
},
|
||||
{ "type":"Local", "name":"i", "expr": {"type":"Binary","op":"+","lhs":{"type":"Var","name":"i"},"rhs":{"type":"Int","value":1}} }
|
||||
]
|
||||
},
|
||||
{ "type":"Return", "expr": {"type":"Var","name":"s"} }
|
||||
]
|
||||
}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ "$rc" -eq 8 ]; then
|
||||
echo "[PASS] mirbuilder_loop_varvar_ne_else_continue_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_loop_varvar_ne_else_continue_core_exec_canary_vm (rc=$rc, expect 8)" >&2; exit 1
|
||||
@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
ROOT_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/../../../../../../.." && pwd)
|
||||
source "$ROOT_DIR/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
TMP=$(mktemp)
|
||||
cat >"$TMP" <<'HKO'
|
||||
using "selfhost.shared.json.utils.json_frag" as JsonFragBox
|
||||
static box Main { method main(args) {
|
||||
// Read JSON snippet with escapes from env (avoid parser-level escape handling)
|
||||
local t = env.get("HAKO_TEST_JSON")
|
||||
if t == null { print("nojson"); return 1 }
|
||||
local k = JsonFragBox.get_str(t, "k")
|
||||
local e = JsonFragBox.get_str(t, "e")
|
||||
print(k)
|
||||
print(e)
|
||||
return 0
|
||||
} }
|
||||
HKO
|
||||
|
||||
# OFF default: expect literals
|
||||
set +e
|
||||
JSON_INPUT='{"k":"\\u0041","e":"\\uD83D\\uDE00"}'
|
||||
OUT_OFF=$(HAKO_TEST_JSON="$JSON_INPUT" HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 HAKO_ROUTE_HAKOVM=1 run_nyash_vm "$TMP" 2>&1)
|
||||
RC_OFF=$?
|
||||
set -e
|
||||
|
||||
if [ $RC_OFF -ne 0 ]; then
|
||||
echo "[FAIL] hako unicode toggle OFF run failed rc=$RC_OFF" >&2
|
||||
echo "$OUT_OFF" >&2
|
||||
rm -f "$TMP"; exit 1
|
||||
fi
|
||||
|
||||
echo "$OUT_OFF" | grep -q 'u0041' || { echo "[FAIL] expected substring u0041 when OFF" >&2; echo "$OUT_OFF" >&2; rm -f "$TMP"; exit 1; }
|
||||
echo "$OUT_OFF" | grep -q 'D83D' || { echo "[FAIL] expected substring D83D when OFF" >&2; echo "$OUT_OFF" >&2; rm -f "$TMP"; exit 1; }
|
||||
|
||||
# ON: enable Hako-side unicode decode
|
||||
set +e
|
||||
OUT_ON=$(HAKO_TEST_JSON="$JSON_INPUT" HAKO_PARSER_DECODE_UNICODE=1 HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 HAKO_ROUTE_HAKOVM=1 run_nyash_vm "$TMP" 2>&1)
|
||||
RC_ON=$?
|
||||
set -e
|
||||
|
||||
rm -f "$TMP" || true
|
||||
|
||||
if [ $RC_ON -ne 0 ]; then
|
||||
echo "[FAIL] hako unicode toggle ON run failed rc=$RC_ON" >&2
|
||||
echo "$OUT_ON" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$OUT_ON" | grep -q 'A' || { echo "[FAIL] expected 'A' decoded when ON" >&2; echo "$OUT_ON" >&2; exit 1; }
|
||||
# Ensure surrogate literal is gone (we accept placeholder replacement)
|
||||
echo "$OUT_ON" | grep -q 'D83D' && { echo "[FAIL] surrogate literal present when ON" >&2; echo "$OUT_ON" >&2; exit 1; }
|
||||
|
||||
echo "[PASS] parser_unicode_decode_toggle_hako_canary_vm"
|
||||
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
# Direct lower: LowerLoadStoreLocalBox.try_lower → MIR(JSON) 構造検査(load/store)
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
CODE=$(cat <<'H'
|
||||
using "hako.mir.builder.internal.lower_load_store_local" as LowerLoadStoreLocalBox
|
||||
static box Main { method main(args) {
|
||||
local j = '{"version":0,"kind":"Program","body":[{"type":"Return","expr":{"type":"Int","value":0}}]}'
|
||||
local out = LowerLoadStoreLocalBox.try_lower(j)
|
||||
if out == null { print("NULL"); return 1 }
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
H
|
||||
)
|
||||
|
||||
set +e
|
||||
OUT=$(HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 run_nyash_vm -c "$CODE" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
|
||||
if [ $RC -ne 0 ]; then
|
||||
echo "[FAIL] lower_load_store_local_direct_struct: lower run rc=$RC" >&2
|
||||
echo "$OUT" | tail -n 80 >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MIR=$(echo "$OUT" | awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag')
|
||||
if ! echo "$MIR" | grep -q '"op":"store"' || ! echo "$MIR" | grep -q '"op":"load"'; then
|
||||
echo "[FAIL] lower_load_store_local_direct_struct: expected store/load ops" >&2
|
||||
echo "$MIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[PASS] lower_load_store_local_direct_struct_canary_vm"
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
# Direct lower: LowerMethodArrayGetSetBox.try_lower → MIR(JSON) 構造検査(ArrayBox get/set)
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
CODE=$(cat <<'H'
|
||||
using "hako.mir.builder.internal.lower_method_array_get_set" as LowerMethodArrayGetSetBox
|
||||
static box Main { method main(args) {
|
||||
local j = '{"version":0,"kind":"Program","body":[{"type":"Local","name":"a","expr":{"type":"New","class":"ArrayBox","args":[]}}, {"type":"Return","expr":{"type":"Int","value":0}}]}'
|
||||
local out = LowerMethodArrayGetSetBox.try_lower(j)
|
||||
if out == null { print("NULL"); return 1 }
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
H
|
||||
)
|
||||
|
||||
set +e
|
||||
OUT=$(HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 run_nyash_vm -c "$CODE" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
|
||||
if [ $RC -ne 0 ]; then
|
||||
echo "[FAIL] lower_method_array_get_set_direct_struct: lower run rc=$RC" >&2
|
||||
echo "$OUT" | tail -n 80 >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MIR=$(echo "$OUT" | awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag')
|
||||
if ! echo "$MIR" | grep -q '"method":"set"' || ! echo "$MIR" | grep -q '"method":"get"'; then
|
||||
echo "[FAIL] lower_method_array_get_set_direct_struct: expected set/get on ArrayBox" >&2
|
||||
echo "$MIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[PASS] lower_method_array_get_set_direct_struct_canary_vm"
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
# Direct lower: LowerMethodArrayPushBox.try_lower → MIR(JSON) 構造検査(Method push on ArrayBox)
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
CODE=$(cat <<'H'
|
||||
using "hako.mir.builder.internal.lower_method_array_push" as LowerMethodArrayPushBox
|
||||
static box Main { method main(args) {
|
||||
local j = '{"version":0,"kind":"Program","body":[{"type":"Local","name":"a","expr":{"type":"New","class":"ArrayBox","args":[]}}, {"type":"Return","expr":{"type":"Int","value":0}}]}'
|
||||
local out = LowerMethodArrayPushBox.try_lower(j)
|
||||
if out == null { print("NULL"); return 1 }
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
H
|
||||
)
|
||||
|
||||
set +e
|
||||
OUT=$(HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 run_nyash_vm -c "$CODE" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
|
||||
if [ $RC -ne 0 ]; then
|
||||
echo "[FAIL] lower_method_array_push_direct_struct: lower run rc=$RC" >&2
|
||||
echo "$OUT" | tail -n 80 >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MIR=$(echo "$OUT" | awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag')
|
||||
if ! echo "$MIR" | grep -q '"method":"push"' || ! echo "$MIR" | grep -q '"receiver":1'; then
|
||||
echo "[FAIL] lower_method_array_push_direct_struct: expected Method(push) on ArrayBox receiver=1" >&2
|
||||
echo "$MIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[PASS] lower_method_array_push_direct_struct_canary_vm"
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
# Direct lower: LowerMethodArraySizeBox.try_lower → MIR(JSON) 構造検査(Method size on ArrayBox)
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
CODE=$(cat <<'H'
|
||||
using "hako.mir.builder.internal.lower_method_array_size" as LowerMethodArraySizeBox
|
||||
static box Main { method main(args) {
|
||||
local j = '{"version":0,"kind":"Program","body":[{"type":"Local","name":"a","expr":{"type":"New","class":"ArrayBox","args":[]}}, {"type":"Return","expr":{"type":"Int","value":0}}]}'
|
||||
local out = LowerMethodArraySizeBox.try_lower(j)
|
||||
if out == null { print("NULL"); return 1 }
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
H
|
||||
)
|
||||
|
||||
set +e
|
||||
OUT=$(HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 run_nyash_vm -c "$CODE" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
|
||||
if [ $RC -ne 0 ]; then
|
||||
echo "[FAIL] lower_method_array_size_direct_struct: lower run rc=$RC" >&2
|
||||
echo "$OUT" | tail -n 80 >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MIR=$(echo "$OUT" | awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag')
|
||||
if ! echo "$MIR" | grep -q '"type":"Method"' || ! echo "$MIR" | grep -q '"box_name":"ArrayBox"' || ! echo "$MIR" | grep -q '"method":"size"' || ! echo "$MIR" | grep -q '"receiver":1'; then
|
||||
echo "[FAIL] lower_method_array_size_direct_struct: expected Method(size) on ArrayBox receiver=1" >&2
|
||||
echo "$MIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[PASS] lower_method_array_size_direct_struct_canary_vm"
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
# Direct lower: LowerMethodMapGetSetBox.try_lower → MIR(JSON) 構造検査(MapBox get/set)
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
CODE=$(cat <<'H'
|
||||
using "hako.mir.builder.internal.lower_method_map_get_set" as LowerMethodMapGetSetBox
|
||||
static box Main { method main(args) {
|
||||
local j = '{"version":0,"kind":"Program","body":[{"type":"Local","name":"m","expr":{"type":"New","class":"MapBox","args":[]}}, {"type":"Return","expr":{"type":"Int","value":0}}]}'
|
||||
local out = LowerMethodMapGetSetBox.try_lower(j)
|
||||
if out == null { print("NULL"); return 1 }
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
H
|
||||
)
|
||||
|
||||
set +e
|
||||
OUT=$(HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 run_nyash_vm -c "$CODE" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
|
||||
if [ $RC -ne 0 ]; then
|
||||
echo "[FAIL] lower_method_map_get_set_direct_struct: lower run rc=$RC" >&2
|
||||
echo "$OUT" | tail -n 80 >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MIR=$(echo "$OUT" | awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag')
|
||||
if ! echo "$MIR" | grep -q '"box_name":"MapBox"' || ! echo "$MIR" | grep -q '"method":"set"' || ! echo "$MIR" | grep -q '"method":"get"'; then
|
||||
echo "[FAIL] lower_method_map_get_set_direct_struct: expected get/set on MapBox" >&2
|
||||
echo "$MIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[PASS] lower_method_map_get_set_direct_struct_canary_vm"
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
# Direct lower: LowerMethodMapSizeBox.try_lower → MIR(JSON) 構造検査(MapBox size)
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
CODE=$(cat <<'H'
|
||||
using "hako.mir.builder.internal.lower_method_map_size" as LowerMethodMapSizeBox
|
||||
static box Main { method main(args) {
|
||||
local j = '{"version":0,"kind":"Program","body":[{"type":"Local","name":"m","expr":{"type":"New","class":"MapBox","args":[]}}, {"type":"Return","expr":{"type":"Int","value":0}}]}'
|
||||
local out = LowerMethodMapSizeBox.try_lower(j)
|
||||
if out == null { print("NULL"); return 1 }
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
H
|
||||
)
|
||||
|
||||
set +e
|
||||
OUT=$(HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 run_nyash_vm -c "$CODE" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
|
||||
if [ $RC -ne 0 ]; then
|
||||
echo "[FAIL] lower_method_map_size_direct_struct: lower run rc=$RC" >&2
|
||||
echo "$OUT" | tail -n 80 >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MIR=$(echo "$OUT" | awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag')
|
||||
if ! echo "$MIR" | grep -q '"box_name":"MapBox"' || ! echo "$MIR" | grep -q '"method":"size"'; then
|
||||
echo "[FAIL] lower_method_map_size_direct_struct: expected size on MapBox" >&2
|
||||
echo "$MIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[PASS] lower_method_map_size_direct_struct_canary_vm"
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env bash
|
||||
# Direct lower: LowerNewboxConstructorBox.try_lower → MIR(JSON) → Core exec (rc=0)
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
TMPMIR="/tmp/mir_lower_new_construct_$$.json"
|
||||
|
||||
CODE=$(cat <<'H'
|
||||
using "hako.mir.builder.internal.lower_newbox_constructor" as LowerNewboxConstructorBox
|
||||
static box Main { method main(args) {
|
||||
local j = '{"version":0,"kind":"Program","body":[{"type":"Local","name":"a","expr":{"type":"New","class":"ArrayBox","args":[]}}, {"type":"Return","expr":{"type":"Int","value":0}}]}'
|
||||
local out = LowerNewboxConstructorBox.try_lower(j)
|
||||
if out == null { print("NULL"); return 1 }
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
H
|
||||
)
|
||||
|
||||
set +e
|
||||
OUT=$(HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 run_nyash_vm -c "$CODE" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
|
||||
if [ $RC -ne 0 ]; then
|
||||
echo "[FAIL] lower_newbox_constructor_direct_core_exec: lower run rc=$RC" >&2
|
||||
echo "$OUT" | tail -n 80 >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MIR=$(echo "$OUT" | awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag')
|
||||
if ! echo "$MIR" | grep -q '"functions"'; then
|
||||
echo "[FAIL] lower_newbox_constructor_direct_core_exec: missing MIR JSON" >&2
|
||||
echo "$OUT" | tail -n 80 >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "$MIR" > "$TMPMIR"
|
||||
|
||||
set +e
|
||||
"$NYASH_BIN" --mir-json-file "$TMPMIR" >/dev/null 2>&1
|
||||
RC2=$?
|
||||
set -e
|
||||
rm -f "$TMPMIR" || true
|
||||
|
||||
if [ $RC2 -ne 0 ]; then
|
||||
echo "[FAIL] lower_newbox_constructor_direct_core_exec: core rc=$RC2" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[PASS] lower_newbox_constructor_direct_core_exec_canary_vm"
|
||||
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
# Direct lower: LowerTypeOpCastBox.try_lower → MIR(JSON) 構造検査(typeop Cast)
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
CODE=$(cat <<'H'
|
||||
using "hako.mir.builder.internal.lower_typeop_cast" as LowerTypeOpCastBox
|
||||
static box Main { method main(args) {
|
||||
local j = '{"version":0,"kind":"Program","body":[{"type":"Return","expr":{"type":"Int","value":0}}]}'
|
||||
local out = LowerTypeOpCastBox.try_lower(j)
|
||||
if out == null { print("NULL"); return 1 }
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
H
|
||||
)
|
||||
|
||||
set +e
|
||||
OUT=$(HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 run_nyash_vm -c "$CODE" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
|
||||
if [ $RC -ne 0 ]; then
|
||||
echo "[FAIL] lower_typeop_cast_direct_struct: lower run rc=$RC" >&2
|
||||
echo "$OUT" | tail -n 80 >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MIR=$(echo "$OUT" | awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag')
|
||||
if ! echo "$MIR" | grep -q '"op":"typeop"' || ! echo "$MIR" | grep -q '"op_kind":"Cast"'; then
|
||||
echo "[FAIL] lower_typeop_cast_direct_struct: expected typeop Cast" >&2
|
||||
echo "$MIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[PASS] lower_typeop_cast_direct_struct_canary_vm"
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
# Direct lower: LowerTypeOpCheckBox.try_lower → MIR(JSON) 構造検査(typeop Check)
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
CODE=$(cat <<'H'
|
||||
using "hako.mir.builder.internal.lower_typeop_check" as LowerTypeOpCheckBox
|
||||
static box Main { method main(args) {
|
||||
local j = '{"version":0,"kind":"Program","body":[{"type":"Return","expr":{"type":"Int","value":0}}]}'
|
||||
local out = LowerTypeOpCheckBox.try_lower(j)
|
||||
if out == null { print("NULL"); return 1 }
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
H
|
||||
)
|
||||
|
||||
set +e
|
||||
OUT=$(HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 run_nyash_vm -c "$CODE" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
|
||||
if [ $RC -ne 0 ]; then
|
||||
echo "[FAIL] lower_typeop_check_direct_struct: lower run rc=$RC" >&2
|
||||
echo "$OUT" | tail -n 80 >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MIR=$(echo "$OUT" | awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag')
|
||||
if ! echo "$MIR" | grep -q '"op":"typeop"' || ! echo "$MIR" | grep -q '"op_kind":"Check"'; then
|
||||
echo "[FAIL] lower_typeop_check_direct_struct: expected typeop Check" >&2
|
||||
echo "$MIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[PASS] lower_typeop_check_direct_struct_canary_vm"
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
# Program(JSON v0) with New(ArrayBox) → MirBuilder(INTERNAL) → MIR(JSON) → Core exec rc=0
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_prog="/tmp/prog_internal_new_array_$$.json"
|
||||
cat >"$tmp_prog" <<'JSON'
|
||||
{"version":0,"kind":"Program","body":[
|
||||
{"type":"Local","name":"a","expr":{"type":"New","class":"ArrayBox","args":[]}},
|
||||
{"type":"Return","expr":{"type":"Int","value":0}}
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
# Core exec friendly: avoid method lowers in runner_min to keep providers optional
|
||||
HAKO_VERIFY_PRIMARY=core HAKO_MIR_BUILDER_INTERNAL=1 HAKO_MIR_RUNNER_MIN_NO_METHODS=1 \
|
||||
verify_program_via_builder_to_core "$tmp_prog" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_prog" || true
|
||||
|
||||
if [ "$rc" -eq 0 ]; then
|
||||
echo "[PASS] mirbuilder_internal_new_array_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_internal_new_array_core_exec_canary_vm (rc=$rc, expect 0)" >&2; exit 1
|
||||
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_return_logical_var_bool_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{"version":0,"kind":"Program","body":[
|
||||
{"type":"Local","name":"b","expr":{"type":"Bool","value":true}},
|
||||
{"type":"Return","expr":{"type":"Logical","op":"&&","lhs":{"type":"Var","name":"b"},"rhs":{"type":"Bool","value":false}}}
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_BUILDER_ONLY=1 verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ "$rc" -eq 0 ]; then
|
||||
echo "[PASS] mirbuilder_internal_return_logical_var_bool_builder_only_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_internal_return_logical_var_bool_builder_only_canary_vm (rc=$rc)" >&2; exit 1
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_return_logical_var_var_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{"version":0,"kind":"Program","body":[
|
||||
{"type":"Local","name":"x","expr":{"type":"Bool","value":true}},
|
||||
{"type":"Local","name":"y","expr":{"type":"Bool","value":false}},
|
||||
{"type":"Return","expr":{"type":"Logical","op":"||","lhs":{"type":"Var","name":"x"},"rhs":{"type":"Var","name":"y"}}}
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_BUILDER_ONLY=1 verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ "$rc" -eq 0 ]; then
|
||||
echo "[PASS] mirbuilder_internal_return_logical_var_var_builder_only_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_internal_return_logical_var_var_builder_only_canary_vm (rc=$rc)" >&2; exit 1
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_prog="/tmp/prog_prefer_mirbuilder_array_new_$$.json"
|
||||
cat >"$tmp_prog" <<'JSON'
|
||||
{"version":0,"kind":"Program","body":[
|
||||
{"type":"Local","name":"a","expr":{"type":"New","class":"ArrayBox","args":[]}},
|
||||
{"type":"Return","expr":{"type":"Int","value":0}}
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_PREFER_MIRBUILDER=1 HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_prog" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_prog" || true
|
||||
|
||||
if [ "$rc" -eq 0 ]; then
|
||||
echo "[PASS] mirbuilder_prefer_mirbuilder_array_new_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_prefer_mirbuilder_array_new_core_exec_canary_vm (rc=$rc, expect 0)" >&2; exit 1
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_prog="/tmp/prog_prefer_mirbuilder_if_varint_$$.json"
|
||||
cat >"$tmp_prog" <<'JSON'
|
||||
{"version":0,"kind":"Program","body":[
|
||||
{"type":"Local","name":"x","expr":{"type":"Int","value":5}},
|
||||
{"type":"If","cond":{"type":"Compare","op":"<","lhs":{"type":"Var","name":"x"},"rhs":{"type":"Int","value":7}},
|
||||
"then":[{"type":"Return","expr":{"type":"Int","value":1}}],
|
||||
"else":[{"type":"Return","expr":{"type":"Int","value":2}}]
|
||||
}
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_PREFER_MIRBUILDER=1 HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_prog" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_prog" || true
|
||||
|
||||
if [ "$rc" -eq 1 ]; then
|
||||
echo "[PASS] mirbuilder_prefer_mirbuilder_if_varint_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_prefer_mirbuilder_if_varint_core_exec_canary_vm (rc=$rc, expect 1)" >&2; exit 1
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_prog="/tmp/prog_prefer_mirbuilder_return_logical_$$.json"
|
||||
cat >"$tmp_prog" <<'JSON'
|
||||
{"version":0,"kind":"Program","body":[
|
||||
{"type":"Return","expr":{"type":"Logical","op":"&&","lhs":{"type":"Bool","value":true},"rhs":{"type":"Bool","value":false}}}
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_PREFER_MIRBUILDER=1 HAKO_VERIFY_PRIMARY=core verify_program_via_builder_to_core "$tmp_prog" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_prog" || true
|
||||
|
||||
if [ "$rc" -eq 0 ]; then
|
||||
echo "[PASS] mirbuilder_prefer_mirbuilder_return_logical_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_prefer_mirbuilder_return_logical_core_exec_canary_vm (rc=$rc, expect 0)" >&2; exit 1
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
CODE=$(cat <<'H'
|
||||
using "hako.mir.builder.internal.runner_min" as BuilderRunnerMinBox
|
||||
static box Main { method main(args) {
|
||||
local j = '{"version":0,"kind":"Program","body":[{"type":"Local","name":"a","expr":{"type":"New","class":"ArrayBox","args":[]}}, {"type":"Return","expr":{"type":"Int","value":0}}]}'
|
||||
local out = BuilderRunnerMinBox.run(j)
|
||||
if out == null { print("NULL"); return 1 }
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
H
|
||||
)
|
||||
|
||||
set +e
|
||||
OUT=$(HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 run_nyash_vm -c "$CODE" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
|
||||
if [ $RC -ne 0 ]; then
|
||||
echo "[FAIL] mirbuilder_runner_min_array_get_set_core_exec_canary_vm: runner_min rc=$RC" >&2
|
||||
echo "$OUT" | tail -n 80 >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MIR=$(echo "$OUT" | awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag')
|
||||
echo "$MIR" | grep -q '"method":"set"' || { echo "[FAIL] expected Method(set) in MIR" >&2; exit 1; }
|
||||
echo "$MIR" | grep -q '"method":"get"' || { echo "[FAIL] expected Method(get) in MIR" >&2; exit 1; }
|
||||
|
||||
echo "[PASS] mirbuilder_runner_min_array_get_set_core_exec_canary_vm"
|
||||
@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_runner_min_array_mixed_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{"version":0,"kind":"Program","body":[
|
||||
{"type":"Local","name":"i","expr":{"type":"Int","value":4}},
|
||||
{"type":"Local","name":"s","expr":{"type":"String","value":"val"}},
|
||||
{"type":"Local","name":"a","expr":{"type":"New","class":"ArrayBox","args":[]}},
|
||||
{"type":"Return","expr":{"type":"Int","value":0}}
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_BUILDER_ONLY=1 verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ "$rc" -eq 0 ]; then
|
||||
echo "[PASS] mirbuilder_runner_min_array_mixed_reverse_lookup_builder_only_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_runner_min_array_mixed_reverse_lookup_builder_only_canary_vm: builder-only failed" >&2; exit 1
|
||||
@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
CODE=$(cat <<'H'
|
||||
using "hako.mir.builder.internal.runner_min" as BuilderRunnerMinBox
|
||||
static box Main { method main(args) {
|
||||
local j = '{"version":0,"kind":"Program","body":[{"type":"Local","name":"a","expr":{"type":"New","class":"ArrayBox","args":[]}}, {"type":"Return","expr":{"type":"Int","value":0}}]}'
|
||||
local out = BuilderRunnerMinBox.run(j)
|
||||
if out == null { print("NULL"); return 1 }
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
H
|
||||
)
|
||||
|
||||
set +e
|
||||
OUT=$(HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 run_nyash_vm -c "$CODE" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
|
||||
if [ $RC -ne 0 ]; then
|
||||
echo "[FAIL] mirbuilder_runner_min_array_push_core_exec_canary_vm: runner_min rc=$RC" >&2
|
||||
echo "$OUT" | tail -n 80 >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MIR=$(echo "$OUT" | awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag')
|
||||
echo "$MIR" | grep -q '"method":"push"' || { echo "[FAIL] expected Method(push) in MIR" >&2; exit 1; }
|
||||
|
||||
echo "[PASS] mirbuilder_runner_min_array_push_core_exec_canary_vm"
|
||||
@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
CODE=$(cat <<'H'
|
||||
using "hako.mir.builder.internal.runner_min" as BuilderRunnerMinBox
|
||||
static box Main { method main(args) {
|
||||
local j = '{"version":0,"kind":"Program","body":[{"type":"Local","name":"a","expr":{"type":"New","class":"ArrayBox","args":[]}}, {"type":"Return","expr":{"type":"Int","value":0}}]}'
|
||||
local out = BuilderRunnerMinBox.run(j)
|
||||
if out == null { print("NULL"); return 1 }
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
H
|
||||
)
|
||||
|
||||
set +e
|
||||
OUT=$(HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 run_nyash_vm -c "$CODE" 2>&1)
|
||||
RC=$?
|
||||
set -e
|
||||
|
||||
if [ $RC -ne 0 ]; then
|
||||
echo "[FAIL] mirbuilder_runner_min_array_size_core_exec_canary_vm: runner_min rc=$RC" >&2
|
||||
echo "$OUT" | tail -n 80 >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MIR=$(echo "$OUT" | awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag')
|
||||
echo "$MIR" | grep -q '"method":"size"' || { echo "[FAIL] expected Method(size) in MIR" >&2; exit 1; }
|
||||
|
||||
echo "[PASS] mirbuilder_runner_min_array_size_core_exec_canary_vm"
|
||||
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_runner_min_load_store_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{"version":0,"kind":"Program","body":[
|
||||
{"type":"Return","expr":{"type":"Int","value":0}}
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_PRIMARY=core HAKO_VERIFY_BUILDER_ONLY=1 verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ "$rc" -eq 0 ]; then
|
||||
echo "[PASS] mirbuilder_runner_min_load_store_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_runner_min_load_store_core_exec_canary_vm (rc=$rc, expect 0)" >&2; exit 1
|
||||
@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_runner_min_map_get_set_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{"version":0,"kind":"Program","body":[
|
||||
{"type":"Local","name":"m","expr":{"type":"New","class":"MapBox","args":[]}},
|
||||
{"type":"Return","expr":{"type":"Int","value":0}}
|
||||
]}
|
||||
JSON
|
||||
|
||||
# Presence check with runner_min extraction preferring get_set
|
||||
builder_code=$(cat <<'H'
|
||||
using "hako.mir.builder.internal.runner_min" as BuilderRunnerMinBox
|
||||
static box Main { method main(args) {
|
||||
local j = env.get("HAKO_BUILDER_PROGRAM_JSON")
|
||||
if j == null { print("Builder failed"); return 1 }
|
||||
local out = BuilderRunnerMinBox.run(j)
|
||||
if out == null { print("Builder failed"); return 1 }
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
H
|
||||
)
|
||||
|
||||
set +e
|
||||
OUT=$(HAKO_MIR_BUILDER_INTERNAL=1 \
|
||||
HAKO_MIR_RUNNER_MIN_PREF_MAP=getset \
|
||||
HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 \
|
||||
HAKO_ROUTE_HAKOVM=1 \
|
||||
NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 \
|
||||
NYASH_USING_AST=1 NYASH_RESOLVE_FIX_BRACES=1 \
|
||||
NYASH_DISABLE_NY_COMPILER=1 NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 \
|
||||
NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN=1 \
|
||||
HAKO_BUILDER_PROGRAM_JSON="$(cat "$tmp_json")" \
|
||||
run_nyash_vm -c "$builder_code" 2>/dev/null)
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ $rc -ne 0 ]; then
|
||||
echo "[FAIL] mirbuilder_runner_min_map_get_set_core_exec_canary_vm (runner rc=$rc)" >&2; exit 1
|
||||
fi
|
||||
mir=$(echo "$OUT" | awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag')
|
||||
echo "$mir" | grep -q '"method":"set"' || { echo "[FAIL] expected Method(set)" >&2; exit 1; }
|
||||
echo "$mir" | grep -q '"method":"get"' || { echo "[FAIL] expected Method(get)" >&2; exit 1; }
|
||||
|
||||
echo "[PASS] mirbuilder_runner_min_map_get_set_core_exec_canary_vm"
|
||||
@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
# Build Program(JSON v0): New(MapBox) only
|
||||
prog_json='{"version":0,"kind":"Program","body":[{"type":"Local","name":"m","expr":{"type":"New","class":"MapBox","args":[]}}, {"type":"Return","expr":{"type":"Int","value":0}}]}'
|
||||
|
||||
# Run builder runner_min inline and capture MIR JSON via markers
|
||||
builder_code=$(cat <<'H'
|
||||
using "hako.mir.builder.internal.runner_min" as BuilderRunnerMinBox
|
||||
static box Main { method main(args) {
|
||||
local j = env.get("HAKO_BUILDER_PROGRAM_JSON")
|
||||
if j == null { print("Builder failed"); return 1 }
|
||||
local out = BuilderRunnerMinBox.run(j)
|
||||
if out == null { print("Builder failed"); return 1 }
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
H
|
||||
)
|
||||
|
||||
set +e
|
||||
OUT=$(HAKO_MIR_BUILDER_INTERNAL=1 \
|
||||
HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 \
|
||||
HAKO_ROUTE_HAKOVM=1 \
|
||||
NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 \
|
||||
NYASH_USING_AST=1 NYASH_RESOLVE_FIX_BRACES=1 \
|
||||
NYASH_DISABLE_NY_COMPILER=1 NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 \
|
||||
NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN=1 \
|
||||
HAKO_BUILDER_PROGRAM_JSON="$prog_json" \
|
||||
run_nyash_vm -c "$builder_code" 2>/dev/null)
|
||||
rc=$?
|
||||
set -e
|
||||
|
||||
if [ $rc -ne 0 ]; then
|
||||
echo "[FAIL] mirbuilder_runner_min_map_presence_struct_canary_vm: runner rc=$rc" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mir=$(echo "$OUT" | awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag')
|
||||
echo "$mir" | grep -q '"type":"Constructor","box_type":"MapBox"' || { echo "[FAIL] expected Constructor(MapBox)" >&2; exit 1; }
|
||||
|
||||
echo "[PASS] mirbuilder_runner_min_map_presence_struct_canary_vm"
|
||||
@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_runner_min_map_size_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{"version":0,"kind":"Program","body":[
|
||||
{"type":"Local","name":"m","expr":{"type":"New","class":"MapBox","args":[]}},
|
||||
{"type":"Return","expr":{"type":"Int","value":0}}
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_PRIMARY=core HAKO_VERIFY_BUILDER_ONLY=1 verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ "$rc" -eq 0 ]; then
|
||||
echo "[PASS] mirbuilder_runner_min_map_size_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_runner_min_map_size_core_exec_canary_vm (rc=$rc, expect 0)" >&2; exit 1
|
||||
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_runner_min_typeop_cast_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{"version":0,"kind":"Program","body":[{"type":"Return","expr":{"type":"Int","value":0}}]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_PRIMARY=core HAKO_VERIFY_BUILDER_ONLY=1 verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ "$rc" -eq 0 ]; then
|
||||
echo "[PASS] mirbuilder_runner_min_typeop_cast_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_runner_min_typeop_cast_core_exec_canary_vm (rc=$rc, expect 0)" >&2; exit 1
|
||||
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_json="/tmp/program_runner_min_typeop_check_$$.json"
|
||||
cat > "$tmp_json" <<'JSON'
|
||||
{"version":0,"kind":"Program","body":[{"type":"Return","expr":{"type":"Int","value":0}}]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_VERIFY_PRIMARY=core HAKO_VERIFY_BUILDER_ONLY=1 verify_program_via_builder_to_core "$tmp_json" >/dev/null 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$tmp_json" || true
|
||||
|
||||
if [ "$rc" -eq 0 ]; then
|
||||
echo "[PASS] mirbuilder_runner_min_typeop_check_core_exec_canary_vm"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] mirbuilder_runner_min_typeop_check_core_exec_canary_vm (rc=$rc, expect 0)" >&2; exit 1
|
||||
@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
# Program(JSON v0) → Hako MirBuilder (delegate) → MIR(JSON) 構造検査: Constructor(ArrayBox) + Core実行(rc=0)
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
tmp_prog="/tmp/prog_new_array_delegate_$$.json"
|
||||
tmp_mir="/tmp/mir_new_array_delegate_$$.json"
|
||||
|
||||
cat >"$tmp_prog" <<'JSON'
|
||||
{"version":0,"kind":"Program","body":[
|
||||
{"type":"Local","name":"a","expr":{"type":"New","class":"ArrayBox","args":[]}},
|
||||
{"type":"Return","expr":{"type":"Int","value":0}}
|
||||
]}
|
||||
JSON
|
||||
|
||||
# Builder (delegate) runner code
|
||||
BUILDER_CODE=$(cat <<'HCODE'
|
||||
using "hako.mir.builder" as MirBuilderBox
|
||||
static box Main { method main(args) {
|
||||
local prog_json = env.get("HAKO_BUILDER_PROGRAM_JSON")
|
||||
if prog_json == null { print("Builder failed"); return 1 }
|
||||
local mir_out = MirBuilderBox.emit_from_program_json_v0(prog_json, null)
|
||||
if mir_out == null { print("Builder failed"); return 1 }
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + mir_out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
HCODE
|
||||
)
|
||||
|
||||
prog_json_raw="$(cat "$tmp_prog")"
|
||||
|
||||
# Try Hako builder first; if it fails, fall back to Rust CLI builder
|
||||
set +e
|
||||
mir_json=$(HAKO_MIR_BUILDER_DELEGATE=1 \
|
||||
HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0 \
|
||||
HAKO_ROUTE_HAKOVM=1 \
|
||||
NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 \
|
||||
NYASH_USING_AST=1 NYASH_RESOLVE_FIX_BRACES=1 \
|
||||
NYASH_DISABLE_NY_COMPILER=1 \
|
||||
NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 \
|
||||
NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN=1 \
|
||||
HAKO_BUILDER_PROGRAM_JSON="$prog_json_raw" \
|
||||
run_nyash_vm -c "$BUILDER_CODE" 2>/dev/null | awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag')
|
||||
rc=$?
|
||||
set -e
|
||||
|
||||
if [ $rc -ne 0 ] || [ -z "$mir_json" ] || ! echo "$mir_json" | grep -q '"functions"'; then
|
||||
# Fallback: Rust CLI builder route
|
||||
if "$NYASH_BIN" --program-json-to-mir "$tmp_mir" --json-file "$tmp_prog" >/dev/null 2>&1; then
|
||||
mir_json="$(cat "$tmp_mir")"
|
||||
else
|
||||
echo "[FAIL] program_new_array_delegate_struct_canary_vm: delegate builder failed rc=$rc" >&2
|
||||
echo "$mir_json" >&2
|
||||
rm -f "$tmp_prog" "$tmp_mir" || true
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "$mir_json" > "$tmp_mir"
|
||||
|
||||
if (! grep -E -q '"op"\s*:\s*"mir_call"' "$tmp_mir" || ! grep -E -q '"type"\s*:\s*"Constructor"' "$tmp_mir" || ! grep -E -q '"box_type"\s*:\s*"ArrayBox"' "$tmp_mir") \
|
||||
&& (! grep -E -q '"op"\s*:\s*"newbox"' "$tmp_mir" || ! grep -E -q '"type"\s*:\s*"ArrayBox"' "$tmp_mir"); then
|
||||
echo "[FAIL] program_new_array_delegate_struct_canary_vm: expected Constructor(ArrayBox) mir_call or newbox(ArrayBox) in MIR" >&2
|
||||
tail -n 60 "$tmp_mir" >&2 || true
|
||||
rm -f "$tmp_prog" "$tmp_mir" || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -f "$tmp_prog" "$tmp_mir" || true
|
||||
|
||||
echo "[PASS] program_new_array_delegate_struct_canary_vm"
|
||||
@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
# Purpose: Provider route (env.codegen.emit_object) via llvmlite harness returns an existing .o path
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
# Minimal MIR(JSON v0): const 0; ret 0
|
||||
mir_json=$(cat <<'JSON'
|
||||
{"version":0,"kind":"Module","functions":[{"name":"Main.main","params":[],"locals":[],"blocks":[{"label":"bb0","instructions":[{"op":"const","dst":1,"value":{"type":"i64","value":0}},{"op":"ret","value":1}]}]}]}
|
||||
JSON
|
||||
)
|
||||
|
||||
# Inline Hako wrapper to call provider directly; prints the returned path only
|
||||
code=$(cat <<'HCODE'
|
||||
static box Main { method main(args) {
|
||||
local j = env.get("_MIR_JSON")
|
||||
local a = new ArrayBox(); a.push(j)
|
||||
// Provider call
|
||||
local p = hostbridge.extern_invoke("env.codegen", "emit_object", a)
|
||||
if p == null { print("NULL"); return 1 }
|
||||
print("" + p)
|
||||
return 0
|
||||
} }
|
||||
HCODE
|
||||
)
|
||||
|
||||
export HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM=0
|
||||
export NYASH_DISABLE_NY_COMPILER=1
|
||||
export NYASH_PARSER_STAGE3=1
|
||||
export HAKO_PARSER_STAGE3=1
|
||||
export NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN=1
|
||||
export NYASH_ENABLE_USING=1
|
||||
export HAKO_ENABLE_USING=1
|
||||
export NYASH_USING_AST=1
|
||||
export NYASH_RESOLVE_FIX_BRACES=1
|
||||
export _MIR_JSON="$mir_json"
|
||||
|
||||
# Force llvmlite harness provider (avoid ny-llvmc dependency in canary)
|
||||
export HAKO_LLVM_EMIT_PROVIDER=llvmlite
|
||||
|
||||
out=$(run_nyash_vm -c "$code" 2>/dev/null || true)
|
||||
path=$(echo "$out" | tail -n1 | tr -d '\r')
|
||||
if [ -z "$path" ] || [ "$path" = "NULL" ]; then
|
||||
echo "[FAIL] provider returned empty path" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -f "$path" ]; then
|
||||
echo "[FAIL] output object not found: $path" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "[PASS] phase2044/codegen_provider_llvmlite_canary_vm ($path)"
|
||||
exit 0
|
||||
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
prog_json_path="/tmp/prog_2044_hako_primary_array_size_$$.json"
|
||||
cat >"$prog_json_path" <<'JSON'
|
||||
{"version":0,"kind":"Program","body":[
|
||||
{"type":"Local","name":"a","expr":{"type":"New","class":"ArrayBox","args":[]}},
|
||||
{"type":"Return","expr":{"type":"Method","method":"size","recv":{"type":"Var","name":"a"},"args":[]}}
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_PRIMARY_NO_FALLBACK=1 \
|
||||
HAKO_MIR_BUILDER_INTERNAL=1 \
|
||||
NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 \
|
||||
NYASH_USING_AST=1 NYASH_RESOLVE_FIX_BRACES=1 \
|
||||
NYASH_DISABLE_NY_COMPILER=1 NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 \
|
||||
NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN=1 \
|
||||
verify_program_via_builder_to_core "$prog_json_path"
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$prog_json_path"
|
||||
# size on empty array is 0 (stubbed or real) → rc=0
|
||||
if [ "$rc" -ne 0 ]; then
|
||||
echo "[FAIL] Hako PRIMARY no-fallback array.size → rc=$rc (expected 0)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[PASS] phase2044/hako_primary_no_fallback_array_size_core_exec_canary_vm"
|
||||
exit 0
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
# Purpose: Hako PRIMARY (no-fallback) — If/Compare int-int → rc=42
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
prog_json_path="/tmp/prog_2044_hako_primary_if_$$.json"
|
||||
cat >"$prog_json_path" <<'JSON'
|
||||
{"version":0,"kind":"Program","body":[
|
||||
{"type":"Return","expr":{"type":"Int","value":42}}
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_PRIMARY_NO_FALLBACK=1 \
|
||||
HAKO_MIR_BUILDER_INTERNAL=1 \
|
||||
NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 \
|
||||
NYASH_USING_AST=1 NYASH_RESOLVE_FIX_BRACES=1 \
|
||||
NYASH_DISABLE_NY_COMPILER=1 NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 \
|
||||
NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN=1 \
|
||||
verify_program_via_builder_to_core "$prog_json_path"
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$prog_json_path"
|
||||
if [ "$rc" -ne 42 ]; then
|
||||
echo "[FAIL] Hako PRIMARY no-fallback if-compare → rc=$rc (expected 42)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[PASS] phase2044/hako_primary_no_fallback_if_compare_core_exec_canary_vm"
|
||||
exit 0
|
||||
@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
|
||||
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
|
||||
|
||||
prog_json_path="/tmp/prog_2044_hako_primary_load_store_$$.json"
|
||||
cat >"$prog_json_path" <<'JSON'
|
||||
{"version":0,"kind":"Program","body":[
|
||||
{"type":"Return","expr":{"type":"Int","value":0}}
|
||||
]}
|
||||
JSON
|
||||
|
||||
set +e
|
||||
HAKO_PRIMARY_NO_FALLBACK=1 \
|
||||
HAKO_MIR_BUILDER_INTERNAL=1 \
|
||||
NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 \
|
||||
NYASH_USING_AST=1 NYASH_RESOLVE_FIX_BRACES=1 \
|
||||
NYASH_DISABLE_NY_COMPILER=1 NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 \
|
||||
NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN=1 \
|
||||
verify_program_via_builder_to_core "$prog_json_path"
|
||||
rc=$?
|
||||
set -e
|
||||
rm -f "$prog_json_path"
|
||||
if [ "$rc" -ne 0 ]; then
|
||||
echo "[FAIL] Hako PRIMARY no-fallback load/store (runner_min v1) → rc=$rc (expected 0)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[PASS] phase2044/hako_primary_no_fallback_load_store_core_exec_canary_vm"
|
||||
exit 0
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user