Instead of using closure function, now I use a interface to organize the generated instructions.
type inst interface {
Exec(ctx *ControlFlow, ebp, esp)
}
There will be many instances like localRefInst, globalRefInst, ifInst, doInst, makeClosureInst etc.
The root of the insts forms a tree.
The benefit of this representation is that in the future, it's easier to do code generation based on the instruction tree.
Just add a GenGoCode() method to the interface should work.
Calling convention: an inst should set the ctx.pc to nil to indicate it's done. Or set ctx.pc to non-nil to indicate there are more works... and the calling of the inst should be in a loop to handle tail-recursive
Manually inline the run function like this:
for ctx.pc = inst; ctx.pc != nil; {
ctx.pc.Exec(...)
}
Instead of using closure function, now I use a interface to organize the generated instructions.
There will be many instances like
localRefInst
,globalRefInst
,ifInst
,doInst
,makeClosureInst
etc. The root of the insts forms a tree.The benefit of this representation is that in the future, it's easier to do code generation based on the instruction tree. Just add a
GenGoCode()
method to the interface should work.Calling convention: an inst should set the
ctx.pc
to nil to indicate it's done. Or setctx.pc
to non-nil to indicate there are more works... and the calling of the inst should be in a loop to handle tail-recursiveManually inline the run function like this: