restore(lang): full lang tree from ff3ef452 (306 files) — compiler, vm, shared, runner, c-abi, etc.\n\n- Restores lang/ directory (files≈306, dirs≈64) as per historical branch with selfhost sources\n- Keeps our recent parser index changes in compiler/* (merged clean by checkout)\n- Unblocks selfhost development and documentation references
This commit is contained in:
@ -168,16 +168,6 @@ static box ParserExprBox {
|
||||
k = ctx.skip_ws(src, k)
|
||||
if src.substring(k, k+1) == ")" { k = k + 1 }
|
||||
node = "{\"type\":\"Method\",\"recv\":" + node + ",\"method\":\"" + mname + "\",\"args\":" + args_json2 + "}"
|
||||
} else if tch == "[" {
|
||||
// Index access: node[ index ] → Method(recv=node, method="get", args=[index])
|
||||
k = k + 1
|
||||
k = ctx.skip_ws(src, k)
|
||||
local idx_json = ctx.parse_expr2(src, k)
|
||||
k = ctx.gpos_get()
|
||||
k = ctx.skip_ws(src, k)
|
||||
if src.substring(k, k+1) == "]" { k = k + 1 }
|
||||
local args_idx = "[" + idx_json + "]"
|
||||
node = "{\\\"type\\\":\\\"Method\\\",\\\"recv\\\":" + node + ",\\\"method\\\":\\\"get\\\",\\\"args\\\":" + args_idx + "}"
|
||||
} else {
|
||||
cont2 = 0
|
||||
}
|
||||
@ -362,3 +352,4 @@ static box ParserExprBox {
|
||||
return out + "@" + ctx.i2s(j)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -14,11 +14,13 @@ using lang.compiler.parser.stmt.parser_control_box
|
||||
box ParserBox {
|
||||
gpos
|
||||
usings_json
|
||||
externs_json
|
||||
stage3
|
||||
|
||||
birth() {
|
||||
me.gpos = 0
|
||||
me.usings_json = "[]"
|
||||
me.externs_json = "[]"
|
||||
me.stage3 = 0
|
||||
return 0
|
||||
}
|
||||
@ -152,6 +154,36 @@ box ParserBox {
|
||||
return me.usings_json
|
||||
}
|
||||
|
||||
// === extern_c annotations ===
|
||||
add_extern_c(symbol, func) {
|
||||
// Entry shape: {"symbol":"hako_add","func":"Name/Arity"}
|
||||
local sym = match symbol { null => "", _ => symbol }
|
||||
local fn = match func { null => "", _ => func }
|
||||
local entry = "{\"symbol\":\"" + me.esc_json(sym) + "\",\"func\":\"" + me.esc_json(fn) + "\"}"
|
||||
local cur = me.externs_json
|
||||
if cur == null || cur.size() == 0 { cur = "[]" }
|
||||
if cur == "[]" {
|
||||
me.externs_json = "[" + entry + "]"
|
||||
return 0
|
||||
}
|
||||
local pos = cur.lastIndexOf("]")
|
||||
if pos < 0 {
|
||||
me.externs_json = "[" + entry + "]"
|
||||
return 0
|
||||
}
|
||||
me.externs_json = cur.substring(0, pos) + "," + entry + "]"
|
||||
return 0
|
||||
}
|
||||
|
||||
extract_externs(_src) {
|
||||
// MVP: rely on ParserStmtBox to call add_extern_c during parse; here no-op for now.
|
||||
return 0
|
||||
}
|
||||
|
||||
get_externs_json() {
|
||||
return me.externs_json
|
||||
}
|
||||
|
||||
// === Delegation to ParserExprBox ===
|
||||
parse_expr2(src, i) {
|
||||
local expr = new ParserExprBox()
|
||||
@ -236,4 +268,3 @@ static box ParserStub {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,45 +11,51 @@ static box ParserStmtBox {
|
||||
local j = ctx.skip_ws(src, i)
|
||||
local stmt_start = j
|
||||
|
||||
// annotation: @extern_c("c_symbol","Func/Arity");
|
||||
if ctx.starts_with(src, j, "@extern_c") == 1 {
|
||||
j = j + 9 // len("@extern_c")
|
||||
j = ctx.skip_ws(src, j)
|
||||
if j < src.size() && src.substring(j, j+1) == "(" { j = j + 1 }
|
||||
j = ctx.skip_ws(src, j)
|
||||
// First string literal: symbol
|
||||
local sym = ""
|
||||
if j < src.size() && src.substring(j, j+1) == "\"" {
|
||||
sym = ctx.read_string_lit(src, j)
|
||||
j = ctx.gpos_get()
|
||||
}
|
||||
j = ctx.skip_ws(src, j)
|
||||
if j < src.size() && src.substring(j, j+1) == "," { j = j + 1 }
|
||||
j = ctx.skip_ws(src, j)
|
||||
// Second string literal: func
|
||||
local fn = ""
|
||||
if j < src.size() && src.substring(j, j+1) == "\"" {
|
||||
fn = ctx.read_string_lit(src, j)
|
||||
j = ctx.gpos_get()
|
||||
}
|
||||
// Skip to ')' if present
|
||||
j = ctx.skip_ws(src, j)
|
||||
if j < src.size() && src.substring(j, j+1) == ")" { j = j + 1 }
|
||||
// Optional semicolon is consumed by caller; still advance if present
|
||||
j = ctx.skip_ws(src, j)
|
||||
if j < src.size() && src.substring(j, j+1) == ";" { j = j + 1 }
|
||||
ctx.gpos_set(j)
|
||||
// Record annotation in parser context and emit no statement
|
||||
ctx.add_extern_c(sym, fn)
|
||||
return ""
|
||||
}
|
||||
|
||||
// using statement
|
||||
if ctx.starts_with_kw(src, j, "using") == 1 {
|
||||
return me.parse_using(src, j, stmt_start, ctx)
|
||||
}
|
||||
|
||||
// assignment: IDENT '[' expr ']' '=' expr or IDENT '=' expr
|
||||
// assignment: IDENT '=' expr
|
||||
if j < src.size() && ctx.is_alpha(src.substring(j, j+1)) {
|
||||
local idp0 = ctx.read_ident2(src, j)
|
||||
local at0 = idp0.lastIndexOf("@")
|
||||
if at0 > 0 {
|
||||
local name0 = idp0.substring(0, at0)
|
||||
local k0 = ctx.to_int(idp0.substring(at0+1, idp0.size()))
|
||||
// Case A: index assignment arr[expr] = value
|
||||
{
|
||||
local kA = ctx.skip_ws(src, k0)
|
||||
if kA < src.size() && src.substring(kA, kA+1) == "[" {
|
||||
kA = kA + 1
|
||||
kA = ctx.skip_ws(src, kA)
|
||||
// parse index expression
|
||||
local idx_json = ctx.parse_expr2(src, kA)
|
||||
kA = ctx.gpos_get()
|
||||
kA = ctx.skip_ws(src, kA)
|
||||
if kA < src.size() && src.substring(kA, kA+1) == "]" { kA = kA + 1 }
|
||||
kA = ctx.skip_ws(src, kA)
|
||||
if kA < src.size() && src.substring(kA, kA+1) == "=" {
|
||||
// parse RHS
|
||||
kA = kA + 1
|
||||
kA = ctx.skip_ws(src, kA)
|
||||
local rhs_json = ctx.parse_expr2(src, kA)
|
||||
kA = ctx.gpos_get()
|
||||
// Build Method set(name[idx], rhs) as Expr statement
|
||||
local recv = "{\\\"type\\\":\\\"Var\\\",\\\"name\\\":\"" + name0 + "\"}"
|
||||
local args = "[" + idx_json + "," + rhs_json + "]"
|
||||
local method = "{\\\"type\\\":\\\"Method\\\",\\\"recv\\\":" + recv + ",\\\"method\\\":\\\"set\\\",\\\"args\\\":" + args + "}"
|
||||
ctx.gpos_set(kA)
|
||||
return "{\"type\":\"Expr\",\"expr\":" + method + "}"
|
||||
}
|
||||
}
|
||||
}
|
||||
k0 = ctx.skip_ws(src, k0)
|
||||
if k0 < src.size() && src.substring(k0, k0+1) == "=" {
|
||||
local eq_two = "="
|
||||
|
||||
Reference in New Issue
Block a user