# More Complex Cmd node example with multimethod-style visitor uses Utility/Node class Cmd : Node<> METHODS method is_literal->Logical return false endClass class CmdStatement : Cmd METHODS method init( operand:Cmd ) add( operand ) endClass class CmdPrint : CmdStatement METHODS method name->String: return "Print" endClass class CmdBinary : Cmd METHODS method init( left:Cmd, right:Cmd ) add( left ) add( right ) method symbol->String return "(undefined)" endClass class CmdBinary<<$name,$symbol>> : CmdBinary METHODS method name->String: return $name method symbol->String: return $symbol endClass class CmdAdd : CmdBinary<<"Add","+">>; class CmdSubtract : CmdBinary<<"Subtract","-">>; class CmdInt32( value:Int32 ) : Cmd METHODS method is_literal->Logical return true method name->String return value->String endClass class CPPWriter : NodeVisitor<> PROPERTIES builder = StringBuilder() code : String METHODS method init builder.println @|#include |using namespace std; | |int main() |{ builder.indent += 2 method handle( node:CmdPrint )->Cmd builder.print @|printf( "%d\n", visit( node.first ) builder.println " );" return node method handle( node:CmdBinary )->Cmd builder.print '(' visit( node.first ) builder.print node.symbol visit( node.last ) builder.print ')' return node method on( node:CmdInt32 ) builder.print node.value method to->String if (code is null) builder.indent -= 2 builder.println " return 0;" builder.println "}" code = builder->String endIf return code endClass local op = CmdPrint( CmdAdd(CmdInt32(3),CmdSubtract(CmdInt32(6),CmdInt32(2))) ) @trace op # op:Print(Add(3,Subtract(6,2))) # ConstantFolder().visit( op ) # another example of possibilities local writer = CPPWriter() writer.visit( op ) println writer # OUTPUT: # #include # using namespace std; # # int main() # { # printf( "%d\n",(3+(6-2)) ); # return 0; # } # class ConstantFolder : NodeVisitor<> # METHODS # method handle( cmd:CmdAdd )->Cmd # visit_children( cmd ) # if (cmd.first.is_literal and cmd.last.is_literal) # if (cmd.first instanceOf CmdInt32 and cmd.last instanceOf CmdInt32) # return visit( CmdInt32( (cmd.first as CmdInt32).value + (cmd.last as CmdInt32).value ) ) # endIf # endIf # return cmd # # method handle( cmd:CmdSubtract )->Cmd # visit_children( cmd ) # if (cmd.first.is_literal and cmd.last.is_literal) # if (cmd.first instanceOf CmdInt32 and cmd.last instanceOf CmdInt32) # return visit( CmdInt32( (cmd.first as CmdInt32).value - (cmd.last as CmdInt32).value ) ) # endIf # endIf # return cmd # endClass