Archive Rust bootstrap — El compiler is now self-hosting
This commit is contained in:
+146
-140
@@ -6,26 +6,30 @@
|
||||
// The cursor (integer position into the token list) is threaded through every
|
||||
// parse function. Functions return { "node": <map>, "pos": <int> }.
|
||||
//
|
||||
// The token list is stored in the VM's global token buffer via
|
||||
// native_tokens_init / native_token_at / native_token_len. This avoids
|
||||
// O(n²) cloning that occurs when passing the list as a function argument.
|
||||
//
|
||||
// Entry point: fn parse(tokens: [Map<String, Any>]) -> [Map<String, Any>]
|
||||
|
||||
// ── Token access helpers ──────────────────────────────────────────────────────
|
||||
|
||||
fn tok_at(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
native_list_get(tokens, pos)
|
||||
fn tok_at(pos: Int) -> Map<String, Any> {
|
||||
native_token_at(pos)
|
||||
}
|
||||
|
||||
fn tok_kind(tokens: [Map<String, Any>], pos: Int) -> String {
|
||||
let t = tok_at(tokens, pos)
|
||||
fn tok_kind(pos: Int) -> String {
|
||||
let t = native_token_at(pos)
|
||||
t["kind"]
|
||||
}
|
||||
|
||||
fn tok_value(tokens: [Map<String, Any>], pos: Int) -> String {
|
||||
let t = tok_at(tokens, pos)
|
||||
fn tok_value(pos: Int) -> String {
|
||||
let t = native_token_at(pos)
|
||||
t["value"]
|
||||
}
|
||||
|
||||
fn expect(tokens: [Map<String, Any>], pos: Int, kind: String) -> Int {
|
||||
let k = tok_kind(tokens, pos)
|
||||
fn expect(pos: Int, kind: String) -> Int {
|
||||
let k = tok_kind(pos)
|
||||
if k == kind {
|
||||
return pos + 1
|
||||
}
|
||||
@@ -43,26 +47,26 @@ fn make_result(node: Map<String, Any>, pos: Int) -> Map<String, Any> {
|
||||
// Skips over a type annotation, returning the new position.
|
||||
// Types can be: Ident, [Type], Map<K,V>, Type?, Type<Type,...>
|
||||
|
||||
fn skip_type(tokens: [Map<String, Any>], pos: Int) -> Int {
|
||||
let k = tok_kind(tokens, pos)
|
||||
fn skip_type(pos: Int) -> Int {
|
||||
let k = tok_kind(pos)
|
||||
// Array type: [Type]
|
||||
if k == "LBracket" {
|
||||
let p = pos + 1
|
||||
let p = skip_type(tokens, p)
|
||||
let p = expect(tokens, p, "RBracket")
|
||||
let p = skip_type(p)
|
||||
let p = expect(p, "RBracket")
|
||||
return p
|
||||
}
|
||||
// Named type (possibly generic)
|
||||
if k == "Ident" {
|
||||
let p = pos + 1
|
||||
let k2 = tok_kind(tokens, p)
|
||||
let k2 = tok_kind(p)
|
||||
if k2 == "Lt" {
|
||||
// Generic params: skip until matching >
|
||||
let p = p + 1
|
||||
let depth = 1
|
||||
let running = true
|
||||
while running {
|
||||
let kk = tok_kind(tokens, p)
|
||||
let kk = tok_kind(p)
|
||||
if kk == "Eof" {
|
||||
let running = false
|
||||
} else {
|
||||
@@ -82,7 +86,7 @@ fn skip_type(tokens: [Map<String, Any>], pos: Int) -> Int {
|
||||
}
|
||||
}
|
||||
}
|
||||
let k3 = tok_kind(tokens, p)
|
||||
let k3 = tok_kind(p)
|
||||
if k3 == "QuestionMark" {
|
||||
let p = p + 1
|
||||
}
|
||||
@@ -100,12 +104,12 @@ fn skip_type(tokens: [Map<String, Any>], pos: Int) -> Int {
|
||||
// ── Parameter list ────────────────────────────────────────────────────────────
|
||||
// Parses (name: Type, name: Type, ...) — returns { "params": [...], "pos": ... }
|
||||
|
||||
fn parse_params(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
let p = expect(tokens, pos, "LParen")
|
||||
fn parse_params(pos: Int) -> Map<String, Any> {
|
||||
let p = expect(pos, "LParen")
|
||||
let params: [Map<String, Any>] = native_list_empty()
|
||||
let running = true
|
||||
while running {
|
||||
let k = tok_kind(tokens, p)
|
||||
let k = tok_kind(p)
|
||||
if k == "RParen" {
|
||||
let running = false
|
||||
} else {
|
||||
@@ -113,28 +117,28 @@ fn parse_params(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
let running = false
|
||||
} else {
|
||||
// param name
|
||||
let pname = tok_value(tokens, p)
|
||||
let pname = tok_value(p)
|
||||
let p = p + 1
|
||||
let p = expect(tokens, p, "Colon")
|
||||
let p = skip_type(tokens, p)
|
||||
let p = expect(p, "Colon")
|
||||
let p = skip_type(p)
|
||||
let param = { "name": pname }
|
||||
let params = native_list_append(params, param)
|
||||
let k2 = tok_kind(tokens, p)
|
||||
let k2 = tok_kind(p)
|
||||
if k2 == "Comma" {
|
||||
let p = p + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let p = expect(tokens, p, "RParen")
|
||||
let p = expect(p, "RParen")
|
||||
{ "params": params, "pos": p }
|
||||
}
|
||||
|
||||
// ── Expression parsing ────────────────────────────────────────────────────────
|
||||
|
||||
fn parse_primary(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
let k = tok_kind(tokens, pos)
|
||||
let v = tok_value(tokens, pos)
|
||||
fn parse_primary(pos: Int) -> Map<String, Any> {
|
||||
let k = tok_kind(pos)
|
||||
let v = tok_value(pos)
|
||||
|
||||
// Integer literal
|
||||
if k == "Int" {
|
||||
@@ -163,10 +167,10 @@ fn parse_primary(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
|
||||
// Grouped expression
|
||||
if k == "LParen" {
|
||||
let r = parse_expr(tokens, pos + 1)
|
||||
let r = parse_expr(pos + 1)
|
||||
let node = r["node"]
|
||||
let p = r["pos"]
|
||||
let p = expect(tokens, p, "RParen")
|
||||
let p = expect(p, "RParen")
|
||||
return make_result(node, p)
|
||||
}
|
||||
|
||||
@@ -176,25 +180,25 @@ fn parse_primary(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
let elems: [Map<String, Any>] = native_list_empty()
|
||||
let running = true
|
||||
while running {
|
||||
let k2 = tok_kind(tokens, p)
|
||||
let k2 = tok_kind(p)
|
||||
if k2 == "RBracket" {
|
||||
let running = false
|
||||
} else {
|
||||
if k2 == "Eof" {
|
||||
let running = false
|
||||
} else {
|
||||
let r = parse_expr(tokens, p)
|
||||
let r = parse_expr(p)
|
||||
let elem = r["node"]
|
||||
let p = r["pos"]
|
||||
let elems = native_list_append(elems, elem)
|
||||
let k3 = tok_kind(tokens, p)
|
||||
let k3 = tok_kind(p)
|
||||
if k3 == "Comma" {
|
||||
let p = p + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let p = expect(tokens, p, "RBracket")
|
||||
let p = expect(p, "RBracket")
|
||||
return make_result({ "expr": "Array", "elems": elems }, p)
|
||||
}
|
||||
|
||||
@@ -204,7 +208,7 @@ fn parse_primary(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
let pairs: [Map<String, Any>] = native_list_empty()
|
||||
let running = true
|
||||
while running {
|
||||
let k2 = tok_kind(tokens, p)
|
||||
let k2 = tok_kind(p)
|
||||
if k2 == "RBrace" {
|
||||
let running = false
|
||||
} else {
|
||||
@@ -212,46 +216,46 @@ fn parse_primary(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
let running = false
|
||||
} else {
|
||||
// key: Str token
|
||||
let key = tok_value(tokens, p)
|
||||
let key = tok_value(p)
|
||||
let p = p + 1
|
||||
let p = expect(tokens, p, "Colon")
|
||||
let r = parse_expr(tokens, p)
|
||||
let p = expect(p, "Colon")
|
||||
let r = parse_expr(p)
|
||||
let val_node = r["node"]
|
||||
let p = r["pos"]
|
||||
let pair = { "key": key, "value": val_node }
|
||||
let pairs = native_list_append(pairs, pair)
|
||||
let k3 = tok_kind(tokens, p)
|
||||
let k3 = tok_kind(p)
|
||||
if k3 == "Comma" {
|
||||
let p = p + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let p = expect(tokens, p, "RBrace")
|
||||
let p = expect(p, "RBrace")
|
||||
return make_result({ "expr": "Map", "pairs": pairs }, p)
|
||||
}
|
||||
|
||||
// if expression
|
||||
if k == "If" {
|
||||
let r = parse_if(tokens, pos)
|
||||
let r = parse_if(pos)
|
||||
return r
|
||||
}
|
||||
|
||||
// match expression
|
||||
if k == "Match" {
|
||||
let r = parse_match(tokens, pos)
|
||||
let r = parse_match(pos)
|
||||
return r
|
||||
}
|
||||
|
||||
// for expression (used as statement)
|
||||
if k == "For" {
|
||||
let r = parse_for_expr(tokens, pos)
|
||||
let r = parse_for_expr(pos)
|
||||
return r
|
||||
}
|
||||
|
||||
// Unary not
|
||||
if k == "Not" {
|
||||
let r = parse_primary(tokens, pos + 1)
|
||||
let r = parse_primary(pos + 1)
|
||||
let inner = r["node"]
|
||||
let p = r["pos"]
|
||||
return make_result({ "expr": "Not", "inner": inner }, p)
|
||||
@@ -259,7 +263,7 @@ fn parse_primary(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
|
||||
// Unary minus
|
||||
if k == "Minus" {
|
||||
let r = parse_primary(tokens, pos + 1)
|
||||
let r = parse_primary(pos + 1)
|
||||
let inner = r["node"]
|
||||
let p = r["pos"]
|
||||
return make_result({ "expr": "Neg", "inner": inner }, p)
|
||||
@@ -269,29 +273,29 @@ fn parse_primary(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
make_result({ "expr": "Nil" }, pos + 1)
|
||||
}
|
||||
|
||||
fn parse_if(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
let p = expect(tokens, pos, "If")
|
||||
let r = parse_expr(tokens, p)
|
||||
fn parse_if(pos: Int) -> Map<String, Any> {
|
||||
let p = expect(pos, "If")
|
||||
let r = parse_expr(p)
|
||||
let cond = r["node"]
|
||||
let p = r["pos"]
|
||||
let r2 = parse_block(tokens, p)
|
||||
let r2 = parse_block(p)
|
||||
let then_stmts = r2["stmts"]
|
||||
let p = r2["pos"]
|
||||
let has_else = false
|
||||
let else_stmts: [Map<String, Any>] = native_list_empty()
|
||||
let k2 = tok_kind(tokens, p)
|
||||
let k2 = tok_kind(p)
|
||||
if k2 == "Else" {
|
||||
let p = p + 1
|
||||
let k3 = tok_kind(tokens, p)
|
||||
let k3 = tok_kind(p)
|
||||
if k3 == "If" {
|
||||
// else-if chain: parse as nested if
|
||||
let r3 = parse_if(tokens, p)
|
||||
let r3 = parse_if(p)
|
||||
let nested = r3["node"]
|
||||
let p = r3["pos"]
|
||||
let else_stmts = native_list_append(else_stmts, { "stmt": "Expr", "value": nested })
|
||||
let has_else = true
|
||||
} else {
|
||||
let r3 = parse_block(tokens, p)
|
||||
let r3 = parse_block(p)
|
||||
let else_stmts = r3["stmts"]
|
||||
let p = r3["pos"]
|
||||
let has_else = true
|
||||
@@ -300,16 +304,16 @@ fn parse_if(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
make_result({ "expr": "If", "cond": cond, "then": then_stmts, "else": else_stmts, "has_else": has_else }, p)
|
||||
}
|
||||
|
||||
fn parse_match(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
let p = expect(tokens, pos, "Match")
|
||||
let r = parse_expr(tokens, p)
|
||||
fn parse_match(pos: Int) -> Map<String, Any> {
|
||||
let p = expect(pos, "Match")
|
||||
let r = parse_expr(p)
|
||||
let subject = r["node"]
|
||||
let p = r["pos"]
|
||||
let p = expect(tokens, p, "LBrace")
|
||||
let p = expect(p, "LBrace")
|
||||
let arms: [Map<String, Any>] = native_list_empty()
|
||||
let running = true
|
||||
while running {
|
||||
let k = tok_kind(tokens, p)
|
||||
let k = tok_kind(p)
|
||||
if k == "RBrace" {
|
||||
let running = false
|
||||
} else {
|
||||
@@ -317,131 +321,131 @@ fn parse_match(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
let running = false
|
||||
} else {
|
||||
// parse pattern => body
|
||||
let r2 = parse_pattern(tokens, p)
|
||||
let r2 = parse_pattern(p)
|
||||
let pattern = r2["node"]
|
||||
let p = r2["pos"]
|
||||
let p = expect(tokens, p, "FatArrow")
|
||||
let r3 = parse_expr(tokens, p)
|
||||
let p = expect(p, "FatArrow")
|
||||
let r3 = parse_expr(p)
|
||||
let body = r3["node"]
|
||||
let p = r3["pos"]
|
||||
let arm = { "pattern": pattern, "body": body }
|
||||
let arms = native_list_append(arms, arm)
|
||||
let k2 = tok_kind(tokens, p)
|
||||
let k2 = tok_kind(p)
|
||||
if k2 == "Comma" {
|
||||
let p = p + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let p = expect(tokens, p, "RBrace")
|
||||
let p = expect(p, "RBrace")
|
||||
make_result({ "expr": "Match", "subject": subject, "arms": arms }, p)
|
||||
}
|
||||
|
||||
fn parse_pattern(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
let k = tok_kind(tokens, pos)
|
||||
fn parse_pattern(pos: Int) -> Map<String, Any> {
|
||||
let k = tok_kind(pos)
|
||||
if k == "Ident" {
|
||||
let v = tok_value(tokens, pos)
|
||||
let v = tok_value(pos)
|
||||
if v == "_" {
|
||||
return make_result({ "pattern": "Wildcard" }, pos + 1)
|
||||
}
|
||||
return make_result({ "pattern": "Binding", "name": v }, pos + 1)
|
||||
}
|
||||
if k == "Int" {
|
||||
return make_result({ "pattern": "LitInt", "value": tok_value(tokens, pos) }, pos + 1)
|
||||
return make_result({ "pattern": "LitInt", "value": tok_value(pos) }, pos + 1)
|
||||
}
|
||||
if k == "Str" {
|
||||
return make_result({ "pattern": "LitStr", "value": tok_value(tokens, pos) }, pos + 1)
|
||||
return make_result({ "pattern": "LitStr", "value": tok_value(pos) }, pos + 1)
|
||||
}
|
||||
if k == "Bool" {
|
||||
return make_result({ "pattern": "LitBool", "value": tok_value(tokens, pos) }, pos + 1)
|
||||
return make_result({ "pattern": "LitBool", "value": tok_value(pos) }, pos + 1)
|
||||
}
|
||||
// Wildcard _
|
||||
make_result({ "pattern": "Wildcard" }, pos + 1)
|
||||
}
|
||||
|
||||
fn parse_for_expr(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
let p = expect(tokens, pos, "For")
|
||||
let item_name = tok_value(tokens, p)
|
||||
fn parse_for_expr(pos: Int) -> Map<String, Any> {
|
||||
let p = expect(pos, "For")
|
||||
let item_name = tok_value(p)
|
||||
let p = p + 1
|
||||
let p = expect(tokens, p, "In")
|
||||
let r = parse_expr(tokens, p)
|
||||
let p = expect(p, "In")
|
||||
let r = parse_expr(p)
|
||||
let list_expr = r["node"]
|
||||
let p = r["pos"]
|
||||
let r2 = parse_block(tokens, p)
|
||||
let r2 = parse_block(p)
|
||||
let body = r2["stmts"]
|
||||
let p = r2["pos"]
|
||||
make_result({ "expr": "For", "item": item_name, "list": list_expr, "body": body }, p)
|
||||
}
|
||||
|
||||
fn parse_block(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
let p = expect(tokens, pos, "LBrace")
|
||||
fn parse_block(pos: Int) -> Map<String, Any> {
|
||||
let p = expect(pos, "LBrace")
|
||||
let stmts: [Map<String, Any>] = native_list_empty()
|
||||
let running = true
|
||||
while running {
|
||||
let k = tok_kind(tokens, p)
|
||||
let k = tok_kind(p)
|
||||
if k == "RBrace" {
|
||||
let running = false
|
||||
} else {
|
||||
if k == "Eof" {
|
||||
let running = false
|
||||
} else {
|
||||
let r = parse_stmt(tokens, p)
|
||||
let r = parse_stmt(p)
|
||||
let stmt = r["node"]
|
||||
let p = r["pos"]
|
||||
let stmts = native_list_append(stmts, stmt)
|
||||
}
|
||||
}
|
||||
}
|
||||
let p = expect(tokens, p, "RBrace")
|
||||
let p = expect(p, "RBrace")
|
||||
{ "stmts": stmts, "pos": p }
|
||||
}
|
||||
|
||||
// ── Postfix expressions (calls, field access, index) ─────────────────────────
|
||||
|
||||
fn parse_postfix(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
let r = parse_primary(tokens, pos)
|
||||
fn parse_postfix(pos: Int) -> Map<String, Any> {
|
||||
let r = parse_primary(pos)
|
||||
let node = r["node"]
|
||||
let p = r["pos"]
|
||||
let running = true
|
||||
while running {
|
||||
let k = tok_kind(tokens, p)
|
||||
let k = tok_kind(p)
|
||||
if k == "LParen" {
|
||||
// function call
|
||||
let p = p + 1
|
||||
let args: [Map<String, Any>] = native_list_empty()
|
||||
let run2 = true
|
||||
while run2 {
|
||||
let k2 = tok_kind(tokens, p)
|
||||
let k2 = tok_kind(p)
|
||||
if k2 == "RParen" {
|
||||
let run2 = false
|
||||
} else {
|
||||
if k2 == "Eof" {
|
||||
let run2 = false
|
||||
} else {
|
||||
let r2 = parse_expr(tokens, p)
|
||||
let r2 = parse_expr(p)
|
||||
let arg = r2["node"]
|
||||
let p = r2["pos"]
|
||||
let args = native_list_append(args, arg)
|
||||
let k3 = tok_kind(tokens, p)
|
||||
let k3 = tok_kind(p)
|
||||
if k3 == "Comma" {
|
||||
let p = p + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let p = expect(tokens, p, "RParen")
|
||||
let p = expect(p, "RParen")
|
||||
let node = { "expr": "Call", "func": node, "args": args }
|
||||
} else {
|
||||
if k == "Dot" {
|
||||
let field = tok_value(tokens, p + 1)
|
||||
let field = tok_value(p + 1)
|
||||
let p = p + 2
|
||||
let node = { "expr": "Field", "object": node, "field": field }
|
||||
} else {
|
||||
if k == "LBracket" {
|
||||
let r2 = parse_expr(tokens, p + 1)
|
||||
let r2 = parse_expr(p + 1)
|
||||
let idx = r2["node"]
|
||||
let p = r2["pos"]
|
||||
let p = expect(tokens, p, "RBracket")
|
||||
let p = expect(p, "RBracket")
|
||||
let node = { "expr": "Index", "object": node, "index": idx }
|
||||
} else {
|
||||
if k == "QuestionMark" {
|
||||
@@ -491,18 +495,18 @@ fn is_binop(kind: String) -> Bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn parse_binop(tokens: [Map<String, Any>], pos: Int, min_prec: Int) -> Map<String, Any> {
|
||||
let r = parse_postfix(tokens, pos)
|
||||
fn parse_binop(pos: Int, min_prec: Int) -> Map<String, Any> {
|
||||
let r = parse_postfix(pos)
|
||||
let left = r["node"]
|
||||
let p = r["pos"]
|
||||
let running = true
|
||||
while running {
|
||||
let k = tok_kind(tokens, p)
|
||||
let k = tok_kind(p)
|
||||
let prec = op_precedence(k)
|
||||
if is_binop(k) {
|
||||
if prec >= min_prec {
|
||||
let op = k
|
||||
let r2 = parse_binop(tokens, p + 1, prec + 1)
|
||||
let r2 = parse_binop(p + 1, prec + 1)
|
||||
let right = r2["node"]
|
||||
let p = r2["pos"]
|
||||
let left = { "expr": "BinOp", "op": op, "left": left, "right": right }
|
||||
@@ -516,28 +520,28 @@ fn parse_binop(tokens: [Map<String, Any>], pos: Int, min_prec: Int) -> Map<Strin
|
||||
make_result(left, p)
|
||||
}
|
||||
|
||||
fn parse_expr(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
parse_binop(tokens, pos, 1)
|
||||
fn parse_expr(pos: Int) -> Map<String, Any> {
|
||||
parse_binop(pos, 1)
|
||||
}
|
||||
|
||||
// ── Statement parsing ─────────────────────────────────────────────────────────
|
||||
|
||||
fn parse_stmt(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
let k = tok_kind(tokens, pos)
|
||||
fn parse_stmt(pos: Int) -> Map<String, Any> {
|
||||
let k = tok_kind(pos)
|
||||
|
||||
// let binding
|
||||
if k == "Let" {
|
||||
let p = pos + 1
|
||||
let name = tok_value(tokens, p)
|
||||
let name = tok_value(p)
|
||||
let p = p + 1
|
||||
let k2 = tok_kind(tokens, p)
|
||||
let k2 = tok_kind(p)
|
||||
// optional type annotation: name: Type
|
||||
if k2 == "Colon" {
|
||||
let p = p + 1
|
||||
let p = skip_type(tokens, p)
|
||||
let p = skip_type(p)
|
||||
}
|
||||
let p = expect(tokens, p, "Eq")
|
||||
let r = parse_expr(tokens, p)
|
||||
let p = expect(p, "Eq")
|
||||
let r = parse_expr(p)
|
||||
let val = r["node"]
|
||||
let p = r["pos"]
|
||||
return make_result({ "stmt": "Let", "name": name, "value": val }, p)
|
||||
@@ -546,14 +550,14 @@ fn parse_stmt(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
// return statement
|
||||
if k == "Return" {
|
||||
let p = pos + 1
|
||||
let k2 = tok_kind(tokens, p)
|
||||
let k2 = tok_kind(p)
|
||||
if k2 == "RBrace" {
|
||||
return make_result({ "stmt": "Return", "value": { "expr": "Nil" } }, p)
|
||||
}
|
||||
if k2 == "Eof" {
|
||||
return make_result({ "stmt": "Return", "value": { "expr": "Nil" } }, p)
|
||||
}
|
||||
let r = parse_expr(tokens, p)
|
||||
let r = parse_expr(p)
|
||||
let val = r["node"]
|
||||
let p = r["pos"]
|
||||
return make_result({ "stmt": "Return", "value": val }, p)
|
||||
@@ -562,18 +566,18 @@ fn parse_stmt(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
// fn definition
|
||||
if k == "Fn" {
|
||||
let p = pos + 1
|
||||
let name = tok_value(tokens, p)
|
||||
let name = tok_value(p)
|
||||
let p = p + 1
|
||||
let r = parse_params(tokens, p)
|
||||
let r = parse_params(p)
|
||||
let params = r["params"]
|
||||
let p = r["pos"]
|
||||
// return type annotation: -> Type
|
||||
let k2 = tok_kind(tokens, p)
|
||||
let k2 = tok_kind(p)
|
||||
if k2 == "Arrow" {
|
||||
let p = p + 1
|
||||
let p = skip_type(tokens, p)
|
||||
let p = skip_type(p)
|
||||
}
|
||||
let r2 = parse_block(tokens, p)
|
||||
let r2 = parse_block(p)
|
||||
let body = r2["stmts"]
|
||||
let p = r2["pos"]
|
||||
return make_result({ "stmt": "FnDef", "name": name, "params": params, "body": body }, p)
|
||||
@@ -582,69 +586,69 @@ fn parse_stmt(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
// type definition
|
||||
if k == "Type" {
|
||||
let p = pos + 1
|
||||
let name = tok_value(tokens, p)
|
||||
let name = tok_value(p)
|
||||
let p = p + 1
|
||||
let p = expect(tokens, p, "LBrace")
|
||||
let p = expect(p, "LBrace")
|
||||
let fields: [Map<String, Any>] = native_list_empty()
|
||||
let running = true
|
||||
while running {
|
||||
let k2 = tok_kind(tokens, p)
|
||||
let k2 = tok_kind(p)
|
||||
if k2 == "RBrace" {
|
||||
let running = false
|
||||
} else {
|
||||
if k2 == "Eof" {
|
||||
let running = false
|
||||
} else {
|
||||
let fname = tok_value(tokens, p)
|
||||
let fname = tok_value(p)
|
||||
let p = p + 1
|
||||
let p = expect(tokens, p, "Colon")
|
||||
let p = skip_type(tokens, p)
|
||||
let p = expect(p, "Colon")
|
||||
let p = skip_type(p)
|
||||
let fields = native_list_append(fields, { "name": fname })
|
||||
let k3 = tok_kind(tokens, p)
|
||||
let k3 = tok_kind(p)
|
||||
if k3 == "Comma" {
|
||||
let p = p + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let p = expect(tokens, p, "RBrace")
|
||||
let p = expect(p, "RBrace")
|
||||
return make_result({ "stmt": "TypeDef", "name": name, "fields": fields }, p)
|
||||
}
|
||||
|
||||
// enum definition
|
||||
if k == "Enum" {
|
||||
let p = pos + 1
|
||||
let name = tok_value(tokens, p)
|
||||
let name = tok_value(p)
|
||||
let p = p + 1
|
||||
let p = expect(tokens, p, "LBrace")
|
||||
let p = expect(p, "LBrace")
|
||||
let variants: [Map<String, Any>] = native_list_empty()
|
||||
let running = true
|
||||
while running {
|
||||
let k2 = tok_kind(tokens, p)
|
||||
let k2 = tok_kind(p)
|
||||
if k2 == "RBrace" {
|
||||
let running = false
|
||||
} else {
|
||||
if k2 == "Eof" {
|
||||
let running = false
|
||||
} else {
|
||||
let vname = tok_value(tokens, p)
|
||||
let vname = tok_value(p)
|
||||
let p = p + 1
|
||||
let variants = native_list_append(variants, { "name": vname })
|
||||
let k3 = tok_kind(tokens, p)
|
||||
let k3 = tok_kind(p)
|
||||
if k3 == "Comma" {
|
||||
let p = p + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let p = expect(tokens, p, "RBrace")
|
||||
let p = expect(p, "RBrace")
|
||||
return make_result({ "stmt": "EnumDef", "name": name, "variants": variants }, p)
|
||||
}
|
||||
|
||||
// import statement
|
||||
if k == "Import" {
|
||||
let p = pos + 1
|
||||
let path = tok_value(tokens, p)
|
||||
let path = tok_value(p)
|
||||
let p = p + 1
|
||||
return make_result({ "stmt": "Import", "path": path }, p)
|
||||
}
|
||||
@@ -652,20 +656,20 @@ fn parse_stmt(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
// from ... import { ... }
|
||||
if k == "From" {
|
||||
let p = pos + 1
|
||||
let module_name = tok_value(tokens, p)
|
||||
let module_name = tok_value(p)
|
||||
let p = p + 1
|
||||
// skip "import" keyword
|
||||
let k2 = tok_kind(tokens, p)
|
||||
let k2 = tok_kind(p)
|
||||
if k2 == "Import" {
|
||||
let p = p + 1
|
||||
}
|
||||
// skip { Name, ... }
|
||||
let k3 = tok_kind(tokens, p)
|
||||
let k3 = tok_kind(p)
|
||||
if k3 == "LBrace" {
|
||||
let p = p + 1
|
||||
let running = true
|
||||
while running {
|
||||
let k4 = tok_kind(tokens, p)
|
||||
let k4 = tok_kind(p)
|
||||
if k4 == "RBrace" {
|
||||
let running = false
|
||||
} else {
|
||||
@@ -673,14 +677,14 @@ fn parse_stmt(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
let running = false
|
||||
} else {
|
||||
let p = p + 1
|
||||
let k5 = tok_kind(tokens, p)
|
||||
let k5 = tok_kind(p)
|
||||
if k5 == "Comma" {
|
||||
let p = p + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let p = expect(tokens, p, "RBrace")
|
||||
let p = expect(p, "RBrace")
|
||||
}
|
||||
return make_result({ "stmt": "Import", "path": module_name }, p)
|
||||
}
|
||||
@@ -688,10 +692,10 @@ fn parse_stmt(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
// while loop
|
||||
if k == "While" {
|
||||
let p = pos + 1
|
||||
let r = parse_expr(tokens, p)
|
||||
let r = parse_expr(p)
|
||||
let cond = r["node"]
|
||||
let p = r["pos"]
|
||||
let r2 = parse_block(tokens, p)
|
||||
let r2 = parse_block(p)
|
||||
let body = r2["stmts"]
|
||||
let p = r2["pos"]
|
||||
return make_result({ "stmt": "While", "cond": cond, "body": body }, p)
|
||||
@@ -700,13 +704,13 @@ fn parse_stmt(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
// for loop
|
||||
if k == "For" {
|
||||
let p = pos + 1
|
||||
let item_name = tok_value(tokens, p)
|
||||
let item_name = tok_value(p)
|
||||
let p = p + 1
|
||||
let p = expect(tokens, p, "In")
|
||||
let r = parse_expr(tokens, p)
|
||||
let p = expect(p, "In")
|
||||
let r = parse_expr(p)
|
||||
let list_expr = r["node"]
|
||||
let p = r["pos"]
|
||||
let r2 = parse_block(tokens, p)
|
||||
let r2 = parse_block(p)
|
||||
let body = r2["stmts"]
|
||||
let p = r2["pos"]
|
||||
return make_result({ "stmt": "For", "item": item_name, "list": list_expr, "body": body }, p)
|
||||
@@ -717,11 +721,11 @@ fn parse_stmt(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
let p = pos + 1
|
||||
// skip decorator name
|
||||
let p = p + 1
|
||||
return parse_stmt(tokens, p)
|
||||
return parse_stmt(p)
|
||||
}
|
||||
|
||||
// bare expression or if/match statement
|
||||
let r = parse_expr(tokens, pos)
|
||||
let r = parse_expr(pos)
|
||||
let val = r["node"]
|
||||
let p = r["pos"]
|
||||
make_result({ "stmt": "Expr", "value": val }, p)
|
||||
@@ -730,7 +734,9 @@ fn parse_stmt(tokens: [Map<String, Any>], pos: Int) -> Map<String, Any> {
|
||||
// ── Top-level parse ────────────────────────────────────────────────────────────
|
||||
|
||||
fn parse(tokens: [Map<String, Any>]) -> [Map<String, Any>] {
|
||||
let total: Int = native_list_len(tokens)
|
||||
// Store tokens in global buffer to avoid O(n²) cloning on every recursive call.
|
||||
native_tokens_init(tokens)
|
||||
let total: Int = native_token_len()
|
||||
let stmts: [Map<String, Any>] = native_list_empty()
|
||||
let pos: Int = 0
|
||||
let running = true
|
||||
@@ -738,11 +744,11 @@ fn parse(tokens: [Map<String, Any>]) -> [Map<String, Any>] {
|
||||
if pos >= total {
|
||||
let running = false
|
||||
} else {
|
||||
let k = tok_kind(tokens, pos)
|
||||
let k = tok_kind(pos)
|
||||
if k == "Eof" {
|
||||
let running = false
|
||||
} else {
|
||||
let r = parse_stmt(tokens, pos)
|
||||
let r = parse_stmt(pos)
|
||||
let stmt = r["node"]
|
||||
let new_pos: Int = r["pos"]
|
||||
let stmts = native_list_append(stmts, stmt)
|
||||
|
||||
Reference in New Issue
Block a user