I decompile a method in three phases:
Reverser: postfix byte codes -> prefix symbolic codes (nodes and atoms)
Parser: prefix symbolic codes -> node tree (same as the compiler)
Printer: node tree -> text (done by the nodes)
Decompile the method from pc up to end and return an array of
expressions. If at run time this block will leave a value on the stack,
set hasValue to true. If the block ends with a jump or return, set exit
to the destination of the jump, or the end of the method; otherwise, set
exit = end. Leave pc = end.
Note that stack initially contains a CaseFlag which will be removed by
a subsequent Pop instruction, so adjust the StackPos accordingly.
Decompile the method from pc up to end and return an array of
expressions. If at run time this block will leave a value on the stack,
set hasValue to true. If the block ends with a jump or return, set exit
to the destination of the jump, or the end of the method; otherwise, set
exit = end. Leave pc = end.
If statements contains the pattern
var _ startExpr.
[var <= limit] whileTrue: [...statements... var _ var + incConst]
then replace this by
startExpr to: limit by: incConst do: [:var | ...statements...]
Answer a MethodNode that is the root of the parse tree for the
argument, aMethod, which is the CompiledMethod associated with the
message, aSelector. Variables are determined with respect to the
argument, aClass.