From dad97a25a538a53d27b037e0d7ad03d93a5fbff0 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Tue, 27 Feb 2018 21:27:29 -0500 Subject: [PATCH] If statements work with the addition of jmp and jnz --- stdlib/bytecode_generator.krak | 49 +++++++++++++++++++++++++++++++--- stdlib/type.krak | 6 +++++ 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/stdlib/bytecode_generator.krak b/stdlib/bytecode_generator.krak index 7317437..79eb356 100644 --- a/stdlib/bytecode_generator.krak +++ b/stdlib/bytecode_generator.krak @@ -78,6 +78,8 @@ adt byte_inst { add: add, ldr: ldr, str: str, + jmp: jmp, + jnz: jnz, call, ret } @@ -100,6 +102,13 @@ obj str { var offset: 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 { 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::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::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::ret() return string("ret") } @@ -164,8 +175,9 @@ obj bytecode_function (Object) { res += "\t\t" + n->identifier.name + ": r0 + " + o }) res += "\n\t bytecode\n" + var pc = 0 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 } @@ -277,10 +289,19 @@ obj bytecode_generator (Object) { return -1 } 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) - 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) + 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 } fun generate_while_loop(node: *ast_node): int { @@ -325,7 +346,10 @@ obj bytecode_generator (Object) { return generate(node->cast.value) } fun generate_value(node: *ast_node): int { - return emit_imm(string_to_num(node->value.string_value)) + if (node->value.value_type->is_bool()) + return emit_imm((node->value.string_value == "true") cast int) + else + return emit_imm(string_to_num(node->value.string_value)) } fun generate_code_block(node: *ast_node): int { node->code_block.children.for_each(fun(child: *ast_node) { @@ -410,6 +434,19 @@ obj bytecode_generator (Object) { functions.last().instructions.add(byte_inst::str(s)) 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 { functions.last().instructions.add(byte_inst::ret()) return -1 @@ -429,12 +466,16 @@ obj bytecode_generator (Object) { stack_mem.size = 10 stack_mem.for_each(fun(i: ref int) { i = 0; }) 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]) { byte_inst::nop() {} 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::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::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::ret() return stack_mem[registers[0]]*/ byte_inst::ret() { diff --git a/stdlib/type.krak b/stdlib/type.krak index 729f2fe..f3d2ae9 100644 --- a/stdlib/type.krak +++ b/stdlib/type.krak @@ -231,6 +231,12 @@ obj type (Object) { } return false } + fun is_bool(): bool { + match (base) { + base_type::boolean() return true + } + return false + } fun is_function(): bool { match (base) { base_type::function() return true