Files
hakorune/apps/selfhost-vm/mini_vm.nyash

310 lines
12 KiB
Plaintext
Raw Normal View History

// Mini-VM: function-based entry using library
using selfhost.vm.json_cur as MiniJsonCur
using selfhost.vm.json as MiniJson
using selfhost.vm.core as MiniVm
// Local static box (duplicated from mini_vm_lib for now to avoid include gate issues)
// Program entry: prefer argv[0] JSON, fallback to embedded sample
static box Main {
// Small helpers for quick JSON scans (avoid cross-box deps)
index_of_from(hay, needle, pos) {
local tail = hay.substring(pos, hay.length())
local rel = tail.indexOf(needle)
if rel < 0 { return -1 } else { return pos + rel }
}
_is_digit(ch) {
if ch == "0" { return 1 }
if ch == "1" { return 1 }
if ch == "2" { return 1 }
if ch == "3" { return 1 }
if ch == "4" { return 1 }
if ch == "5" { return 1 }
if ch == "6" { return 1 }
if ch == "7" { return 1 }
if ch == "8" { return 1 }
if ch == "9" { return 1 }
return 0
}
_digit_value(ch) {
if ch == "0" { return 0 }
if ch == "1" { return 1 }
if ch == "2" { return 2 }
if ch == "3" { return 3 }
if ch == "4" { return 4 }
if ch == "5" { return 5 }
if ch == "6" { return 6 }
if ch == "7" { return 7 }
if ch == "8" { return 8 }
if ch == "9" { return 9 }
return 0
}
_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
}
main(args) {
local json = "{\"kind\":\"Program\",\"statements\":[{\"kind\":\"Print\",\"expression\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":42}}}]}"
// If args provided, use the first as JSON source (guard None)
if args {
if args.size() > 0 {
local s = args.get(0)
if s { json = s }
}
}
// Top-level fast paths for simple Print cases (Literal/FunctionCall/Compare/BinaryOp)
// 0) If(literal int) then/else branch (string prints)
if json.indexOf("\"If\"") >= 0 {
local kc = "\"condition\""
local pc = json.indexOf(kc)
if pc >= 0 {
local kv = "\"type\":\"int\",\"value\":"
local pv = json.indexOf(kv, pc)
if pv >= 0 {
local vi = pv + kv.length()
local ve = json.indexOf("}", vi)
if ve >= 0 {
local cond_str = json.substring(vi, ve)
// parse int
local a = 0
local i = 0
loop (i < cond_str.length()) {
local ch = cond_str.substring(i, i+1)
if ch == "0" { a = a*10 i = i + 1 continue }
if ch == "1" { a = a*10+1 i = i + 1 continue }
if ch == "2" { a = a*10+2 i = i + 1 continue }
if ch == "3" { a = a*10+3 i = i + 1 continue }
if ch == "4" { a = a*10+4 i = i + 1 continue }
if ch == "5" { a = a*10+5 i = i + 1 continue }
if ch == "6" { a = a*10+6 i = i + 1 continue }
if ch == "7" { a = a*10+7 i = i + 1 continue }
if ch == "8" { a = a*10+8 i = i + 1 continue }
if ch == "9" { a = a*10+9 i = i + 1 continue }
break
}
local truthy = 0
if a != 0 { truthy = 1 }
local bkey = "\"then_body\""
if truthy == 0 { bkey = "\"else_body\"" }
local pb = json.indexOf(bkey, ve)
if pb >= 0 {
// search first string literal value inside the chosen body
local ts = "\"type\":\"string\",\"value\":\""
local ps = json.indexOf(ts, pb)
if ps >= 0 {
local si = ps + ts.length()
local sj = json.indexOf("\"", si)
if sj >= 0 { print(json.substring(si, sj)) return 0 }
}
}
}
}
}
}
// 1) Print(Literal string)
if json.indexOf("\"expression\":{\"kind\":\"Literal\",\"value\":{\"type\":\"string\"") >= 0 {
local ks = "\"expression\":{\"kind\":\"Literal\",\"value\":{\"type\":\"string\",\"value\":\""
local ps = json.indexOf(ks)
if ps >= 0 {
local si = ps + ks.length()
local sj = json.indexOf("\"", si)
if sj >= 0 { print(json.substring(si, sj)) return 0 }
}
}
// 2) Print(Literal int)
if json.indexOf("\"expression\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\"") >= 0 {
local ki = "\"expression\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
local pi = json.indexOf(ki)
if pi >= 0 {
local ii = pi + ki.length()
// take until next non-digit or closing brace
local ie = json.indexOf("}", ii)
if ie < 0 { ie = ii }
local d = json.substring(ii, ie)
print(d)
return 0
}
}
// 3) Print(FunctionCall) minimal (echo/itoa)
if json.indexOf("\"FunctionCall\"") >= 0 {
local pos = 0
loop (true) {
local kfc = "\"kind\":\"FunctionCall\""
local fcp = json.indexOf(kfc, pos)
if fcp < 0 { break }
local kn = "\"name\":\""
local pn = json.indexOf(kn, fcp)
if pn < 0 { break }
local ni = pn + kn.length()
local nj = json.indexOf("\"", ni)
if nj < 0 { break }
local fname = json.substring(ni, nj)
local ka = "\"arguments\":["
local pa = json.indexOf(ka, nj)
if pa < 0 { pos = nj + 1 continue }
// string arg
local ts = "\"type\":\"string\",\"value\":\""
local ti = json.indexOf(ts, pa)
if ti >= 0 {
local si = ti + ts.length()
local sj = json.indexOf("\"", si)
if sj >= 0 {
local sval = json.substring(si, sj)
if fname == "echo" { print(sval) }
pos = sj + 1
continue
}
}
// int arg
local ti2 = json.indexOf("\"type\":\"int\",\"value\":", pa)
if ti2 >= 0 {
local vi = ti2 + "\"type\":\"int\",\"value\":".length()
local ve = json.indexOf("}", vi)
if ve < 0 { ve = vi }
local ival = json.substring(vi, ve)
if fname == "itoa" || fname == "echo" { print(ival) }
pos = ve + 1
continue
}
pos = pn + 1
}
return 0
}
// 4) Print(Compare) minimal
if json.indexOf("\"Compare\"") >= 0 {
local ko = "\"operation\":\""
local po = json.indexOf(ko)
if po >= 0 {
local oi = po + ko.length()
local oj = json.indexOf("\"", oi)
if oj >= 0 {
local op = json.substring(oi, oj)
local kv = "\"value\":\""
// lhs int
local kl = "\"lhs\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
local pl = json.indexOf(kl, oj)
if pl >= 0 {
local li = pl + kl.length()
local le = json.indexOf("}", li)
if le >= 0 {
local la = json.substring(li, le)
// rhs int
local kr = "\"rhs\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":"
local pr = json.indexOf(kr, le)
if pr >= 0 {
local ri = pr + kr.length()
local re = json.indexOf("}", ri)
if re >= 0 {
local rb = json.substring(ri, re)
// compute
local a = 0
local i = 0
loop (i < la.length()) { local ch = la.substring(i, i+1) if ch == "0" { a = a*10+0 i=i+1 continue } if ch == "1" { a=a*10+1 i=i+1 continue } if ch == "2" { a=a*10+2 i=i+1 continue } if ch == "3" { a=a*10+3 i=i+1 continue } if ch == "4" { a=a*10+4 i=i+1 continue } if ch == "5" { a=a*10+5 i=i+1 continue } if ch == "6" { a=a*10+6 i=i+1 continue } if ch == "7" { a=a*10+7 i=i+1 continue } if ch == "8" { a=a*10+8 i=i+1 continue } if ch == "9" { a=a*10+9 i=i+1 continue } break }
local b = 0
local j = 0
loop (j < rb.length()) { local ch2 = rb.substring(j, j+1) if ch2 == "0" { b = b*10+0 j=j+1 continue } if ch2 == "1" { b=b*10+1 j=j+1 continue } if ch2 == "2" { b=b*10+2 j=j+1 continue } if ch2 == "3" { b=b*10+3 j=j+1 continue } if ch2 == "4" { b=b*10+4 j=j+1 continue } if ch2 == "5" { b=b*10+5 j=j+1 continue } if ch2 == "6" { b=b*10+6 j=j+1 continue } if ch2 == "7" { b=b*10+7 j=j+1 continue } if ch2 == "8" { b=b*10+8 j=j+1 continue } if ch2 == "9" { b=b*10+9 j=j+1 continue } break }
local res = 0
if op == "<" { if a < b { res = 1 } }
if op == "==" { if a == b { res = 1 } }
if op == "<=" { if a <= b { res = 1 } }
if op == ">" { if a > b { res = 1 } }
if op == ">=" { if a >= b { res = 1 } }
if op == "!=" { if a != b { res = 1 } }
print(res)
return 0
}
}
}
}
}
}
}
// 5) BinaryOp(int+int) typed pattern twice and add保険
if json.indexOf("\"BinaryOp\"") >= 0 && json.indexOf("\"operator\":\"+\"") >= 0 {
local pat = "\"type\":\"int\",\"value\":"
local p1 = json.indexOf(pat)
if p1 >= 0 {
// parse first integer by taking until next closing brace
local i = p1 + pat.length()
local end1 = json.indexOf("}", i)
if end1 < 0 { end1 = i }
local a_str = json.substring(i, end1)
// convert a_str to int
local a = 0
local k = 0
loop (k < a_str.length()) {
local ch = a_str.substring(k, k+1)
if ch == "0" { a = a * 10 + 0 k = k + 1 continue }
if ch == "1" { a = a * 10 + 1 k = k + 1 continue }
if ch == "2" { a = a * 10 + 2 k = k + 1 continue }
if ch == "3" { a = a * 10 + 3 k = k + 1 continue }
if ch == "4" { a = a * 10 + 4 k = k + 1 continue }
if ch == "5" { a = a * 10 + 5 k = k + 1 continue }
if ch == "6" { a = a * 10 + 6 k = k + 1 continue }
if ch == "7" { a = a * 10 + 7 k = k + 1 continue }
if ch == "8" { a = a * 10 + 8 k = k + 1 continue }
if ch == "9" { a = a * 10 + 9 k = k + 1 continue }
break
}
// parse second integer
local p2 = json.lastIndexOf(pat)
if p2 >= 0 && p2 != p1 {
local j = p2 + pat.length()
local end2 = json.indexOf("}", j)
if end2 < 0 { end2 = j }
local b_str = json.substring(j, end2)
local b = 0
local m = 0
loop (m < b_str.length()) {
local ch2 = b_str.substring(m, m+1)
if ch2 == "0" { b = b * 10 + 0 m = m + 1 continue }
if ch2 == "1" { b = b * 10 + 1 m = m + 1 continue }
if ch2 == "2" { b = b * 10 + 2 m = m + 1 continue }
if ch2 == "3" { b = b * 10 + 3 m = m + 1 continue }
if ch2 == "4" { b = b * 10 + 4 m = m + 1 continue }
if ch2 == "5" { b = b * 10 + 5 m = m + 1 continue }
if ch2 == "6" { b = b * 10 + 6 m = m + 1 continue }
if ch2 == "7" { b = b * 10 + 7 m = m + 1 continue }
if ch2 == "8" { b = b * 10 + 8 m = m + 1 continue }
if ch2 == "9" { b = b * 10 + 9 m = m + 1 continue }
break
}
print(a + b)
return 0
}
}
}
// Fallback to full MiniVm runner
local vm = new MiniVm()
return vm.run(json)
}
}
// Top-level fallback entry for current runner
function main(args) {
local json = "{\"kind\":\"Program\",\"statements\":[{\"kind\":\"Print\",\"expression\":{\"kind\":\"Literal\",\"value\":{\"type\":\"int\",\"value\":42}}}]}"
if args {
if args.size() > 0 {
local s = args.get(0)
if s { json = s }
}
}
local vm = new MiniVm()
return vm.run(json)
}