diff --git a/lib/slot_language/README.md b/lib/slot_language/README.md index ff514b2d..966806e6 100644 --- a/lib/slot_language/README.md +++ b/lib/slot_language/README.md @@ -10,11 +10,11 @@ The Problem with the current way is that some of the slot_machine instruction ar really quite complex. They are really more function than instructions. This is especially true for everything around the dynamic call. Dynamic call itself -is still or, but resolve_method is too much. And it even uses method_missing, another +is still ok, but resolve_method is too much. And it even uses method_missing, another instruction that is too much, which in turn should use raise and now we really see the point. -I though about making those "super" instruction real methods and just calling them, +I thought about making those "super" instruction real methods and just calling them, but the calling overhead is just too much, and really it is the wrong tool for the job. Calling implies switching of context, while resolve_method and raise and mm really all operate on the same context. @@ -23,7 +23,7 @@ really all operate on the same context. The Slot Machine is a kind of memory based, oo abstraction of the risc machine, that in turn mirrors a cpu relatively closely. The machine "knows" the message in the way a -cpu knows it's registers. And the oo part means it also knows the parfait object +cpu knows its registers. And the oo part means it also knows the parfait object model. While Ruby/Sol code only ever assumes the type of self, the Slot Machine assumes types @@ -41,10 +41,15 @@ the message. ## Syntax (projection) -Since we are not defining methods, etc, there is no scope. In other words the only -"scope" is the current message and global constants. This also means we will -use the file scope, ie one file defines one instruction, by convention of the -same name. +Since we are not defining methods, there is no seperate scope. We create objects that +will transform to SlotMachine Instructions _in_ the scope of the current method. +In other words they will have access to the compiler and the callable, when transforming +to SlotMachine (similar to Sol in that way). This means at compile time we have +can use the frame type and constants, while we can always assume the Message (and not +much else) at runtime. + +As the scope is "fixed", we will use the file scope, ie one file defines one +instruction/macro, by convention of the same name. For starters we will use ruby syntax, with these semantics: - only globals and message (the literal) are valid variable names diff --git a/lib/slot_language/check_maker.rb b/lib/slot_language/check_maker.rb new file mode 100644 index 00000000..734a1774 --- /dev/null +++ b/lib/slot_language/check_maker.rb @@ -0,0 +1,14 @@ +module SlotLanguage + class CheckMaker + attr_reader :check , :left , :right, :goto + + def initialize(check , left , right) + @check = check + @left = left + @right = right + end + def set_goto(go) + @goto = go + end + end +end diff --git a/lib/slot_language/slot_compiler.rb b/lib/slot_language/slot_compiler.rb index bb7e3b20..a2788d9b 100644 --- a/lib/slot_language/slot_compiler.rb +++ b/lib/slot_language/slot_compiler.rb @@ -16,19 +16,27 @@ module SlotLanguage not_implemented(node) end def on_send(statement) - #puts statement kids = statement.children.dup receiver = process(kids.shift) || MessageSlot.new name = kids.shift return label(name) if(name.to_s.end_with?("_label")) + return goto(name,kids) if(name == :goto) + return check(name,receiver, kids) if(name == :==) SlotMaker.new( name , receiver ) end def on_lvasgn expression - #puts expression name = expression.children[0] value = process(expression.children[1]) Sol::LocalAssignment.new(name,value) end + def on_if(expression) + condition = process(expression.children[0]) + condition.set_goto( process(expression.children[1]) ) + condition + end + def on_begin(exp) + process(exp.first) + end def on_ivar expression Sol::InstanceVariable.new(instance_name(expression.children.first)) end @@ -40,8 +48,21 @@ module SlotLanguage def label(name) SlotMachine::Label.new(name.to_s , name) end + def goto(name , args) + # error handling would not hurt + label = process(args.first) + SlotMachine::Jump.new( label ) + end + def check(name , receiver , kids) + raise "Only ==, not #{name}" unless name == :== + raise "Familiy too large #{kids}" if kids.length > 1 + puts "Kids " + kids.to_s + right = process(kids.first) + CheckMaker.new(name , receiver , right) + end end end require_relative "named_slot" require_relative "message_slot" require_relative "slot_maker" +require_relative "check_maker" diff --git a/test/slot_language/helper.rb b/test/slot_language/helper.rb index ea82ec10..82ebe3b9 100644 --- a/test/slot_language/helper.rb +++ b/test/slot_language/helper.rb @@ -6,7 +6,7 @@ module SlotLanguage SlotCompiler.compile(input) end def compile_class(input) - compile.class + compile(input).class end end end diff --git a/test/slot_language/test_slot_compiler.rb b/test/slot_language/test_slot_compiler.rb index ce741a3d..d3b2715c 100644 --- a/test/slot_language/test_slot_compiler.rb +++ b/test/slot_language/test_slot_compiler.rb @@ -19,7 +19,15 @@ module SlotLanguage assert_equal :while_label , label.name end def test_slot_load - compile("a = @b") + assert_equal Sol::LocalAssignment , compile_class("a = @b") + end + def test_goto + assert_equal SlotMachine::Jump , compile_class("goto(exit_label)") + end + def test_if + check = compile("goto(exit_label) if(a == b)") + assert_equal CheckMaker , check.class + assert_equal SlotMachine::Jump , check.goto.class end end end