diff --git a/lib/ast/README.md b/lib/ast/README.md new file mode 100644 index 00000000..5ca3b81b --- /dev/null +++ b/lib/ast/README.md @@ -0,0 +1,63 @@ +### Ast + +The Ast (abstract syntax tree) is created by kide-reader gem and the classes defined there + +### Compiling + +The code in this directory compiles the AST to the virtual machine code. + +If this were an intrepreter, we would just walk the tree and do what it says. Since it's not things are a little more +difficult, especially in time. + +When compiling we deal with two times, compile-time and run-time. All the headache comes from mixing those two up.* + +Similarly, the result of compiling is two-fold: a static and a dynamic part. + +- the static part are objects like the constants, but also defined classes and their methods +- the dynamic part is the code, which is stored as streams of instructions in the MethodDefinition + +Too make things a little simpler, we create a very high level instruction stream at first and then run +transformation and optimisation passes on the stream to improve it. + +Each ast class gets a compile method that does the compilation. + +#### Method Definition and Instructions + +The first argument to the compile method is the MethodDefinition. All code is encoded as a stream of Instructions in the +MethodDefinition. In fact Instructions are a linked list and so the MethodDefinition only hold the head, and the current +insertion point. + +Code is added to the method (using add()), rather than working with the actual instructions. This is so each compile method +can just do it's bit and be unaware of the larger structure that is being created. The genearal structure of the instructions +is a graph (what with if's and whiles and breaks and what), but we build it to have one start and *one* end (return). + + +#### Messages and frames + +The virtual machine instructions obviously operate on the virtual machine. Since the machine is virtual, we have to define +it, and since it is oo we define it in objects. + +Also it is important to define how instructions, which is is in a ohysical machine by changing the contents of registers or +some stack. + +Our machine is ot a register machine, but an object machine: it operates directly on objects and also has no stack. + +When a Method needs to make a call, or send a message, it creates a Message object. Messages contain return addresses and +arguemnts. + +Then the machine must find the method to call. + +Then a new Method receives the message, creates a Frame for local and temporary variables and continues execution. + +The important thing here is that Messages and Frames are normal objects. + +Anf interestingly we can partly use ruby to find the method, so in a way it is not just a top down transformation. but +the sending goes back up and then down again. + +The Message object is the second parameter to the compile method, the run-time part as it were. + + +* +As ruby is a dynamic language, it also compiles at run-time. This line of thought does not help though as it sort of mixes +the seperate times up, even they are not. Even in a running ruby programm the stages of compile and run are seperate. +Similarly it does not help to argue that the code is static too, not dynamic, as that leaves us with a worse working model. \ No newline at end of file diff --git a/lib/ast/call_site_expression.rb b/lib/ast/call_site_expression.rb index 046e70ae..42aaec35 100644 --- a/lib/ast/call_site_expression.rb +++ b/lib/ast/call_site_expression.rb @@ -3,7 +3,7 @@ module Ast class CallSiteExpression < Expression # attr_reader :name, :args , :receiver - @@counter = 0 + def compile method , message me = receiver.compile( method, message ) with = args.collect{|a| a.compile( method,message)} diff --git a/lib/virtual/machine.rb b/lib/virtual/machine.rb index d2bd98a9..4c26dea3 100644 --- a/lib/virtual/machine.rb +++ b/lib/virtual/machine.rb @@ -11,7 +11,7 @@ module Virtual # - low level means it's basic instructions are realively easily implemented in a register machine. ie send is not # a an instruction but a function. # - # So the memory model of the machine allows for indexed access into and "object" . A fixed number of objects exist + # So the memory model of the machine allows for indexed access into an "object" . A fixed number of objects exist # (ie garbage collection is reclaming, not destroying and recreating) although there may be a way to increase that number. # # The ast is transformed to virtaul-machine objects, some of which represent code, some data. @@ -19,12 +19,12 @@ module Virtual # The next step transforms to the register machine layer, which is what actually executes. # - # More concretely, an virtual machine is a sort of oo turing machine, it has a current instruction, executes the + # More concretely, a virtual machine is a sort of oo turing machine, it has a current instruction, executes the # instructions, fetches the next one and so on. # Off course the instructions are not soo simple, but in oo terms quite so. # - # The machine is virtual in the sense that it is completely - # modeled in software, it's complete state explicitly available (not implicitly by walking stacks or something) + # The machine is virtual in the sense that it is completely modeled in software, + # it's complete state explicitly available (not implicitly by walking stacks or something) # The machine has a no register, but local variables, a scope at each point in time. # Scope changes with calls and blocks, but is saved at each level. In terms of lower level implementation this means @@ -34,9 +34,9 @@ module Virtual def initialize the_end = Halt.new - @frame = Message.new(the_end , the_end , :Object) + @message = Message.new(the_end , the_end , :Object) end - attr_reader :frame + attr_reader :message # run the instruction stream given. Instructions are a graph and executing means traversing it. # If there is no next instruction the machine stops diff --git a/test/virtual/virtual_helper.rb b/test/virtual/virtual_helper.rb index 5d529efa..9de786b9 100644 --- a/test/virtual/virtual_helper.rb +++ b/test/virtual/virtual_helper.rb @@ -13,7 +13,7 @@ module VirtualHelper parts = Parser::Transform.new.apply(syntax) machine = Virtual::Machine.new main = Virtual::MethodDefinition.main - expressions = parts.compile( main, machine.frame ) + expressions = parts.compile( main, machine.message ) should = YAML.load(@output.gsub("RETURN_MARKER" , "\n")) assert_equal should , expressions , expressions.to_yaml.gsub("\n" , "RETURN_MARKER") + "\n" + expressions.to_yaml end