If statements work with the addition of jmp and jnz
This commit is contained in:
@@ -78,6 +78,8 @@ adt byte_inst {
|
|||||||
add: add,
|
add: add,
|
||||||
ldr: ldr,
|
ldr: ldr,
|
||||||
str: str,
|
str: str,
|
||||||
|
jmp: jmp,
|
||||||
|
jnz: jnz,
|
||||||
call,
|
call,
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
@@ -100,6 +102,13 @@ obj str {
|
|||||||
var offset: int
|
var offset: int
|
||||||
var from_reg: int
|
var from_reg: int
|
||||||
}
|
}
|
||||||
|
obj jmp {
|
||||||
|
var offset: int
|
||||||
|
}
|
||||||
|
obj jnz {
|
||||||
|
var reg: int
|
||||||
|
var offset: int
|
||||||
|
}
|
||||||
|
|
||||||
fun to_string(b: byte_inst): string {
|
fun to_string(b: byte_inst): string {
|
||||||
match (b) {
|
match (b) {
|
||||||
@@ -108,6 +117,8 @@ fun to_string(b: byte_inst): string {
|
|||||||
byte_inst::add(a) return string("r") + a.to_reg + " = r" + a.a + " + r" + a.b
|
byte_inst::add(a) return string("r") + a.to_reg + " = r" + a.a + " + r" + a.b
|
||||||
byte_inst::ldr(l) return string("r") + l.to_reg + " = ldr r" + l.from_reg + " (" + l.offset + ")"
|
byte_inst::ldr(l) return string("r") + l.to_reg + " = ldr r" + l.from_reg + " (" + l.offset + ")"
|
||||||
byte_inst::str(s) return string("str(r") + s.to_reg + "(" + s.offset + ") <= r" + s.from_reg + ")"
|
byte_inst::str(s) return string("str(r") + s.to_reg + "(" + s.offset + ") <= r" + s.from_reg + ")"
|
||||||
|
byte_inst::jmp(j) return string("jmp(pc += ") + j.offset + ")"
|
||||||
|
byte_inst::jnz(j) return string("jmp(r") + j.reg + " != 0, pc += " + j.offset + ")"
|
||||||
byte_inst::call() return string("call")
|
byte_inst::call() return string("call")
|
||||||
byte_inst::ret() return string("ret")
|
byte_inst::ret() return string("ret")
|
||||||
}
|
}
|
||||||
@@ -164,8 +175,9 @@ obj bytecode_function (Object) {
|
|||||||
res += "\t\t" + n->identifier.name + ": r0 + " + o
|
res += "\t\t" + n->identifier.name + ": r0 + " + o
|
||||||
})
|
})
|
||||||
res += "\n\t bytecode\n"
|
res += "\n\t bytecode\n"
|
||||||
|
var pc = 0
|
||||||
instructions.for_each(fun(b: byte_inst) {
|
instructions.for_each(fun(b: byte_inst) {
|
||||||
res += "\t\t" + to_string(b) + "\n"
|
res += string("\t\t") + pc++ + string(": ") + to_string(b) + "\n"
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
@@ -277,10 +289,19 @@ obj bytecode_generator (Object) {
|
|||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
fun generate_if_statement(node: *ast_node): int {
|
fun generate_if_statement(node: *ast_node): int {
|
||||||
generate(node->if_statement.condition)
|
var cond_reg = generate(node->if_statement.condition)
|
||||||
|
var jnz_index = functions.last().instructions.size
|
||||||
|
emit_jnz(cond_reg,0)
|
||||||
generate(node->if_statement.then_part)
|
generate(node->if_statement.then_part)
|
||||||
if (node->if_statement.else_part)
|
if (node->if_statement.else_part) {
|
||||||
|
var jmp_index = functions.last().instructions.size
|
||||||
|
emit_jmp(0)
|
||||||
|
functions.last().instructions[jnz_index].jnz.offset = functions.last().instructions.size - jnz_index
|
||||||
generate(node->if_statement.else_part)
|
generate(node->if_statement.else_part)
|
||||||
|
functions.last().instructions[jmp_index].jmp.offset = functions.last().instructions.size - jmp_index
|
||||||
|
} else {
|
||||||
|
functions.last().instructions[jnz_index].jnz.offset = functions.last().instructions.size - jnz_index
|
||||||
|
}
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
fun generate_while_loop(node: *ast_node): int {
|
fun generate_while_loop(node: *ast_node): int {
|
||||||
@@ -325,6 +346,9 @@ obj bytecode_generator (Object) {
|
|||||||
return generate(node->cast.value)
|
return generate(node->cast.value)
|
||||||
}
|
}
|
||||||
fun generate_value(node: *ast_node): int {
|
fun generate_value(node: *ast_node): int {
|
||||||
|
if (node->value.value_type->is_bool())
|
||||||
|
return emit_imm((node->value.string_value == "true") cast int)
|
||||||
|
else
|
||||||
return emit_imm(string_to_num<int>(node->value.string_value))
|
return emit_imm(string_to_num<int>(node->value.string_value))
|
||||||
}
|
}
|
||||||
fun generate_code_block(node: *ast_node): int {
|
fun generate_code_block(node: *ast_node): int {
|
||||||
@@ -410,6 +434,19 @@ obj bytecode_generator (Object) {
|
|||||||
functions.last().instructions.add(byte_inst::str(s))
|
functions.last().instructions.add(byte_inst::str(s))
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
fun emit_jmp(offset: int): int {
|
||||||
|
var j: jmp
|
||||||
|
j.offset = offset
|
||||||
|
functions.last().instructions.add(byte_inst::jmp(j))
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
fun emit_jnz(reg: int, offset: int): int {
|
||||||
|
var j: jnz
|
||||||
|
j.reg = reg
|
||||||
|
j.offset = offset
|
||||||
|
functions.last().instructions.add(byte_inst::jnz(j))
|
||||||
|
return -1
|
||||||
|
}
|
||||||
fun emit_ret(): int {
|
fun emit_ret(): int {
|
||||||
functions.last().instructions.add(byte_inst::ret())
|
functions.last().instructions.add(byte_inst::ret())
|
||||||
return -1
|
return -1
|
||||||
@@ -429,12 +466,16 @@ obj bytecode_generator (Object) {
|
|||||||
stack_mem.size = 10
|
stack_mem.size = 10
|
||||||
stack_mem.for_each(fun(i: ref int) { i = 0; })
|
stack_mem.for_each(fun(i: ref int) { i = 0; })
|
||||||
for (var i = 0; i < main_entry.instructions.size; i++;) {
|
for (var i = 0; i < main_entry.instructions.size; i++;) {
|
||||||
|
println(string("evaling: ") + i + ": " + to_string(main_entry.instructions[i]))
|
||||||
match(main_entry.instructions[i]) {
|
match(main_entry.instructions[i]) {
|
||||||
byte_inst::nop() {}
|
byte_inst::nop() {}
|
||||||
byte_inst::imm(i) registers[i.reg] = i.val
|
byte_inst::imm(i) registers[i.reg] = i.val
|
||||||
byte_inst::add(a) registers[a.to_reg] = registers[a.a] + registers[a.b]
|
byte_inst::add(a) registers[a.to_reg] = registers[a.a] + registers[a.b]
|
||||||
byte_inst::ldr(l) registers[l.to_reg] = stack_mem[registers[l.from_reg] + l.offset]
|
byte_inst::ldr(l) registers[l.to_reg] = stack_mem[registers[l.from_reg] + l.offset]
|
||||||
byte_inst::str(s) stack_mem[registers[s.to_reg] + s.offset] = registers[s.from_reg]
|
byte_inst::str(s) stack_mem[registers[s.to_reg] + s.offset] = registers[s.from_reg]
|
||||||
|
byte_inst::jmp(j) i += j.offset - 1 // to counteract pc inc
|
||||||
|
byte_inst::jnz(j) if (registers[j.reg] != 0)
|
||||||
|
i += j.offset - 1 // to counteract pc inc
|
||||||
byte_inst::call() error("call")
|
byte_inst::call() error("call")
|
||||||
/*byte_inst::ret() return stack_mem[registers[0]]*/
|
/*byte_inst::ret() return stack_mem[registers[0]]*/
|
||||||
byte_inst::ret() {
|
byte_inst::ret() {
|
||||||
|
|||||||
@@ -231,6 +231,12 @@ obj type (Object) {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
fun is_bool(): bool {
|
||||||
|
match (base) {
|
||||||
|
base_type::boolean() return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
fun is_function(): bool {
|
fun is_function(): bool {
|
||||||
match (base) {
|
match (base) {
|
||||||
base_type::function() return true
|
base_type::function() return true
|
||||||
|
|||||||
Reference in New Issue
Block a user