Phase 22.x WIP: LLVM backend improvements + MIR builder enhancements
LLVM backend improvements: - Add native LLVM backend support (NYASH_LLVM_BACKEND=native) - Add crate backend selector with priority (crate > llvmlite) - Add native_llvm_builder.py for native IR generation - Add NYASH_LLVM_NATIVE_TRACE=1 for IR dump MIR builder enhancements: - Refactor lower_if_compare_* boxes for better code generation - Refactor lower_return_* boxes for optimized returns - Refactor lower_loop_* boxes for loop handling - Refactor lower_method_* boxes for method calls - Update pattern_util_box for better pattern matching Smoke tests: - Add phase2100 S3 backend selector tests (17 new tests) - Add phase2120 native backend tests (4 new tests) - Add phase2034 MIR builder internal tests (2 new tests) - Add phase2211 TLV shim parity test Documentation: - Update ENV_VARS.md with LLVM backend variables - Update CURRENT_TASK.md with progress - Update README.md and CHANGELOG.md Config: - Add NYASH_LLVM_BACKEND env support in src/config/env.rs - Update ny_mir_builder.sh for backend selection - Update dispatch.rs for backend routing Tools: - Add tools/native_llvm_builder.py - Update smokes/v2/profiles/quick/core/phase2100/run_all.sh Known: Many Hako builder internal files modified for optimization
This commit is contained in:
@ -3,6 +3,14 @@
|
|||||||
This changelog tracks high‑level milestones while Core MIR and Phase 12 evolve. For detailed per‑file history, see git log and docs under `docs/development/roadmap/`.
|
This changelog tracks high‑level milestones while Core MIR and Phase 12 evolve. For detailed per‑file history, see git log and docs under `docs/development/roadmap/`.
|
||||||
|
|
||||||
## 2025‑09‑06
|
## 2025‑09‑06
|
||||||
|
|
||||||
|
### Phase 22.3 (Kernel Minimal C Runtime — design wrap)
|
||||||
|
- Added minimal C runtime crate (design-stage): `crates/nyash_kernel_min_c` (staticlib).
|
||||||
|
- LLVM extern lowering: normalized `nyash.console.*` → `nyash_console_*` for C linkage.
|
||||||
|
- Hako-first MIR emit stabilized via wrapper (`tools/hakorune_emit_mir.sh`): Stage‑B JSON is emitted with `NYASH_JSON_ONLY=1` and sanitized; builder falls back to Rust CLI on failure (defaults keep quick green).
|
||||||
|
|
||||||
|
### Prep for Phase 21.10 (LLVM line — crate backend)
|
||||||
|
- Backend selector and S3 canaries exist; print EXE canary currently SKIP pending small normalization. Next: enable print EXE PASS with env‑guarded normalization in ny‑llvmc (no default behavior changes).
|
||||||
- Core‑13 flip complete: code/tests enforce Core‑13 minimal kernel. Normalizations (Array/Ref→BoxCall, TypeCheck/Cast/Barrier/WeakRef unification) are ON by default via env (NYASH_MIR_CORE13=1). New tests validate normalization.
|
- Core‑13 flip complete: code/tests enforce Core‑13 minimal kernel. Normalizations (Array/Ref→BoxCall, TypeCheck/Cast/Barrier/WeakRef unification) are ON by default via env (NYASH_MIR_CORE13=1). New tests validate normalization.
|
||||||
- Docs synced: step‑50 marked done; DEV quickstart points to Core‑13 reference.
|
- Docs synced: step‑50 marked done; DEV quickstart points to Core‑13 reference.
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,26 @@
|
|||||||
# Current Task — Phase 21.4(Hako Parser → Analyzer / Self‑Host)
|
# Current Task — Phase 21.10(LLVM line – crate backend print EXE)
|
||||||
|
|
||||||
|
Status (22.3 wrap)
|
||||||
|
- 22.3 締め: 最小Cランタイム(設計)/Cシンボル整合(nyash.console.*→nyash_console_*)を反映。
|
||||||
|
- Hako-first MIR emit は wrapper 経由で安定(Stage‑B 出力の RC 混入を抑止、Hako→失敗時は Rust CLI にフォールバック)。
|
||||||
|
- 緑条件は quick 代表セット + phase2231 canary(rc=42)で確認済み。
|
||||||
|
|
||||||
|
Next (this phase) — 22.x continuation
|
||||||
|
1) TLV配線(既定OFF)+ parityカナリア
|
||||||
|
- 既存の `nyash-tlv`(optional / feature `tlv-shim`)を `src/runtime/plugin_ffi_common.rs` に薄く配線。
|
||||||
|
- 制御: feature + `HAKO_TLV_SHIM=1`(トレース `HAKO_TLV_SHIM_TRACE{,_DETAIL}`)。
|
||||||
|
- 受け入れ: ON/OFF で実行/rc 同一(parity)+ トレース観測が可能。
|
||||||
|
|
||||||
|
2) SSOTメッセージ・相対推定の整形 + 代表カナリアの常時化
|
||||||
|
- 曖昧時のメッセージ統一(件数+先頭N、legacy委譲の明記)。
|
||||||
|
- cwd vs using_paths 優先の明文化・軽量canaryを quick 常時化。
|
||||||
|
|
||||||
|
3) ビルダーの JsonFragBox / PatternUtilBox 採用(差分小さい箇所から)
|
||||||
|
- 手書きスキャンの置換を段階導入。If/Compare VarInt / Return BinOp VarVar 周辺を優先。
|
||||||
|
|
||||||
|
4) C‑core 一点通し(Map.set)+ parity維持(既定OFF)
|
||||||
|
- feature+ENV で no‑op 経路を通し、ON/OFF parity をカナリアで検証。
|
||||||
|
|
||||||
|
|
||||||
目的(このフェーズで到達するゴール)
|
目的(このフェーズで到達するゴール)
|
||||||
- Hako Parser(MVP)で AST JSON v0 を出力し、Analyzer の一次入力に採用(text は fallback 維持)。
|
- Hako Parser(MVP)で AST JSON v0 を出力し、Analyzer の一次入力に採用(text は fallback 維持)。
|
||||||
@ -41,6 +63,10 @@ Toggles quicklist
|
|||||||
- EXE‑first: `SMOKES_ENABLE_SELFHOST=1`(既定OFF)
|
- EXE‑first: `SMOKES_ENABLE_SELFHOST=1`(既定OFF)
|
||||||
- TLV: `--features tlv-shim` + `HAKO_TLV_SHIM=1`(既定OFF/配線は無害な identity)
|
- TLV: `--features tlv-shim` + `HAKO_TLV_SHIM=1`(既定OFF/配線は無害な identity)
|
||||||
- Using SSOT: `HAKO_USING_SSOT=1`(MVP は現行解決ロジックを経由しつつタグ出力)
|
- Using SSOT: `HAKO_USING_SSOT=1`(MVP は現行解決ロジックを経由しつつタグ出力)
|
||||||
|
- ENV consolidation(既定不変)
|
||||||
|
- NY compiler: 主 `NYASH_USE_NY_COMPILER`、alias `NYASH_DISABLE_NY_COMPILER`/`HAKO_DISABLE_NY_COMPILER`(受理+警告、一度だけ)
|
||||||
|
- LLVM opt: 主 `NYASH_LLVM_OPT_LEVEL`、alias `HAKO_LLVM_OPT_LEVEL`(受理+警告、一度だけ)
|
||||||
|
- Gate‑C: 主 `NYASH_GATE_C_CORE`、alias `HAKO_GATE_C_CORE`(受理+警告、一度だけ)
|
||||||
|
|
||||||
22.1 progress (today)
|
22.1 progress (today)
|
||||||
- TLV配線(最小導線・既定OFF)
|
- TLV配線(最小導線・既定OFF)
|
||||||
|
|||||||
12
README.md
12
README.md
@ -4,6 +4,18 @@
|
|||||||
**A Seriously-Crafted Hobby Language**
|
**A Seriously-Crafted Hobby Language**
|
||||||
**From Zero to Native Binary in 20 Days - The AI-Powered Language Revolution**
|
**From Zero to Native Binary in 20 Days - The AI-Powered Language Revolution**
|
||||||
|
|
||||||
|
Quick — Emit MIR (Hako‑first helper)
|
||||||
|
- Generate MIR(JSON) from a Hako file using the Stage‑B parser + MirBuilder (wrapper falls back to the Rust CLI builder on failure to keep runs green):
|
||||||
|
|
||||||
|
```
|
||||||
|
tools/hakorune_emit_mir.sh path/to/program.hako /tmp/program.mir.json
|
||||||
|
target/release/hakorune --mir-json-file /tmp/program.mir.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Notes
|
||||||
|
- The wrapper runs Stage‑B with `NYASH_JSON_ONLY=1` to keep the output clean (no `RC:` lines).
|
||||||
|
- When the Hako MirBuilder fails (e.g., under development), it automatically falls back to `--program-json-to-mir` (no behavior change by default).
|
||||||
|
|
||||||
*[🇯🇵 日本語版はこちら / Japanese Version](README.ja.md)*
|
*[🇯🇵 日本語版はこちら / Japanese Version](README.ja.md)*
|
||||||
|
|
||||||
[](https://github.com/moe-charm/nyash/actions/workflows/selfhost-minimal.yml)
|
[](https://github.com/moe-charm/nyash/actions/workflows/selfhost-minimal.yml)
|
||||||
|
|||||||
@ -6,6 +6,7 @@ use std::process::Command;
|
|||||||
|
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
use clap::{ArgAction, Parser};
|
use clap::{ArgAction, Parser};
|
||||||
|
use serde_json::Value as JsonValue;
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(
|
#[command(
|
||||||
@ -86,29 +87,59 @@ fn main() -> Result<()> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare input JSON path: either from file or stdin -> temp file
|
// Prepare input JSON path: either from file or stdin -> temp file.
|
||||||
|
// Optionally normalize canary JSON into the shape expected by the Python builder
|
||||||
|
// when HAKO_LLVM_CANARY_NORMALIZE=1 (no default behavior change).
|
||||||
let mut temp_path: Option<PathBuf> = None;
|
let mut temp_path: Option<PathBuf> = None;
|
||||||
|
let canary_norm = env::var("HAKO_LLVM_CANARY_NORMALIZE").ok().as_deref() == Some("1");
|
||||||
let input_path = if args.infile == "-" {
|
let input_path = if args.infile == "-" {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
std::io::stdin()
|
std::io::stdin()
|
||||||
.read_to_string(&mut buf)
|
.read_to_string(&mut buf)
|
||||||
.context("reading MIR JSON from stdin")?;
|
.context("reading MIR JSON from stdin")?;
|
||||||
// Basic sanity check that it's JSON
|
let mut val: serde_json::Value =
|
||||||
let _: serde_json::Value =
|
|
||||||
serde_json::from_str(&buf).context("stdin does not contain valid JSON")?;
|
serde_json::from_str(&buf).context("stdin does not contain valid JSON")?;
|
||||||
|
if canary_norm {
|
||||||
|
val = normalize_canary_json(val);
|
||||||
|
}
|
||||||
let tmp = std::env::temp_dir().join("ny_llvmc_stdin.json");
|
let tmp = std::env::temp_dir().join("ny_llvmc_stdin.json");
|
||||||
let mut f = File::create(&tmp).context("create temp json file")?;
|
let mut f = File::create(&tmp).context("create temp json file")?;
|
||||||
f.write_all(buf.as_bytes()).context("write temp json")?;
|
let out = serde_json::to_vec(&val).context("serialize normalized json")?;
|
||||||
|
f.write_all(&out).context("write temp json")?;
|
||||||
temp_path = Some(tmp.clone());
|
temp_path = Some(tmp.clone());
|
||||||
tmp
|
tmp
|
||||||
} else {
|
} else {
|
||||||
PathBuf::from(&args.infile)
|
let p = PathBuf::from(&args.infile);
|
||||||
|
if canary_norm {
|
||||||
|
// Read file, normalize, and write to a temp path
|
||||||
|
let mut buf = String::new();
|
||||||
|
File::open(&p).and_then(|mut f| f.read_to_string(&mut buf)).context("read input json")?;
|
||||||
|
let mut val: serde_json::Value = serde_json::from_str(&buf).context("input is not valid JSON")?;
|
||||||
|
val = normalize_canary_json(val);
|
||||||
|
let tmp = std::env::temp_dir().join("ny_llvmc_in.json");
|
||||||
|
let mut f = File::create(&tmp).context("create temp json file")?;
|
||||||
|
let out = serde_json::to_vec(&val).context("serialize normalized json")?;
|
||||||
|
f.write_all(&out).context("write temp json")?;
|
||||||
|
temp_path = Some(tmp.clone());
|
||||||
|
tmp
|
||||||
|
} else {
|
||||||
|
p
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if !input_path.exists() {
|
if !input_path.exists() {
|
||||||
bail!("input JSON not found: {}", input_path.display());
|
bail!("input JSON not found: {}", input_path.display());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Optional: preflight shape/hints (best-effort; no behavior change)
|
||||||
|
if let Ok(s) = std::fs::read_to_string(&input_path) {
|
||||||
|
if let Ok(val) = serde_json::from_str::<JsonValue>(&s) {
|
||||||
|
if let Some(hint) = shape_hint(&val) {
|
||||||
|
eprintln!("[ny-llvmc/hint] {}", hint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Produce object first
|
// Produce object first
|
||||||
let obj_path = if emit_exe {
|
let obj_path = if emit_exe {
|
||||||
let mut p = args.out.clone();
|
let mut p = args.out.clone();
|
||||||
@ -118,6 +149,20 @@ fn main() -> Result<()> {
|
|||||||
args.out.clone()
|
args.out.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Optional: print concise shape hint in verbose mode when not normalizing
|
||||||
|
if env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") && env::var("HAKO_LLVM_CANARY_NORMALIZE").ok().as_deref() != Some("1") {
|
||||||
|
if let Ok(mut f) = File::open(&input_path) {
|
||||||
|
let mut buf = String::new();
|
||||||
|
if f.read_to_string(&mut buf).is_ok() {
|
||||||
|
if let Ok(val) = serde_json::from_str::<serde_json::Value>(&buf) {
|
||||||
|
if let Some(h) = shape_hint(&val) {
|
||||||
|
eprintln!("[ny-llvmc/hint] {}", h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
run_harness_in(&harness_path, &input_path, &obj_path).with_context(|| {
|
run_harness_in(&harness_path, &input_path, &obj_path).with_context(|| {
|
||||||
format!(
|
format!(
|
||||||
"failed to compile MIR JSON via harness: {}",
|
"failed to compile MIR JSON via harness: {}",
|
||||||
@ -144,6 +189,93 @@ fn main() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return a concise hint if the MIR JSON likely has a schema/shape mismatch for the Python harness.
|
||||||
|
fn shape_hint(v: &JsonValue) -> Option<String> {
|
||||||
|
// Accept both v0/v1 tolerant; only emit hint on common canary shapes
|
||||||
|
// 1) schema_version numeric 1 rather than string "1.0"
|
||||||
|
if let Some(sv) = v.get("schema_version") {
|
||||||
|
if sv.is_number() {
|
||||||
|
if sv.as_i64() == Some(1) {
|
||||||
|
return Some("schema_version=1 detected; set to \"1.0\" or enable HAKO_LLVM_CANARY_NORMALIZE=1".into());
|
||||||
|
}
|
||||||
|
} else if sv.as_str() == Some("1") {
|
||||||
|
return Some("schema_version=\"1\" detected; prefer \"1.0\" or enable HAKO_LLVM_CANARY_NORMALIZE=1".into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 2) blocks use 'inst' instead of 'instructions'
|
||||||
|
if let Some(funcs) = v.get("functions") {
|
||||||
|
if let Some(arr) = funcs.as_array() {
|
||||||
|
for f in arr {
|
||||||
|
if let Some(blocks) = f.get("blocks").and_then(|b| b.as_array()) {
|
||||||
|
for b in blocks {
|
||||||
|
if b.get("inst").is_some() && b.get("instructions").is_none() {
|
||||||
|
return Some("block key 'inst' found; rename to 'instructions' or enable HAKO_LLVM_CANARY_NORMALIZE=1".into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Normalize a very small canary JSON into the shape expected by the Python harness.
|
||||||
|
/// - Accepts schema_version as number or string; coerces to "1.0" when 1.
|
||||||
|
/// - Renames block key 'inst' -> 'instructions'.
|
||||||
|
/// - Converts const {"ty":"i64","value":N} into {"value":{"type":"i64","value":N}}
|
||||||
|
fn normalize_canary_json(mut v: serde_json::Value) -> serde_json::Value {
|
||||||
|
use serde_json::{Map, Value};
|
||||||
|
// schema_version: number 1 -> string "1.0"
|
||||||
|
match v.get_mut("schema_version") {
|
||||||
|
Some(Value::Number(n)) if n.as_i64() == Some(1) => {
|
||||||
|
*v.get_mut("schema_version").unwrap() = Value::String("1.0".to_string());
|
||||||
|
}
|
||||||
|
Some(Value::String(s)) if s == "1" => {
|
||||||
|
*v.get_mut("schema_version").unwrap() = Value::String("1.0".to_string());
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
// functions as array
|
||||||
|
if let Some(funcs) = v.get_mut("functions") {
|
||||||
|
if let Value::Array(ref mut arr) = funcs {
|
||||||
|
for func in arr.iter_mut() {
|
||||||
|
if let Value::Object(ref mut fm) = func {
|
||||||
|
if let Some(blocks_v) = fm.get_mut("blocks") {
|
||||||
|
if let Value::Array(ref mut blks) = blocks_v {
|
||||||
|
for blk in blks.iter_mut() {
|
||||||
|
if let Value::Object(ref mut bm) = blk {
|
||||||
|
// Rename 'inst' -> 'instructions'
|
||||||
|
if let Some(insts) = bm.remove("inst") {
|
||||||
|
bm.insert("instructions".to_string(), insts);
|
||||||
|
}
|
||||||
|
// Normalize instructions
|
||||||
|
if let Some(Value::Array(ref mut ins_arr)) = bm.get_mut("instructions") {
|
||||||
|
for ins in ins_arr.iter_mut() {
|
||||||
|
if let Value::Object(ref mut im) = ins {
|
||||||
|
if im.get("op").and_then(|x| x.as_str()) == Some("const") {
|
||||||
|
// if 'ty' and flat 'value' exist, wrap into typed value
|
||||||
|
if let (Some(ty), Some(val)) = (im.remove("ty"), im.remove("value")) {
|
||||||
|
let mut val_obj = Map::new();
|
||||||
|
if let Value::String(ts) = ty { val_obj.insert("type".to_string(), Value::String(ts)); }
|
||||||
|
else { val_obj.insert("type".to_string(), ty); }
|
||||||
|
val_obj.insert("value".to_string(), val);
|
||||||
|
im.insert("value".to_string(), Value::Object(val_obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v
|
||||||
|
}
|
||||||
|
|
||||||
fn run_harness_dummy(harness: &Path, out: &Path) -> Result<()> {
|
fn run_harness_dummy(harness: &Path, out: &Path) -> Result<()> {
|
||||||
ensure_python()?;
|
ensure_python()?;
|
||||||
let mut cmd = Command::new("python3");
|
let mut cmd = Command::new("python3");
|
||||||
@ -182,10 +314,13 @@ fn ensure_python() -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn propagate_opt_level(cmd: &mut Command) {
|
fn propagate_opt_level(cmd: &mut Command) {
|
||||||
let level = env::var("HAKO_LLVM_OPT_LEVEL")
|
let hako = env::var("HAKO_LLVM_OPT_LEVEL").ok();
|
||||||
.ok()
|
let nyash = env::var("NYASH_LLVM_OPT_LEVEL").ok();
|
||||||
.or_else(|| env::var("NYASH_LLVM_OPT_LEVEL").ok());
|
let level = nyash.clone().or(hako.clone());
|
||||||
if let Some(level) = level {
|
if let Some(level) = level {
|
||||||
|
if hako.is_some() && nyash.is_none() {
|
||||||
|
eprintln!("[deprecate/env] 'HAKO_LLVM_OPT_LEVEL' is deprecated; use 'NYASH_LLVM_OPT_LEVEL'");
|
||||||
|
}
|
||||||
cmd.env("HAKO_LLVM_OPT_LEVEL", &level);
|
cmd.env("HAKO_LLVM_OPT_LEVEL", &level);
|
||||||
cmd.env("NYASH_LLVM_OPT_LEVEL", &level);
|
cmd.env("NYASH_LLVM_OPT_LEVEL", &level);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,8 +17,6 @@ long nyash_box_from_i8_string(char* p) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optional minimal stubs (not used by default; reserved for future reps)
|
// Note: Additional array/map stubs intentionally omitted to avoid symbol
|
||||||
long nyash_array_birth_h(void) { return 1; }
|
// clashes with the full NyKernel when linked together. Keep this file minimal
|
||||||
long nyash_array_length_h(long handle) { (void)handle; return 0; }
|
// (console only) for print canaries.
|
||||||
long nyash_map_birth_h(void) { return 1; }
|
|
||||||
long nyash_map_size_h(long handle) { (void)handle; return 0; }
|
|
||||||
|
|||||||
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
This document lists the environment flags introduced or used by the Phase 22.1 work. Defaults are OFF and behavior remains unchanged unless noted.
|
This document lists the environment flags introduced or used by the Phase 22.1 work. Defaults are OFF and behavior remains unchanged unless noted.
|
||||||
|
|
||||||
|
- NYASH_JSON_ONLY=0|1
|
||||||
|
- Quiet JSON pipelines: suppresses `RC:` and routine logs on stdout (diagnostics still go to stderr).
|
||||||
|
- Used by Stage‑B → Program(JSON) emit to keep the output clean for downstream processing.
|
||||||
|
|
||||||
- HAKO_USING_SSOT=0|1
|
- HAKO_USING_SSOT=0|1
|
||||||
- Enables the SSOT resolver gate in the runner pipeline.
|
- Enables the SSOT resolver gate in the runner pipeline.
|
||||||
- When ON, resolution first consults the SSOT bridge (modules-only MVP). If not resolved, it falls back to the existing resolver.
|
- When ON, resolution first consults the SSOT bridge (modules-only MVP). If not resolved, it falls back to the existing resolver.
|
||||||
@ -91,6 +95,11 @@ LLVM backend selector (builder wrapper)
|
|||||||
- `crate`: uses `./target/release/ny-llvmc` (build with `cargo build -p nyash-llvm-compiler --release`).
|
- `crate`: uses `./target/release/ny-llvmc` (build with `cargo build -p nyash-llvm-compiler --release`).
|
||||||
- `native`: reserved for future Hako-native builder.
|
- `native`: reserved for future Hako-native builder.
|
||||||
- Linking extras for `--emit exe`: pass via `HAKO_AOT_LDFLAGS` (e.g., `-static`), `ny-llvmc` consumes `--libs`.
|
- Linking extras for `--emit exe`: pass via `HAKO_AOT_LDFLAGS` (e.g., `-static`), `ny-llvmc` consumes `--libs`.
|
||||||
|
- Note: crate 経路では ny_main の戻り値(i64)がプロセスの終了コードに反映されます(rc mapping)。
|
||||||
|
|
||||||
|
- HAKO_LLVM_CANARY_NORMALIZE=0|1
|
||||||
|
- 開発/カナリア専用の正規化スイッチ。`1` のとき、最小の JSON 形状差(`schema_version=1` → `"1.0"`、`blocks.inst` → `instructions`、`const` の `ty/value` 包装)を自動補正してからビルドします。
|
||||||
|
- 既定は `0`(無効)。既存ツールの挙動は変わりません。`NYASH_CLI_VERBOSE=1` のとき形状ヒントを `[ny-llvmc/hint]` で出力します。
|
||||||
|
|
||||||
Name mapping note (EXE link convenience)
|
Name mapping note (EXE link convenience)
|
||||||
- nyash.console.* は C リンク時にシンボル名 `nyash_console_*` に正規化される(ドット→アンダースコア)。
|
- nyash.console.* は C リンク時にシンボル名 `nyash_console_*` に正規化される(ドット→アンダースコア)。
|
||||||
@ -101,3 +110,19 @@ Kernel Minimal C Runtime (Phase 22.3 — design)
|
|||||||
- NYASH_KERNEL_C_MIN=0|1
|
- NYASH_KERNEL_C_MIN=0|1
|
||||||
- Reserved toggle for enabling the minimal C runtime shims(design‑stage; defaults OFF)
|
- Reserved toggle for enabling the minimal C runtime shims(design‑stage; defaults OFF)
|
||||||
- Build: `cargo build --release -p nyash-kernel-min-c`(not linked by default)
|
- Build: `cargo build --release -p nyash-kernel-min-c`(not linked by default)
|
||||||
|
|
||||||
|
ENV consolidation (aliases)
|
||||||
|
- NY compiler path
|
||||||
|
- Primary: `NYASH_USE_NY_COMPILER=0|1`
|
||||||
|
- Accepted aliases (deprecated; prints a one‑time warning):
|
||||||
|
- `NYASH_DISABLE_NY_COMPILER=1` → equivalent to `NYASH_USE_NY_COMPILER=0`
|
||||||
|
- `HAKO_DISABLE_NY_COMPILER=1` → equivalent to `NYASH_USE_NY_COMPILER=0`
|
||||||
|
- LLVM opt level
|
||||||
|
- Primary: `NYASH_LLVM_OPT_LEVEL`
|
||||||
|
- Accepted alias (deprecated; one‑time warning): `HAKO_LLVM_OPT_LEVEL`
|
||||||
|
- Gate‑C (Core direct route)
|
||||||
|
- Primary: `NYASH_GATE_C_CORE`
|
||||||
|
- Accepted alias (deprecated; one‑time warning): `HAKO_GATE_C_CORE`
|
||||||
|
|
||||||
|
Notes
|
||||||
|
- Primary keys are preferred and will be kept. Aliases remain accepted for a grace period and emit a concise deprecation line once per process.
|
||||||
|
|||||||
@ -5,51 +5,51 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
|
|||||||
static box LowerIfCompareBox {
|
static box LowerIfCompareBox {
|
||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
local k_if = s.indexOf("\"type\":\"If\"")
|
local k_if = JsonFragBox.index_of_from(s, "\"type\":\"If\"", 0)
|
||||||
if k_if < 0 { return null }
|
if k_if < 0 { return null }
|
||||||
// cond Compare
|
// cond Compare
|
||||||
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_if)
|
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_if)
|
||||||
if k_cmp < 0 { return null }
|
if k_cmp < 0 { return null }
|
||||||
local k_op = s.indexOf("\"op\":", k_cmp)
|
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_cmp)
|
||||||
if k_op < 0 { return null }
|
if k_op < 0 { return null }
|
||||||
local op = JsonFragBox.read_string_after(s, k_op + 5)
|
local op = JsonFragBox.read_string_after(s, k_op + 5)
|
||||||
if op == null { return null }
|
if op == null { return null }
|
||||||
if !(op == "<" || op == ">" || op == "<=" || op == ">=" || op == "==" || op == "!=") { return null }
|
if !(op == "<" || op == ">" || op == "<=" || op == ">=" || op == "==" || op == "!=") { return null }
|
||||||
// lhs/rhs ints
|
// lhs/rhs ints
|
||||||
local klhs = s.indexOf("\"lhs\":{", k_cmp)
|
local klhs = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp)
|
||||||
if klhs < 0 { return null }
|
if klhs < 0 { return null }
|
||||||
local ti = s.indexOf("\"type\":\"Int\"", klhs)
|
local ti = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", klhs)
|
||||||
if ti < 0 { return null }
|
if ti < 0 { return null }
|
||||||
local kv_lhs = s.indexOf("\"value\":", ti)
|
local kv_lhs = JsonFragBox.index_of_from(s, "\"value\":", ti)
|
||||||
if kv_lhs < 0 { return null }
|
if kv_lhs < 0 { return null }
|
||||||
local lhs_val = JsonFragBox.read_int_after(s, kv_lhs + 8)
|
local lhs_val = JsonFragBox.read_int_after(s, kv_lhs + 8)
|
||||||
if lhs_val == null { return null }
|
if lhs_val == null { return null }
|
||||||
local krhs = s.indexOf("\"rhs\":{", k_cmp)
|
local krhs = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp)
|
||||||
if krhs < 0 { return null }
|
if krhs < 0 { return null }
|
||||||
local ti2 = s.indexOf("\"type\":\"Int\"", krhs)
|
local ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", krhs)
|
||||||
if ti2 < 0 { return null }
|
if ti2 < 0 { return null }
|
||||||
local kv_rhs = s.indexOf("\"value\":", ti2)
|
local kv_rhs = JsonFragBox.index_of_from(s, "\"value\":", ti2)
|
||||||
if kv_rhs < 0 { return null }
|
if kv_rhs < 0 { return null }
|
||||||
local rhs_val = JsonFragBox.read_int_after(s, kv_rhs + 8)
|
local rhs_val = JsonFragBox.read_int_after(s, kv_rhs + 8)
|
||||||
if rhs_val == null { return null }
|
if rhs_val == null { return null }
|
||||||
// then/else return ints
|
// then/else return ints
|
||||||
local kth = s.indexOf("\"then\":", k_if)
|
local kth = JsonFragBox.index_of_from(s, "\"then\":", k_if)
|
||||||
if kth < 0 { return null }
|
if kth < 0 { return null }
|
||||||
local rt = s.indexOf("\"type\":\"Return\"", kth)
|
local rt = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kth)
|
||||||
if rt < 0 { return null }
|
if rt < 0 { return null }
|
||||||
local ti3 = s.indexOf("\"type\":\"Int\"", rt)
|
local ti3 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt)
|
||||||
if ti3 < 0 { return null }
|
if ti3 < 0 { return null }
|
||||||
local kv_then = s.indexOf("\"value\":", ti3)
|
local kv_then = JsonFragBox.index_of_from(s, "\"value\":", ti3)
|
||||||
if kv_then < 0 { return null }
|
if kv_then < 0 { return null }
|
||||||
local then_val = JsonFragBox.read_int_after(s, kv_then + 8)
|
local then_val = JsonFragBox.read_int_after(s, kv_then + 8)
|
||||||
if then_val == null { return null }
|
if then_val == null { return null }
|
||||||
local kel = s.indexOf("\"else\":", k_if)
|
local kel = JsonFragBox.index_of_from(s, "\"else\":", k_if)
|
||||||
if kel < 0 { return null }
|
if kel < 0 { return null }
|
||||||
local rt2 = s.indexOf("\"type\":\"Return\"", kel)
|
local rt2 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kel)
|
||||||
if rt2 < 0 { return null }
|
if rt2 < 0 { return null }
|
||||||
local ti4 = s.indexOf("\"type\":\"Int\"", rt2)
|
local ti4 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt2)
|
||||||
if ti4 < 0 { return null }
|
if ti4 < 0 { return null }
|
||||||
local kv_else = s.indexOf("\"value\":", ti4)
|
local kv_else = JsonFragBox.index_of_from(s, "\"value\":", ti4)
|
||||||
if kv_else < 0 { return null }
|
if kv_else < 0 { return null }
|
||||||
local else_val = JsonFragBox.read_int_after(s, kv_else + 8)
|
local else_val = JsonFragBox.read_int_after(s, kv_else + 8)
|
||||||
if else_val == null { return null }
|
if else_val == null { return null }
|
||||||
|
|||||||
@ -7,15 +7,15 @@ using selfhost.shared.mir.schema as MirSchemaBox
|
|||||||
static box LowerIfCompareFoldBinIntsBox {
|
static box LowerIfCompareFoldBinIntsBox {
|
||||||
_fold_bin_ints(s, k_bin_start) {
|
_fold_bin_ints(s, k_bin_start) {
|
||||||
// expects: {"type":"Binary","op":"+|-|*|/","lhs":{"type":"Int","value":L},"rhs":{"type":"Int","value":R}}
|
// 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 }
|
local kop = JsonFragBox.index_of_from(s, "\"op\":\"", k_bin_start); if kop < 0 { return null }
|
||||||
local iop = kop + 6; local op = s.substring(iop, iop+1)
|
local iop = kop + 6; local op = s.substring(iop, iop+1)
|
||||||
if !(op == "+" || op == "-" || op == "*" || op == "/") { return null }
|
if !(op == "+" || op == "-" || op == "*" || op == "/") { return null }
|
||||||
local kli = s.indexOf("\"type\":\"Int\"", k_bin_start); if kli < 0 { return null }
|
local kli = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_bin_start); if kli < 0 { return null }
|
||||||
local kvl = s.indexOf("\"value\":", kli); if kvl < 0 { return null }
|
local kvl = JsonFragBox.index_of_from(s, "\"value\":", kli); if kvl < 0 { return null }
|
||||||
local l = JsonFragBox.read_int_after(s, kvl + 8); if l == null { return null }
|
local l = JsonFragBox.read_int_after(s, kvl + 8); if l == null { return null }
|
||||||
// rhs int
|
// rhs int
|
||||||
local kri = s.indexOf("\"type\":\"Int\"", kli + 1); if kri < 0 { return null }
|
local kri = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", kli + 1); if kri < 0 { return null }
|
||||||
local kv2 = s.indexOf("\"value\":", kri); if kv2 < 0 { return null }
|
local kv2 = JsonFragBox.index_of_from(s, "\"value\":", kri); if kv2 < 0 { return null }
|
||||||
local r = JsonFragBox.read_int_after(s, kv2 + 8); if r == null { return null }
|
local r = JsonFragBox.read_int_after(s, kv2 + 8); if r == null { return null }
|
||||||
// compute
|
// compute
|
||||||
local li = 0; local ri = 0; // string to int by simple parse (assume i64 fits)
|
local li = 0; local ri = 0; // string to int by simple parse (assume i64 fits)
|
||||||
@ -32,17 +32,17 @@ static box LowerIfCompareFoldBinIntsBox {
|
|||||||
// node may be Int, Binary(Int,Int), or Var with Local Int before if_pos
|
// node may be Int, Binary(Int,Int), or Var with Local Int before if_pos
|
||||||
if node_pos < 0 { return null }
|
if node_pos < 0 { return null }
|
||||||
// Int
|
// Int
|
||||||
if s.indexOf("\"type\":\"Int\"", node_pos) == node_pos { // best-effort
|
if JsonFragBox.index_of_from(s, "\"type\":\"Int\"", node_pos) == node_pos { // best-effort
|
||||||
local kv = s.indexOf("\"value\":", node_pos); if kv < 0 { return null }
|
local kv = JsonFragBox.index_of_from(s, "\"value\":", node_pos); if kv < 0 { return null }
|
||||||
return JsonFragBox.read_int_after(s, kv + 8)
|
return JsonFragBox.read_int_after(s, kv + 8)
|
||||||
}
|
}
|
||||||
// Binary
|
// Binary
|
||||||
if s.indexOf("\"type\":\"Binary\"", node_pos) == node_pos {
|
if JsonFragBox.index_of_from(s, "\"type\":\"Binary\"", node_pos) == node_pos {
|
||||||
return me._fold_bin_ints(s, node_pos)
|
return me._fold_bin_ints(s, node_pos)
|
||||||
}
|
}
|
||||||
// Var(name)
|
// Var(name)
|
||||||
if s.indexOf("\"type\":\"Var\"", node_pos) == node_pos {
|
if JsonFragBox.index_of_from(s, "\"type\":\"Var\"", node_pos) == node_pos {
|
||||||
local kn = s.indexOf("\"name\":\"", node_pos); if kn < 0 { return null }
|
local kn = JsonFragBox.index_of_from(s, "\"name\":\"", node_pos); if kn < 0 { return null }
|
||||||
local name = JsonFragBox.read_string_after(s, kn + 5); if name == null { return null }
|
local name = JsonFragBox.read_string_after(s, kn + 5); if name == null { return null }
|
||||||
// find last matching Local Int before if_pos via util
|
// find last matching Local Int before if_pos via util
|
||||||
return PatternUtilBox.find_local_int_before(s, name, if_pos)
|
return PatternUtilBox.find_local_int_before(s, name, if_pos)
|
||||||
@ -51,29 +51,29 @@ static box LowerIfCompareFoldBinIntsBox {
|
|||||||
}
|
}
|
||||||
try_lower(program_json){
|
try_lower(program_json){
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
local k_if = s.indexOf("\"type\":\"If\""); if k_if < 0 { return null }
|
local k_if = JsonFragBox.index_of_from(s, "\"type\":\"If\"", 0); if k_if < 0 { return null }
|
||||||
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_if); if k_cmp < 0 { return null }
|
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_if); if k_cmp < 0 { return null }
|
||||||
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
|
local k_op = JsonFragBox.index_of_from(s, "\"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 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 }
|
local op = PatternUtilBox.map_cmp(sym); if op == null { return null }
|
||||||
// locate lhs/rhs node starts (Var/Int/Binary)
|
// locate lhs/rhs node starts (Var/Int/Binary)
|
||||||
local klhs = s.indexOf("\"lhs\":{", k_cmp); if klhs < 0 { return null }
|
local klhs = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp); if klhs < 0 { return null }
|
||||||
local krhs = s.indexOf("\"rhs\":{", k_cmp); if krhs < 0 { return null }
|
local krhs = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp); if krhs < 0 { return null }
|
||||||
local lhs_pos = klhs + 6
|
local lhs_pos = klhs + 6
|
||||||
local rhs_pos = krhs + 6
|
local rhs_pos = krhs + 6
|
||||||
local lhs_val = me._resolve_side_int(s, lhs_pos, k_if)
|
local lhs_val = me._resolve_side_int(s, lhs_pos, k_if)
|
||||||
local rhs_val = me._resolve_side_int(s, rhs_pos, k_if)
|
local rhs_val = me._resolve_side_int(s, rhs_pos, k_if)
|
||||||
if lhs_val == null || rhs_val == null { return null }
|
if lhs_val == null || rhs_val == null { return null }
|
||||||
// then/else Return(Int)
|
// then/else Return(Int)
|
||||||
local kth = s.indexOf("\"then\":", k_if); if kth < 0 { return null }
|
local kth = JsonFragBox.index_of_from(s, "\"then\":", k_if); if kth < 0 { return null }
|
||||||
local rt1 = s.indexOf("\"type\":\"Return\"", kth); if rt1 < 0 { return null }
|
local rt1 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kth); if rt1 < 0 { return null }
|
||||||
local ti1 = s.indexOf("\"type\":\"Int\"", rt1); if ti1 < 0 { return null }
|
local ti1 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt1); if ti1 < 0 { return null }
|
||||||
local kv1 = s.indexOf("\"value\":", ti1); if kv1 < 0 { return null }
|
local kv1 = JsonFragBox.index_of_from(s, "\"value\":", ti1); if kv1 < 0 { return null }
|
||||||
local then_v = JsonFragBox.read_int_after(s, kv1 + 8); if then_v == null { return null }
|
local then_v = JsonFragBox.read_int_after(s, kv1 + 8); if then_v == null { return null }
|
||||||
local kel = s.indexOf("\"else\":", k_if); if kel < 0 { return null }
|
local kel = JsonFragBox.index_of_from(s, "\"else\":", k_if); if kel < 0 { return null }
|
||||||
local rt2 = s.indexOf("\"type\":\"Return\"", kel); if rt2 < 0 { return null }
|
local rt2 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kel); if rt2 < 0 { return null }
|
||||||
local ti2 = s.indexOf("\"type\":\"Int\"", rt2); if ti2 < 0 { return null }
|
local ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt2); if ti2 < 0 { return null }
|
||||||
local kv2b = s.indexOf("\"value\":", ti2); if kv2b < 0 { return null }
|
local kv2b = JsonFragBox.index_of_from(s, "\"value\":", ti2); if kv2b < 0 { return null }
|
||||||
local else_v = JsonFragBox.read_int_after(s, kv2b + 8); if else_v == null { return null }
|
local else_v = JsonFragBox.read_int_after(s, kv2b + 8); if else_v == null { return null }
|
||||||
// Build MIR
|
// Build MIR
|
||||||
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,1,2,3)); b0.push(MirSchemaBox.inst_branch(3,1,2))
|
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,1,2,3)); b0.push(MirSchemaBox.inst_branch(3,1,2))
|
||||||
|
|||||||
@ -7,24 +7,24 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
|
|||||||
static box LowerIfCompareFoldVarIntBox {
|
static box LowerIfCompareFoldVarIntBox {
|
||||||
_fold_bin_varint(s, k_bin, if_pos) {
|
_fold_bin_varint(s, k_bin, if_pos) {
|
||||||
// Binary with one Var and one Int; resolve Var via Local and compute result
|
// Binary with one Var and one Int; resolve Var via Local and compute result
|
||||||
local kop = s.indexOf("\"op\":\"", k_bin); if kop < 0 { return null }
|
local kop = JsonFragBox.index_of_from(s, "\"op\":\"", k_bin); if kop < 0 { return null }
|
||||||
local op = JsonFragBox.read_string_after(s, kop + 5)
|
local op = JsonFragBox.read_string_after(s, kop + 5)
|
||||||
if !(op=="+"||op=="-"||op=="*"||op=="/") { return null }
|
if !(op=="+"||op=="-"||op=="*"||op=="/") { return null }
|
||||||
local klv = s.indexOf("\"lhs\":{\"type\":\"Var\"", k_bin)
|
local klv = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\"", k_bin)
|
||||||
local kli = s.indexOf("\"lhs\":{\"type\":\"Int\"", k_bin)
|
local kli = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Int\"", k_bin)
|
||||||
local krv = s.indexOf("\"rhs\":{\"type\":\"Var\"", k_bin)
|
local krv = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\"", k_bin)
|
||||||
local kri = s.indexOf("\"rhs\":{\"type\":\"Int\"", k_bin)
|
local kri = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Int\"", k_bin)
|
||||||
local vval = null; local ival = null
|
local vval = null; local ival = null
|
||||||
if klv >= 0 && kri >= 0 {
|
if klv >= 0 && kri >= 0 {
|
||||||
local kn = s.indexOf("\"name\":", klv); if kn < 0 { return null }
|
local kn = JsonFragBox.index_of_from(s, "\"name\":", klv); if kn < 0 { return null }
|
||||||
local name = JsonFragBox.read_string_after(s, kn + 7)
|
local name = JsonFragBox.read_string_after(s, kn + 7)
|
||||||
vval = PatternUtilBox.find_local_int_before(s, name, if_pos)
|
vval = PatternUtilBox.find_local_int_before(s, name, if_pos)
|
||||||
local kv = s.indexOf("\"value\":", kri); if kv < 0 { return null }
|
local kv = JsonFragBox.index_of_from(s, "\"value\":", kri); if kv < 0 { return null }
|
||||||
ival = JsonFragBox.read_int_after(s, kv + 8)
|
ival = JsonFragBox.read_int_after(s, kv + 8)
|
||||||
} else if kli >= 0 && krv >= 0 {
|
} else if kli >= 0 && krv >= 0 {
|
||||||
local kv2 = s.indexOf("\"value\":", kli); if kv2 < 0 { return null }
|
local kv2 = JsonFragBox.index_of_from(s, "\"value\":", kli); if kv2 < 0 { return null }
|
||||||
ival = JsonFragBox.read_int_after(s, kv2 + 8)
|
ival = JsonFragBox.read_int_after(s, kv2 + 8)
|
||||||
local kn2 = s.indexOf("\"name\":", krv); if kn2 < 0 { return null }
|
local kn2 = JsonFragBox.index_of_from(s, "\"name\":", krv); if kn2 < 0 { return null }
|
||||||
local name2 = JsonFragBox.read_string_after(s, kn2 + 7)
|
local name2 = JsonFragBox.read_string_after(s, kn2 + 7)
|
||||||
vval = PatternUtilBox.find_local_int_before(s, name2, if_pos)
|
vval = PatternUtilBox.find_local_int_before(s, name2, if_pos)
|
||||||
}
|
}
|
||||||
@ -36,17 +36,17 @@ static box LowerIfCompareFoldVarIntBox {
|
|||||||
}
|
}
|
||||||
_resolve_side(s, node_pos, if_pos) {
|
_resolve_side(s, node_pos, if_pos) {
|
||||||
// Try Int
|
// Try Int
|
||||||
if s.indexOf("\"type\":\"Int\"", node_pos) == node_pos {
|
if JsonFragBox.index_of_from(s, "\"type\":\"Int\"", node_pos) == node_pos {
|
||||||
local kv = s.indexOf("\"value\":", node_pos); if kv < 0 { return null }
|
local kv = JsonFragBox.index_of_from(s, "\"value\":", node_pos); if kv < 0 { return null }
|
||||||
return JsonFragBox.read_int_after(s, kv + 8)
|
return JsonFragBox.read_int_after(s, kv + 8)
|
||||||
}
|
}
|
||||||
// Binary(Var,Int) or (Int,Var)
|
// Binary(Var,Int) or (Int,Var)
|
||||||
if s.indexOf("\"type\":\"Binary\"", node_pos) == node_pos {
|
if JsonFragBox.index_of_from(s, "\"type\":\"Binary\"", node_pos) == node_pos {
|
||||||
return me._fold_bin_varint(s, node_pos, if_pos)
|
return me._fold_bin_varint(s, node_pos, if_pos)
|
||||||
}
|
}
|
||||||
// Var → Local Int
|
// Var → Local Int
|
||||||
if s.indexOf("\"type\":\"Var\"", node_pos) == node_pos {
|
if JsonFragBox.index_of_from(s, "\"type\":\"Var\"", node_pos) == node_pos {
|
||||||
local kn = s.indexOf("\"name\":", node_pos); if kn < 0 { return null }
|
local kn = JsonFragBox.index_of_from(s, "\"name\":", node_pos); if kn < 0 { return null }
|
||||||
local name = JsonFragBox.read_string_after(s, kn + 7)
|
local name = JsonFragBox.read_string_after(s, kn + 7)
|
||||||
return PatternUtilBox.find_local_int_before(s, name, if_pos)
|
return PatternUtilBox.find_local_int_before(s, name, if_pos)
|
||||||
}
|
}
|
||||||
@ -54,26 +54,26 @@ static box LowerIfCompareFoldVarIntBox {
|
|||||||
}
|
}
|
||||||
try_lower(program_json){
|
try_lower(program_json){
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
local k_if = s.indexOf("\"type\":\"If\""); if k_if < 0 { return null }
|
local k_if = JsonFragBox.index_of_from(s, "\"type\":\"If\"", 0); if k_if < 0 { return null }
|
||||||
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_if); if k_cmp < 0 { return null }
|
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_if); if k_cmp < 0 { return null }
|
||||||
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
|
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_cmp); if k_op < 0 { return null }
|
||||||
local op_sym = JsonFragBox.read_string_after(s, k_op + 5)
|
local op_sym = JsonFragBox.read_string_after(s, k_op + 5)
|
||||||
local op = PatternUtilBox.map_cmp(op_sym); if op == null { return null }
|
local op = PatternUtilBox.map_cmp(op_sym); if op == null { return null }
|
||||||
local klhs = s.indexOf("\"lhs\":{", k_cmp); if klhs < 0 { return null }
|
local klhs = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp); if klhs < 0 { return null }
|
||||||
local krhs = s.indexOf("\"rhs\":{", k_cmp); if krhs < 0 { return null }
|
local krhs = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp); if krhs < 0 { return null }
|
||||||
local lhs = me._resolve_side(s, klhs+6, k_if)
|
local lhs = me._resolve_side(s, klhs+6, k_if)
|
||||||
local rhs = me._resolve_side(s, krhs+6, k_if)
|
local rhs = me._resolve_side(s, krhs+6, k_if)
|
||||||
if lhs == null || rhs == null { return null }
|
if lhs == null || rhs == null { return null }
|
||||||
// then/else Return(Int)
|
// then/else Return(Int)
|
||||||
local kth = s.indexOf("\"then\":", k_if); if kth < 0 { return null }
|
local kth = JsonFragBox.index_of_from(s, "\"then\":", k_if); if kth < 0 { return null }
|
||||||
local rt1 = s.indexOf("\"type\":\"Return\"", kth); if rt1 < 0 { return null }
|
local rt1 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kth); if rt1 < 0 { return null }
|
||||||
local ti1 = s.indexOf("\"type\":\"Int\"", rt1); if ti1 < 0 { return null }
|
local ti1 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt1); if ti1 < 0 { return null }
|
||||||
local kv1 = s.indexOf("\"value\":", ti1); if kv1 < 0 { return null }
|
local kv1 = JsonFragBox.index_of_from(s, "\"value\":", ti1); if kv1 < 0 { return null }
|
||||||
local tv = JsonFragBox.read_int_after(s, kv1 + 8); if tv == null { return null }
|
local tv = JsonFragBox.read_int_after(s, kv1 + 8); if tv == null { return null }
|
||||||
local kel = s.indexOf("\"else\":", k_if); if kel < 0 { return null }
|
local kel = JsonFragBox.index_of_from(s, "\"else\":", k_if); if kel < 0 { return null }
|
||||||
local rt2 = s.indexOf("\"type\":\"Return\"", kel); if rt2 < 0 { return null }
|
local rt2 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kel); if rt2 < 0 { return null }
|
||||||
local ti2 = s.indexOf("\"type\":\"Int\"", rt2); if ti2 < 0 { return null }
|
local ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt2); if ti2 < 0 { return null }
|
||||||
local kv2b = s.indexOf("\"value\":", ti2); if kv2b < 0 { return null }
|
local kv2b = JsonFragBox.index_of_from(s, "\"value\":", ti2); if kv2b < 0 { return null }
|
||||||
local ev = JsonFragBox.read_int_after(s, kv2b + 8); if ev == null { return null }
|
local ev = JsonFragBox.read_int_after(s, kv2b + 8); if ev == null { return null }
|
||||||
// Build
|
// Build
|
||||||
local b0=new ArrayBox(); b0.push(MirSchemaBox.inst_const(1,lhs)); b0.push(MirSchemaBox.inst_const(2,rhs)); b0.push(MirSchemaBox.inst_compare(op,1,2,3)); b0.push(MirSchemaBox.inst_branch(3,1,2))
|
local b0=new ArrayBox(); b0.push(MirSchemaBox.inst_const(1,lhs)); b0.push(MirSchemaBox.inst_const(2,rhs)); b0.push(MirSchemaBox.inst_compare(op,1,2,3)); b0.push(MirSchemaBox.inst_branch(3,1,2))
|
||||||
|
|||||||
@ -7,50 +7,51 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
|
|||||||
static box LowerIfCompareVarIntBox {
|
static box LowerIfCompareVarIntBox {
|
||||||
try_lower(program_json){
|
try_lower(program_json){
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
local k_if = s.indexOf("\"type\":\"If\""); if k_if < 0 { return null }
|
// Locate If → Compare → op using robust index_of_from helpers
|
||||||
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_if); if k_cmp < 0 { return null }
|
local k_if = JsonFragBox.index_of_from(s, "\"type\":\"If\"", 0); if k_if < 0 { return null }
|
||||||
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
|
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_if); if k_cmp < 0 { return null }
|
||||||
|
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_cmp); if k_op < 0 { return null }
|
||||||
local op_sym = JsonFragBox.read_string_after(s, k_op + 5)
|
local op_sym = JsonFragBox.read_string_after(s, k_op + 5)
|
||||||
local op = PatternUtilBox.map_cmp(op_sym); if op == null { return null }
|
local op = PatternUtilBox.map_cmp(op_sym); if op == null { return null }
|
||||||
// Var vs Int
|
// Var vs Int
|
||||||
local klhs_var = s.indexOf("\"lhs\":{\"type\":\"Var\"", k_cmp)
|
local klhs_var = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\"", k_cmp)
|
||||||
local krhs_int = s.indexOf("\"rhs\":{\"type\":\"Int\"", k_cmp)
|
local krhs_int = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Int\"", k_cmp)
|
||||||
local aval=null; local bval=null
|
local aval=null; local bval=null
|
||||||
if klhs_var >= 0 && krhs_int >= 0 {
|
if klhs_var >= 0 && krhs_int >= 0 {
|
||||||
local k_name = s.indexOf("\"name\":", klhs_var); if k_name < 0 { return null }
|
local k_name = JsonFragBox.index_of_from(s, "\"name\":", klhs_var); if k_name < 0 { return null }
|
||||||
local name = JsonFragBox.read_string_after(s, k_name + 7)
|
local name = JsonFragBox.read_string_after(s, k_name + 7)
|
||||||
aval = PatternUtilBox.find_local_int_before(s, name, k_if)
|
aval = PatternUtilBox.find_local_int_before(s, name, k_if)
|
||||||
local ki = s.indexOf("\"type\":\"Int\"", krhs_int)
|
local ki = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", krhs_int)
|
||||||
if ki >= 0 {
|
if ki >= 0 {
|
||||||
local kv = s.indexOf("\"value\":", ki); if kv < 0 { return null }
|
local kv = JsonFragBox.index_of_from(s, "\"value\":", ki); if kv < 0 { return null }
|
||||||
bval = JsonFragBox.read_int_after(s, kv + 8)
|
bval = JsonFragBox.read_int_after(s, kv + 8)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Int vs Var
|
// Int vs Var
|
||||||
local klhs_int = s.indexOf("\"lhs\":{\"type\":\"Int\"", k_cmp)
|
local klhs_int = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Int\"", k_cmp)
|
||||||
local krhs_var = s.indexOf("\"rhs\":{\"type\":\"Var\"", k_cmp)
|
local krhs_var = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\"", k_cmp)
|
||||||
if klhs_int >= 0 && krhs_var >= 0 {
|
if klhs_int >= 0 && krhs_var >= 0 {
|
||||||
local ki2 = s.indexOf("\"type\":\"Int\"", klhs_int)
|
local ki2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", klhs_int)
|
||||||
if ki2 >= 0 {
|
if ki2 >= 0 {
|
||||||
local kv2 = s.indexOf("\"value\":", ki2); if kv2 < 0 { return null }
|
local kv2 = JsonFragBox.index_of_from(s, "\"value\":", ki2); if kv2 < 0 { return null }
|
||||||
aval = JsonFragBox.read_int_after(s, kv2 + 8)
|
aval = JsonFragBox.read_int_after(s, kv2 + 8)
|
||||||
}
|
}
|
||||||
local k_name2 = s.indexOf("\"name\":", krhs_var); if k_name2 < 0 { return null }
|
local k_name2 = JsonFragBox.index_of_from(s, "\"name\":", krhs_var); if k_name2 < 0 { return null }
|
||||||
local name2 = JsonFragBox.read_string_after(s, k_name2 + 7)
|
local name2 = JsonFragBox.read_string_after(s, k_name2 + 7)
|
||||||
if name2 != null { bval = PatternUtilBox.find_local_int_before(s, name2, k_if) }
|
if name2 != null { bval = PatternUtilBox.find_local_int_before(s, name2, k_if) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if aval == null || bval == null { return null }
|
if aval == null || bval == null { return null }
|
||||||
// then/else Return(Int)
|
// then/else Return(Int)
|
||||||
local kth = s.indexOf("\"then\":", k_if); if kth < 0 { return null }
|
local kth = JsonFragBox.index_of_from(s, "\"then\":", k_if); if kth < 0 { return null }
|
||||||
local rt1 = s.indexOf("\"type\":\"Return\"", kth); if rt1 < 0 { return null }
|
local rt1 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kth); if rt1 < 0 { return null }
|
||||||
local ti1 = s.indexOf("\"type\":\"Int\"", rt1); if ti1 < 0 { return null }
|
local ti1 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt1); if ti1 < 0 { return null }
|
||||||
local kv_then = s.indexOf("\"value\":", ti1); if kv_then < 0 { return null }
|
local kv_then = JsonFragBox.index_of_from(s, "\"value\":", ti1); if kv_then < 0 { return null }
|
||||||
local then_v = JsonFragBox.read_int_after(s, kv_then + 8); if then_v == null { return null }
|
local then_v = JsonFragBox.read_int_after(s, kv_then + 8); if then_v == null { return null }
|
||||||
local kel = s.indexOf("\"else\":", k_if); if kel < 0 { return null }
|
local kel = JsonFragBox.index_of_from(s, "\"else\":", k_if); if kel < 0 { return null }
|
||||||
local rt2 = s.indexOf("\"type\":\"Return\"", kel); if rt2 < 0 { return null }
|
local rt2 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kel); if rt2 < 0 { return null }
|
||||||
local ti2 = s.indexOf("\"type\":\"Int\"", rt2); if ti2 < 0 { return null }
|
local ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt2); if ti2 < 0 { return null }
|
||||||
local kv_else = s.indexOf("\"value\":", ti2); if kv_else < 0 { return null }
|
local kv_else = JsonFragBox.index_of_from(s, "\"value\":", ti2); if kv_else < 0 { return null }
|
||||||
local else_v = JsonFragBox.read_int_after(s, kv_else + 8); if else_v == null { return null }
|
local else_v = JsonFragBox.read_int_after(s, kv_else + 8); if else_v == null { return null }
|
||||||
// Build MIR
|
// Build MIR
|
||||||
local b0=new ArrayBox(); b0.push(MirSchemaBox.inst_const(1,aval)); b0.push(MirSchemaBox.inst_const(2,bval)); b0.push(MirSchemaBox.inst_compare(op,1,2,3)); b0.push(MirSchemaBox.inst_branch(3,1,2))
|
local b0=new ArrayBox(); b0.push(MirSchemaBox.inst_const(1,aval)); b0.push(MirSchemaBox.inst_const(2,bval)); b0.push(MirSchemaBox.inst_compare(op,1,2,3)); b0.push(MirSchemaBox.inst_branch(3,1,2))
|
||||||
|
|||||||
@ -11,21 +11,21 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
|
|||||||
static box LowerIfCompareVarVarBox {
|
static box LowerIfCompareVarVarBox {
|
||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
local k_if = s.indexOf("\"type\":\"If\"")
|
local k_if = JsonFragBox.index_of_from(s, "\"type\":\"If\"", 0)
|
||||||
if k_if < 0 { return null }
|
if k_if < 0 { return null }
|
||||||
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_if)
|
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_if)
|
||||||
if k_cmp < 0 { return null }
|
if k_cmp < 0 { return null }
|
||||||
// LHS/RHS Var names
|
// LHS/RHS Var names
|
||||||
local lhs_name = null
|
local lhs_name = null
|
||||||
local klhs = s.indexOf("\"lhs\":{\"type\":\"Var\"", k_cmp)
|
local klhs = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\"", k_cmp)
|
||||||
if klhs >= 0 {
|
if klhs >= 0 {
|
||||||
local k_name_lhs = s.indexOf("\"name\":", klhs); if k_name_lhs < 0 { return null }
|
local k_name_lhs = JsonFragBox.index_of_from(s, "\"name\":", klhs); if k_name_lhs < 0 { return null }
|
||||||
lhs_name = JsonFragBox.read_string_after(s, k_name_lhs + 7)
|
lhs_name = JsonFragBox.read_string_after(s, k_name_lhs + 7)
|
||||||
}
|
}
|
||||||
local rhs_name = null
|
local rhs_name = null
|
||||||
local krhs = s.indexOf("\"rhs\":{\"type\":\"Var\"", k_cmp)
|
local krhs = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\"", k_cmp)
|
||||||
if krhs >= 0 {
|
if krhs >= 0 {
|
||||||
local k_name_rhs = s.indexOf("\"name\":", krhs); if k_name_rhs < 0 { return null }
|
local k_name_rhs = JsonFragBox.index_of_from(s, "\"name\":", krhs); if k_name_rhs < 0 { return null }
|
||||||
rhs_name = JsonFragBox.read_string_after(s, k_name_rhs + 7)
|
rhs_name = JsonFragBox.read_string_after(s, k_name_rhs + 7)
|
||||||
}
|
}
|
||||||
if lhs_name == null || rhs_name == null { return null }
|
if lhs_name == null || rhs_name == null { return null }
|
||||||
@ -34,21 +34,21 @@ static box LowerIfCompareVarVarBox {
|
|||||||
local bval = PatternUtilBox.find_local_int_before(s, rhs_name, k_if)
|
local bval = PatternUtilBox.find_local_int_before(s, rhs_name, k_if)
|
||||||
if aval == null || bval == null { return null }
|
if aval == null || bval == null { return null }
|
||||||
// op map
|
// op map
|
||||||
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
|
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_cmp); if k_op < 0 { return null }
|
||||||
local sym = JsonFragBox.read_string_after(s, k_op + 5)
|
local sym = JsonFragBox.read_string_after(s, k_op + 5)
|
||||||
if sym == null { return null }
|
if sym == null { return null }
|
||||||
local op = PatternUtilBox.map_cmp(sym)
|
local op = PatternUtilBox.map_cmp(sym)
|
||||||
if op == null { return null }
|
if op == null { return null }
|
||||||
// then/else Return(Int)
|
// then/else Return(Int)
|
||||||
local kth = s.indexOf("\"then\":", k_if); if kth < 0 { return null }
|
local kth = JsonFragBox.index_of_from(s, "\"then\":", k_if); if kth < 0 { return null }
|
||||||
local rt1 = s.indexOf("\"type\":\"Return\"", kth); if rt1 < 0 { return null }
|
local rt1 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kth); if rt1 < 0 { return null }
|
||||||
local ti1 = s.indexOf("\"type\":\"Int\"", rt1); if ti1 < 0 { return null }
|
local ti1 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt1); if ti1 < 0 { return null }
|
||||||
local kv_then = s.indexOf("\"value\":", ti1); if kv_then < 0 { return null }
|
local kv_then = JsonFragBox.index_of_from(s, "\"value\":", ti1); if kv_then < 0 { return null }
|
||||||
local then_val = JsonFragBox.read_int_after(s, kv_then + 8); if then_val == null { return null }
|
local then_val = JsonFragBox.read_int_after(s, kv_then + 8); if then_val == null { return null }
|
||||||
local kel = s.indexOf("\"else\":", k_if); if kel < 0 { return null }
|
local kel = JsonFragBox.index_of_from(s, "\"else\":", k_if); if kel < 0 { return null }
|
||||||
local rt2 = s.indexOf("\"type\":\"Return\"", kel); if rt2 < 0 { return null }
|
local rt2 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kel); if rt2 < 0 { return null }
|
||||||
local ti2 = s.indexOf("\"type\":\"Int\"", rt2); if ti2 < 0 { return null }
|
local ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt2); if ti2 < 0 { return null }
|
||||||
local kv_else = s.indexOf("\"value\":", ti2); if kv_else < 0 { return null }
|
local kv_else = JsonFragBox.index_of_from(s, "\"value\":", ti2); if kv_else < 0 { return null }
|
||||||
local else_val = JsonFragBox.read_int_after(s, kv_else + 8); if else_val == null { return null }
|
local else_val = JsonFragBox.read_int_after(s, kv_else + 8); if else_val == null { return null }
|
||||||
|
|
||||||
// Build MIR
|
// Build MIR
|
||||||
|
|||||||
@ -19,53 +19,53 @@ using "hako.mir.builder.internal.pattern_util" as PatternUtilBox
|
|||||||
static box LowerIfNestedBox {
|
static box LowerIfNestedBox {
|
||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
local k_if1 = s.indexOf("\"type\":\"If\"")
|
local k_if1 = JsonFragBox.index_of_from(s, "\"type\":\"If\"", 0)
|
||||||
if k_if1 < 0 { return null }
|
if k_if1 < 0 { return null }
|
||||||
local k_cmp1 = s.indexOf("\"type\":\"Compare\"", k_if1)
|
local k_cmp1 = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_if1)
|
||||||
if k_cmp1 < 0 { return null }
|
if k_cmp1 < 0 { return null }
|
||||||
local kop1 = s.indexOf("\"op\":", k_cmp1); if kop1 < 0 { return null }
|
local kop1 = JsonFragBox.index_of_from(s, "\"op\":", k_cmp1); if kop1 < 0 { return null }
|
||||||
local op1s = JsonFragBox.read_string_after(s, kop1 + 5); if op1s == null { return null }
|
local op1s = JsonFragBox.read_string_after(s, kop1 + 5); if op1s == null { return null }
|
||||||
local op1 = PatternUtilBox.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 klhs1 = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp1); if klhs1 < 0 { return null }
|
||||||
local ti11 = s.indexOf("\"type\":\"Int\"", klhs1); if ti11 < 0 { return null }
|
local ti11 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", klhs1); if ti11 < 0 { return null }
|
||||||
local kv11 = s.indexOf("\"value\":", ti11); if kv11 < 0 { return null }
|
local kv11 = JsonFragBox.index_of_from(s, "\"value\":", ti11); if kv11 < 0 { return null }
|
||||||
local lhs1 = JsonFragBox.read_int_after(s, kv11 + 8); if lhs1 == null { return null }
|
local lhs1 = JsonFragBox.read_int_after(s, kv11 + 8); if lhs1 == null { return null }
|
||||||
local krhs1 = s.indexOf("\"rhs\":{", k_cmp1); if krhs1 < 0 { return null }
|
local krhs1 = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp1); if krhs1 < 0 { return null }
|
||||||
local ti12 = s.indexOf("\"type\":\"Int\"", krhs1); if ti12 < 0 { return null }
|
local ti12 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", krhs1); if ti12 < 0 { return null }
|
||||||
local kv12 = s.indexOf("\"value\":", ti12); if kv12 < 0 { return null }
|
local kv12 = JsonFragBox.index_of_from(s, "\"value\":", ti12); if kv12 < 0 { return null }
|
||||||
local rhs1 = JsonFragBox.read_int_after(s, kv12 + 8); if rhs1 == null { return null }
|
local rhs1 = JsonFragBox.read_int_after(s, kv12 + 8); if rhs1 == null { return null }
|
||||||
// then Return(Int A)
|
// then Return(Int A)
|
||||||
local kth = s.indexOf("\"then\":", k_if1); if kth < 0 { return null }
|
local kth = JsonFragBox.index_of_from(s, "\"then\":", k_if1); if kth < 0 { return null }
|
||||||
local rt1 = s.indexOf("\"type\":\"Return\"", kth); if rt1 < 0 { return null }
|
local rt1 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kth); if rt1 < 0 { return null }
|
||||||
local ti13 = s.indexOf("\"type\":\"Int\"", rt1); if ti13 < 0 { return null }
|
local ti13 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt1); if ti13 < 0 { return null }
|
||||||
local kv13 = s.indexOf("\"value\":", ti13); if kv13 < 0 { return null }
|
local kv13 = JsonFragBox.index_of_from(s, "\"value\":", ti13); if kv13 < 0 { return null }
|
||||||
local aval = JsonFragBox.read_int_after(s, kv13 + 8); if aval == null { return null }
|
local aval = JsonFragBox.read_int_after(s, kv13 + 8); if aval == null { return null }
|
||||||
// else contains nested If with Return(Int)/Return(Int)
|
// else contains nested If with Return(Int)/Return(Int)
|
||||||
local kel = s.indexOf("\"else\":", k_if1); if kel < 0 { return null }
|
local kel = JsonFragBox.index_of_from(s, "\"else\":", k_if1); if kel < 0 { return null }
|
||||||
local k_if2 = s.indexOf("\"type\":\"If\"", kel); if k_if2 < 0 { return null }
|
local k_if2 = JsonFragBox.index_of_from(s, "\"type\":\"If\"", kel); if k_if2 < 0 { return null }
|
||||||
local k_cmp2 = s.indexOf("\"type\":\"Compare\"", k_if2); if k_cmp2 < 0 { return null }
|
local k_cmp2 = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_if2); if k_cmp2 < 0 { return null }
|
||||||
local kop2 = s.indexOf("\"op\":", k_cmp2); if kop2 < 0 { return null }
|
local kop2 = JsonFragBox.index_of_from(s, "\"op\":", k_cmp2); if kop2 < 0 { return null }
|
||||||
local op2s = JsonFragBox.read_string_after(s, kop2 + 5); if op2s == null { return null }
|
local op2s = JsonFragBox.read_string_after(s, kop2 + 5); if op2s == null { return null }
|
||||||
local op2 = PatternUtilBox.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 klhs2 = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp2); if klhs2 < 0 { return null }
|
||||||
local ti21 = s.indexOf("\"type\":\"Int\"", klhs2); if ti21 < 0 { return null }
|
local ti21 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", klhs2); if ti21 < 0 { return null }
|
||||||
local kv21 = s.indexOf("\"value\":", ti21); if kv21 < 0 { return null }
|
local kv21 = JsonFragBox.index_of_from(s, "\"value\":", ti21); if kv21 < 0 { return null }
|
||||||
local lhs2 = JsonFragBox.read_int_after(s, kv21 + 8); if lhs2 == null { return null }
|
local lhs2 = JsonFragBox.read_int_after(s, kv21 + 8); if lhs2 == null { return null }
|
||||||
local krhs2 = s.indexOf("\"rhs\":{", k_cmp2); if krhs2 < 0 { return null }
|
local krhs2 = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp2); if krhs2 < 0 { return null }
|
||||||
local ti22 = s.indexOf("\"type\":\"Int\"", krhs2); if ti22 < 0 { return null }
|
local ti22 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", krhs2); if ti22 < 0 { return null }
|
||||||
local kv22 = s.indexOf("\"value\":", ti22); if kv22 < 0 { return null }
|
local kv22 = JsonFragBox.index_of_from(s, "\"value\":", ti22); if kv22 < 0 { return null }
|
||||||
local rhs2 = JsonFragBox.read_int_after(s, kv22 + 8); if rhs2 == null { return null }
|
local rhs2 = JsonFragBox.read_int_after(s, kv22 + 8); if rhs2 == null { return null }
|
||||||
// then Return(Int B)
|
// then Return(Int B)
|
||||||
local kth2 = s.indexOf("\"then\":", k_if2); if kth2 < 0 { return null }
|
local kth2 = JsonFragBox.index_of_from(s, "\"then\":", k_if2); if kth2 < 0 { return null }
|
||||||
local rt2 = s.indexOf("\"type\":\"Return\"", kth2); if rt2 < 0 { return null }
|
local rt2 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kth2); if rt2 < 0 { return null }
|
||||||
local ti23 = s.indexOf("\"type\":\"Int\"", rt2); if ti23 < 0 { return null }
|
local ti23 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt2); if ti23 < 0 { return null }
|
||||||
local kv23 = s.indexOf("\"value\":", ti23); if kv23 < 0 { return null }
|
local kv23 = JsonFragBox.index_of_from(s, "\"value\":", ti23); if kv23 < 0 { return null }
|
||||||
local bval = JsonFragBox.read_int_after(s, kv23 + 8); if bval == null { return null }
|
local bval = JsonFragBox.read_int_after(s, kv23 + 8); if bval == null { return null }
|
||||||
// else Return(Int C)
|
// else Return(Int C)
|
||||||
local kel2 = s.indexOf("\"else\":", k_if2); if kel2 < 0 { return null }
|
local kel2 = JsonFragBox.index_of_from(s, "\"else\":", k_if2); if kel2 < 0 { return null }
|
||||||
local rt3 = s.indexOf("\"type\":\"Return\"", kel2); if rt3 < 0 { return null }
|
local rt3 = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kel2); if rt3 < 0 { return null }
|
||||||
local ti24 = s.indexOf("\"type\":\"Int\"", rt3); if ti24 < 0 { return null }
|
local ti24 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt3); if ti24 < 0 { return null }
|
||||||
local kv24 = s.indexOf("\"value\":", ti24); if kv24 < 0 { return null }
|
local kv24 = JsonFragBox.index_of_from(s, "\"value\":", ti24); if kv24 < 0 { return null }
|
||||||
local cval = JsonFragBox.read_int_after(s, kv24 + 8); if cval == null { return null }
|
local cval = JsonFragBox.read_int_after(s, kv24 + 8); if cval == null { return null }
|
||||||
|
|
||||||
// Build MIR(JSON)
|
// Build MIR(JSON)
|
||||||
|
|||||||
@ -10,29 +10,29 @@ static box LowerIfThenElseFollowingReturnBox {
|
|||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
// If with Compare(Int,Int)
|
// If with Compare(Int,Int)
|
||||||
local k_if = s.indexOf("\"type\":\"If\"")
|
local k_if = JsonFragBox.index_of_from(s, "\"type\":\"If\"", 0)
|
||||||
if k_if < 0 { return null }
|
if k_if < 0 { return null }
|
||||||
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_if)
|
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_if)
|
||||||
if k_cmp < 0 { return null }
|
if k_cmp < 0 { return null }
|
||||||
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
|
local k_op = JsonFragBox.index_of_from(s, "\"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 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 }
|
local op = PatternUtilBox.map_cmp(sym); if op == null { return null }
|
||||||
// LHS/RHS ints
|
// LHS/RHS ints
|
||||||
local klhs = s.indexOf("\"lhs\":{", k_cmp); if klhs < 0 { return null }
|
local klhs = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp); if klhs < 0 { return null }
|
||||||
local ti1 = s.indexOf("\"type\":\"Int\"", klhs); if ti1 < 0 { return null }
|
local ti1 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", klhs); if ti1 < 0 { return null }
|
||||||
{ local kv = s.indexOf("\"value\":", ti1); if kv < 0 { return null }; var lhs_val = JsonFragBox.read_int_after(s, kv + 8); if lhs_val == null { return null } }
|
{ local kv = JsonFragBox.index_of_from(s, "\"value\":", ti1); if kv < 0 { return null }; var lhs_val = JsonFragBox.read_int_after(s, kv + 8); if lhs_val == null { return null } }
|
||||||
local krhs = s.indexOf("\"rhs\":{", k_cmp); if krhs < 0 { return null }
|
local krhs = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp); if krhs < 0 { return null }
|
||||||
local ti2 = s.indexOf("\"type\":\"Int\"", krhs); if ti2 < 0 { return null }
|
local ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", krhs); if ti2 < 0 { return null }
|
||||||
{ local kv2 = s.indexOf("\"value\":", ti2); if kv2 < 0 { return null }; var rhs_val = JsonFragBox.read_int_after(s, kv2 + 8); if rhs_val == null { return null } }
|
{ local kv2 = JsonFragBox.index_of_from(s, "\"value\":", ti2); if kv2 < 0 { return null }; var rhs_val = JsonFragBox.read_int_after(s, kv2 + 8); if rhs_val == null { return null } }
|
||||||
// then: Return(Int)
|
// then: Return(Int)
|
||||||
local kth = s.indexOf("\"then\":", k_if); if kth < 0 { return null }
|
local kth = JsonFragBox.index_of_from(s, "\"then\":", k_if); if kth < 0 { return null }
|
||||||
local rt = s.indexOf("\"type\":\"Return\"", kth); if rt < 0 { return null }
|
local rt = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", kth); if rt < 0 { return null }
|
||||||
local ti3 = s.indexOf("\"type\":\"Int\"", rt); if ti3 < 0 { return null }
|
local ti3 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", rt); if ti3 < 0 { return null }
|
||||||
{ local kv3 = s.indexOf("\"value\":", ti3); if kv3 < 0 { return null }; var then_val = JsonFragBox.read_int_after(s, kv3 + 8); if then_val == null { return null } }
|
{ local kv3 = JsonFragBox.index_of_from(s, "\"value\":", ti3); if kv3 < 0 { return null }; var then_val = JsonFragBox.read_int_after(s, kv3 + 8); if then_val == null { return null } }
|
||||||
// else is omitted → following Return(Int) in Program body
|
// else is omitted → following Return(Int) in Program body
|
||||||
local k_after = s.indexOf("\"type\":\"Return\"", k_if + 1); if k_after < 0 { return null }
|
local k_after = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", k_if + 1); if k_after < 0 { return null }
|
||||||
local ti4 = s.indexOf("\"type\":\"Int\"", k_after); if ti4 < 0 { return null }
|
local ti4 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_after); if ti4 < 0 { return null }
|
||||||
{ local kv4 = s.indexOf("\"value\":", ti4); if kv4 < 0 { return null }; var else_val = JsonFragBox.read_int_after(s, kv4 + 8); if else_val == null { return null } }
|
{ local kv4 = JsonFragBox.index_of_from(s, "\"value\":", ti4); if kv4 < 0 { return null }; var else_val = JsonFragBox.read_int_after(s, kv4 + 8); if else_val == null { return null } }
|
||||||
|
|
||||||
// Build MIR(JSON)
|
// Build MIR(JSON)
|
||||||
local b0 = new ArrayBox()
|
local b0 = new ArrayBox()
|
||||||
|
|||||||
@ -12,27 +12,27 @@ static box LowerLoopCountParamBox {
|
|||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
// Discover loop variable name from Compare first
|
// Discover loop variable name from Compare first
|
||||||
// We'll accept either lhs Var(name) or rhs Var(name)
|
// We'll accept either lhs Var(name) or rhs Var(name)
|
||||||
local k_loop = s.indexOf("\"type\":\"Loop\"", 0)
|
local k_loop = JsonFragBox.index_of_from(s, "\"type\":\"Loop\"", 0)
|
||||||
if k_loop < 0 { return null }
|
if k_loop < 0 { return null }
|
||||||
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_loop)
|
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_loop)
|
||||||
if k_cmp < 0 { return null }
|
if k_cmp < 0 { return null }
|
||||||
local varname = LoopScanBox.find_loop_var_name(s, k_cmp)
|
local varname = LoopScanBox.find_loop_var_name(s, k_cmp)
|
||||||
if varname == null { return null }
|
if varname == null { return null }
|
||||||
|
|
||||||
// Local <varname> = (Int init | Var initName)
|
// Local <varname> = (Int init | Var initName)
|
||||||
local k_local_i = s.indexOf("\"type\":\"Local\"")
|
local k_local_i = JsonFragBox.index_of_from(s, "\"type\":\"Local\"", 0)
|
||||||
if k_local_i < 0 { return null }
|
if k_local_i < 0 { return null }
|
||||||
if s.indexOf("\"name\":\"" + varname + "\"", k_local_i) < 0 { return null }
|
if JsonFragBox.index_of_from(s, "\"name\":\"" + varname + "\"", k_local_i) < 0 { return null }
|
||||||
local init = null
|
local init = null
|
||||||
{
|
{
|
||||||
local k_init_int = s.indexOf("\"type\":\"Int\"", k_local_i)
|
local k_init_int = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_local_i)
|
||||||
local k_loop_next = s.indexOf("\"type\":\"Loop\"", k_local_i)
|
local k_loop_next = JsonFragBox.index_of_from(s, "\"type\":\"Loop\"", k_local_i)
|
||||||
if k_init_int >= 0 && (k_loop_next < 0 || k_init_int < k_loop_next) {
|
if k_init_int >= 0 && (k_loop_next < 0 || k_init_int < k_loop_next) {
|
||||||
local kv_i = s.indexOf("\"value\":", k_init_int); if kv_i >= 0 { init = JsonFragBox.read_int_after(s, kv_i + 8) }
|
local kv_i = JsonFragBox.index_of_from(s, "\"value\":", k_init_int); if kv_i >= 0 { init = JsonFragBox.read_int_after(s, kv_i + 8) }
|
||||||
} else {
|
} else {
|
||||||
local k_init_var = s.indexOf("\"type\":\"Var\"", k_local_i)
|
local k_init_var = JsonFragBox.index_of_from(s, "\"type\":\"Var\"", k_local_i)
|
||||||
if k_init_var >= 0 && (k_loop_next < 0 || k_init_var < k_loop_next) {
|
if k_init_var >= 0 && (k_loop_next < 0 || k_init_var < k_loop_next) {
|
||||||
local kn_i = s.indexOf("\"name\":\"", k_init_var); if kn_i < 0 { return null }
|
local kn_i = JsonFragBox.index_of_from(s, "\"name\":\"", k_init_var); if kn_i < 0 { return null }
|
||||||
local vname = JsonFragBox.read_string_after(s, kn_i)
|
local vname = JsonFragBox.read_string_after(s, kn_i)
|
||||||
if vname != null { init = PatternUtilBox.find_local_int_before(s, vname, k_local_i) }
|
if vname != null { init = PatternUtilBox.find_local_int_before(s, vname, k_local_i) }
|
||||||
}
|
}
|
||||||
@ -41,22 +41,22 @@ static box LowerLoopCountParamBox {
|
|||||||
if init == null { return null }
|
if init == null { return null }
|
||||||
// Loop Compare normalize: accept < / <= / > / >= with Var(varname) on either side
|
// 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)
|
// op: accept '<'/'<=' with i on lhs; '>'/'>=' with i on lhs (descending); swapped '>'/'>=' with i on rhs (ascending)
|
||||||
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
|
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_cmp); if k_op < 0 { return null }
|
||||||
local op = JsonFragBox.read_string_after(s, k_op + 5)
|
local op = JsonFragBox.read_string_after(s, k_op + 5)
|
||||||
if op == null { return null }
|
if op == null { return null }
|
||||||
local has_lhs_i = s.indexOf("\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
|
local has_lhs_i = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
|
||||||
local has_rhs_i = s.indexOf("\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
|
local has_rhs_i = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
|
||||||
if !has_lhs_i && !has_rhs_i { return null }
|
if !has_lhs_i && !has_rhs_i { return null }
|
||||||
local cmp = null
|
local cmp = null
|
||||||
local limit = null
|
local limit = null
|
||||||
if has_lhs_i {
|
if has_lhs_i {
|
||||||
// rhs Int/Var → resolve limit
|
// rhs Int/Var → resolve limit
|
||||||
local k_rhs = s.indexOf("\"rhs\":{", k_cmp); if k_rhs < 0 { return null }
|
local k_rhs = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp); if k_rhs < 0 { return null }
|
||||||
local k_lim_t = s.indexOf("\"type\":\"Int\"", k_rhs)
|
local k_lim_t = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhs)
|
||||||
if k_lim_t >= 0 { local kv = s.indexOf("\"value\":", k_lim_t); if kv >= 0 { limit = JsonFragBox.read_int_after(s, kv + 8) } }
|
if k_lim_t >= 0 { local kv = JsonFragBox.index_of_from(s, "\"value\":", k_lim_t); if kv >= 0 { limit = JsonFragBox.read_int_after(s, kv + 8) } }
|
||||||
else {
|
else {
|
||||||
local k_rv = s.indexOf("\"type\":\"Var\"", k_rhs); if k_rv < 0 { return null }
|
local k_rv = JsonFragBox.index_of_from(s, "\"type\":\"Var\"", k_rhs); if k_rv < 0 { return null }
|
||||||
local kn = s.indexOf("\"name\":\"", k_rhs); if kn < 0 { return null }
|
local kn = JsonFragBox.index_of_from(s, "\"name\":\"", k_rhs); if kn < 0 { return null }
|
||||||
local lname = JsonFragBox.read_string_after(s, kn); if lname == null { 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)
|
limit = PatternUtilBox.find_local_int_before(s, lname, k_cmp)
|
||||||
}
|
}
|
||||||
@ -69,12 +69,12 @@ static box LowerLoopCountParamBox {
|
|||||||
limit = norm.substring(cpos+1, norm.length())
|
limit = norm.substring(cpos+1, norm.length())
|
||||||
} else {
|
} else {
|
||||||
if op != ">" && 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_lhs = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp); if k_lhs < 0 { return null }
|
||||||
local k_lim_t2 = s.indexOf("\"type\":\"Int\"", k_lhs)
|
local k_lim_t2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_lhs)
|
||||||
if k_lim_t2 >= 0 { local kv2 = s.indexOf("\"value\":", k_lim_t2); if kv2 >= 0 { limit = JsonFragBox.read_int_after(s, kv2 + 8) } }
|
if k_lim_t2 >= 0 { local kv2 = JsonFragBox.index_of_from(s, "\"value\":", k_lim_t2); if kv2 >= 0 { limit = JsonFragBox.read_int_after(s, kv2 + 8) } }
|
||||||
else {
|
else {
|
||||||
local k_lv = s.indexOf("\"type\":\"Var\"", k_lhs); if k_lv < 0 { return null }
|
local k_lv = JsonFragBox.index_of_from(s, "\"type\":\"Var\"", k_lhs); if k_lv < 0 { return null }
|
||||||
local kn3 = s.indexOf("\"name\":\"", k_lhs); if kn3 < 0 { return null }
|
local kn3 = JsonFragBox.index_of_from(s, "\"name\":\"", k_lhs); if kn3 < 0 { return null }
|
||||||
local lname3 = JsonFragBox.read_string_after(s, kn3); if lname3 == null { 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)
|
limit = PatternUtilBox.find_local_int_before(s, lname3, k_cmp)
|
||||||
}
|
}
|
||||||
@ -86,27 +86,27 @@ static box LowerLoopCountParamBox {
|
|||||||
limit = norm2.substring(cpos2+1, norm2.length())
|
limit = norm2.substring(cpos2+1, norm2.length())
|
||||||
}
|
}
|
||||||
// Body increment: Local i = Binary('+', Var i, Int step)
|
// Body increment: Local i = Binary('+', Var i, Int step)
|
||||||
local k_body_i = s.indexOf("\"name\":\"" + varname + "\"", k_loop)
|
local k_body_i = JsonFragBox.index_of_from(s, "\"name\":\"" + varname + "\"", k_loop)
|
||||||
if k_body_i < 0 { return null }
|
if k_body_i < 0 { return null }
|
||||||
local k_bop = s.indexOf("\"type\":\"Binary\"", k_body_i)
|
local k_bop = JsonFragBox.index_of_from(s, "\"type\":\"Binary\"", k_body_i)
|
||||||
if k_bop < 0 { return null }
|
if k_bop < 0 { return null }
|
||||||
// Body increment: Local i = Binary(op '+' or '-', Var i, (Int step | Var stepName))
|
// Body increment: Local i = Binary(op '+' or '-', Var i, (Int step | Var stepName))
|
||||||
local bop_plus = (s.indexOf("\"op\":\"+\"", k_bop) >= 0)
|
local bop_plus = (JsonFragBox.index_of_from(s, "\"op\":\"+\"", k_bop) >= 0)
|
||||||
local bop_minus = (s.indexOf("\"op\":\"-\"", k_bop) >= 0)
|
local bop_minus = (JsonFragBox.index_of_from(s, "\"op\":\"-\"", k_bop) >= 0)
|
||||||
if (!bop_plus && !bop_minus) { return null }
|
if (!bop_plus && !bop_minus) { return null }
|
||||||
if s.indexOf("\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_bop) < 0 { return null }
|
if JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_bop) < 0 { return null }
|
||||||
|
|
||||||
local step = null
|
local step = null
|
||||||
// Prefer rhs Int if present; otherwise try rhs Var and reverse-lookup its Local Int
|
// Prefer rhs Int if present; otherwise try rhs Var and reverse-lookup its Local Int
|
||||||
{
|
{
|
||||||
local k_rhsb = s.indexOf("\"rhs\":{", k_bop); if k_rhsb < 0 { return null }
|
local k_rhsb = JsonFragBox.index_of_from(s, "\"rhs\":{", k_bop); if k_rhsb < 0 { return null }
|
||||||
local k_t_int = s.indexOf("\"type\":\"Int\"", k_rhsb)
|
local k_t_int = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhsb)
|
||||||
if k_t_int >= 0 {
|
if k_t_int >= 0 {
|
||||||
local kvs = s.indexOf("\"value\":", k_t_int); if kvs >= 0 { step = JsonFragBox.read_int_after(s, kvs + 8) }
|
local kvs = JsonFragBox.index_of_from(s, "\"value\":", k_t_int); if kvs >= 0 { step = JsonFragBox.read_int_after(s, kvs + 8) }
|
||||||
} else {
|
} else {
|
||||||
local k_t_var = s.indexOf("\"type\":\"Var\"", k_rhsb)
|
local k_t_var = JsonFragBox.index_of_from(s, "\"type\":\"Var\"", k_rhsb)
|
||||||
if k_t_var < 0 { return null }
|
if k_t_var < 0 { return null }
|
||||||
local kns = s.indexOf("\"name\":\"", k_rhsb); if kns < 0 { return null }
|
local kns = JsonFragBox.index_of_from(s, "\"name\":\"", k_rhsb); if kns < 0 { return null }
|
||||||
local vname = JsonFragBox.read_string_after(s, kns); if vname == null { 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)
|
step = PatternUtilBox.find_local_int_before(s, vname, k_bop)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,38 +12,38 @@ static box LowerLoopSimpleBox {
|
|||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
// Find Loop with cond Compare and normalize to canonical (<) with dynamic var name
|
// Find Loop with cond Compare and normalize to canonical (<) with dynamic var name
|
||||||
local k_loop = s.indexOf("\"type\":\"Loop\"")
|
local k_loop = JsonFragBox.index_of_from(s, "\"type\":\"Loop\"", 0)
|
||||||
if k_loop < 0 { return null }
|
if k_loop < 0 { return null }
|
||||||
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_loop)
|
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_loop)
|
||||||
if k_cmp < 0 { return null }
|
if k_cmp < 0 { return null }
|
||||||
// discover loop var name from cond (lhs or rhs Var)
|
// discover loop var name from cond (lhs or rhs Var)
|
||||||
local varname = LoopScanBox.find_loop_var_name(s, k_cmp)
|
local varname = LoopScanBox.find_loop_var_name(s, k_cmp)
|
||||||
if varname == null { return null }
|
if varname == null { return null }
|
||||||
|
|
||||||
// op: accept '<' / '<=' as-is, '!=' (with var on lhs) as '<', and swapped '>' / '>=' (with var on rhs)
|
// op: accept '<' / '<=' as-is, '!=' (with var on lhs) as '<', and swapped '>' / '>=' (with var on rhs)
|
||||||
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
|
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_cmp); if k_op < 0 { return null }
|
||||||
local op = JsonFragBox.read_string_after(s, k_op + 5)
|
local op = JsonFragBox.read_string_after(s, k_op + 5)
|
||||||
if op == null { return null }
|
if op == null { return null }
|
||||||
// Determine where Var(varname) is and extract the Int from the opposite side
|
// 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
|
local has_lhs_i = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
|
||||||
local has_rhs_i = s.indexOf("\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
|
local has_rhs_i = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
|
||||||
if !has_lhs_i && !has_rhs_i { return null }
|
if !has_lhs_i && !has_rhs_i { return null }
|
||||||
|
|
||||||
local swapped = 0
|
local swapped = 0
|
||||||
local limit = null
|
local limit = null
|
||||||
if has_lhs_i {
|
if has_lhs_i {
|
||||||
// rhs Int value
|
// rhs Int value
|
||||||
local k_rhs = s.indexOf("\"rhs\":{", k_cmp); if k_rhs < 0 { return null }
|
local k_rhs = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp); if k_rhs < 0 { return null }
|
||||||
local k_ti = s.indexOf("\"type\":\"Int\"", k_rhs); if k_ti < 0 { return null }
|
local k_ti = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhs); if k_ti < 0 { return null }
|
||||||
local k_v = s.indexOf("\"value\":", k_ti); if k_v < 0 { return null }
|
local k_v = JsonFragBox.index_of_from(s, "\"value\":", k_ti); if k_v < 0 { return null }
|
||||||
limit = JsonFragBox.read_int_after(s, k_v + 8)
|
limit = JsonFragBox.read_int_after(s, k_v + 8)
|
||||||
if limit == null { return null }
|
if limit == null { return null }
|
||||||
} else {
|
} else {
|
||||||
// Var is on rhs; lhs must be Int
|
// Var is on rhs; lhs must be Int
|
||||||
swapped = 1
|
swapped = 1
|
||||||
local k_lhs = s.indexOf("\"lhs\":{", k_cmp); if k_lhs < 0 { return null }
|
local k_lhs = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp); if k_lhs < 0 { return null }
|
||||||
local k_ti2 = s.indexOf("\"type\":\"Int\"", k_lhs); if k_ti2 < 0 { return null }
|
local k_ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_lhs); if k_ti2 < 0 { return null }
|
||||||
local k_v2 = s.indexOf("\"value\":", k_ti2); if k_v2 < 0 { return null }
|
local k_v2 = JsonFragBox.index_of_from(s, "\"value\":", k_ti2); if k_v2 < 0 { return null }
|
||||||
limit = JsonFragBox.read_int_after(s, k_v2 + 8)
|
limit = JsonFragBox.read_int_after(s, k_v2 + 8)
|
||||||
if limit == null { return null }
|
if limit == null { return null }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,19 +21,19 @@ static box LowerLoopSumBcBox {
|
|||||||
print("[sum_bc] enter lower")
|
print("[sum_bc] enter lower")
|
||||||
}
|
}
|
||||||
// Loop and Compare normalize to canonical (<) with dynamic var name
|
// Loop and Compare normalize to canonical (<) with dynamic var name
|
||||||
local k_loop = s.indexOf("\"type\":\"Loop\"")
|
local k_loop = JsonFragBox.index_of_from(s, "\"type\":\"Loop\"", 0)
|
||||||
if k_loop < 0 { return null }
|
if k_loop < 0 { return null }
|
||||||
local k_cmp = s.indexOf("\"type\":\"Compare\"", k_loop)
|
local k_cmp = JsonFragBox.index_of_from(s, "\"type\":\"Compare\"", k_loop)
|
||||||
if k_cmp < 0 { return null }
|
if k_cmp < 0 { return null }
|
||||||
// discover loop var name from cond (lhs or rhs Var)
|
// discover loop var name from cond (lhs or rhs Var)
|
||||||
local varname = null
|
local varname = null
|
||||||
{
|
{
|
||||||
local kl = s.indexOf("\"lhs\":{", k_cmp); local kr = s.indexOf("\"rhs\":{", k_cmp)
|
local kl = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp); local kr = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp)
|
||||||
if kl >= 0 && s.indexOf("\"type\":\"Var\"", kl) >= 0 {
|
if kl >= 0 && JsonFragBox.index_of_from(s, "\"type\":\"Var\"", kl) >= 0 {
|
||||||
local kn = s.indexOf("\"name\":\"", kl); if kn >= 0 { varname = JsonFragBox.read_string_after(s, kn) }
|
local kn = JsonFragBox.index_of_from(s, "\"name\":\"", kl); if kn >= 0 { varname = JsonFragBox.read_string_after(s, kn) }
|
||||||
}
|
}
|
||||||
if varname == null && kr >= 0 && s.indexOf("\"type\":\"Var\"", kr) >= 0 {
|
if varname == null && kr >= 0 && JsonFragBox.index_of_from(s, "\"type\":\"Var\"", kr) >= 0 {
|
||||||
local kn2 = s.indexOf("\"name\":\"", kr); if kn2 >= 0 { varname = JsonFragBox.read_string_after(s, kn2) }
|
local kn2 = JsonFragBox.index_of_from(s, "\"name\":\"", kr); if kn2 >= 0 { varname = JsonFragBox.read_string_after(s, kn2) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if varname == null { return null }
|
if varname == null { return null }
|
||||||
@ -41,27 +41,27 @@ static box LowerLoopSumBcBox {
|
|||||||
print("[sum_bc] var=" + varname)
|
print("[sum_bc] var=" + varname)
|
||||||
}
|
}
|
||||||
// op: accept '<'/'<=' with var on lhs; also accept swapped '>'/'>=' with var on rhs
|
// op: accept '<'/'<=' with var on lhs; also accept swapped '>'/'>=' with var on rhs
|
||||||
local k_op = s.indexOf("\"op\":", k_cmp); if k_op < 0 { return null }
|
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_cmp); if k_op < 0 { return null }
|
||||||
local op = JsonFragBox.read_string_after(s, k_op + 5)
|
local op = JsonFragBox.read_string_after(s, k_op + 5)
|
||||||
if op == null { return null }
|
if op == null { return null }
|
||||||
local has_lhs_i = s.indexOf("\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
|
local has_lhs_i = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
|
||||||
local has_rhs_i = s.indexOf("\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
|
local has_rhs_i = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", k_cmp) >= 0
|
||||||
if !has_lhs_i && !has_rhs_i { return null }
|
if !has_lhs_i && !has_rhs_i { return null }
|
||||||
local limit = null
|
local limit = null
|
||||||
if has_lhs_i {
|
if has_lhs_i {
|
||||||
if op != "<" && op != "<=" { return null }
|
if op != "<" && op != "<=" { return null }
|
||||||
// rhs Int limit
|
// rhs Int limit
|
||||||
local k_rhs = s.indexOf("\"rhs\":{", k_cmp); if k_rhs < 0 { return null }
|
local k_rhs = JsonFragBox.index_of_from(s, "\"rhs\":{", k_cmp); if k_rhs < 0 { return null }
|
||||||
local k_ti = s.indexOf("\"type\":\"Int\"", k_rhs); if k_ti < 0 { return null }
|
local k_ti = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhs); if k_ti < 0 { return null }
|
||||||
local kv = s.indexOf("\"value\":", k_ti); if kv < 0 { return null }
|
local kv = JsonFragBox.index_of_from(s, "\"value\":", k_ti); if kv < 0 { return null }
|
||||||
limit = JsonFragBox.read_int_after(s, kv + 8); if limit == null { 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) }
|
if op == "<=" { limit = StringHelpers.int_to_str(JsonFragBox._str_to_int(limit) + 1) }
|
||||||
} else {
|
} else {
|
||||||
// swapped: Int on lhs, Var i on rhs, op should be '>' or '>='
|
// swapped: Int on lhs, Var i on rhs, op should be '>' or '>='
|
||||||
if op != ">" && op != ">=" { return null }
|
if op != ">" && op != ">=" { return null }
|
||||||
local k_lhs = s.indexOf("\"lhs\":{", k_cmp); if k_lhs < 0 { return null }
|
local k_lhs = JsonFragBox.index_of_from(s, "\"lhs\":{", k_cmp); if k_lhs < 0 { return null }
|
||||||
local k_ti2 = s.indexOf("\"type\":\"Int\"", k_lhs); if k_ti2 < 0 { return null }
|
local k_ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_lhs); if k_ti2 < 0 { return null }
|
||||||
local kv2 = s.indexOf("\"value\":", k_ti2); if kv2 < 0 { return null }
|
local kv2 = JsonFragBox.index_of_from(s, "\"value\":", k_ti2); if kv2 < 0 { return null }
|
||||||
limit = JsonFragBox.read_int_after(s, kv2 + 8); if limit == null { 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) }
|
if op == ">=" { limit = StringHelpers.int_to_str(JsonFragBox._str_to_int(limit) + 1) }
|
||||||
}
|
}
|
||||||
@ -69,22 +69,24 @@ static box LowerLoopSumBcBox {
|
|||||||
// Break sentinel: If(cond Compare var==X or X==var) then Break
|
// Break sentinel: If(cond Compare var==X or X==var) then Break
|
||||||
local break_value = null
|
local break_value = null
|
||||||
{
|
{
|
||||||
local kb = s.indexOf("\"type\":\"Break\"", k_loop)
|
local kb = JsonFragBox.index_of_from(s, "\"type\":\"Break\"", k_loop)
|
||||||
if kb >= 0 {
|
if kb >= 0 {
|
||||||
// Find nearest previous Compare and grab rhs Int
|
// Find nearest previous Compare and grab rhs Int
|
||||||
local kbc = s.lastIndexOf("\"type\":\"Compare\"", kb)
|
local kbc = s.lastIndexOf("\"type\":\"Compare\"", kb)
|
||||||
if kbc >= 0 {
|
if kbc >= 0 {
|
||||||
// Ensure op=="==" and lhs Var i
|
// Ensure op=="==" and lhs Var i
|
||||||
local kop = s.indexOf("\"op\":", kbc); local bop = null; if kop >= 0 { bop = JsonFragBox.read_string_after(s, kop + 5) }
|
local kop = JsonFragBox.index_of_from(s, "\"op\":", kbc); local bop = null; if kop >= 0 { bop = JsonFragBox.read_string_after(s, kop + 5) }
|
||||||
if bop != null && bop == "==" {
|
if bop != null && bop == "==" {
|
||||||
local lhs_i = s.indexOf("\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kbc) >= 0
|
local lhs_i = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kbc) >= 0
|
||||||
local rhs_i = s.indexOf("\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kbc) >= 0
|
local rhs_i = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kbc) >= 0
|
||||||
if lhs_i {
|
if lhs_i {
|
||||||
local kbi = s.indexOf("\"type\":\"Int\"", s.indexOf("\"rhs\":{", kbc))
|
local k_rhsb = JsonFragBox.index_of_from(s, "\"rhs\":{", kbc)
|
||||||
if kbi >= 0 { local kvb = s.indexOf("\"value\":", kbi); if kvb >= 0 { break_value = JsonFragBox.read_int_after(s, kvb + 8) } }
|
local kbi = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhsb)
|
||||||
|
if kbi >= 0 { local kvb = JsonFragBox.index_of_from(s, "\"value\":", kbi); if kvb >= 0 { break_value = JsonFragBox.read_int_after(s, kvb + 8) } }
|
||||||
} else if rhs_i {
|
} else if rhs_i {
|
||||||
local kbi2 = s.indexOf("\"type\":\"Int\"", s.indexOf("\"lhs\":{", kbc))
|
local k_lhsb = JsonFragBox.index_of_from(s, "\"lhs\":{", kbc)
|
||||||
if kbi2 >= 0 { local kvb2 = s.indexOf("\"value\":", kbi2); if kvb2 >= 0 { break_value = JsonFragBox.read_int_after(s, kvb2 + 8) } }
|
local kbi2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_lhsb)
|
||||||
|
if kbi2 >= 0 { local kvb2 = JsonFragBox.index_of_from(s, "\"value\":", kbi2); if kvb2 >= 0 { break_value = JsonFragBox.read_int_after(s, kvb2 + 8) } }
|
||||||
}
|
}
|
||||||
} else if bop != null && bop == "!=" {
|
} else if bop != null && bop == "!=" {
|
||||||
// Delegate to loop-scan helper for '!=' + else [Break]
|
// Delegate to loop-scan helper for '!=' + else [Break]
|
||||||
@ -92,11 +94,11 @@ static box LowerLoopSumBcBox {
|
|||||||
// Fallback: try local JsonFragBox-based extraction near kbc
|
// Fallback: try local JsonFragBox-based extraction near kbc
|
||||||
if break_value == null {
|
if break_value == null {
|
||||||
// Read Int from lhs or rhs around kbc
|
// Read Int from lhs or rhs around kbc
|
||||||
local k_rhsb = s.indexOf("\"rhs\":{", kbc); local k_lhsb = s.indexOf("\"lhs\":{", kbc)
|
local k_rhsb = JsonFragBox.index_of_from(s, "\"rhs\":{", kbc); local k_lhsb = JsonFragBox.index_of_from(s, "\"lhs\":{", kbc)
|
||||||
if k_rhsb >= 0 && s.indexOf("\"type\":\"Int\"", k_rhsb) >= 0 {
|
if k_rhsb >= 0 && JsonFragBox.index_of_from(s, "\"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) }
|
local kvi = JsonFragBox.index_of_from(s, "\"value\":", JsonFragBox.index_of_from(s, "\"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 {
|
} else if k_lhsb >= 0 && JsonFragBox.index_of_from(s, "\"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) }
|
local kvj = JsonFragBox.index_of_from(s, "\"value\":", JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_lhsb)); if kvj >= 0 { break_value = JsonFragBox.read_int_after(s, kvj + 8) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,31 +108,33 @@ static box LowerLoopSumBcBox {
|
|||||||
// Continue sentinel: If(cond Compare var==Y or Y==var) then Continue
|
// Continue sentinel: If(cond Compare var==Y or Y==var) then Continue
|
||||||
local skip_value = null
|
local skip_value = null
|
||||||
{
|
{
|
||||||
local kc = s.indexOf("\"type\":\"Continue\"", k_loop)
|
local kc = JsonFragBox.index_of_from(s, "\"type\":\"Continue\"", k_loop)
|
||||||
if kc >= 0 {
|
if kc >= 0 {
|
||||||
local kcc = s.lastIndexOf("\"type\":\"Compare\"", kc)
|
local kcc = s.lastIndexOf("\"type\":\"Compare\"", kc)
|
||||||
if kcc >= 0 {
|
if kcc >= 0 {
|
||||||
local kop2 = s.indexOf("\"op\":", kcc); local cop = null; if kop2 >= 0 { cop = JsonFragBox.read_string_after(s, kop2 + 5) }
|
local kop2 = JsonFragBox.index_of_from(s, "\"op\":", kcc); local cop = null; if kop2 >= 0 { cop = JsonFragBox.read_string_after(s, kop2 + 5) }
|
||||||
if cop != null && cop == "==" {
|
if cop != null && cop == "==" {
|
||||||
local lhs_i2 = s.indexOf("\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kcc) >= 0
|
local lhs_i2 = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kcc) >= 0
|
||||||
local rhs_i2 = s.indexOf("\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kcc) >= 0
|
local rhs_i2 = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\",\"name\":\"" + varname + "\"}", kcc) >= 0
|
||||||
if lhs_i2 {
|
if lhs_i2 {
|
||||||
local kci = s.indexOf("\"type\":\"Int\"", s.indexOf("\"rhs\":{", kcc))
|
local k_rhsb2 = JsonFragBox.index_of_from(s, "\"rhs\":{", kcc)
|
||||||
if kci >= 0 { local kvs = s.indexOf("\"value\":", kci); if kvs >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs + 8) } }
|
local kci = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhsb2)
|
||||||
|
if kci >= 0 { local kvs = JsonFragBox.index_of_from(s, "\"value\":", kci); if kvs >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs + 8) } }
|
||||||
} else if rhs_i2 {
|
} else if rhs_i2 {
|
||||||
local kci2 = s.indexOf("\"type\":\"Int\"", s.indexOf("\"lhs\":{", kcc))
|
local k_lhsb2 = JsonFragBox.index_of_from(s, "\"lhs\":{", kcc)
|
||||||
if kci2 >= 0 { local kvs2 = s.indexOf("\"value\":", kci2); if kvs2 >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs2 + 8) } }
|
local kci2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_lhsb2)
|
||||||
|
if kci2 >= 0 { local kvs2 = JsonFragBox.index_of_from(s, "\"value\":", kci2); if kvs2 >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs2 + 8) } }
|
||||||
}
|
}
|
||||||
} else if cop != null && cop == "!=" {
|
} else if cop != null && cop == "!=" {
|
||||||
// Delegate to loop-scan helper for '!=' + else [Continue]
|
// 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) }
|
if skip_value == null { skip_value = LoopScanBox.extract_ne_else_sentinel_value(s, "Continue", k_loop, varname) }
|
||||||
// Fallback: JsonFragBox-based local extraction near kcc
|
// Fallback: JsonFragBox-based local extraction near kcc
|
||||||
if skip_value == null {
|
if skip_value == null {
|
||||||
local k_rhsb2 = s.indexOf("\"rhs\":{", kcc); local k_lhsb2 = s.indexOf("\"lhs\":{", kcc)
|
local k_rhsb2x = JsonFragBox.index_of_from(s, "\"rhs\":{", kcc); local k_lhsb2x = JsonFragBox.index_of_from(s, "\"lhs\":{", kcc)
|
||||||
if k_rhsb2 >= 0 && s.indexOf("\"type\":\"Int\"", k_rhsb2) >= 0 {
|
if k_rhsb2x >= 0 && JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhsb2x) >= 0 {
|
||||||
local kvs = s.indexOf("\"value\":", s.indexOf("\"type\":\"Int\"", k_rhsb2)); if kvs >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs + 8) }
|
local kvs = JsonFragBox.index_of_from(s, "\"value\":", JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_rhsb2x)); if kvs >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs + 8) }
|
||||||
} else if k_lhsb2 >= 0 && s.indexOf("\"type\":\"Int\"", k_lhsb2) >= 0 {
|
} else if k_lhsb2x >= 0 && JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_lhsb2x) >= 0 {
|
||||||
local kvs2 = s.indexOf("\"value\":", s.indexOf("\"type\":\"Int\"", k_lhsb2)); if kvs2 >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs2 + 8) }
|
local kvs2 = JsonFragBox.index_of_from(s, "\"value\":", JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_lhsb2x)); if kvs2 >= 0 { skip_value = JsonFragBox.read_int_after(s, kvs2 + 8) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,8 +5,8 @@ static box LowerMethodArrayGetSetBox {
|
|||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
if program_json == null { return null }
|
if program_json == null { return null }
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
if s.indexOf("\"type\":\"New\"") < 0 { return null }
|
if JsonFragBox.index_of_from(s, "\"type\":\"New\"", 0) < 0 { return null }
|
||||||
if s.indexOf("\"class\":\"ArrayBox\"") < 0 { return null }
|
if JsonFragBox.index_of_from(s, "\"class\":\"ArrayBox\"", 0) < 0 { return null }
|
||||||
// Reverse-lookup (safe subset): prefer Local(Int) for index, Local(String) for value
|
// Reverse-lookup (safe subset): prefer Local(Int) for index, Local(String) for value
|
||||||
local n = s.length()
|
local n = s.length()
|
||||||
local idx = PatternUtilBox.find_any_local_int_before(s, n)
|
local idx = PatternUtilBox.find_any_local_int_before(s, n)
|
||||||
|
|||||||
@ -5,8 +5,8 @@ static box LowerMethodArrayPushBox {
|
|||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
if program_json == null { return null }
|
if program_json == null { return null }
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
if s.indexOf("\"type\":\"New\"") < 0 { return null }
|
if JsonFragBox.index_of_from(s, "\"type\":\"New\"", 0) < 0 { return null }
|
||||||
if s.indexOf("\"class\":\"ArrayBox\"") < 0 { return null }
|
if JsonFragBox.index_of_from(s, "\"class\":\"ArrayBox\"", 0) < 0 { return null }
|
||||||
// Reverse-lookup (safe subset): prefer Local(Int) for push values when present
|
// Reverse-lookup (safe subset): prefer Local(Int) for push values when present
|
||||||
local n = s.length()
|
local n = s.length()
|
||||||
local p1 = PatternUtilBox.find_any_local_int_before(s, n); if p1 == null { p1 = "1" }
|
local p1 = PatternUtilBox.find_any_local_int_before(s, n); if p1 == null { p1 = "1" }
|
||||||
|
|||||||
@ -5,8 +5,8 @@ static box LowerMethodArraySizeBox {
|
|||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
if program_json == null { return null }
|
if program_json == null { return null }
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
if s.indexOf("\"type\":\"New\"") < 0 { return null }
|
if JsonFragBox.index_of_from(s, "\"type\":\"New\"", 0) < 0 { return null }
|
||||||
if s.indexOf("\"class\":\"ArrayBox\"") < 0 { return null }
|
if JsonFragBox.index_of_from(s, "\"class\":\"ArrayBox\"", 0) < 0 { return null }
|
||||||
// Emit MIR v1 JSON: new ArrayBox -> r1, size(r1) -> r2, const 0 -> r3, ret r3
|
// 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\":[" +
|
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\":1,\"mir_call\":{\"callee\":{\"type\":\"Constructor\",\"box_type\":\"ArrayBox\"},\"args\":[],\"effects\":[]}}," +
|
||||||
@ -16,4 +16,3 @@ static box LowerMethodArraySizeBox {
|
|||||||
return json
|
return json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,8 @@ static box LowerMethodMapGetSetBox {
|
|||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
if program_json == null { return null }
|
if program_json == null { return null }
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
if s.indexOf("\"type\":\"New\"") < 0 { return null }
|
if JsonFragBox.index_of_from(s, "\"type\":\"New\"", 0) < 0 { return null }
|
||||||
if s.indexOf("\"class\":\"MapBox\"") < 0 { return null }
|
if JsonFragBox.index_of_from(s, "\"class\":\"MapBox\"", 0) < 0 { return null }
|
||||||
// Reverse-lookup (safe subset): prefer Local(String) for key, Local(Int) for value
|
// Reverse-lookup (safe subset): prefer Local(String) for key, Local(Int) for value
|
||||||
local n = s.length()
|
local n = s.length()
|
||||||
local key = PatternUtilBox.find_any_local_string_before(s, n)
|
local key = PatternUtilBox.find_any_local_string_before(s, n)
|
||||||
|
|||||||
@ -4,8 +4,8 @@ static box LowerMethodMapSizeBox {
|
|||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
if program_json == null { return null }
|
if program_json == null { return null }
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
if s.indexOf("\"type\":\"New\"") < 0 { return null }
|
if JsonFragBox.index_of_from(s, "\"type\":\"New\"", 0) < 0 { return null }
|
||||||
if s.indexOf("\"class\":\"MapBox\"") < 0 { return null }
|
if JsonFragBox.index_of_from(s, "\"class\":\"MapBox\"", 0) < 0 { return null }
|
||||||
local json = "{\"kind\":\"MIR\",\"schema_version\":\"1.0\",\"functions\":[{\"name\":\"main\",\"blocks\":[{\"id\":0,\"instructions\":[" +
|
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\":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\":\"mir_call\",\"dst\":2,\"mir_call\":{\"callee\":{\"type\":\"Method\",\"box_name\":\"MapBox\",\"method\":\"size\",\"receiver\":1},\"args\":[],\"effects\":[]}}," +
|
||||||
@ -14,4 +14,3 @@ static box LowerMethodMapSizeBox {
|
|||||||
return json
|
return json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,11 +7,11 @@ static box LowerNewboxConstructorBox {
|
|||||||
if program_json == null { return null }
|
if program_json == null { return null }
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
// Quick pattern check
|
// Quick pattern check
|
||||||
if s.indexOf("\"type\":\"New\"") < 0 { return null }
|
if JsonFragBox.index_of_from(s, "\"type\":\"New\"", 0) < 0 { return null }
|
||||||
// Find class name (minimal scan)
|
// Find class name (minimal scan)
|
||||||
local cls = null
|
local cls = null
|
||||||
if s.indexOf("\"class\":\"ArrayBox\"") >= 0 { cls = "ArrayBox" }
|
if JsonFragBox.index_of_from(s, "\"class\":\"ArrayBox\"", 0) >= 0 { cls = "ArrayBox" }
|
||||||
else { if s.indexOf("\"class\":\"MapBox\"") >= 0 { cls = "MapBox" } }
|
else { if JsonFragBox.index_of_from(s, "\"class\":\"MapBox\"", 0) >= 0 { cls = "MapBox" } }
|
||||||
if cls == null { return null }
|
if cls == null { return null }
|
||||||
// Only accept known minimal boxes
|
// Only accept known minimal boxes
|
||||||
if !(cls == "ArrayBox" || cls == "MapBox") { return null }
|
if !(cls == "ArrayBox" || cls == "MapBox") { return null }
|
||||||
|
|||||||
@ -5,34 +5,34 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
|
|||||||
static box LowerReturnBinOpBox {
|
static box LowerReturnBinOpBox {
|
||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
local k_ret = s.indexOf("\"type\":\"Return\"")
|
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0)
|
||||||
if k_ret < 0 { return null }
|
if k_ret < 0 { return null }
|
||||||
local k_bin = s.indexOf("\"type\":\"Binary\"", k_ret)
|
local k_bin = JsonFragBox.index_of_from(s, "\"type\":\"Binary\"", k_ret)
|
||||||
if k_bin < 0 { return null }
|
if k_bin < 0 { return null }
|
||||||
// op
|
// op
|
||||||
local k_op = s.indexOf("\"op\":", k_bin)
|
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_bin)
|
||||||
if k_op < 0 { return null }
|
if k_op < 0 { return null }
|
||||||
local op = JsonFragBox.read_string_after(s, k_op + 5)
|
local op = JsonFragBox.read_string_after(s, k_op + 5)
|
||||||
if op == null { return null }
|
if op == null { return null }
|
||||||
if !(op == "+" || op == "-" || op == "*" || op == "/") { return null }
|
if !(op == "+" || op == "-" || op == "*" || op == "/") { return null }
|
||||||
// lhs/rhs object starts
|
// lhs/rhs object starts
|
||||||
local klhs = s.indexOf("\"lhs\":{", k_bin)
|
local klhs = JsonFragBox.index_of_from(s, "\"lhs\":{", k_bin)
|
||||||
local krhs = s.indexOf("\"rhs\":{", k_bin)
|
local krhs = JsonFragBox.index_of_from(s, "\"rhs\":{", k_bin)
|
||||||
if klhs < 0 { return null }
|
if klhs < 0 { return null }
|
||||||
// strictly ensure lhs node is Int by bounding search before rhs start
|
// strictly ensure lhs node is Int by bounding search before rhs start
|
||||||
local ti = s.indexOf("\"type\":\"Int\"", klhs)
|
local ti = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", klhs)
|
||||||
if ti < 0 { return null }
|
if ti < 0 { return null }
|
||||||
if krhs >= 0 && ti >= krhs { return null }
|
if krhs >= 0 && ti >= krhs { return null }
|
||||||
local kv_lhs = s.indexOf("\"value\":", ti)
|
local kv_lhs = JsonFragBox.index_of_from(s, "\"value\":", ti)
|
||||||
if kv_lhs < 0 { return null }
|
if kv_lhs < 0 { return null }
|
||||||
if krhs >= 0 && kv_lhs >= krhs { return null }
|
if krhs >= 0 && kv_lhs >= krhs { return null }
|
||||||
local lhs_val = JsonFragBox.read_int_after(s, kv_lhs + 8)
|
local lhs_val = JsonFragBox.read_int_after(s, kv_lhs + 8)
|
||||||
if lhs_val == null { return null }
|
if lhs_val == null { return null }
|
||||||
// rhs int
|
// rhs int
|
||||||
if krhs < 0 { return null }
|
if krhs < 0 { return null }
|
||||||
local ti2 = s.indexOf("\"type\":\"Int\"", krhs)
|
local ti2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", krhs)
|
||||||
if ti2 < 0 { return null }
|
if ti2 < 0 { return null }
|
||||||
local kv_rhs = s.indexOf("\"value\":", ti2)
|
local kv_rhs = JsonFragBox.index_of_from(s, "\"value\":", ti2)
|
||||||
if kv_rhs < 0 { return null }
|
if kv_rhs < 0 { return null }
|
||||||
local rhs_val = JsonFragBox.read_int_after(s, kv_rhs + 8)
|
local rhs_val = JsonFragBox.read_int_after(s, kv_rhs + 8)
|
||||||
if rhs_val == null { return null }
|
if rhs_val == null { return null }
|
||||||
|
|||||||
@ -10,26 +10,27 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
|
|||||||
static box LowerReturnBinOpVarIntBox {
|
static box LowerReturnBinOpVarIntBox {
|
||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
local k_ret = s.indexOf("\"type\":\"Return\"")
|
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0)
|
||||||
if k_ret < 0 { return null }
|
if k_ret < 0 { return null }
|
||||||
local k_bin = s.indexOf("\"type\":\"Binary\"", k_ret)
|
local k_bin = JsonFragBox.index_of_from(s, "\"type\":\"Binary\"", k_ret)
|
||||||
if k_bin < 0 { return null }
|
if k_bin < 0 { return null }
|
||||||
local k_op = s.indexOf("\"op\":", k_bin)
|
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_bin)
|
||||||
if k_op < 0 { return null }
|
if k_op < 0 { return null }
|
||||||
local op = JsonFragBox.read_string_after(s, k_op + 5)
|
local op = JsonFragBox.read_string_after(s, k_op + 5)
|
||||||
if op == null { return null }
|
if op == null { return null }
|
||||||
if !(op == "+" || op == "-" || op == "*" || op == "/") { return null }
|
// Map op symbol to MIR op_kind via shared util
|
||||||
|
local kind = PatternUtilBox.map_binop(op); if kind == null { return null }
|
||||||
// Try Var + Int
|
// Try Var + Int
|
||||||
local klhs_var = s.indexOf("\"lhs\":{\"type\":\"Var\"", k_bin)
|
local klhs_var = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Var\"", k_bin)
|
||||||
local krhs_int = s.indexOf("\"rhs\":{\"type\":\"Int\"", k_bin)
|
local krhs_int = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Int\"", k_bin)
|
||||||
local var_name = null
|
local var_name = null
|
||||||
local rhs_val = null
|
local rhs_val = null
|
||||||
if klhs_var >= 0 && krhs_int >= 0 {
|
if klhs_var >= 0 && krhs_int >= 0 {
|
||||||
local k_name = s.indexOf("\"name\":", klhs_var); if k_name < 0 { return null }
|
local k_name = JsonFragBox.index_of_from(s, "\"name\":", klhs_var); if k_name < 0 { return null }
|
||||||
var_name = JsonFragBox.read_string_after(s, k_name + 7)
|
var_name = JsonFragBox.read_string_after(s, k_name + 7)
|
||||||
local kvi = s.indexOf("\"type\":\"Int\"", krhs_int)
|
local kvi = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", krhs_int)
|
||||||
if kvi >= 0 {
|
if kvi >= 0 {
|
||||||
local kv = s.indexOf("\"value\":", kvi); if kv < 0 { return null }
|
local kv = JsonFragBox.index_of_from(s, "\"value\":", kvi); if kv < 0 { return null }
|
||||||
rhs_val = JsonFragBox.read_int_after(s, kv + 8)
|
rhs_val = JsonFragBox.read_int_after(s, kv + 8)
|
||||||
}
|
}
|
||||||
if var_name != null && rhs_val != null {
|
if var_name != null && rhs_val != null {
|
||||||
@ -38,7 +39,7 @@ static box LowerReturnBinOpVarIntBox {
|
|||||||
local b0 = new ArrayBox()
|
local b0 = new ArrayBox()
|
||||||
b0.push(MirSchemaBox.inst_const(1, var_val))
|
b0.push(MirSchemaBox.inst_const(1, var_val))
|
||||||
b0.push(MirSchemaBox.inst_const(2, rhs_val))
|
b0.push(MirSchemaBox.inst_const(2, rhs_val))
|
||||||
b0.push(MirSchemaBox.inst_binop(op == "+" ? "Add" : (op == "-" ? "Sub" : (op == "*" ? "Mul" : "Div")), 1, 2, 3))
|
b0.push(MirSchemaBox.inst_binop(kind, 1, 2, 3))
|
||||||
b0.push(MirSchemaBox.inst_ret(3))
|
b0.push(MirSchemaBox.inst_ret(3))
|
||||||
local blocks = new ArrayBox(); blocks.push(MirSchemaBox.block(0, b0))
|
local blocks = new ArrayBox(); blocks.push(MirSchemaBox.block(0, b0))
|
||||||
return MirSchemaBox.module(MirSchemaBox.fn_main(blocks))
|
return MirSchemaBox.module(MirSchemaBox.fn_main(blocks))
|
||||||
@ -46,17 +47,17 @@ static box LowerReturnBinOpVarIntBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Try Int + Var
|
// Try Int + Var
|
||||||
local klhs_int = s.indexOf("\"lhs\":{\"type\":\"Int\"", k_bin)
|
local klhs_int = JsonFragBox.index_of_from(s, "\"lhs\":{\"type\":\"Int\"", k_bin)
|
||||||
local krhs_var = s.indexOf("\"rhs\":{\"type\":\"Var\"", k_bin)
|
local krhs_var = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\"", k_bin)
|
||||||
var_name = null
|
var_name = null
|
||||||
local lhs_val = null
|
local lhs_val = null
|
||||||
if klhs_int >= 0 && krhs_var >= 0 {
|
if klhs_int >= 0 && krhs_var >= 0 {
|
||||||
local kvi2 = s.indexOf("\"type\":\"Int\"", klhs_int)
|
local kvi2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", klhs_int)
|
||||||
if kvi2 >= 0 {
|
if kvi2 >= 0 {
|
||||||
local kv2 = s.indexOf("\"value\":", kvi2); if kv2 < 0 { return null }
|
local kv2 = JsonFragBox.index_of_from(s, "\"value\":", kvi2); if kv2 < 0 { return null }
|
||||||
lhs_val = JsonFragBox.read_int_after(s, kv2 + 8)
|
lhs_val = JsonFragBox.read_int_after(s, kv2 + 8)
|
||||||
}
|
}
|
||||||
local k_name2 = s.indexOf("\"name\":", krhs_var); if k_name2 < 0 { return null }
|
local k_name2 = JsonFragBox.index_of_from(s, "\"name\":", krhs_var); if k_name2 < 0 { return null }
|
||||||
var_name = JsonFragBox.read_string_after(s, k_name2 + 7)
|
var_name = JsonFragBox.read_string_after(s, k_name2 + 7)
|
||||||
if lhs_val != null && var_name != null {
|
if lhs_val != null && var_name != null {
|
||||||
local var_val2 = PatternUtilBox.find_local_int_before(s, var_name, k_ret)
|
local var_val2 = PatternUtilBox.find_local_int_before(s, var_name, k_ret)
|
||||||
@ -64,7 +65,7 @@ static box LowerReturnBinOpVarIntBox {
|
|||||||
local b1 = new ArrayBox()
|
local b1 = new ArrayBox()
|
||||||
b1.push(MirSchemaBox.inst_const(1, lhs_val))
|
b1.push(MirSchemaBox.inst_const(1, lhs_val))
|
||||||
b1.push(MirSchemaBox.inst_const(2, var_val2))
|
b1.push(MirSchemaBox.inst_const(2, var_val2))
|
||||||
b1.push(MirSchemaBox.inst_binop(op == "+" ? "Add" : (op == "-" ? "Sub" : (op == "*" ? "Mul" : "Div")), 1, 2, 3))
|
b1.push(MirSchemaBox.inst_binop(kind, 1, 2, 3))
|
||||||
b1.push(MirSchemaBox.inst_ret(3))
|
b1.push(MirSchemaBox.inst_ret(3))
|
||||||
local blocks = new ArrayBox(); blocks.push(MirSchemaBox.block(0, b1))
|
local blocks = new ArrayBox(); blocks.push(MirSchemaBox.block(0, b1))
|
||||||
return MirSchemaBox.module(MirSchemaBox.fn_main(blocks))
|
return MirSchemaBox.module(MirSchemaBox.fn_main(blocks))
|
||||||
|
|||||||
@ -7,20 +7,20 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
|
|||||||
static box LowerReturnBinOpVarVarBox {
|
static box LowerReturnBinOpVarVarBox {
|
||||||
try_lower(program_json){
|
try_lower(program_json){
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
local k_ret = s.indexOf("\"type\":\"Return\""); if k_ret < 0 { return null }
|
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0); if k_ret < 0 { return null }
|
||||||
local k_bin = s.indexOf("\"type\":\"Binary\"", k_ret); if k_bin < 0 { return null }
|
local k_bin = JsonFragBox.index_of_from(s, "\"type\":\"Binary\"", k_ret); if k_bin < 0 { return null }
|
||||||
local k_op = s.indexOf("\"op\":", k_bin); if k_op < 0 { return null }
|
local k_op = JsonFragBox.index_of_from(s, "\"op\":", k_bin); if k_op < 0 { return null }
|
||||||
local op = JsonFragBox.read_string_after(s, k_op + 5); if op == null { 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 kind = PatternUtilBox.map_binop(op); if kind == null { return null }
|
||||||
local klhs = s.indexOf("\"lhs\":{\"type\":\"Var\"", k_bin); if klhs < 0 { return null }
|
local klhs = JsonFragBox.index_of_from(s, "\"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 krhs = JsonFragBox.index_of_from(s, "\"rhs\":{\"type\":\"Var\"", k_bin); if krhs < 0 { return null }
|
||||||
local knl = s.indexOf("\"name\":", klhs); if knl < 0 { return null }
|
local knl = JsonFragBox.index_of_from(s, "\"name\":", klhs); if knl < 0 { return null }
|
||||||
local lname = JsonFragBox.read_string_after(s, knl + 7); if lname == null { 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 knr = JsonFragBox.index_of_from(s, "\"name\":", krhs); if knr < 0 { return null }
|
||||||
local rname = JsonFragBox.read_string_after(s, knr + 7); if rname == null { 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 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 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 b0=new ArrayBox(); b0.push(MirSchemaBox.inst_const(1,lval)); b0.push(MirSchemaBox.inst_const(2,rval)); b0.push(MirSchemaBox.inst_binop(kind,1,2,3)); b0.push(MirSchemaBox.inst_ret(3))
|
||||||
local blocks=new ArrayBox(); blocks.push(MirSchemaBox.block(0,b0));
|
local blocks=new ArrayBox(); blocks.push(MirSchemaBox.block(0,b0));
|
||||||
return MirSchemaBox.module(MirSchemaBox.fn_main(blocks))
|
return MirSchemaBox.module(MirSchemaBox.fn_main(blocks))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,16 +5,16 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
|
|||||||
static box LowerReturnBoolBox {
|
static box LowerReturnBoolBox {
|
||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
local k_ret = s.indexOf("\"type\":\"Return\"")
|
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0)
|
||||||
if k_ret < 0 { return null }
|
if k_ret < 0 { return null }
|
||||||
// Restrict to Return(expr=Bool …): require expr 開始直後に Bool が来る
|
// Restrict to Return(expr=Bool …): require expr 開始直後に Bool が来る
|
||||||
// 例: "expr":{"type":"Bool","value":true}
|
// 例: "expr":{"type":"Bool","value":true}
|
||||||
local k_expr = s.indexOf("\"expr\":", k_ret)
|
local k_expr = JsonFragBox.index_of_from(s, "\"expr\":", k_ret)
|
||||||
if k_expr < 0 { return null }
|
if k_expr < 0 { return null }
|
||||||
local k_bool = s.indexOf("\"type\":\"Bool\"", k_expr)
|
local k_bool = JsonFragBox.index_of_from(s, "\"type\":\"Bool\"", k_expr)
|
||||||
if k_bool < 0 { return null }
|
if k_bool < 0 { return null }
|
||||||
// Ensure this Bool belongs to the same expr (次の '}' までに value があることを確認)
|
// Ensure this Bool belongs to the same expr (次の '}' までに value があることを確認)
|
||||||
local k_val = s.indexOf("\"value\":", k_bool)
|
local k_val = JsonFragBox.index_of_from(s, "\"value\":", k_bool)
|
||||||
if k_val < 0 { return null }
|
if k_val < 0 { return null }
|
||||||
local is_true = JsonFragBox.read_bool_after(s, k_val+8)
|
local is_true = JsonFragBox.read_bool_after(s, k_val+8)
|
||||||
if is_true == null { return null }
|
if is_true == null { return null }
|
||||||
|
|||||||
@ -6,11 +6,11 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
|
|||||||
static box LowerReturnFloatBox {
|
static box LowerReturnFloatBox {
|
||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
local k_ret = s.indexOf("\"type\":\"Return\"")
|
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0)
|
||||||
if k_ret < 0 { return null }
|
if k_ret < 0 { return null }
|
||||||
local k_float = s.indexOf("\"type\":\"Float\"", k_ret)
|
local k_float = JsonFragBox.index_of_from(s, "\"type\":\"Float\"", k_ret)
|
||||||
if k_float < 0 { return null }
|
if k_float < 0 { return null }
|
||||||
local k_val = s.indexOf("\"value\":", k_float)
|
local k_val = JsonFragBox.index_of_from(s, "\"value\":", k_float)
|
||||||
if k_val < 0 { return null }
|
if k_val < 0 { return null }
|
||||||
local fstr = JsonFragBox.read_float_after(s, k_val+8)
|
local fstr = JsonFragBox.read_float_after(s, k_val+8)
|
||||||
if fstr == null { return null }
|
if fstr == null { return null }
|
||||||
|
|||||||
@ -5,14 +5,14 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
|
|||||||
static box LowerReturnIntBox {
|
static box LowerReturnIntBox {
|
||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
local k_ret = s.indexOf("\"type\":\"Return\"")
|
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0)
|
||||||
if k_ret < 0 { return null }
|
if k_ret < 0 { return null }
|
||||||
// Find expr object
|
// Find expr object
|
||||||
local k_expr = s.indexOf("\"expr\":{", k_ret)
|
local k_expr = JsonFragBox.index_of_from(s, "\"expr\":{", k_ret)
|
||||||
if k_expr < 0 { return null }
|
if k_expr < 0 { return null }
|
||||||
// Check that expr.type is directly Int (not Binary, Logical, Var, etc)
|
// Check that expr.type is directly Int (not Binary, Logical, Var, etc)
|
||||||
local k_type_start = k_expr + 8
|
local k_type_start = k_expr + 8
|
||||||
local k_type = s.indexOf("\"type\":", k_type_start)
|
local k_type = JsonFragBox.index_of_from(s, "\"type\":", k_type_start)
|
||||||
if k_type < 0 || k_type > k_type_start + 20 { return null }
|
if k_type < 0 || k_type > k_type_start + 20 { return null }
|
||||||
// Extract type value to verify it's "Int"
|
// Extract type value to verify it's "Int"
|
||||||
local k_type_val = k_type + 7
|
local k_type_val = k_type + 7
|
||||||
@ -28,9 +28,9 @@ static box LowerReturnIntBox {
|
|||||||
if k_type_val + 3 >= n { return null }
|
if k_type_val + 3 >= n { return null }
|
||||||
if s.substring(k_type_val+3, k_type_val+4) != "\"" { return null }
|
if s.substring(k_type_val+3, k_type_val+4) != "\"" { return null }
|
||||||
// Now extract the value
|
// Now extract the value
|
||||||
local k_int = s.indexOf("\"type\":\"Int\"", k_expr)
|
local k_int = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_expr)
|
||||||
if k_int < 0 { return null }
|
if k_int < 0 { return null }
|
||||||
local kv = s.indexOf("\"value\":", k_int); if kv < 0 { return null }
|
local kv = JsonFragBox.index_of_from(s, "\"value\":", k_int); if kv < 0 { return null }
|
||||||
local val = JsonFragBox.read_int_after(s, kv + 8)
|
local val = JsonFragBox.read_int_after(s, kv + 8)
|
||||||
if val == null { return null }
|
if val == null { return null }
|
||||||
local debug_on = 0
|
local debug_on = 0
|
||||||
|
|||||||
@ -11,7 +11,7 @@ static box LowerReturnLogicalBox {
|
|||||||
|
|
||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
local k_ret = s.indexOf("\"type\":\"Return\"")
|
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0)
|
||||||
if k_ret < 0 { return null }
|
if k_ret < 0 { return null }
|
||||||
local k_log = JsonFragBox.index_of_from(s, "\"type\":\"Logical\"", k_ret)
|
local k_log = JsonFragBox.index_of_from(s, "\"type\":\"Logical\"", k_ret)
|
||||||
if k_log < 0 { return null }
|
if k_log < 0 { return null }
|
||||||
|
|||||||
@ -8,12 +8,12 @@ using selfhost.vm.helpers.method_alias_policy as MethodAliasPolicy
|
|||||||
static box LowerReturnMethodArrayMapBox {
|
static box LowerReturnMethodArrayMapBox {
|
||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
local k_ret = s.indexOf("\"type\":\"Return\""); if k_ret < 0 { return null }
|
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0); if k_ret < 0 { return null }
|
||||||
local k_m = s.indexOf("\"type\":\"Method\"", k_ret); if k_m < 0 { return null }
|
local k_m = JsonFragBox.index_of_from(s, "\"type\":\"Method\"", k_ret); if k_m < 0 { return null }
|
||||||
// receiver must be Var(name)
|
// receiver must be Var(name)
|
||||||
local k_recv = s.indexOf("\"recv\":{\"type\":\"Var\"", k_m); if k_recv < 0 { return null }
|
local k_recv = JsonFragBox.index_of_from(s, "\"recv\":{\"type\":\"Var\"", k_m); if k_recv < 0 { return null }
|
||||||
local method = null
|
local method = null
|
||||||
{ local km = s.indexOf("\"method\":\"", k_m); if km < 0 { return null } method = JsonFragBox.read_string_after(s, km) }
|
{ local km = JsonFragBox.index_of_from(s, "\"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)
|
// Standardize: generate 'size' (len/length are accepted aliases at receiver)
|
||||||
method = MethodAliasPolicy.normalize_size(method)
|
method = MethodAliasPolicy.normalize_size(method)
|
||||||
// Allow basic methods
|
// Allow basic methods
|
||||||
@ -23,91 +23,56 @@ static box LowerReturnMethodArrayMapBox {
|
|||||||
local b0 = new ArrayBox()
|
local b0 = new ArrayBox()
|
||||||
// Receiver placeholder (Var resolve未実装のため 0 を置く)
|
// Receiver placeholder (Var resolve未実装のため 0 を置く)
|
||||||
b0.push(MirSchemaBox.inst_const(1, 0))
|
b0.push(MirSchemaBox.inst_const(1, 0))
|
||||||
local k_args = s.indexOf("\"args\":", k_m)
|
local k_args = JsonFragBox.index_of_from(s, "\"args\":", k_m)
|
||||||
local next_id = 2
|
local next_id = 2
|
||||||
if k_args >= 0 {
|
if k_args >= 0 {
|
||||||
// first arg: Int or Var(Int)
|
// first arg: Int or Var(Int)
|
||||||
local k_i1 = s.indexOf("\"type\":\"Int\"", k_args)
|
local k_i1 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_args)
|
||||||
local k_v1 = s.indexOf("\"type\":\"Var\"", k_args)
|
local k_v1 = JsonFragBox.index_of_from(s, "\"type\":\"Var\"", k_args)
|
||||||
if k_i1 >= 0 && (k_v1 < 0 || k_i1 < k_v1) {
|
if k_i1 >= 0 && (k_v1 < 0 || k_i1 < k_v1) {
|
||||||
// read numeric after value:
|
// read numeric after value:
|
||||||
local k_val1 = s.indexOf("\"value\":", k_i1)
|
local k_val1 = JsonFragBox.index_of_from(s, "\"value\":", k_i1)
|
||||||
if k_val1 >= 0 {
|
if k_val1 >= 0 {
|
||||||
local v1 = JsonFragBox.read_int_after(s, k_val1 + 8)
|
local v1 = JsonFragBox.read_int_after(s, k_val1 + 8)
|
||||||
if v1 != null { b0.push(MirSchemaBox.inst_const(next_id, v1)) args_ids.push(next_id) next_id = next_id + 1 }
|
if v1 != null { b0.push(MirSchemaBox.inst_const(next_id, v1)) args_ids.push(next_id) next_id = next_id + 1 }
|
||||||
}
|
}
|
||||||
// second arg after first
|
// second arg after first
|
||||||
local k_i2 = s.indexOf("\"type\":\"Int\"", k_i1 + 1)
|
local k_i2 = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_i1 + 1)
|
||||||
local k_v2a = s.indexOf("\"type\":\"Var\"", k_i1 + 1)
|
local k_v2a = JsonFragBox.index_of_from(s, "\"type\":\"Var\"", k_i1 + 1)
|
||||||
if k_i2 >= 0 {
|
if k_i2 >= 0 {
|
||||||
local k_v2 = s.indexOf("\"value\":", k_i2)
|
local k_v2 = JsonFragBox.index_of_from(s, "\"value\":", k_i2)
|
||||||
if k_v2 >= 0 { local v2 = JsonFragBox.read_int_after(s, k_v2 + 8); if v2 != null { b0.push(MirSchemaBox.inst_const(next_id, v2)) args_ids.push(next_id) next_id = next_id + 1 } }
|
if k_v2 >= 0 { local v2 = JsonFragBox.read_int_after(s, k_v2 + 8); if v2 != null { b0.push(MirSchemaBox.inst_const(next_id, v2)) args_ids.push(next_id) next_id = next_id + 1 } }
|
||||||
} else if k_v2a >= 0 {
|
} else if k_v2a >= 0 {
|
||||||
// second arg is Var: resolve Local Int value
|
// second arg is Var: resolve Local Int value
|
||||||
local kn = s.indexOf("\"name\":\"", k_v2a)
|
local kn = JsonFragBox.index_of_from(s, "\"name\":\"", k_v2a)
|
||||||
if kn >= 0 {
|
if kn >= 0 {
|
||||||
local name2 = JsonFragBox.read_string_after(s, kn)
|
local name2 = JsonFragBox.read_string_after(s, kn)
|
||||||
// scan backwards for Local name2 Int
|
local v = PatternUtilBox.find_local_int_before(s, name2, k_m)
|
||||||
local pos = 0; local last = -1
|
if v != null { b0.push(MirSchemaBox.inst_const(next_id, v)) args_ids.push(next_id) next_id = next_id + 1 }
|
||||||
loop(true) {
|
|
||||||
local kL = s.indexOf("\"type\":\"Local\"", pos)
|
|
||||||
if kL < 0 || kL >= k_m { break }
|
|
||||||
local nm = null
|
|
||||||
{
|
|
||||||
local kn2 = s.indexOf("\"name\":\"", kL)
|
|
||||||
if kn2 >= 0 {
|
|
||||||
local iii = kn2 + 8; local nnn = s.length(); local jjj = iii
|
|
||||||
loop(jjj < nnn) { if s.substring(jjj,jjj+1) == '"' { break } jjj = jjj + 1 }
|
|
||||||
nm = s.substring(iii, jjj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if nm != null && nm == name2 { last = kL }
|
|
||||||
pos = kL + 1
|
|
||||||
}
|
|
||||||
if last >= 0 {
|
|
||||||
local ki = s.indexOf("\"type\":\"Int\"", last)
|
|
||||||
if ki >= 0 && ki < k_m {
|
|
||||||
local kv = s.indexOf("\"value\":", ki)
|
|
||||||
if kv >= 0 { local v = JsonFragBox.read_int_after(s, kv + 8); if v != null { b0.push(MirSchemaBox.inst_const(next_id, v)) args_ids.push(next_id) next_id = next_id + 1 } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if k_v1 >= 0 && (k_i1 < 0 || k_v1 < k_i1) {
|
} else if k_v1 >= 0 && (k_i1 < 0 || k_v1 < k_i1) {
|
||||||
// first arg is Var: resolve Local value (Int/Bool/Float/String)
|
// first arg is Var: resolve Local value (Int/Bool/Float/String)
|
||||||
local kn = s.indexOf("\"name\":\"", k_v1)
|
local kn = JsonFragBox.index_of_from(s, "\"name\":\"", k_v1)
|
||||||
if kn >= 0 {
|
if kn >= 0 {
|
||||||
local namev = JsonFragBox.read_string_after(s, kn)
|
local namev = JsonFragBox.read_string_after(s, kn)
|
||||||
// find last Local namev Int before method
|
// Prefer exact-name Local lookups via PatternUtilBox
|
||||||
local pos2 = 0; local last2 = -1
|
// Int / Bool / Float / String (in this order)
|
||||||
loop(true) {
|
{
|
||||||
local kL2 = s.indexOf("\"type\":\"Local\"", pos2)
|
local vi = PatternUtilBox.find_local_int_before(s, namev, k_m)
|
||||||
if kL2 < 0 || kL2 >= k_m { break }
|
if vi != null { b0.push(MirSchemaBox.inst_const(next_id, vi)) args_ids.push(next_id) next_id = next_id + 1 }
|
||||||
local nm2 = null
|
|
||||||
{
|
|
||||||
local knm = s.indexOf("\"name\":\"", kL2)
|
|
||||||
if knm >= 0 {
|
|
||||||
local iii2 = knm + 8; local nnn2 = s.length(); local jjj2 = iii2
|
|
||||||
loop(jjj2 < nnn2) { if s.substring(jjj2,jjj2+1) == '"' { break } jjj2 = jjj2 + 1 }
|
|
||||||
nm2 = s.substring(iii2, jjj2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if nm2 != null && nm2 == namev { last2 = kL2 }
|
|
||||||
pos2 = kL2 + 1
|
|
||||||
}
|
}
|
||||||
if last2 >= 0 {
|
{
|
||||||
// Int
|
local vb = PatternUtilBox.find_local_bool_before(s, namev, k_m)
|
||||||
local ki3 = s.indexOf("\"type\":\"Int\"", last2)
|
if vb != null { b0.push(MirSchemaBox.inst_const(next_id, vb)) args_ids.push(next_id) next_id = next_id + 1 }
|
||||||
if ki3 >= 0 && ki3 < k_m { local kv3 = s.indexOf("\"value\":", ki3); if kv3 >= 0 { local v = JsonFragBox.read_int_after(s, kv3 + 8); if v != null { b0.push(MirSchemaBox.inst_const(next_id, v)) args_ids.push(next_id) next_id = next_id + 1 } } }
|
}
|
||||||
// Bool
|
{
|
||||||
local kb3 = s.indexOf("\"type\":\"Bool\"", last2)
|
local vf = PatternUtilBox.find_local_float_before(s, namev, k_m)
|
||||||
if kb3 >= 0 && kb3 < k_m { local kvb = s.indexOf("\"value\":", kb3); if kvb >= 0 { local vb = JsonFragBox.read_bool_after(s, kvb + 8); if vb != null { b0.push(MirSchemaBox.inst_const(next_id, vb)) args_ids.push(next_id) next_id = next_id + 1 } } }
|
if vf != null { b0.push(MirSchemaBox.inst_const_f64(next_id, vf)) args_ids.push(next_id) next_id = next_id + 1 }
|
||||||
// Float
|
}
|
||||||
local kf3 = s.indexOf("\"type\":\"Float\"", last2)
|
{
|
||||||
if kf3 >= 0 && kf3 < k_m { local kvf = s.indexOf("\"value\":", kf3); if kvf >= 0 { local fv = JsonFragBox.read_float_after(s, kvf + 8); if fv != null { b0.push(MirSchemaBox.inst_const_f64(next_id, fv)) args_ids.push(next_id) next_id = next_id + 1 } } }
|
local vs = PatternUtilBox.find_local_string_before(s, namev, k_m)
|
||||||
// String
|
if vs != null { b0.push(MirSchemaBox.inst_const_str(next_id, vs)) args_ids.push(next_id) next_id = next_id + 1 }
|
||||||
local ks3 = s.indexOf("\"type\":\"String\"", last2)
|
|
||||||
if ks3 >= 0 && ks3 < k_m { local kvs = s.indexOf("\"value\":\"", ks3); if kvs >= 0 { local sv = JsonFragBox.read_string_after(s, kvs + 8); if sv != null { b0.push(MirSchemaBox.inst_const_str(next_id, sv)) args_ids.push(next_id) next_id = next_id + 1 } } }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,11 +6,11 @@ using selfhost.shared.json.utils.json_frag as JsonFragBox
|
|||||||
static box LowerReturnStringBox {
|
static box LowerReturnStringBox {
|
||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
local k_ret = s.indexOf("\"type\":\"Return\"")
|
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", 0)
|
||||||
if k_ret < 0 { return null }
|
if k_ret < 0 { return null }
|
||||||
local k_str = s.indexOf("\"type\":\"String\"", k_ret)
|
local k_str = JsonFragBox.index_of_from(s, "\"type\":\"String\"", k_ret)
|
||||||
if k_str < 0 { return null }
|
if k_str < 0 { return null }
|
||||||
local k_val = s.indexOf("\"value\":", k_str)
|
local k_val = JsonFragBox.index_of_from(s, "\"value\":", k_str)
|
||||||
if k_val < 0 { return null }
|
if k_val < 0 { return null }
|
||||||
local sval = JsonFragBox.read_string_after(s, k_val+8)
|
local sval = JsonFragBox.read_string_after(s, k_val+8)
|
||||||
if sval == null { return null }
|
if sval == null { return null }
|
||||||
|
|||||||
@ -7,25 +7,25 @@ static box LowerReturnVarLocalBox {
|
|||||||
try_lower(program_json) {
|
try_lower(program_json) {
|
||||||
local s = "" + program_json
|
local s = "" + program_json
|
||||||
// Find Local with name:"x" and expr Int value
|
// Find Local with name:"x" and expr Int value
|
||||||
local k_loc = s.indexOf("\"type\":\"Local\"")
|
local k_loc = JsonFragBox.index_of_from(s, "\"type\":\"Local\"", 0)
|
||||||
if k_loc < 0 { return null }
|
if k_loc < 0 { return null }
|
||||||
// Extract name
|
// Extract name
|
||||||
local k_name = s.indexOf("\"name\":", k_loc); if k_name < 0 { return null }
|
local k_name = JsonFragBox.index_of_from(s, "\"name\":", k_loc); if k_name < 0 { return null }
|
||||||
local name = JsonFragBox.read_string_after(s, k_name + 5)
|
local name = JsonFragBox.read_string_after(s, k_name + 5)
|
||||||
if name == null || name == "" { return null }
|
if name == null || name == "" { return null }
|
||||||
// Ensure expr Int after this Local
|
// Ensure expr Int after this Local
|
||||||
local k_int = s.indexOf("\"type\":\"Int\"", k_loc)
|
local k_int = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", k_loc)
|
||||||
if k_int < 0 { return null }
|
if k_int < 0 { return null }
|
||||||
local kv = s.indexOf("\"value\":", k_int); if kv < 0 { return null }
|
local kv = JsonFragBox.index_of_from(s, "\"value\":", k_int); if kv < 0 { return null }
|
||||||
local val = JsonFragBox.read_int_after(s, kv + 8)
|
local val = JsonFragBox.read_int_after(s, kv + 8)
|
||||||
if val == null { return null }
|
if val == null { return null }
|
||||||
// Following Return Var(name)
|
// Following Return Var(name)
|
||||||
local k_ret = s.indexOf("\"type\":\"Return\"", k_loc)
|
local k_ret = JsonFragBox.index_of_from(s, "\"type\":\"Return\"", k_loc)
|
||||||
if k_ret < 0 { return null }
|
if k_ret < 0 { return null }
|
||||||
// Verify Var(name)
|
// Verify Var(name)
|
||||||
local k_var = s.indexOf("\"type\":\"Var\"", k_ret)
|
local k_var = JsonFragBox.index_of_from(s, "\"type\":\"Var\"", k_ret)
|
||||||
if k_var < 0 { return null }
|
if k_var < 0 { return null }
|
||||||
local k_vn = s.indexOf("\"name\":", k_var); if k_vn < 0 { return null }
|
local k_vn = JsonFragBox.index_of_from(s, "\"name\":", k_var); if k_vn < 0 { return null }
|
||||||
local vname = JsonFragBox.read_string_after(s, k_vn + 5)
|
local vname = JsonFragBox.read_string_after(s, k_vn + 5)
|
||||||
if vname == null || vname != name { return null }
|
if vname == null || vname != name { return null }
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ using selfhost.shared.common.string_helpers as StringHelpers
|
|||||||
|
|
||||||
static box PatternUtilBox {
|
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 }
|
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 }
|
||||||
|
map_binop(sym) { if sym=="+" {return "Add"} if sym=="-" {return "Sub"} if sym=="*" {return "Mul"} if sym=="/" {return "Div"} return null }
|
||||||
// Normalize (op, swapped, limit) → (cmp, limit') where cmp in {Lt, Le, Gt, Ge}
|
// Normalize (op, swapped, limit) → (cmp, limit') where cmp in {Lt, Le, Gt, Ge}
|
||||||
// swapped=0: i ? L, swapped=1: L ? i
|
// swapped=0: i ? L, swapped=1: L ? i
|
||||||
normalize_cmp_limit(op, swapped, limit_str) {
|
normalize_cmp_limit(op, swapped, limit_str) {
|
||||||
@ -50,9 +51,9 @@ static box PatternUtilBox {
|
|||||||
// Bound the search between this Local and the next Local/before_pos
|
// Bound the search between this Local and the next Local/before_pos
|
||||||
local next = JsonFragBox.index_of_from(s, "\"type\":\"Local\"", last + 1)
|
local next = JsonFragBox.index_of_from(s, "\"type\":\"Local\"", last + 1)
|
||||||
if next < 0 || next > before_pos { next = before_pos }
|
if next < 0 || next > before_pos { next = before_pos }
|
||||||
local ki = s.indexOf("\"type\":\"Int\"", last)
|
local ki = JsonFragBox.index_of_from(s, "\"type\":\"Int\"", last)
|
||||||
if ki < 0 || ki >= next { return null }
|
if ki < 0 || ki >= next { return null }
|
||||||
local kv = s.indexOf("\"value\":", ki)
|
local kv = JsonFragBox.index_of_from(s, "\"value\":", ki)
|
||||||
if kv < 0 || kv >= next { return null }
|
if kv < 0 || kv >= next { return null }
|
||||||
return JsonFragBox.read_int_after(s, kv+8)
|
return JsonFragBox.read_int_after(s, kv+8)
|
||||||
}
|
}
|
||||||
@ -62,14 +63,64 @@ static box PatternUtilBox {
|
|||||||
if last<0 { return null }
|
if last<0 { return null }
|
||||||
local next = JsonFragBox.index_of_from(s, "\"type\":\"Local\"", last + 1)
|
local next = JsonFragBox.index_of_from(s, "\"type\":\"Local\"", last + 1)
|
||||||
if next < 0 || next > before_pos { next = before_pos }
|
if next < 0 || next > before_pos { next = before_pos }
|
||||||
local kb = s.indexOf("\"type\":\"Bool\"", last)
|
local kb = JsonFragBox.index_of_from(s, "\"type\":\"Bool\"", last)
|
||||||
if kb < 0 || kb >= next { return null }
|
if kb < 0 || kb >= next { return null }
|
||||||
local kv = s.indexOf("\"value\":", kb)
|
local kv = JsonFragBox.index_of_from(s, "\"value\":", kb)
|
||||||
if kv < 0 || kv >= next { return null }
|
if kv < 0 || kv >= next { return null }
|
||||||
// JSON v0 uses 0/1 for bool values, not true/false literals
|
// JSON v0 uses 0/1 for bool values, not true/false literals
|
||||||
return JsonFragBox.read_int_after(s, kv+8)
|
return JsonFragBox.read_int_after(s, kv+8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find the last Local(String) with given name before a given position.
|
||||||
|
// Returns raw string or null when not found.
|
||||||
|
find_local_string_before(s, name, before_pos) {
|
||||||
|
local pos=0; local last=-1
|
||||||
|
loop(true){
|
||||||
|
local k=JsonFragBox.index_of_from(s, "\"type\":\"Local\"",pos)
|
||||||
|
if k<0||k>=before_pos{break}
|
||||||
|
local kn=JsonFragBox.index_of_from(s, "\"name\":\"",k)
|
||||||
|
if kn>=0{
|
||||||
|
local ii=kn+8; local nn=(""+s).length(); local jj=ii
|
||||||
|
loop(jj<nn){ if (""+s).substring(jj,jj+1)=="\"" {break} jj=jj+1 }
|
||||||
|
if (""+s).substring(ii,jj)==name { last=k }
|
||||||
|
}
|
||||||
|
pos=k+1
|
||||||
|
}
|
||||||
|
if last<0 { return null }
|
||||||
|
local next=JsonFragBox.index_of_from(s, "\"type\":\"Local\"", last+1)
|
||||||
|
if next<0||next>before_pos{ next=before_pos }
|
||||||
|
local ts=(""+s).indexOf("\"type\":\"String\"", last)
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the last Local(Float) with given name before a given position.
|
||||||
|
// Returns float string (as scanned) or null when not found.
|
||||||
|
find_local_float_before(s, name, before_pos) {
|
||||||
|
local pos=0; local last=-1
|
||||||
|
loop(true){
|
||||||
|
local k=JsonFragBox.index_of_from(s, "\"type\":\"Local\"",pos)
|
||||||
|
if k<0||k>=before_pos{break}
|
||||||
|
local kn=JsonFragBox.index_of_from(s, "\"name\":\"",k)
|
||||||
|
if kn>=0{
|
||||||
|
local ii=kn+8; local nn=(""+s).length(); local jj=ii
|
||||||
|
loop(jj<nn){ if (""+s).substring(jj,jj+1)=="\"" {break} jj=jj+1 }
|
||||||
|
if (""+s).substring(ii,jj)==name { last=k }
|
||||||
|
}
|
||||||
|
pos=k+1
|
||||||
|
}
|
||||||
|
if last<0 { return null }
|
||||||
|
local next=JsonFragBox.index_of_from(s, "\"type\":\"Local\"", last+1)
|
||||||
|
if next<0||next>before_pos{ next=before_pos }
|
||||||
|
local tf=(""+s).indexOf("\"type\":\"Float\"", last)
|
||||||
|
if tf<0||tf>=next { return null }
|
||||||
|
local kv=(""+s).indexOf("\"value\":", tf)
|
||||||
|
if kv<0||kv>=next { return null }
|
||||||
|
return JsonFragBox.read_float_after(s, kv+8)
|
||||||
|
}
|
||||||
|
|
||||||
// Find the last Local(Int) before a given position (name-agnostic).
|
// Find the last Local(Int) before a given position (name-agnostic).
|
||||||
// Returns string digits or null when not found.
|
// Returns string digits or null when not found.
|
||||||
find_any_local_int_before(s, before_pos) {
|
find_any_local_int_before(s, before_pos) {
|
||||||
|
|||||||
@ -33,9 +33,12 @@ impl NyashEnv {
|
|||||||
|
|
||||||
// Global current env config (thread-safe)
|
// Global current env config (thread-safe)
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::sync::Mutex;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
||||||
static GLOBAL_ENV: OnceCell<RwLock<NyashEnv>> = OnceCell::new();
|
static GLOBAL_ENV: OnceCell<RwLock<NyashEnv>> = OnceCell::new();
|
||||||
|
static WARNED_ALIASES: OnceCell<Mutex<HashSet<String>>> = OnceCell::new();
|
||||||
// フェーズM.2: PHI_ON_GATED_WARNED削除(phi-legacy簡略化により不要)
|
// フェーズM.2: PHI_ON_GATED_WARNED削除(phi-legacy簡略化により不要)
|
||||||
|
|
||||||
pub fn current() -> NyashEnv {
|
pub fn current() -> NyashEnv {
|
||||||
@ -376,11 +379,19 @@ pub fn cli_verbose() -> bool {
|
|||||||
}
|
}
|
||||||
pub fn enable_using() -> bool {
|
pub fn enable_using() -> bool {
|
||||||
// Phase 15: デフォルトON(using systemはメイン機能)
|
// Phase 15: デフォルトON(using systemはメイン機能)
|
||||||
// NYASH_ENABLE_USING=0 で明示的に無効化可能
|
// NYASH_ENABLE_USING=0 で明示的に無効化可能。HAKO_ENABLE_USING は互換のため受理(警告)。
|
||||||
match std::env::var("NYASH_ENABLE_USING").ok().as_deref() {
|
match std::env::var("NYASH_ENABLE_USING").ok().as_deref() {
|
||||||
Some("0") | Some("false") | Some("off") => false,
|
Some("0") | Some("false") | Some("off") => return false,
|
||||||
_ => true, // デフォルト: ON
|
Some(_) => return true,
|
||||||
|
None => {}
|
||||||
}
|
}
|
||||||
|
// Fallback to alias
|
||||||
|
if let Some(v) = std::env::var("HAKO_ENABLE_USING").ok() {
|
||||||
|
warn_alias_once("HAKO_ENABLE_USING", "NYASH_ENABLE_USING");
|
||||||
|
let lv = v.to_ascii_lowercase();
|
||||||
|
return !(lv == "0" || lv == "false" || lv == "off");
|
||||||
|
}
|
||||||
|
true // default ON
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Using profiles (dev|ci|prod) ----
|
// ---- Using profiles (dev|ci|prod) ----
|
||||||
@ -466,7 +477,14 @@ pub fn ny_compiler_stage3() -> bool {
|
|||||||
/// When enabled, the Rust parser accepts Stage-3 surface (try/catch/finally, throw).
|
/// When enabled, the Rust parser accepts Stage-3 surface (try/catch/finally, throw).
|
||||||
/// Default is OFF to keep Stage-2 stable.
|
/// Default is OFF to keep Stage-2 stable.
|
||||||
pub fn parser_stage3() -> bool {
|
pub fn parser_stage3() -> bool {
|
||||||
std::env::var("NYASH_PARSER_STAGE3").ok().as_deref() == Some("1")
|
if std::env::var("NYASH_PARSER_STAGE3").ok().as_deref() == Some("1") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if std::env::var("HAKO_PARSER_STAGE3").ok().as_deref() == Some("1") {
|
||||||
|
warn_alias_once("HAKO_PARSER_STAGE3", "NYASH_PARSER_STAGE3");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parser gate for Block‑Postfix Catch acceptance
|
/// Parser gate for Block‑Postfix Catch acceptance
|
||||||
@ -578,3 +596,72 @@ pub fn oob_strict_fail() -> bool {
|
|||||||
.or_else(|| env_flag("NYASH_OOB_STRICT_FAIL"))
|
.or_else(|| env_flag("NYASH_OOB_STRICT_FAIL"))
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Primary verification route: return true when Hakorune VM is requested as primary.
|
||||||
|
/// Accepts HAKO_VERIFY_PRIMARY=hakovm (preferred) or legacy HAKO_ROUTE_HAKOVM=1 (deprecated, warns).
|
||||||
|
pub fn verify_primary_is_hakovm() -> bool {
|
||||||
|
if std::env::var("HAKO_VERIFY_PRIMARY").ok().as_deref() == Some("hakovm") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if env_bool("HAKO_ROUTE_HAKOVM") {
|
||||||
|
warn_alias_once("HAKO_ROUTE_HAKOVM", "HAKO_VERIFY_PRIMARY=hakovm");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn warn_alias_once(alias: &str, primary: &str) {
|
||||||
|
let set = WARNED_ALIASES.get_or_init(|| Mutex::new(HashSet::new()));
|
||||||
|
if let Ok(mut s) = set.lock() {
|
||||||
|
if !s.contains(alias) {
|
||||||
|
eprintln!("[deprecate/env] '{}' is deprecated; use '{}'", alias, primary);
|
||||||
|
s.insert(alias.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- ENV consolidation helpers (Phase 21.10/22.1) ----
|
||||||
|
/// LLVM opt level (primary: NYASH_LLVM_OPT_LEVEL; alias: HAKO_LLVM_OPT_LEVEL)
|
||||||
|
/// Returns string level (e.g., "0", "1", ...). Default: "0" when unset.
|
||||||
|
pub fn llvm_opt_level() -> String {
|
||||||
|
if let Some(v) = std::env::var("NYASH_LLVM_OPT_LEVEL").ok() {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
if let Some(v) = std::env::var("HAKO_LLVM_OPT_LEVEL").ok() {
|
||||||
|
warn_alias_once("HAKO_LLVM_OPT_LEVEL", "NYASH_LLVM_OPT_LEVEL");
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
"0".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gate‑C(Core) route request (primary: NYASH_GATE_C_CORE; alias: HAKO_GATE_C_CORE)
|
||||||
|
pub fn gate_c_core() -> bool {
|
||||||
|
if env_bool("NYASH_GATE_C_CORE") { return true; }
|
||||||
|
if env_bool("HAKO_GATE_C_CORE") {
|
||||||
|
warn_alias_once("HAKO_GATE_C_CORE", "NYASH_GATE_C_CORE");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consolidated toggle for selfhost NY compiler pipeline.
|
||||||
|
/// Primary: NYASH_USE_NY_COMPILER=0|1. Legacy disables accepted (with warning):
|
||||||
|
/// NYASH_DISABLE_NY_COMPILER/HAKO_DISABLE_NY_COMPILER (any true value disables).
|
||||||
|
pub fn use_ny_compiler() -> bool {
|
||||||
|
// Primary knob takes precedence when explicitly set
|
||||||
|
if let Some(v) = std::env::var("NYASH_USE_NY_COMPILER").ok() {
|
||||||
|
let lv = v.trim().to_ascii_lowercase();
|
||||||
|
return lv == "1" || lv == "true" || lv == "on";
|
||||||
|
}
|
||||||
|
// Legacy disable aliases — if any is true, treat as disabled and warn
|
||||||
|
if env_bool("NYASH_DISABLE_NY_COMPILER") {
|
||||||
|
warn_alias_once("NYASH_DISABLE_NY_COMPILER", "NYASH_USE_NY_COMPILER=0");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if env_bool("HAKO_DISABLE_NY_COMPILER") {
|
||||||
|
warn_alias_once("HAKO_DISABLE_NY_COMPILER", "NYASH_USE_NY_COMPILER=0");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Default: ON (MVP selfhost path)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|||||||
@ -24,8 +24,8 @@ def lower_function(builder, func_data: Dict[str, Any]):
|
|||||||
|
|
||||||
# Determine function signature
|
# Determine function signature
|
||||||
if name == "ny_main":
|
if name == "ny_main":
|
||||||
# Special case: ny_main returns i32
|
# Special case: ny_main returns i64 to match runtime (nyrt) expectations
|
||||||
func_ty = ir.FunctionType(builder.i32, [])
|
func_ty = ir.FunctionType(builder.i64, [])
|
||||||
else:
|
else:
|
||||||
# Default: i64(i64, ...) signature; derive arity from '/N' suffix when params missing
|
# Default: i64(i64, ...) signature; derive arity from '/N' suffix when params missing
|
||||||
m = re.search(r"/(\d+)$", name)
|
m = re.search(r"/(\d+)$", name)
|
||||||
|
|||||||
@ -45,6 +45,22 @@ def lower_binop(
|
|||||||
lhs_val = ir.Constant(ir.IntType(64), 0)
|
lhs_val = ir.Constant(ir.IntType(64), 0)
|
||||||
if rhs_val is None:
|
if rhs_val is None:
|
||||||
rhs_val = ir.Constant(ir.IntType(64), 0)
|
rhs_val = ir.Constant(ir.IntType(64), 0)
|
||||||
|
# Normalize operation aliases (textual -> symbolic)
|
||||||
|
op_raw = op or ''
|
||||||
|
op_l = op_raw.lower()
|
||||||
|
alias = {
|
||||||
|
'add': '+', 'plus': '+',
|
||||||
|
'sub': '-', 'minus': '-',
|
||||||
|
'mul': '*', 'times': '*',
|
||||||
|
'div': '/',
|
||||||
|
'mod': '%', 'rem': '%',
|
||||||
|
'band': '&', 'bitand': '&',
|
||||||
|
'bor': '|', 'bitor': '|',
|
||||||
|
'bxor': '^', 'xor': '^',
|
||||||
|
'shl': '<<',
|
||||||
|
'shr': '>>', 'ashr': '>>',
|
||||||
|
}
|
||||||
|
op = alias.get(op_l, op_raw)
|
||||||
|
|
||||||
# Relational/equality operators delegate to compare
|
# Relational/equality operators delegate to compare
|
||||||
if op in ('==','!=','<','>','<=','>='):
|
if op in ('==','!=','<','>','<=','>='):
|
||||||
|
|||||||
@ -97,9 +97,16 @@ def lower_return(
|
|||||||
# Pointer type - null
|
# Pointer type - null
|
||||||
ret_val = ir.Constant(return_type, None)
|
ret_val = ir.Constant(return_type, None)
|
||||||
|
|
||||||
# If still zero-like and we have predecessor snapshots, synthesize a minimal PHI at block head.
|
# If still zero-like (typed zero) and we have predecessor snapshots, synthesize a minimal PHI at block head.
|
||||||
try:
|
try:
|
||||||
zero_like = isinstance(ret_val, ir.Constant)
|
zero_like = False
|
||||||
|
if isinstance(ret_val, ir.Constant):
|
||||||
|
if isinstance(return_type, ir.IntType):
|
||||||
|
zero_like = (str(ret_val) == str(ir.Constant(return_type, 0)))
|
||||||
|
elif isinstance(return_type, ir.DoubleType):
|
||||||
|
zero_like = (str(ret_val) == str(ir.Constant(return_type, 0.0)))
|
||||||
|
elif isinstance(return_type, ir.PointerType):
|
||||||
|
zero_like = (str(ret_val) == str(ir.Constant(return_type, None)))
|
||||||
if zero_like and preds is not None and block_end_values is not None and bb_map is not None and isinstance(value_id, int):
|
if zero_like and preds is not None and block_end_values is not None and bb_map is not None and isinstance(value_id, int):
|
||||||
# Derive current block id from name like 'bb3'
|
# Derive current block id from name like 'bb3'
|
||||||
cur_bid = None
|
cur_bid = None
|
||||||
|
|||||||
@ -152,7 +152,8 @@ class NyashLLVMBuilder:
|
|||||||
else:
|
else:
|
||||||
arity = int(m.group(1)) if m else len(params_list)
|
arity = int(m.group(1)) if m else len(params_list)
|
||||||
if name == "ny_main":
|
if name == "ny_main":
|
||||||
fty = ir.FunctionType(self.i32, [])
|
# Align with runtime expectation: ny_main returns i64
|
||||||
|
fty = ir.FunctionType(self.i64, [])
|
||||||
else:
|
else:
|
||||||
fty = ir.FunctionType(self.i64, [self.i64] * arity)
|
fty = ir.FunctionType(self.i64, [self.i64] * arity)
|
||||||
exists = False
|
exists = False
|
||||||
|
|||||||
@ -13,8 +13,7 @@ fn main() {
|
|||||||
// If NYASH_VERIFY_JSON is present and route is requested, execute and exit.
|
// If NYASH_VERIFY_JSON is present and route is requested, execute and exit.
|
||||||
// This avoids plugin host/registry initialization and keeps output minimal.
|
// This avoids plugin host/registry initialization and keeps output minimal.
|
||||||
let has_json = std::env::var("NYASH_VERIFY_JSON").is_ok();
|
let has_json = std::env::var("NYASH_VERIFY_JSON").is_ok();
|
||||||
let route = nyash_rust::config::env::env_bool("HAKO_ROUTE_HAKOVM")
|
let route = nyash_rust::config::env::verify_primary_is_hakovm();
|
||||||
|| std::env::var("HAKO_VERIFY_PRIMARY").ok().as_deref() == Some("hakovm");
|
|
||||||
// Force flag may allow hv1-inline without route
|
// Force flag may allow hv1-inline without route
|
||||||
let force_hv1_flag = nyash_rust::config::env::env_bool("HAKO_VERIFY_V1_FORCE_HAKOVM");
|
let force_hv1_flag = nyash_rust::config::env::env_bool("HAKO_VERIFY_V1_FORCE_HAKOVM");
|
||||||
if has_json && (route || force_hv1_flag) {
|
if has_json && (route || force_hv1_flag) {
|
||||||
|
|||||||
@ -12,30 +12,9 @@ pub(crate) fn execute_file_with_backend(runner: &NyashRunner, filename: &str) {
|
|||||||
// Note: hv1 direct route is now handled at main.rs entry point (before NyashRunner creation).
|
// Note: hv1 direct route is now handled at main.rs entry point (before NyashRunner creation).
|
||||||
// This function is only called after plugins and runner initialization have already occurred.
|
// This function is only called after plugins and runner initialization have already occurred.
|
||||||
|
|
||||||
// Selfhost pipeline (Ny -> JSON v0)
|
// Selfhost pipeline (Ny -> JSON v0) — consolidated env toggle
|
||||||
// Default: ON. Backward‑compat envs:
|
// Primary: NYASH_USE_NY_COMPILER=0|1; legacy disables accepted with deprecation warning
|
||||||
// - NYASH_USE_NY_COMPILER={1|true|on} to force ON
|
if crate::config::env::use_ny_compiler() {
|
||||||
// - NYASH_USE_NY_COMPILER={0|false|off} or NYASH_DISABLE_NY_COMPILER/HAKO_DISABLE_NY_COMPILER to disable
|
|
||||||
let mut use_selfhost = true;
|
|
||||||
if let Ok(v) = std::env::var("NYASH_USE_NY_COMPILER") {
|
|
||||||
let lv = v.trim().to_ascii_lowercase();
|
|
||||||
use_selfhost = matches!(lv.as_str(), "1" | "true" | "on");
|
|
||||||
}
|
|
||||||
let disabled = std::env::var("NYASH_DISABLE_NY_COMPILER")
|
|
||||||
.ok()
|
|
||||||
.map(|v| {
|
|
||||||
let lv = v.trim().to_ascii_lowercase();
|
|
||||||
matches!(lv.as_str(), "1" | "true" | "on")
|
|
||||||
})
|
|
||||||
.unwrap_or(false)
|
|
||||||
|| std::env::var("HAKO_DISABLE_NY_COMPILER")
|
|
||||||
.ok()
|
|
||||||
.map(|v| {
|
|
||||||
let lv = v.trim().to_ascii_lowercase();
|
|
||||||
matches!(lv.as_str(), "1" | "true" | "on")
|
|
||||||
})
|
|
||||||
.unwrap_or(false);
|
|
||||||
if use_selfhost && !disabled {
|
|
||||||
if runner.try_run_selfhost_pipeline(filename) {
|
if runner.try_run_selfhost_pipeline(filename) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
241
tools/native_llvm_builder.py
Normal file
241
tools/native_llvm_builder.py
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Native LLVM Builder (bootstrap)
|
||||||
|
|
||||||
|
Goal: minimal Python-only emitter that generates LLVM IR text from a tiny
|
||||||
|
subset of Nyash MIR JSON and compiles it to an object via `llc`.
|
||||||
|
|
||||||
|
Supported (MVP):
|
||||||
|
- schema_version v1 or tolerant shapes
|
||||||
|
- Single function: ny_main(): i64
|
||||||
|
- Instructions: const(i64), binop(add/sub/mul/div/mod/&/|/^/<< >>), compare(==)
|
||||||
|
- ret(value)
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python3 tools/native_llvm_builder.py --in in.json --emit obj --out out.o
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
- No external Python packages required. Assumes `llc` is in PATH.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def _normalize_canary(v: dict) -> dict:
|
||||||
|
# Coerce schema_version
|
||||||
|
sv = v.get("schema_version")
|
||||||
|
if isinstance(sv, int) and sv == 1:
|
||||||
|
v["schema_version"] = "1.0"
|
||||||
|
if isinstance(sv, str) and sv == "1":
|
||||||
|
v["schema_version"] = "1.0"
|
||||||
|
# Normalize blocks.inst -> instructions
|
||||||
|
funs = v.get("functions")
|
||||||
|
if isinstance(funs, list):
|
||||||
|
for f in funs:
|
||||||
|
blks = f.get("blocks")
|
||||||
|
if isinstance(blks, list):
|
||||||
|
for b in blks:
|
||||||
|
if "inst" in b and "instructions" not in b:
|
||||||
|
b["instructions"] = b.pop("inst")
|
||||||
|
ins = b.get("instructions")
|
||||||
|
if isinstance(ins, list):
|
||||||
|
for insn in ins:
|
||||||
|
if insn.get("op") == "const":
|
||||||
|
if "value" in insn and isinstance(insn["value"], dict) and "type" in insn["value"]:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
ty = insn.pop("ty", "i64")
|
||||||
|
val = insn.pop("value", 0)
|
||||||
|
insn["value"] = {"type": ty, "value": val}
|
||||||
|
return v
|
||||||
|
|
||||||
|
|
||||||
|
def build_ir(ny_json: dict) -> str:
|
||||||
|
ny = _normalize_canary(ny_json)
|
||||||
|
funs = ny.get("functions", [])
|
||||||
|
fn = None
|
||||||
|
for f in funs:
|
||||||
|
if f.get("name") == "ny_main":
|
||||||
|
fn = f
|
||||||
|
break
|
||||||
|
if fn is None:
|
||||||
|
raise ValueError("ny_main not found")
|
||||||
|
blocks = fn.get("blocks", [])
|
||||||
|
if not blocks:
|
||||||
|
# trivial
|
||||||
|
return (
|
||||||
|
"; ModuleID = \"nyash_native\"\n"
|
||||||
|
"define i64 @ny_main(){\n ret i64 0\n}\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
# IR pieces
|
||||||
|
lines = []
|
||||||
|
# Keep IR minimal; let llc choose target triple/datalayout
|
||||||
|
lines.append("; ModuleID = \"nyash_native\"")
|
||||||
|
lines.append("")
|
||||||
|
lines.append("define i64 @ny_main(){")
|
||||||
|
|
||||||
|
# Simple vmap; const map holds immediate ints; ssa map holds emitted names
|
||||||
|
const_map = {}
|
||||||
|
ssa_map = {}
|
||||||
|
is_i1 = set()
|
||||||
|
|
||||||
|
def val_of(vid):
|
||||||
|
if vid in ssa_map:
|
||||||
|
return f"%{ssa_map[vid]}", (vid in is_i1)
|
||||||
|
if vid in const_map:
|
||||||
|
return f"i64 {const_map[vid]}", False
|
||||||
|
# default zero
|
||||||
|
return "i64 0", False
|
||||||
|
|
||||||
|
tmp_idx = 0
|
||||||
|
def fresh(name):
|
||||||
|
nonlocal tmp_idx
|
||||||
|
tmp_idx += 1
|
||||||
|
return f"{name}_{tmp_idx}"
|
||||||
|
|
||||||
|
# Emit each block with an explicit label: bb<id>:
|
||||||
|
for b in blocks:
|
||||||
|
bid = b.get("id")
|
||||||
|
lines.append(f"bb{bid}:")
|
||||||
|
ins = b.get("instructions", [])
|
||||||
|
for insn in ins:
|
||||||
|
op = insn.get("op")
|
||||||
|
if op == "const":
|
||||||
|
dst = insn.get("dst")
|
||||||
|
v = insn.get("value", {})
|
||||||
|
ty = v.get("type", insn.get("ty", "i64"))
|
||||||
|
val = v.get("value", 0)
|
||||||
|
if ty != "i64":
|
||||||
|
val = 0
|
||||||
|
const_map[dst] = int(val)
|
||||||
|
elif op == "binop":
|
||||||
|
dst = insn.get("dst")
|
||||||
|
opx = (insn.get("operation") or '').lower()
|
||||||
|
aliases = {
|
||||||
|
'add': '+', 'plus': '+', 'sub': '-', 'minus': '-', 'mul': '*', 'times': '*',
|
||||||
|
'div': '/', 'mod': '%', 'rem': '%', 'band': '&', 'bitand': '&', 'bor': '|', 'bitor': '|',
|
||||||
|
'bxor': '^', 'xor': '^', 'shl': '<<', 'shr': '>>', 'ashr': '>>'
|
||||||
|
}
|
||||||
|
sym = aliases.get(opx, opx)
|
||||||
|
lhs = insn.get("lhs"); rhs = insn.get("rhs")
|
||||||
|
lv, _ = val_of(lhs); rv, _ = val_of(rhs)
|
||||||
|
name = fresh("bin")
|
||||||
|
if sym == '+':
|
||||||
|
lines.append(f" %{name} = add i64 {lv.split()[-1]}, {rv.split()[-1]}")
|
||||||
|
elif sym == '-':
|
||||||
|
lines.append(f" %{name} = sub i64 {lv.split()[-1]}, {rv.split()[-1]}")
|
||||||
|
elif sym == '*':
|
||||||
|
lines.append(f" %{name} = mul i64 {lv.split()[-1]}, {rv.split()[-1]}")
|
||||||
|
elif sym == '/':
|
||||||
|
lines.append(f" %{name} = sdiv i64 {lv.split()[-1]}, {rv.split()[-1]}")
|
||||||
|
elif sym == '%':
|
||||||
|
lines.append(f" %{name} = srem i64 {lv.split()[-1]}, {rv.split()[-1]}")
|
||||||
|
elif sym == '&':
|
||||||
|
lines.append(f" %{name} = and i64 {lv.split()[-1]}, {rv.split()[-1]}")
|
||||||
|
elif sym == '|':
|
||||||
|
lines.append(f" %{name} = or i64 {lv.split()[-1]}, {rv.split()[-1]}")
|
||||||
|
elif sym == '^':
|
||||||
|
lines.append(f" %{name} = xor i64 {lv.split()[-1]}, {rv.split()[-1]}")
|
||||||
|
elif sym == '<<':
|
||||||
|
lines.append(f" %{name} = shl i64 {lv.split()[-1]}, {rv.split()[-1]}")
|
||||||
|
elif sym == '>>':
|
||||||
|
lines.append(f" %{name} = ashr i64 {lv.split()[-1]}, {rv.split()[-1]}")
|
||||||
|
else:
|
||||||
|
lines.append(f" %{name} = add i64 0, 0")
|
||||||
|
ssa_map[dst] = name
|
||||||
|
elif op == "compare":
|
||||||
|
dst = insn.get("dst")
|
||||||
|
opx = insn.get("operation") or insn.get("cmp") or '=='
|
||||||
|
lhs = insn.get("lhs"); rhs = insn.get("rhs")
|
||||||
|
lv, _ = val_of(lhs); rv, _ = val_of(rhs)
|
||||||
|
name = fresh("cmp")
|
||||||
|
# Support eq/lt minimal
|
||||||
|
if opx in ('==', 'Eq'): pred = 'eq'
|
||||||
|
elif opx in ('<', 'Lt'): pred = 'slt'
|
||||||
|
else: pred = 'ne'
|
||||||
|
lines.append(f" %{name} = icmp {pred} i64 {lv.split()[-1]}, {rv.split()[-1]}")
|
||||||
|
ssa_map[dst] = name
|
||||||
|
is_i1.add(dst)
|
||||||
|
elif op == "branch":
|
||||||
|
# Conditional branch: {cond, then, else}
|
||||||
|
cond = insn.get("cond")
|
||||||
|
then_id = insn.get("then")
|
||||||
|
else_id = insn.get("else")
|
||||||
|
cv, ci1 = val_of(cond)
|
||||||
|
if ci1:
|
||||||
|
cond_name = cv if cv.startswith('%') else f"%{cv}"
|
||||||
|
lines.append(f" br i1 {cond_name}, label %bb{then_id}, label %bb{else_id}")
|
||||||
|
else:
|
||||||
|
# Build i1 from i64 via icmp ne 0
|
||||||
|
name = fresh("cnd")
|
||||||
|
lines.append(f" %{name} = icmp ne i64 {cv.split()[-1]}, 0")
|
||||||
|
lines.append(f" br i1 %{name}, label %bb{then_id}, label %bb{else_id}")
|
||||||
|
elif op == "jump":
|
||||||
|
target = insn.get("target")
|
||||||
|
lines.append(f" br label %bb{target}")
|
||||||
|
elif op == "ret":
|
||||||
|
vid = insn.get("value")
|
||||||
|
if vid in is_i1:
|
||||||
|
vname = ssa_map.get(vid)
|
||||||
|
z = fresh("zext")
|
||||||
|
lines.append(f" %{z} = zext i1 %{vname} to i64")
|
||||||
|
lines.append(f" ret i64 %{z}")
|
||||||
|
elif vid in ssa_map:
|
||||||
|
lines.append(f" ret i64 %{ssa_map[vid]}")
|
||||||
|
elif vid in const_map:
|
||||||
|
lines.append(f" ret i64 {const_map[vid]}")
|
||||||
|
else:
|
||||||
|
lines.append(" ret i64 0")
|
||||||
|
lines.append("}")
|
||||||
|
return "\n".join(lines) + "\n"
|
||||||
|
|
||||||
|
|
||||||
|
def compile_ir_to_obj(ir_text: str, out_obj: Path) -> None:
|
||||||
|
tmp = Path("/tmp/native_ir_{}.ll".format(os.getpid()))
|
||||||
|
tmp.write_text(ir_text)
|
||||||
|
try:
|
||||||
|
subprocess.check_call(["llc", "-filetype=obj", "-o", str(out_obj), str(tmp)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
tmp.unlink()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
ap = argparse.ArgumentParser()
|
||||||
|
ap.add_argument("--in", dest="infile", required=True)
|
||||||
|
ap.add_argument("--emit", dest="emit", default="obj")
|
||||||
|
ap.add_argument("--out", dest="out", required=True)
|
||||||
|
args = ap.parse_args()
|
||||||
|
|
||||||
|
with open(args.infile, 'r') as f:
|
||||||
|
ny = json.load(f)
|
||||||
|
|
||||||
|
ir = build_ir(ny)
|
||||||
|
if os.environ.get('NYASH_LLVM_NATIVE_TRACE') in ('1','true','on','YES','yes','True'):
|
||||||
|
print(ir, file=sys.stderr)
|
||||||
|
if args.emit == 'll':
|
||||||
|
Path(args.out).write_text(ir)
|
||||||
|
print(f"[native] ll written: {args.out}")
|
||||||
|
return
|
||||||
|
if args.emit == 'obj':
|
||||||
|
compile_ir_to_obj(ir, Path(args.out))
|
||||||
|
print(f"[native] obj written: {args.out}")
|
||||||
|
return
|
||||||
|
print("error: unsupported emit kind", file=sys.stderr)
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
main()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[native] error: {e}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
@ -24,7 +24,17 @@ TARGET=""
|
|||||||
NYRT_DIR=""
|
NYRT_DIR=""
|
||||||
VERIFY=0
|
VERIFY=0
|
||||||
QUIET=0
|
QUIET=0
|
||||||
BACKEND="${NYASH_LLVM_BACKEND:-llvmlite}" # llvmlite | crate | native (reserved)
|
# Backend selection (21.11): default to 'crate' when ny-llvmc is available, otherwise fallback to llvmlite.
|
||||||
|
# Explicit env NYASH_LLVM_BACKEND overrides this auto-detection.
|
||||||
|
if [[ -n "${NYASH_LLVM_BACKEND:-}" ]]; then
|
||||||
|
BACKEND="${NYASH_LLVM_BACKEND}"
|
||||||
|
else
|
||||||
|
if [[ -x "./target/release/ny-llvmc" ]]; then
|
||||||
|
BACKEND="crate"
|
||||||
|
else
|
||||||
|
BACKEND="llvmlite"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
@ -51,9 +61,12 @@ if [[ -z "$OUT" ]]; then
|
|||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! command -v llvm-config-18 >/dev/null 2>&1; then
|
# Require LLVM18 only for llvmlite backend
|
||||||
echo "error: llvm-config-18 not found (install LLVM 18 dev)" >&2
|
if [[ "${NYASH_LLVM_BACKEND:-$BACKEND}" == "llvmlite" ]]; then
|
||||||
exit 3
|
if ! command -v llvm-config-18 >/dev/null 2>&1; then
|
||||||
|
echo "error: llvm-config-18 not found (install LLVM 18 dev)" >&2
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Build nyash + NyRT as needed(skip allowed)
|
# Build nyash + NyRT as needed(skip allowed)
|
||||||
@ -126,6 +139,15 @@ case "$EMIT" in
|
|||||||
rm -f "$OUT"
|
rm -f "$OUT"
|
||||||
"$BIN_NYLLVMC" --in "$IN_FILE" --emit obj --out "$OUT" >/dev/null 2>&1 || { echo "error: ny-llvmc failed" >&2; exit 4; }
|
"$BIN_NYLLVMC" --in "$IN_FILE" --emit obj --out "$OUT" >/dev/null 2>&1 || { echo "error: ny-llvmc failed" >&2; exit 4; }
|
||||||
;;
|
;;
|
||||||
|
native)
|
||||||
|
if ! command -v llc >/dev/null 2>&1; then
|
||||||
|
echo "error: llc not found (install LLVM tools)" >&2; exit 4
|
||||||
|
fi
|
||||||
|
rm -f "$OUT"
|
||||||
|
if ! python3 "$PWD/tools/native_llvm_builder.py" --in "$IN_FILE" --emit obj --out "$OUT" >/dev/null 2>&1; then
|
||||||
|
echo "error: native builder failed" >&2; exit 4
|
||||||
|
fi
|
||||||
|
;;
|
||||||
llvmlite|*)
|
llvmlite|*)
|
||||||
# Directly use llvmlite harness with MIR v1 JSON input
|
# Directly use llvmlite harness with MIR v1 JSON input
|
||||||
rm -f "$OUT"
|
rm -f "$OUT"
|
||||||
@ -153,6 +175,22 @@ case "$EMIT" in
|
|||||||
echo "error: ny-llvmc failed to link exe" >&2; exit 4
|
echo "error: ny-llvmc failed to link exe" >&2; exit 4
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
native)
|
||||||
|
if ! command -v llc >/dev/null 2>&1; then
|
||||||
|
echo "error: llc not found (install LLVM tools)" >&2; exit 4
|
||||||
|
fi
|
||||||
|
if ! python3 "$PWD/tools/native_llvm_builder.py" --in "$IN_FILE" --emit obj --out "$OBJ" >/dev/null 2>&1; then
|
||||||
|
echo "error: native builder failed to produce object $OBJ" >&2; exit 4
|
||||||
|
fi
|
||||||
|
if [[ ! -f "$OBJ" ]]; then echo "error: failed to produce object $OBJ" >&2; exit 4; fi
|
||||||
|
# Link with NyRT (same as llvmlite branch)
|
||||||
|
NYRT_BASE=${NYRT_DIR:-"$PWD/crates/nyash_kernel"}
|
||||||
|
cc "$OBJ" \
|
||||||
|
-L target/release \
|
||||||
|
-L "$NYRT_BASE/target/release" \
|
||||||
|
-Wl,--whole-archive -lnyash_kernel -Wl,--no-whole-archive \
|
||||||
|
-lpthread -ldl -lm -o "$OUT"
|
||||||
|
;;
|
||||||
llvmlite|*)
|
llvmlite|*)
|
||||||
if ! python3 "$PWD/tools/llvmlite_harness.py" --in "$IN_FILE" --out "$OBJ" >/dev/null 2>&1; then
|
if ! python3 "$PWD/tools/llvmlite_harness.py" --in "$IN_FILE" --out "$OBJ" >/dev/null 2>&1; then
|
||||||
echo "error: harness failed to produce object $OBJ" >&2; exit 4
|
echo "error: harness failed to produce object $OBJ" >&2; exit 4
|
||||||
|
|||||||
@ -0,0 +1,31 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# If(Compare Var/Int) with negative numbers → compare+branch+ret (structure 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
|
||||||
|
|
||||||
|
tmp_hako="/tmp/mirbuilder_if_varint_neg_$$.hako"
|
||||||
|
cat > "$tmp_hako" <<'HAKO'
|
||||||
|
include "lang/src/mir/builder/MirBuilderBox.hako"
|
||||||
|
static box Main { method main(args) {
|
||||||
|
// Local a=-5; if (a < -3) return 1; else return 0;
|
||||||
|
local j = "{\"version\":0,\"kind\":\"Program\",\"body\":[" +
|
||||||
|
"{\"type\":\"Local\",\"name\":\"a\",\"expr\":{\"type\":\"Int\",\"value\":-5}}," +
|
||||||
|
"{\"type\":\"If\",\"cond\":{\"type\":\"Compare\",\"op\":\"<\",\"lhs\":{\"type\":\"Var\",\"name\":\"a\"},\"rhs\":{\"type\":\"Int\",\"value\":-3}},\"then\":[{\"type\":\"Return\",\"expr\":{\"type\":\"Int\",\"value\":1}}],\"else\":[{\"type\":\"Return\",\"expr\":{\"type\":\"Int\",\"value\":0}}]}]}";
|
||||||
|
local out = MirBuilderBox.emit_from_program_json_v0(j, null);
|
||||||
|
if out == null { return 0 }
|
||||||
|
local s = "" + out
|
||||||
|
if s.indexOf("\"op\":\"compare\"") >= 0 && s.indexOf("\"op\":\"branch\"") >= 0 { return 1 }
|
||||||
|
return 0
|
||||||
|
} }
|
||||||
|
HAKO
|
||||||
|
|
||||||
|
set +e
|
||||||
|
out="$(HAKO_MIR_BUILDER_INTERNAL=1 "$NYASH_BIN" --backend vm "$tmp_hako" 2>&1)"; rc=$?
|
||||||
|
set -e
|
||||||
|
rm -f "$tmp_hako" || true
|
||||||
|
|
||||||
|
if [ "$rc" -eq 1 ]; then echo "[PASS] mirbuilder_internal_if_compare_varint_negative_canary_vm"; exit 0; fi
|
||||||
|
echo "[FAIL] mirbuilder_internal_if_compare_varint_negative_canary_vm (rc=$rc)" >&2; exit 1
|
||||||
|
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Return(Binary Var/Int) with negative constants → const+const+binop+ret (structure)
|
||||||
|
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_hako="/tmp/mirbuilder_return_binop_varint_neg_$$.hako"
|
||||||
|
cat > "$tmp_hako" <<'HAKO'
|
||||||
|
include "lang/src/mir/builder/MirBuilderBox.hako"
|
||||||
|
static box Main { method main(args) {
|
||||||
|
// Local x=-2; return x + -3;
|
||||||
|
local j = "{\"version\":0,\"kind\":\"Program\",\"body\":[{\"type\":\"Local\",\"name\":\"x\",\"expr\":{\"type\":\"Int\",\"value\":-2}},{\"type\":\"Return\",\"expr\":{\"type\":\"Binary\",\"op\":\"+\",\"lhs\":{\"type\":\"Var\",\"name\":\"x\"},\"rhs\":{\"type\":\"Int\",\"value\":-3}}}]}";
|
||||||
|
local out = MirBuilderBox.emit_from_program_json_v0(j, null);
|
||||||
|
if out == null { return 0 }
|
||||||
|
local s = "" + out
|
||||||
|
if s.indexOf("\"op\":\"binop\"") >= 0 && s.indexOf("\"op_kind\":\"Add\"") >= 0 { return 1 }
|
||||||
|
return 0
|
||||||
|
} }
|
||||||
|
HAKO
|
||||||
|
|
||||||
|
set +e
|
||||||
|
out="$(HAKO_MIR_BUILDER_INTERNAL=1 "$NYASH_BIN" --backend vm "$tmp_hako" 2>&1)"; rc=$?
|
||||||
|
set -e
|
||||||
|
rm -f "$tmp_hako" || true
|
||||||
|
|
||||||
|
if [ "$rc" -eq 1 ]; then echo "[PASS] mirbuilder_internal_return_binop_varint_negative_canary_vm"; exit 0; fi
|
||||||
|
echo "[FAIL] mirbuilder_internal_return_binop_varint_negative_canary_vm (rc=$rc)" >&2; exit 1
|
||||||
|
|
||||||
@ -64,4 +64,34 @@ if [[ "${SMOKES_ENABLE_SELFHOST:-0}" == "1" ]]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Crate backend (ny-llvmc) — run a tiny representative set always when available
|
||||||
|
echo "[phase2100] S3 (crate ny-llvmc) reps..."
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
# Prebuild crate tools quickly (best-effort)
|
||||||
|
(cd "$ROOT/crates/nyash-llvm-compiler" && timeout 180 cargo build --release -j 24 >/dev/null 2>&1) || true
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && timeout 180 cargo build --release -j 24 >/dev/null 2>&1) || true
|
||||||
|
# Probe ny-llvmc availability by compiling a minimal ret0 ny_main
|
||||||
|
BIN_NYLLVMC="$ROOT/target/release/ny-llvmc"
|
||||||
|
if [[ -x "$BIN_NYLLVMC" ]]; then
|
||||||
|
tmpj="/tmp/ny_crate_probe_$$.json"; echo '{"schema_version":1,"functions":[{"name":"ny_main","blocks":[{"id":0,"inst":[{"op":"const","dst":1,"ty":"i64","value":0},{"op":"ret","value":1}]}]}]}' > "$tmpj"
|
||||||
|
tmpo="/tmp/ny_crate_probe_$$.o"
|
||||||
|
if HAKO_LLVM_CANARY_NORMALIZE=1 "$BIN_NYLLVMC" --in "$tmpj" --out "$tmpo" >/dev/null 2>&1; then
|
||||||
|
rm -f "$tmpo" "$tmpj" || true
|
||||||
|
# Run representative crate EXE canaries (fast)
|
||||||
|
bash "$ROOT/tools/smokes/v2/run.sh" --profile quick --filter 'phase2100/s3_backend_selector_crate_exe_return42_canary_vm.sh'
|
||||||
|
bash "$ROOT/tools/smokes/v2/run.sh" --profile quick --filter 'phase2100/s3_backend_selector_crate_exe_compare_eq_true_canary_vm.sh'
|
||||||
|
bash "$ROOT/tools/smokes/v2/run.sh" --profile quick --filter 'phase2100/s3_backend_selector_crate_exe_binop_return_canary_vm.sh'
|
||||||
|
else
|
||||||
|
rm -f "$tmpo" "$tmpj" || true
|
||||||
|
echo "[phase2100] SKIP crate reps (ny-llvmc probe failed)" >&2
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "[phase2100] SKIP crate reps (ny-llvmc not built)" >&2
|
||||||
|
fi
|
||||||
|
) || echo "[phase2100] crate reps encountered a non-fatal issue; continuing"
|
||||||
|
|
||||||
|
# SSOT relative inference — unique case (always-on, quick)
|
||||||
|
bash "$ROOT/tools/smokes/v2/run.sh" --profile quick --filter 'phase2211/ssot_relative_unique_canary_vm.sh'
|
||||||
|
|
||||||
echo "[phase2100] Done."
|
echo "[phase2100] Done."
|
||||||
|
|||||||
@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_NYLLVMC="$ROOT/target/release/ny-llvmc"
|
||||||
|
|
||||||
|
# Prebuild required tools/libraries
|
||||||
|
(cd "$ROOT" && cargo build -q --release -p nyash-llvm-compiler >/dev/null) || true
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
# Minimal MIR v1 JSON that computes 40+2 then returns 42.
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":40},
|
||||||
|
{"op":"const","dst":2,"ty":"i64","value":2},
|
||||||
|
{"op":"binop","operation":"add","lhs":1,"rhs":2,"dst":3},
|
||||||
|
{"op":"ret","value":3}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
APP="/tmp/ny_crate_backend_exe_binop_$$"
|
||||||
|
TMP_JSON="/tmp/ny_crate_backend_exe_binop_$$.json"
|
||||||
|
echo "$JSON" > "$TMP_JSON"
|
||||||
|
|
||||||
|
if HAKO_LLVM_CANARY_NORMALIZE=1 "$BIN_NYLLVMC" --in "$TMP_JSON" --emit exe --nyrt "$ROOT/target/release" --out "$APP" >/dev/null 2>&1; then
|
||||||
|
if [[ -x "$APP" ]]; then
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
if [ "$rc" -eq 42 ]; then
|
||||||
|
echo "[PASS] s3_backend_selector_crate_exe_binop_return_canary_vm"
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "[FAIL] s3_backend_selector_crate_exe_binop_return_canary_vm" >&2
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_NYLLVMC="$ROOT/target/release/ny-llvmc"
|
||||||
|
|
||||||
|
(cd "$ROOT" && cargo build -q --release -p nyash-llvm-compiler >/dev/null) || true
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":5},
|
||||||
|
{"op":"const","dst":2,"ty":"i64","value":3},
|
||||||
|
{"op":"binop","operation":"&","lhs":1,"rhs":2,"dst":3},
|
||||||
|
{"op":"ret","value":3}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
APP="/tmp/ny_crate_backend_exe_and_$$"
|
||||||
|
TMP_JSON="/tmp/ny_crate_backend_exe_and_$$.json"
|
||||||
|
echo "$JSON" > "$TMP_JSON"
|
||||||
|
|
||||||
|
if HAKO_LLVM_CANARY_NORMALIZE=1 "$BIN_NYLLVMC" --in "$TMP_JSON" --emit exe --nyrt "$ROOT/target/release" --out "$APP" >/dev/null 2>&1; then
|
||||||
|
if [[ -x "$APP" ]]; then
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
if [ "$rc" -eq 1 ]; then
|
||||||
|
echo "[PASS] s3_backend_selector_crate_exe_bitwise_and_canary_vm"
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "[FAIL] s3_backend_selector_crate_exe_bitwise_and_canary_vm" >&2
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
|
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_NYLLVMC="$ROOT/target/release/ny-llvmc"
|
||||||
|
|
||||||
|
(cd "$ROOT" && cargo build -q --release -p nyash-llvm-compiler >/dev/null) || true
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":7},
|
||||||
|
{"op":"const","dst":2,"ty":"i64","value":7},
|
||||||
|
{"op":"compare","operation":"==","lhs":1,"rhs":2,"dst":3},
|
||||||
|
{"op":"ret","value":3}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
APP="/tmp/ny_crate_backend_exe_cmp_eq_$$"
|
||||||
|
TMP_JSON="/tmp/ny_crate_backend_exe_cmp_eq_$$.json"
|
||||||
|
echo "$JSON" > "$TMP_JSON"
|
||||||
|
|
||||||
|
if HAKO_LLVM_CANARY_NORMALIZE=1 "$BIN_NYLLVMC" --in "$TMP_JSON" --emit exe --nyrt "$ROOT/target/release" --out "$APP" >/dev/null 2>&1; then
|
||||||
|
if [[ -x "$APP" ]]; then
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
if [ "$rc" -eq 1 ]; then
|
||||||
|
echo "[PASS] s3_backend_selector_crate_exe_compare_eq_true_canary_vm"
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "[FAIL] s3_backend_selector_crate_exe_compare_eq_true_canary_vm" >&2
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
|
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_NYLLVMC="$ROOT/target/release/ny-llvmc"
|
||||||
|
|
||||||
|
(cd "$ROOT" && cargo build -q --release -p nyash-llvm-compiler >/dev/null) || true
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":0},
|
||||||
|
{"op":"const","dst":2,"ty":"i64","value":-1},
|
||||||
|
{"op":"compare","operation":">=","lhs":1,"rhs":2,"dst":3},
|
||||||
|
{"op":"ret","value":3}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
APP="/tmp/ny_crate_backend_exe_cmp_ge_b_$$"
|
||||||
|
TMP_JSON="/tmp/ny_crate_backend_exe_cmp_ge_b_$$.json"
|
||||||
|
echo "$JSON" > "$TMP_JSON"
|
||||||
|
|
||||||
|
if HAKO_LLVM_CANARY_NORMALIZE=1 "$BIN_NYLLVMC" --in "$TMP_JSON" --emit exe --nyrt "$ROOT/target/release" --out "$APP" >/dev/null 2>&1; then
|
||||||
|
if [[ -x "$APP" ]]; then
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
if [ "$rc" -eq 1 ]; then
|
||||||
|
echo "[PASS] s3_backend_selector_crate_exe_compare_ge_boundary_canary_vm"
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "[FAIL] s3_backend_selector_crate_exe_compare_ge_boundary_canary_vm" >&2
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
|
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_NYLLVMC="$ROOT/target/release/ny-llvmc"
|
||||||
|
|
||||||
|
(cd "$ROOT" && cargo build -q --release -p nyash-llvm-compiler >/dev/null) || true
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":-1},
|
||||||
|
{"op":"const","dst":2,"ty":"i64","value":0},
|
||||||
|
{"op":"compare","operation":"<=","lhs":1,"rhs":2,"dst":3},
|
||||||
|
{"op":"ret","value":3}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
APP="/tmp/ny_crate_backend_exe_cmp_le_b_$$"
|
||||||
|
TMP_JSON="/tmp/ny_crate_backend_exe_cmp_le_b_$$.json"
|
||||||
|
echo "$JSON" > "$TMP_JSON"
|
||||||
|
|
||||||
|
if HAKO_LLVM_CANARY_NORMALIZE=1 "$BIN_NYLLVMC" --in "$TMP_JSON" --emit exe --nyrt "$ROOT/target/release" --out "$APP" >/dev/null 2>&1; then
|
||||||
|
if [[ -x "$APP" ]]; then
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
if [ "$rc" -eq 1 ]; then
|
||||||
|
echo "[PASS] s3_backend_selector_crate_exe_compare_le_boundary_canary_vm"
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "[FAIL] s3_backend_selector_crate_exe_compare_le_boundary_canary_vm" >&2
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
|
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_NYLLVMC="$ROOT/target/release/ny-llvmc"
|
||||||
|
|
||||||
|
(cd "$ROOT" && cargo build -q --release -p nyash-llvm-compiler >/dev/null) || true
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":-5},
|
||||||
|
{"op":"const","dst":2,"ty":"i64","value":0},
|
||||||
|
{"op":"compare","operation":"<","lhs":1,"rhs":2,"dst":3},
|
||||||
|
{"op":"ret","value":3}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
APP="/tmp/ny_crate_backend_exe_cmp_lt_neg_$$"
|
||||||
|
TMP_JSON="/tmp/ny_crate_backend_exe_cmp_lt_neg_$$.json"
|
||||||
|
echo "$JSON" > "$TMP_JSON"
|
||||||
|
|
||||||
|
if HAKO_LLVM_CANARY_NORMALIZE=1 "$BIN_NYLLVMC" --in "$TMP_JSON" --emit exe --nyrt "$ROOT/target/release" --out "$APP" >/dev/null 2>&1; then
|
||||||
|
if [[ -x "$APP" ]]; then
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
if [ "$rc" -eq 1 ]; then
|
||||||
|
echo "[PASS] s3_backend_selector_crate_exe_compare_lt_neg_canary_vm"
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "[FAIL] s3_backend_selector_crate_exe_compare_lt_neg_canary_vm" >&2
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
|
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_NYLLVMC="$ROOT/target/release/ny-llvmc"
|
||||||
|
|
||||||
|
(cd "$ROOT" && cargo build -q --release -p nyash-llvm-compiler >/dev/null) || true
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":7},
|
||||||
|
{"op":"const","dst":2,"ty":"i64","value":8},
|
||||||
|
{"op":"compare","operation":"!=","lhs":1,"rhs":2,"dst":3},
|
||||||
|
{"op":"ret","value":3}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
APP="/tmp/ny_crate_backend_exe_cmp_ne_$$"
|
||||||
|
TMP_JSON="/tmp/ny_crate_backend_exe_cmp_ne_$$.json"
|
||||||
|
echo "$JSON" > "$TMP_JSON"
|
||||||
|
|
||||||
|
if HAKO_LLVM_CANARY_NORMALIZE=1 "$BIN_NYLLVMC" --in "$TMP_JSON" --emit exe --nyrt "$ROOT/target/release" --out "$APP" >/dev/null 2>&1; then
|
||||||
|
if [[ -x "$APP" ]]; then
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
if [ "$rc" -eq 1 ]; then
|
||||||
|
echo "[PASS] s3_backend_selector_crate_exe_compare_ne_true_canary_vm"
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "[FAIL] s3_backend_selector_crate_exe_compare_ne_true_canary_vm" >&2
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
|
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_NYLLVMC="$ROOT/target/release/ny-llvmc"
|
||||||
|
|
||||||
|
(cd "$ROOT" && cargo build -q --release -p nyash-llvm-compiler >/dev/null) || true
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":5},
|
||||||
|
{"op":"const","dst":2,"ty":"i64","value":2},
|
||||||
|
{"op":"binop","operation":"/","lhs":1,"rhs":2,"dst":3},
|
||||||
|
{"op":"ret","value":3}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
APP="/tmp/ny_crate_backend_exe_div_$$"
|
||||||
|
TMP_JSON="/tmp/ny_crate_backend_exe_div_$$.json"
|
||||||
|
echo "$JSON" > "$TMP_JSON"
|
||||||
|
|
||||||
|
if HAKO_LLVM_CANARY_NORMALIZE=1 "$BIN_NYLLVMC" --in "$TMP_JSON" --emit exe --nyrt "$ROOT/target/release" --out "$APP" >/dev/null 2>&1; then
|
||||||
|
if [[ -x "$APP" ]]; then
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
if [ "$rc" -eq 2 ]; then
|
||||||
|
echo "[PASS] s3_backend_selector_crate_exe_div_canary_vm"
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "[FAIL] s3_backend_selector_crate_exe_div_canary_vm" >&2
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
|
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_NYLLVMC="$ROOT/target/release/ny-llvmc"
|
||||||
|
|
||||||
|
(cd "$ROOT" && cargo build -q --release -p nyash-llvm-compiler >/dev/null) || true
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
# Branch: if (1 == 1) then return 42 else return 7 → expect rc=42
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":1},
|
||||||
|
{"op":"const","dst":2,"ty":"i64","value":1},
|
||||||
|
{"op":"compare","operation":"==","lhs":1,"rhs":2,"dst":3},
|
||||||
|
{"op":"branch","cond":3,"then":1,"else":2}
|
||||||
|
]},
|
||||||
|
{"id":1,"inst":[
|
||||||
|
{"op":"const","dst":4,"ty":"i64","value":42},
|
||||||
|
{"op":"ret","value":4}
|
||||||
|
]},
|
||||||
|
{"id":2,"inst":[
|
||||||
|
{"op":"const","dst":5,"ty":"i64","value":7},
|
||||||
|
{"op":"ret","value":5}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
APP="/tmp/ny_crate_backend_exe_phi_ret42_$$"
|
||||||
|
TMP_JSON="/tmp/ny_crate_backend_exe_phi_ret42_$$.json"
|
||||||
|
echo "$JSON" > "$TMP_JSON"
|
||||||
|
|
||||||
|
if HAKO_LLVM_CANARY_NORMALIZE=1 "$BIN_NYLLVMC" --in "$TMP_JSON" --emit exe --nyrt "$ROOT/target/release" --out "$APP" >/dev/null 2>&1; then
|
||||||
|
if [[ -x "$APP" ]]; then
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
if [ "$rc" -eq 42 ]; then
|
||||||
|
echo "[PASS] s3_backend_selector_crate_exe_phi_branch_return42_canary_vm"
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "[FAIL] s3_backend_selector_crate_exe_phi_branch_return42_canary_vm" >&2
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
|
|
||||||
@ -29,10 +29,10 @@ APP="/tmp/ny_crate_backend_exe_print_$$"
|
|||||||
TMP_JSON="/tmp/ny_crate_backend_exe_print_$$.json"
|
TMP_JSON="/tmp/ny_crate_backend_exe_print_$$.json"
|
||||||
echo "$JSON" > "$TMP_JSON"
|
echo "$JSON" > "$TMP_JSON"
|
||||||
|
|
||||||
LIBDIR_MIN="$ROOT/crates/nyash_kernel_min_c/target/release"
|
LIBDIR_MIN="$ROOT/target/release"
|
||||||
LIBS="-L $LIBDIR_MIN -lnyash_kernel_min_c"
|
LIBS="-L $LIBDIR_MIN -lnyash_kernel_min_c"
|
||||||
|
|
||||||
if "$BIN_NYLLVMC" --in "$TMP_JSON" --emit exe --nyrt "$ROOT/target/release" --libs "$LIBS" --out "$APP" >/dev/null 2>&1; then
|
if HAKO_LLVM_CANARY_NORMALIZE=1 "$BIN_NYLLVMC" --in "$TMP_JSON" --emit exe --nyrt "$ROOT/target/release" --libs="$LIBS" --out "$APP" >/dev/null 2>&1; then
|
||||||
if [[ -x "$APP" ]]; then
|
if [[ -x "$APP" ]]; then
|
||||||
set +e
|
set +e
|
||||||
out="$($APP 2>/dev/null)"; rc=$?
|
out="$($APP 2>/dev/null)"; rc=$?
|
||||||
|
|||||||
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_NYLLVMC="$ROOT/target/release/ny-llvmc"
|
||||||
|
|
||||||
|
(cd "$ROOT" && cargo build -q --release -p nyash-llvm-compiler >/dev/null) || true
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":5},
|
||||||
|
{"op":"const","dst":2,"ty":"i64","value":2},
|
||||||
|
{"op":"binop","operation":"%","lhs":1,"rhs":2,"dst":3},
|
||||||
|
{"op":"ret","value":3}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
APP="/tmp/ny_crate_backend_exe_rem_$$"
|
||||||
|
TMP_JSON="/tmp/ny_crate_backend_exe_rem_$$.json"
|
||||||
|
echo "$JSON" > "$TMP_JSON"
|
||||||
|
|
||||||
|
if HAKO_LLVM_CANARY_NORMALIZE=1 "$BIN_NYLLVMC" --in "$TMP_JSON" --emit exe --nyrt "$ROOT/target/release" --out "$APP" >/dev/null 2>&1; then
|
||||||
|
if [[ -x "$APP" ]]; then
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
if [ "$rc" -eq 1 ]; then
|
||||||
|
echo "[PASS] s3_backend_selector_crate_exe_rem_canary_vm"
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "[FAIL] s3_backend_selector_crate_exe_rem_canary_vm" >&2
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
|
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_NYLLVMC="$ROOT/target/release/ny-llvmc"
|
||||||
|
|
||||||
|
# Prebuild required tools/libraries
|
||||||
|
(cd "$ROOT" && cargo build -q --release -p nyash-llvm-compiler >/dev/null) || true
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
# Minimal MIR v1 JSON that returns 42.
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":42},
|
||||||
|
{"op":"ret","value":1}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
APP="/tmp/ny_crate_backend_exe_ret42_$$"
|
||||||
|
TMP_JSON="/tmp/ny_crate_backend_exe_ret42_$$.json"
|
||||||
|
echo "$JSON" > "$TMP_JSON"
|
||||||
|
|
||||||
|
if HAKO_LLVM_CANARY_NORMALIZE=1 "$BIN_NYLLVMC" --in "$TMP_JSON" --emit exe --nyrt "$ROOT/target/release" --out "$APP" >/dev/null 2>&1; then
|
||||||
|
if [[ -x "$APP" ]]; then
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
if [ "$rc" -eq 42 ]; then
|
||||||
|
echo "[PASS] s3_backend_selector_crate_exe_return42_canary_vm"
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "[SKIP] s3_backend_selector_crate_exe_return42_canary_vm (rc mapping not active)" >&2
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_NYLLVMC="$ROOT/target/release/ny-llvmc"
|
||||||
|
|
||||||
|
# Prebuild required tools/libraries
|
||||||
|
(cd "$ROOT" && cargo build -q --release -p nyash-llvm-compiler >/dev/null) || true
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
# Minimal MIR v1 JSON that returns 0.
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":0},
|
||||||
|
{"op":"ret","value":1}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
APP="/tmp/ny_crate_backend_exe_ret_$$"
|
||||||
|
TMP_JSON="/tmp/ny_crate_backend_exe_ret_$$.json"
|
||||||
|
echo "$JSON" > "$TMP_JSON"
|
||||||
|
|
||||||
|
if HAKO_LLVM_CANARY_NORMALIZE=1 "$BIN_NYLLVMC" --in "$TMP_JSON" --emit exe --nyrt "$ROOT/target/release" --out "$APP" >/dev/null 2>&1; then
|
||||||
|
if [[ -x "$APP" ]]; then
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
if [ "$rc" -eq 0 ]; then
|
||||||
|
echo "[PASS] s3_backend_selector_crate_exe_return_canary_vm"
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "[FAIL] s3_backend_selector_crate_exe_return_canary_vm" >&2
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
|
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_NYLLVMC="$ROOT/target/release/ny-llvmc"
|
||||||
|
|
||||||
|
(cd "$ROOT" && cargo build -q --release -p nyash-llvm-compiler >/dev/null) || true
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":4},
|
||||||
|
{"op":"const","dst":2,"ty":"i64","value":1},
|
||||||
|
{"op":"binop","operation":"<<","lhs":1,"rhs":2,"dst":3},
|
||||||
|
{"op":"ret","value":3}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
APP="/tmp/ny_crate_backend_exe_shl_$$"
|
||||||
|
TMP_JSON="/tmp/ny_crate_backend_exe_shl_$$.json"
|
||||||
|
echo "$JSON" > "$TMP_JSON"
|
||||||
|
|
||||||
|
if HAKO_LLVM_CANARY_NORMALIZE=1 "$BIN_NYLLVMC" --in "$TMP_JSON" --emit exe --nyrt "$ROOT/target/release" --out "$APP" >/dev/null 2>&1; then
|
||||||
|
if [[ -x "$APP" ]]; then
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
if [ "$rc" -eq 8 ]; then
|
||||||
|
echo "[PASS] s3_backend_selector_crate_exe_shift_left_canary_vm"
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "[FAIL] s3_backend_selector_crate_exe_shift_left_canary_vm" >&2
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
|
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_NYLLVMC="$ROOT/target/release/ny-llvmc"
|
||||||
|
|
||||||
|
(cd "$ROOT" && cargo build -q --release -p nyash-llvm-compiler >/dev/null) || true
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":8},
|
||||||
|
{"op":"const","dst":2,"ty":"i64","value":1},
|
||||||
|
{"op":"binop","operation":">>","lhs":1,"rhs":2,"dst":3},
|
||||||
|
{"op":"ret","value":3}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
APP="/tmp/ny_crate_backend_exe_shr_$$"
|
||||||
|
TMP_JSON="/tmp/ny_crate_backend_exe_shr_$$.json"
|
||||||
|
echo "$JSON" > "$TMP_JSON"
|
||||||
|
|
||||||
|
if HAKO_LLVM_CANARY_NORMALIZE=1 "$BIN_NYLLVMC" --in "$TMP_JSON" --emit exe --nyrt "$ROOT/target/release" --out "$APP" >/dev/null 2>&1; then
|
||||||
|
if [[ -x "$APP" ]]; then
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
if [ "$rc" -eq 4 ]; then
|
||||||
|
echo "[PASS] s3_backend_selector_crate_exe_shift_right_canary_vm"
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "[FAIL] s3_backend_selector_crate_exe_shift_right_canary_vm" >&2
|
||||||
|
rm -f "$APP" "$TMP_JSON" 2>/dev/null || true
|
||||||
|
exit 1
|
||||||
|
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_BUILDER="$ROOT/tools/ny_mir_builder.sh"
|
||||||
|
|
||||||
|
if ! command -v llc >/dev/null 2>&1; then
|
||||||
|
echo "[SKIP] native_backend_binop_add_canary_vm (llc not found)" >&2
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build NyRT quietly (link step)
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":40},
|
||||||
|
{"op":"const","dst":2,"ty":"i64","value":2},
|
||||||
|
{"op":"binop","dst":3,"operation":"Add","lhs":1,"rhs":2},
|
||||||
|
{"op":"ret","value":3}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
TMP_JSON="/tmp/native_binop_add_$$.json"; echo "$JSON" > "$TMP_JSON"
|
||||||
|
APP="/tmp/native_binop_add_$$"
|
||||||
|
|
||||||
|
set +e
|
||||||
|
NYASH_LLVM_BACKEND=native NYASH_LLVM_SKIP_BUILD=1 bash "$BIN_BUILDER" --in "$TMP_JSON" --emit exe -o "$APP" >/dev/null 2>&1
|
||||||
|
RC_BUILD=$?
|
||||||
|
set -e
|
||||||
|
if [ "$RC_BUILD" -ne 0 ]; then
|
||||||
|
echo "[SKIP] native_backend_binop_add_canary_vm (native builder failed)" >&2
|
||||||
|
rm -f "$TMP_JSON" "$APP"; exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
rm -f "$TMP_JSON" "$APP" 2>/dev/null || true
|
||||||
|
if [ "$rc" -eq 42 ]; then
|
||||||
|
echo "[PASS] native_backend_binop_add_canary_vm"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "[FAIL] native_backend_binop_add_canary_vm (rc=$rc)" >&2
|
||||||
|
exit 1
|
||||||
|
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_BUILDER="$ROOT/tools/ny_mir_builder.sh"
|
||||||
|
|
||||||
|
if ! command -v llc >/dev/null 2>&1; then
|
||||||
|
echo "[SKIP] native_backend_branch_eq_canary_vm (llc not found)" >&2
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
# Compare false (5==6) -> branch to else (ret 42)
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":5},
|
||||||
|
{"op":"const","dst":2,"ty":"i64","value":42},
|
||||||
|
{"op":"compare","dst":3,"operation":"==","lhs":1,"rhs":2},
|
||||||
|
{"op":"branch","cond":3, "then":1, "else":2}
|
||||||
|
]},
|
||||||
|
{"id":1,"inst":[
|
||||||
|
{"op":"ret","value":1}
|
||||||
|
]},
|
||||||
|
{"id":2,"inst":[
|
||||||
|
{"op":"ret","value":2}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
TMP_JSON="/tmp/native_branch_eq_$$.json"; echo "$JSON" > "$TMP_JSON"
|
||||||
|
APP="/tmp/native_branch_eq_$$"
|
||||||
|
|
||||||
|
set +e
|
||||||
|
NYASH_LLVM_BACKEND=native NYASH_LLVM_SKIP_BUILD=1 bash "$BIN_BUILDER" --in "$TMP_JSON" --emit exe -o "$APP" >/dev/null 2>&1
|
||||||
|
RC_BUILD=$?
|
||||||
|
set -e
|
||||||
|
if [ "$RC_BUILD" -ne 0 ]; then
|
||||||
|
echo "[SKIP] native_backend_branch_eq_canary_vm (native builder failed)" >&2
|
||||||
|
rm -f "$TMP_JSON" "$APP"; exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
rm -f "$TMP_JSON" "$APP" 2>/dev/null || true
|
||||||
|
if [ "$rc" -eq 42 ]; then
|
||||||
|
echo "[PASS] native_backend_branch_eq_canary_vm"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "[FAIL] native_backend_branch_eq_canary_vm (rc=$rc)" >&2
|
||||||
|
exit 1
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_BUILDER="$ROOT/tools/ny_mir_builder.sh"
|
||||||
|
|
||||||
|
if ! command -v llc >/dev/null 2>&1; then
|
||||||
|
echo "[SKIP] native_backend_compare_eq_canary_vm (llc not found)" >&2
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":5},
|
||||||
|
{"op":"const","dst":2,"ty":"i64","value":5},
|
||||||
|
{"op":"compare","dst":3,"operation":"==","lhs":1,"rhs":2},
|
||||||
|
{"op":"ret","value":3}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
TMP_JSON="/tmp/native_cmp_eq_$$.json"; echo "$JSON" > "$TMP_JSON"
|
||||||
|
APP="/tmp/native_cmp_eq_$$"
|
||||||
|
|
||||||
|
set +e
|
||||||
|
NYASH_LLVM_BACKEND=native NYASH_LLVM_SKIP_BUILD=1 bash "$BIN_BUILDER" --in "$TMP_JSON" --emit exe -o "$APP" >/dev/null 2>&1
|
||||||
|
RC_BUILD=$?
|
||||||
|
set -e
|
||||||
|
if [ "$RC_BUILD" -ne 0 ]; then
|
||||||
|
echo "[SKIP] native_backend_compare_eq_canary_vm (native builder failed)" >&2
|
||||||
|
rm -f "$TMP_JSON" "$APP"; exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
rm -f "$TMP_JSON" "$APP" 2>/dev/null || true
|
||||||
|
if [ "$rc" -eq 1 ]; then
|
||||||
|
echo "[PASS] native_backend_compare_eq_canary_vm"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "[FAIL] native_backend_compare_eq_canary_vm (rc=$rc)" >&2
|
||||||
|
exit 1
|
||||||
|
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../../../../../../.." && pwd)"
|
||||||
|
BIN_BUILDER="$ROOT/tools/ny_mir_builder.sh"
|
||||||
|
|
||||||
|
# Require llc (native path)
|
||||||
|
if ! command -v llc >/dev/null 2>&1; then
|
||||||
|
echo "[SKIP] native_backend_return42_canary_vm (llc not found)" >&2
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prebuild NyRT (for linking)
|
||||||
|
(cd "$ROOT/crates/nyash_kernel" && cargo build -q --release >/dev/null) || true
|
||||||
|
|
||||||
|
JSON='{
|
||||||
|
"schema_version": 1,
|
||||||
|
"functions": [
|
||||||
|
{"name":"ny_main","blocks":[
|
||||||
|
{"id":0,"inst":[
|
||||||
|
{"op":"const","dst":1,"ty":"i64","value":42},
|
||||||
|
{"op":"ret","value":1}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
|
||||||
|
TMP_JSON="/tmp/native_ret42_$$.json"; echo "$JSON" > "$TMP_JSON"
|
||||||
|
APP="/tmp/native_ret42_$$"
|
||||||
|
|
||||||
|
if ! NYASH_LLVM_BACKEND=native NYASH_LLVM_SKIP_BUILD=1 bash "$BIN_BUILDER" --in "$TMP_JSON" --emit exe -o "$APP" >/dev/null 2>&1; then
|
||||||
|
echo "[SKIP] native_backend_return42_canary_vm (native builder failed)" >&2
|
||||||
|
rm -f "$TMP_JSON" "$APP"; exit 0
|
||||||
|
fi
|
||||||
|
set +e
|
||||||
|
"$APP" >/dev/null 2>&1; rc=$?
|
||||||
|
set -e
|
||||||
|
rm -f "$TMP_JSON" "$APP" 2>/dev/null || true
|
||||||
|
if [ "$rc" -eq 42 ]; then
|
||||||
|
echo "[PASS] native_backend_return42_canary_vm"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "[FAIL] native_backend_return42_canary_vm" >&2
|
||||||
|
exit 1
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
source "$(dirname "$0")/../../../../lib/test_runner.sh"
|
||||||
|
require_env >/dev/null || exit 2
|
||||||
|
|
||||||
|
# Build nyash with tlv-shim feature (even if we run OFF for parity)
|
||||||
|
( cd "$NYASH_ROOT" && cargo build -q --release -p nyash-rust --features tlv-shim )
|
||||||
|
|
||||||
|
CODE='
|
||||||
|
static box Main {
|
||||||
|
main() {
|
||||||
|
local m = new MapBox()
|
||||||
|
m.set("k", "v")
|
||||||
|
print(m.get("k"))
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'
|
||||||
|
|
||||||
|
o1=$(HAKO_TLV_SHIM=0 run_nyash_vm -c "$CODE" 2>&1 | tr -d '\r')
|
||||||
|
o2=$(HAKO_TLV_SHIM=1 run_nyash_vm -c "$CODE" 2>&1 | tr -d '\r')
|
||||||
|
|
||||||
|
# Strip shim trace if any to compare pure program output
|
||||||
|
o1p=$(printf "%s\n" "$o1" | awk '!/^\[tlv\/shim:/')
|
||||||
|
o2p=$(printf "%s\n" "$o2" | awk '!/^\[tlv\/shim:/')
|
||||||
|
|
||||||
|
if diff -u <(printf "%s\n" "$o1p") <(printf "%s\n" "$o2p") >/dev/null; then
|
||||||
|
echo "[PASS] tlv_shim_parity_canary_vm"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "[FAIL] tlv_shim_parity_canary_vm" >&2
|
||||||
|
echo "--- OFF ---" >&2; echo "$o1" >&2
|
||||||
|
echo "--- ON ----" >&2; echo "$o2" >&2
|
||||||
|
exit 1
|
||||||
|
|
||||||
Reference in New Issue
Block a user