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

113 lines
3.9 KiB
Plaintext
Raw Normal View History

// mir_vm_m2.nyash — Ny製の最小MIR(JSON v0)実行器M2: const/binop/ret
static box MirVmM2 {
_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
}
_find_int_in(seg, keypat) {
local p = seg.indexOf(keypat)
if p < 0 { return null }
p = p + keypat.length()
local i = p
local out = ""
loop(true) {
local ch = seg.substring(i, i+1)
if ch == "" { break }
if ch == "0" || ch == "1" || ch == "2" || ch == "3" || ch == "4" || ch == "5" || ch == "6" || ch == "7" || ch == "8" || ch == "9" { out = out + ch i = i + 1 } else { break }
}
if out == "" { return null }
return me._str_to_int(out)
}
_find_str_in(seg, keypat) {
local p = seg.indexOf(keypat)
if p < 0 { return "" }
p = p + keypat.length()
local q = seg.indexOf(""", p)
if q < 0 { return "" }
return seg.substring(p, q)
}
_get(regs, id) { if regs.has(id) { return regs.get(id) } return 0 }
_set(regs, id, v) { regs.set(id, v) }
_bin(kind, a, b) {
if kind == "Add" { return a + b }
if kind == "Sub" { return a - b }
if kind == "Mul" { return a * b }
if kind == "Div" { if b == 0 { return 0 } else { return a / b } }
return 0
}
run(json) {
local regs = new MapBox()
local pos = json.indexOf(""instructions":[")
if pos < 0 {
print("0")
return 0
}
local cur = pos
loop(true) {
local op_pos = json.indexOf(""op":"", cur)
if op_pos < 0 { break }
local name_start = op_pos + 6
local name_end = json.indexOf(""", name_start)
if name_end < 0 { break }
local opname = json.substring(name_start, name_end)
local next_pos = json.indexOf(""op":"", name_end)
if next_pos < 0 { next_pos = json.length() }
local seg = json.substring(op_pos, next_pos)
if opname == "const" {
local dst = me._find_int_in(seg, ""dst":")
local val = me._find_int_in(seg, ""value":{"type":"i64","value":")
if dst != null and val != null { me._set(regs, "" + dst, val) }
} else { if opname == "binop" {
local dst = me._find_int_in(seg, ""dst":")
local kind = me._find_str_in(seg, ""op_kind":"")
local lhs = me._find_int_in(seg, ""lhs":")
local rhs = me._find_int_in(seg, ""rhs":")
if dst != null and lhs != null and rhs != null {
local a = me._get(regs, "" + lhs)
local b = me._get(regs, "" + rhs)
me._set(regs, "" + dst, me._bin(kind, a, b))
}
} else { if opname == "ret" {
local v = me._find_int_in(seg, ""value":")
if v == null { v = 0 }
local out = me._get(regs, "" + v)
print(me._int_to_str(out))
return 0
} } }
cur = next_pos
}
print("0")
return 0
}
}