Files
hakorune/apps/selfhost/vm/boxes/mir_vm_min.nyash

100 lines
3.4 KiB
Plaintext
Raw Normal View History

// mir_vm_min.nyash — Ny製の最小MIR(JSON v0)実行器const→retのみ
// 目的: M2スケルトン。仕様は既定OFFに影響しない新規アプリのみ。
// 入力: MIR(JSON v0) 文字列。形式例:
// {
// "functions":[{"name":"main","params":[],"blocks":[{"id":0,"instructions":[
// {"op":"const","dst":1,"value":{"type":"i64","value":42}},
// {"op":"ret","value":1}
// ]}]}]
// }
// 振る舞い: 最初の const i64 の値を読み取り、print する。ret は value スロット参照を想定するが、MVPでは無視。
static box MirVmMin {
// 最小限のスキャン関数(依存ゼロ版)
index_of_from(hay, needle, pos) {
if pos < 0 { pos = 0 }
local n = hay.length()
if pos >= n { return -1 }
local m = needle.length()
if m <= 0 { return pos }
local i = pos
local limit = n - m
loop (i <= limit) {
local seg = hay.substring(i, i + m)
if seg == needle { return i }
i = i + 1
}
return -1
}
read_digits(json, pos) {
local out = ""
local i = pos
loop (true) {
local s = json.substring(i, i+1)
if s == "" { break }
if s == "0" || s == "1" || s == "2" || s == "3" || s == "4" || s == "5" || s == "6" || s == "7" || s == "8" || s == "9" {
out = out + s
i = i + 1
} else { break }
}
return out
}
_str_to_int(s) {
local i = 0
local n = s.length()
local acc = 0
loop (i < n) {
local ch = s.substring(i, i+1)
if ch == "0" { acc = acc * 10 + 0 i = i + 1 continue }
if ch == "1" { acc = acc * 10 + 1 i = i + 1 continue }
if ch == "2" { acc = acc * 10 + 2 i = i + 1 continue }
if ch == "3" { acc = acc * 10 + 3 i = i + 1 continue }
if ch == "4" { acc = acc * 10 + 4 i = i + 1 continue }
if ch == "5" { acc = acc * 10 + 5 i = i + 1 continue }
if ch == "6" { acc = acc * 10 + 6 i = i + 1 continue }
if ch == "7" { acc = acc * 10 + 7 i = i + 1 continue }
if ch == "8" { acc = acc * 10 + 8 i = i + 1 continue }
if ch == "9" { acc = acc * 10 + 9 i = i + 1 continue }
break
}
return acc
}
_int_to_str(n) {
if n == 0 { return "0" }
local v = n
local out = ""
loop (v > 0) {
local d = v % 10
local ch = "0"
if d == 1 { ch = "1" } else { if d == 2 { ch = "2" } else { if d == 3 { ch = "3" } else { if d == 4 { ch = "4" } else { if d == 5 { ch = "5" } else { if d == 6 { ch = "6" } else { if d == 7 { ch = "7" } else { if d == 8 { ch = "8" } else { if d == 9 { ch = "9" } } } } } } } }
out = ch + out
v = v / 10
}
return out
}
// MVP: 最初の const i64 の値を抽出
_extract_first_const_i64(json) {
if json == null { return 0 }
// "op":"const" を探す
local p = json.indexOf("\"op\":\"const\"")
if p < 0 { return 0 }
// そこから "\"value\":{\"type\":\"i64\",\"value\":" を探す
local key = "\"value\":{\"type\":\"i64\",\"value\":"
local q = me.index_of_from(json, key, p)
if q < 0 { return 0 }
q = q + key.length()
// 連続する数字を読む
local digits = me.read_digits(json, q)
if digits == "" { return 0 }
return me._str_to_int(digits)
}
// 実行: 値を print し、0 を返すMVP。将来は exit code 連動可。
run(mir_json_text) {
local v = me._extract_first_const_i64(mir_json_text)
print(me._int_to_str(v))
return 0
}
}