mirror of
https://github.com/bearlanguageorg/bear.git
synced 2026-08-26 15:37:18 +00:00
Loops
This commit is contained in:
@@ -41,6 +41,11 @@ const op_print = u8(28)
|
||||
const op_println = u8(29)
|
||||
const op_assert = u8(30)
|
||||
const op_enter = u8(31)
|
||||
const op_mkarray = u8(32)
|
||||
const op_aget = u8(33)
|
||||
const op_aset = u8(34)
|
||||
const op_alen = u8(35)
|
||||
const op_apush = u8(36)
|
||||
|
||||
// compile parses and compiles VuurRaaf source into an object file.
|
||||
pub fn compile(src string) !obj.Obj {
|
||||
@@ -151,6 +156,12 @@ fn (mut g Gen) gen_stmt(st Stmt) ! {
|
||||
g.code << op_store
|
||||
g.code << obj.encode_i64(i64(idx))
|
||||
}
|
||||
.index_assign {
|
||||
g.gen_expr(st.base)!
|
||||
g.gen_expr(st.idx)!
|
||||
g.gen_expr(st.expr)!
|
||||
g.code << op_aset
|
||||
}
|
||||
.if_stmt {
|
||||
else_l := g.new_label()
|
||||
end_l := g.new_label()
|
||||
@@ -186,6 +197,87 @@ fn (mut g Gen) gen_stmt(st Stmt) ! {
|
||||
g.fixups << Fixup{ name: loop_l, off: u32(g.code.len) - 8 }
|
||||
g.emit_label(end_l)
|
||||
}
|
||||
.for_range_stmt {
|
||||
// for i in a..b / for i in a...b → i := a; while i <(<=) b { body; i++ }
|
||||
var_idx := g.new_local()
|
||||
bound_idx := g.new_local()
|
||||
loop_l := g.new_label()
|
||||
end_l := g.new_label()
|
||||
g.gen_expr(st.expr)!
|
||||
g.gen_expr(st.cond)!
|
||||
g.emit_store(bound_idx)
|
||||
g.emit_store(var_idx)
|
||||
g.emit_label(loop_l)
|
||||
g.emit_load(var_idx)
|
||||
g.emit_load(bound_idx)
|
||||
g.code << if st.inclusive { op_le } else { op_lt }
|
||||
g.code << op_jz
|
||||
g.code << obj.encode_i64(0)
|
||||
g.fixups << Fixup{ name: end_l, off: u32(g.code.len) - 8 }
|
||||
prev := g.locals[st.target] or { -1 }
|
||||
g.locals[st.target] = var_idx
|
||||
for s in st.body {
|
||||
g.gen_stmt(s)!
|
||||
}
|
||||
if prev >= 0 {
|
||||
g.locals[st.target] = prev
|
||||
} else {
|
||||
g.locals.delete(st.target)
|
||||
}
|
||||
g.emit_load(var_idx)
|
||||
g.code << op_push_i
|
||||
g.code << obj.encode_i64(1)
|
||||
g.code << op_add
|
||||
g.emit_store(var_idx)
|
||||
g.code << op_jmp
|
||||
g.code << obj.encode_i64(0)
|
||||
g.fixups << Fixup{ name: loop_l, off: u32(g.code.len) - 8 }
|
||||
g.emit_label(end_l)
|
||||
}
|
||||
.for_in_stmt {
|
||||
// for x in arr → idx := 0; while idx < len(arr) { x := arr[idx]; body; idx++ }
|
||||
arr_idx := g.new_local()
|
||||
idx_idx := g.new_local()
|
||||
elem_idx := g.new_local()
|
||||
loop_l := g.new_label()
|
||||
end_l := g.new_label()
|
||||
g.gen_expr(st.expr)!
|
||||
g.emit_store(arr_idx)
|
||||
g.code << op_push_i
|
||||
g.code << obj.encode_i64(0)
|
||||
g.emit_store(idx_idx)
|
||||
g.emit_label(loop_l)
|
||||
g.emit_load(idx_idx)
|
||||
g.emit_load(arr_idx)
|
||||
g.code << op_alen
|
||||
g.code << op_lt
|
||||
g.code << op_jz
|
||||
g.code << obj.encode_i64(0)
|
||||
g.fixups << Fixup{ name: end_l, off: u32(g.code.len) - 8 }
|
||||
g.emit_load(arr_idx)
|
||||
g.emit_load(idx_idx)
|
||||
g.code << op_aget
|
||||
g.emit_store(elem_idx)
|
||||
prev := g.locals[st.target] or { -1 }
|
||||
g.locals[st.target] = elem_idx
|
||||
for s in st.body {
|
||||
g.gen_stmt(s)!
|
||||
}
|
||||
if prev >= 0 {
|
||||
g.locals[st.target] = prev
|
||||
} else {
|
||||
g.locals.delete(st.target)
|
||||
}
|
||||
g.emit_load(idx_idx)
|
||||
g.code << op_push_i
|
||||
g.code << obj.encode_i64(1)
|
||||
g.code << op_add
|
||||
g.emit_store(idx_idx)
|
||||
g.code << op_jmp
|
||||
g.code << obj.encode_i64(0)
|
||||
g.fixups << Fixup{ name: loop_l, off: u32(g.code.len) - 8 }
|
||||
g.emit_label(end_l)
|
||||
}
|
||||
.ret_stmt {
|
||||
if st.has_val {
|
||||
g.gen_expr(st.expr)!
|
||||
@@ -214,6 +306,18 @@ fn (mut g Gen) gen_expr(e Expr) ! {
|
||||
g.code << obj.encode_i64(0)
|
||||
g.relocs << obj.Reloc{ offset: u32(g.code.len) - 8, name: e.str_v, kind: 1 }
|
||||
}
|
||||
.array_lit {
|
||||
for el in e.elems {
|
||||
g.gen_expr(el)!
|
||||
}
|
||||
g.code << op_mkarray
|
||||
g.code << obj.encode_i64(i64(e.elems.len))
|
||||
}
|
||||
.index {
|
||||
g.gen_expr(*e.left)!
|
||||
g.gen_expr(*e.right)!
|
||||
g.code << op_aget
|
||||
}
|
||||
.bool_lit {
|
||||
g.code << op_push_i
|
||||
g.code << obj.encode_i64(e.int_v)
|
||||
@@ -251,6 +355,23 @@ fn (mut g Gen) gen_call(e Expr) ! {
|
||||
g.code << if e.name == 'print' { op_print } else { op_println }
|
||||
return
|
||||
}
|
||||
if e.name == 'len' {
|
||||
if e.args.len != 1 {
|
||||
return error('len() takes exactly one argument (line ${e.line})')
|
||||
}
|
||||
g.gen_expr(e.args[0])!
|
||||
g.code << op_alen
|
||||
return
|
||||
}
|
||||
if e.name == 'push' {
|
||||
if e.args.len != 2 {
|
||||
return error('push() takes exactly two arguments (line ${e.line})')
|
||||
}
|
||||
g.gen_expr(e.args[0])!
|
||||
g.gen_expr(e.args[1])!
|
||||
g.code << op_apush
|
||||
return
|
||||
}
|
||||
for a in e.args {
|
||||
g.gen_expr(a)!
|
||||
}
|
||||
@@ -340,6 +461,24 @@ fn (mut g Gen) intern(s string) int {
|
||||
return idx
|
||||
}
|
||||
|
||||
fn (mut g Gen) new_local() int {
|
||||
idx := g.local_cnt
|
||||
g.local_cnt++
|
||||
return idx
|
||||
}
|
||||
|
||||
fn (mut g Gen) emit_load(idx int) {
|
||||
g.code << op_load
|
||||
g.code << obj.encode_i64(i64(idx))
|
||||
}
|
||||
|
||||
fn (mut g Gen) emit_store(idx int) {
|
||||
g.code << op_store
|
||||
g.code << obj.encode_i64(i64(idx))
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn (mut g Gen) new_label() string {
|
||||
g.next_lbl++
|
||||
return 'L${g.next_lbl}'
|
||||
|
||||
Reference in New Issue
Block a user