72 lines
2.6 KiB
Plaintext
72 lines
2.6 KiB
Plaintext
%p
|
|
Since i got the ideas of Slots and the associated instruction Set, i have been wondering how that
|
|
fits in with the code generation.
|
|
%p
|
|
I moved the patched AST compiler methods to a Compiler, ok. But still what do all those compile
|
|
methods return.
|
|
%h2#expression Expression
|
|
%p
|
|
In ruby, everything is an expression. To recap “Expressions have a value, while statements do not”,
|
|
or statements represent actions while expressions represent values.
|
|
%p
|
|
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.
|
|
%p
|
|
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.
|
|
%h2#return-slot Return slot
|
|
%p Today i realized that the Slot representing the return value is special.
|
|
%p It does not hold the value that is returned, but rather the other way around.
|
|
%p A function returns what is in the Return slot, at the time of return.
|
|
%p
|
|
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.
|
|
%p
|
|
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!
|
|
%h2#example Example
|
|
%p Constants: say the expression
|
|
%pre
|
|
%code
|
|
:preserve
|
|
true
|
|
%p would compile to a
|
|
%pre
|
|
%code
|
|
:preserve
|
|
ConstantLoad(ReturnSlot , TrueConstant)
|
|
%p While
|
|
%pre
|
|
%code
|
|
:preserve
|
|
2 + 4
|
|
%p would compile to
|
|
%pre
|
|
%code
|
|
:preserve
|
|
ConstantLoad(ReturnSlot , IntegerConstant(2))
|
|
Set(ReturnSlot , OtherSlot)
|
|
ConstantLoad(ReturnSlot , IntegerConstant(4))
|
|
Set(ReturnSlot , EvenOtherSlot)
|
|
MethodCall() # unspecified details here
|
|
%h2#optimisations Optimisations
|
|
%p
|
|
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.
|
|
%p
|
|
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
|
|
%pre
|
|
%code
|
|
:preserve
|
|
ConstantLoad(ReturnSlot , IntegerConstant(2))
|
|
Set(ReturnSlot , OtherSlot)
|
|
%p can easily be optimized into
|
|
%pre
|
|
%code
|
|
:preserve
|
|
ConstantLoad(OtherSlot , IntegerConstant(2))
|
|
%p tbc
|