diff --git a/2015-05-20-expression_is_slot.md b/2015-05-20-expression_is_slot.md new file mode 100644 index 0000000..6638450 --- /dev/null +++ b/2015-05-20-expression_is_slot.md @@ -0,0 +1,77 @@ +--- +layout: site +author: Torsten +--- + +Since i got the ideas of Slots and the associated instruction Set, i have been wondering how that +fits in with the code generation. + +I moved the patched AST compiler methods to a Compiler, ok. But still what do all those compile +methods return. + +## Expression + +In ruby, everything is an expression. To recap "Expressions have a value, while statements do not", +or statements represent actions while expressions represent values. + +So in ruby everything represents a value, also statements, or functions. There is no such thing +as the return void in C. Even loops and ifs result in a value, for a loop the last computed value +and for an if the value of the branch taken. + +Having had a vague grasp of this concept i tried to sort of haphazardly return the kind of value +that i though appropriate. Sometimes literals, sometimes slots. Sometimes "Return" , a slot +representing the return value of a function. + +## Return slot + +Today i realized that the Slot representing the return value is special. + +It does not hold the value that is returned, but rather the other way around. + +A function returns what is in the Return slot, at the time of return. + +From there it is easy to see that it must be the Return that holds the last computed value. +A function can return at any time after all. + +The last computed value is the Expression that is currently evaluated. So the compile, which +initiates the evaluation, returns the Return slot. Always. Easy, simple, nice! + +## Example + +Constants: say the expression + + true + +would compile to a + + ConstantLoad(ReturnSlot , TrueConstant) + +While + + 2 + 4 + +would compile to + + ConstantLoad(ReturnSlot , IntegerConstant(2)) + Set(ReturnSlot , OtherSlot) + ConstantLoad(ReturnSlot , IntegerConstant(4)) + Set(ReturnSlot , EvenOtherSlot) + MethodCall() # unspecified details here + + +## Optimisations + +But but but i hear that is so totally inefficient. All the time we move data around, to and from +that one Return slot, just so that the return is simple. Yes but no. + +It is very easy to optimize the trivial extra away. Many times the expression moves a value to Return +just to move it away in the next Instruction. A sequence like in above example + + ConstantLoad(ReturnSlot , IntegerConstant(2)) + Set(ReturnSlot , OtherSlot) + +can easily be optimized into + + ConstantLoad(OtherSlot , IntegerConstant(2)) + +tbc diff --git a/2015-06-20-closing-the-chasm.md b/2015-06-20-closing-the-chasm.md new file mode 100644 index 0000000..601086e --- /dev/null +++ b/2015-06-20-closing-the-chasm.md @@ -0,0 +1,43 @@ +--- +layout: site +author: Torsten +--- + +As noted in previous posts, differentiating between compile- and run-time is one of the more +difficult things in doing the vm. That is because the computing that needs to happen is so similar, +in other words almost all of the vm - level is available at run-time too. + +But off course we try to do as much as posible at compile-time. + +One hears or reads that exactly this is a topic causing (also) other vms problems. +Specifically how one assures that what is compiled at compile-time and and run-time are +identical or at least compatible. + +The obvious answer seems to me to **use the same code**.In a way that "just" moves the question +around a bit, becuase then one would have to know how to do that. I'll go into that below, +but find that the concept is worth exploring first. + +Let's take a simple example of accessing an instance variable. This is off course available at +run-time through the function *instance_variable_get* , which could go something like: + + def instance_variable_get name + index = @layout.index name + return nil unless index + at_index(index) + end + +Let's assume the *builtin* at_index function and take the layout to be an array like structure. +As noted in previous posts, when this is compiled we get a Method with Blocks, and exactly one +Block will initiate the return. The previous post detailed how at that time the return value will +be in the ReturnSlot. + +So then we get to the idea of how: We "just" need to take the blocks from the method and paste +them where the instance variable is accessed. Following code will pick the value from the ReturnSlot +as it would any other value and continue. + +The only glitch in this plan is that the code will assume a new message and frame. But if we just +paste it it will use message/frame/self from the enclosing method. So that is where the work is: +translating slots from the inner, inlined fuction to the outer one. Possibly creating new frame +entries. + +tbc