From 9b5c3b795e9f980d2db400107eef5860a8e15761 Mon Sep 17 00:00:00 2001 From: Sami Samhuri Date: Sun, 14 Feb 2010 23:15:38 -0800 Subject: [PATCH] implement lazy boolean OR and AND operators, || and && respectively --- compiler.rb | 72 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 24 deletions(-) diff --git a/compiler.rb b/compiler.rb index a9916a4..5f4b9b5 100644 --- a/compiler.rb +++ b/compiler.rb @@ -264,39 +264,63 @@ class Compiler # boolean expressions # ####################### - def op(name) - asm.push(EAX) - expected(name) unless match_word(name) - yield - asm.add(ESP, 4) - end - def boolean_expression boolean_term while @look == '|' - op '||' do - boolean_term - # !!! this method has moved, IMPLEMENT THIS! - emit("") - end + scan + expected('||') unless match_word('||') + + false_label = asm.mklabel(:false) + truthy_label = asm.mklabel(:truthy) + done_label = asm.mklabel(:done) + + asm.cmp(EAX, FALSE) + asm.jne(truthy_label) + + boolean_term + asm.cmp(EAX, FALSE) + asm.je(false_label) + + asm.deflabel(truthy_label) + asm.mov(EAX, TRUE) + asm.jmp(done_label) + + asm.deflabel(false_label) + asm.mov(EAX, FALSE) + + asm.deflabel(done_label) end end def boolean_term not_factor while @look == '&' - op '&&' do - not_factor - # !!! this method has moved, IMPLEMENT THIS! - emit("") - end + scan + expected('&&') unless match_word('&&') + false_label = asm.mklabel(:false) + done_label = asm.mklabel(:done) + + asm.cmp(EAX, FALSE) + asm.je(false_label) + + not_factor + asm.cmp(EAX, FALSE) + asm.je(false_label) + + asm.mov(EAX, TRUE) + asm.jmp(done_label) + + asm.deflabel(false_label) + asm.mov(EAX, TRUE) + + asm.deflabel(done_label) end end def boolean_factor if boolean?(@look) if get_boolean == 'true' - asm.mov(EAX, -1) + asm.mov(EAX, TRUE) else asm.xor(EAX, EAX) end @@ -321,9 +345,9 @@ class Compiler # semantically equivalent to !!reg in C or Ruby. def make_boolean(reg=EAX) end_label = asm.mklabel(:endmakebool) - asm.cmp(reg, 0) # if false do nothing + asm.cmp(reg, FALSE) # if false do nothing asm.jz(end_label) - asm.mov(reg, -1) # truthy, make it true + asm.mov(reg, TRUE) # truthy, make it true asm.deflabel(end_label) end @@ -389,13 +413,13 @@ class Compiler asm.cmp(a, b) asm.jl(true_label) - asm.xor(EAX, EAX) # return false - asm.not_(EAX) if invert # (or true if inverted) + asm.mov(EAX, FALSE) # return false + asm.not_(EAX) if invert # (or true if inverted) asm.jmp(end_label) asm.deflabel(true_label) - asm.xor(EAX, EAX) # return true - asm.not_(EAX) unless invert # (or false if inverted) + asm.mov(EAX, FALSE) # return true + asm.not_(EAX) unless invert # (or false if inverted) asm.deflabel(end_label) end