diff --git a/src/objects.cr b/src/objects.cr index aec05b2..4e22b60 100644 --- a/src/objects.cr +++ b/src/objects.cr @@ -53,23 +53,11 @@ module Objects abstract def inspect : String def if_not_error(& : MObject -> MObject?) : MObject? - case self - when MError - return self - else - return yield self - end + yield self end def is_truthy? : Bool - case self - when MBoolean - return self.value - when MNull - return false - else - return true - end + true end end @@ -149,6 +137,10 @@ module Objects def initialize(@message : String) end + def if_not_error(& : MObject -> MObject?) : MObject? + self + end + def inspect : String return "ERROR: #{@message}" end @@ -162,20 +154,23 @@ module Objects def inspect : String return "null" end + + def is_truthy? : Bool + false + end end class MBoolean < MValue(Bool) def hash_type : HashType - return HashType::Boolean + HashType::Boolean + end + + def same?(other : self) + other.value == @value end def same?(other) - case other - when MBoolean - return other.value == @value - else - return false - end + false end # def object_id @@ -185,6 +180,10 @@ module Objects def hash_key : HashKey return HashKey.new(hash_type, (@value ? 1 : 0).to_u64) end + + def is_truthy? : Bool + value + end end class MString < MValue(String) diff --git a/src/vm.cr b/src/vm.cr index 3a0c6bf..58099a4 100644 --- a/src/vm.cr +++ b/src/vm.cr @@ -4,7 +4,7 @@ require "./objects" macro execute_build_and_push(col) num_elements = Code.read_int(ins, ip + 1) - current_frame.ip += 2 + current_frame.ip &+= 2 {{col}} = build_{{col}}(@sp - num_elements, @sp) @sp -= num_elements push({{col}}) @@ -41,6 +41,9 @@ module Vm @frames = Array(Vm::Frame?).new(MAX_FRAME_SIZE) { nil } @frame_index = 1 @globals = [] of MObject + private getter current_frame : Frame do + @frames[@frame_index - 1].not_nil! + end def initialize(@bytecode : Bytecode) @constants = @bytecode.constants @@ -60,14 +63,14 @@ module Vm ins : Instructions op : Opcode while current_frame.ip < current_frame.instructions.size - 1 - current_frame.ip += 1 + current_frame.ip &+= 1 ip = current_frame.ip ins = current_frame.instructions op = Opcode.new(ins[ip].to_i) case op when Opcode::OpConstant const_index = Code.read_int(ins, ip + 1) - current_frame.ip += 2 + current_frame.ip &+= 2 push(@constants[const_index]) when Opcode::OpPop pop @@ -85,7 +88,7 @@ module Vm execute_bang_operator when Opcode::OpJumpNotTruthy pos = Code.read_int(ins, ip + 1) - current_frame.ip += 2 + current_frame.ip &+= 2 condition = pop if !condition.is_truthy? current_frame.ip = pos - 1 @@ -97,7 +100,7 @@ module Vm current_frame.ip = pos - 1 when Opcode::OpSetGlobal global_index = Code.read_int(ins, ip + 1) - current_frame.ip += 2 + current_frame.ip &+= 2 if global_index == @globals.size @globals << pop.not_nil! else @@ -105,7 +108,7 @@ module Vm end when Opcode::OpGetGlobal global_index = Code.read_int(ins, ip + 1) - current_frame.ip += 2 + current_frame.ip &+= 2 push(@globals[global_index]) when Opcode::OpArray execute_build_and_push array @@ -118,11 +121,11 @@ module Vm when Opcode::OpClosure const_index = Code.read_int(ins, ip + 1) num_free = Code.read_byte(ins, ip + 3) - current_frame.ip += 3 + current_frame.ip &+= 3 push_closure(const_index, num_free.to_i) when Opcode::OpCall num_args = Code.read_byte(ins, ip + 1) - current_frame.ip += 1 + current_frame.ip &+= 1 execute_call(num_args.to_i) when Opcode::OpReturnValue return_value = pop @@ -135,21 +138,21 @@ module Vm push(VM_NULL) when Opcode::OpSetLocal local_index = Code.read_byte(ins, ip + 1) - current_frame.ip += 1 + current_frame.ip &+= 1 frame = current_frame @stack[frame.base_pointer + local_index.to_i] = pop when Opcode::OpGetLocal local_index = Code.read_byte(ins, ip + 1) - current_frame.ip += 1 + current_frame.ip &+= 1 frame = current_frame push(@stack[frame.base_pointer + local_index.to_i].not_nil!) when Opcode::OpGetBuiltin built_index = Code.read_byte(ins, ip + 1) - current_frame.ip += 1 + current_frame.ip &+= 1 push(Objects::BUILTINS[built_index.to_i][1]) when Opcode::OpGetFree free_index = Code.read_byte(ins, ip + 1) - current_frame.ip += 1 + current_frame.ip &+= 1 current_closure = current_frame.cl push(current_closure.free[free_index.to_i]) when Opcode::OpCurrentClosure @@ -164,16 +167,12 @@ module Vm return @stack[@sp]? end - private def current_frame : Vm::Frame - return @frames[@frame_index - 1].not_nil! - end - private def push(obj : MObject) if @sp > STACK_SIZE raise VMException.new("stack overflow") end @stack[@sp] = obj - @sp += 1 + @sp &+= 1 end private def pop : MObject? @@ -282,7 +281,7 @@ module Vm i = start_index while i < end_index elements[i - start_index] = @stack[i] - i += 1 + i &+= 1 end return MArray.new(elements) end @@ -385,12 +384,14 @@ module Vm private def push_frame(frame : Frame) @frames[@frame_index] = frame - @frame_index += 1 + @current_frame = nil + @frame_index &+= 1 end private def pop_frame : Frame @frame_index -= 1 - return @frames[@frame_index].not_nil! + @current_frame = nil + @frames[@frame_index].not_nil! end end