// I'm writing ++ for string contactenation. So e.g. // // "hello" ++ " " ++ "world" // // will be the string // // "hello world" // // I use "string interpolation" (see https://en.wikipedia.org/wiki/String_interpolation) // to construct strings. For example the string // // s"hello ${ prog } world" // // (note the s in front of the first quotation mark) is constructed from three parts // // - "hello " // - the result of the program prog // - " world" // // If running the program prog returns // // "my lovely" // // then s"hello ${ prog } world" evaluates to // // s"hello my lovely world" // private var labelCount = 0 def freshLabel ( s : String ) : String = { labelCount += 1 s"${ s }_${ labelCount.toString }" } val pad = " " def codegenExp ( exp : Exp ) : String = { exp match { case IntLit ( n ) => { s"${ pad }LoadImm ${ n.toString }\n" } case Var ( x ) => { s"${ pad }Load ${ x }\n" } case Add ( l, r ) => { codegenExp ( l ) ++ s"${ pad }Push\n" ++ codegenExp ( r ) ++ s"${ pad }Plus\n" } case Subt ( l, r ) => { codegenExp ( l ) ++ s"${ pad }Push\n" ++ codegenExp ( r ) ++ s"${ pad }Minus\n" } case Mult ( l, r ) => { codegenExp ( l ) ++ s"${ pad }Push\n" ++ codegenExp ( r ) ++ s"${ pad }Times\n" } case Div ( l, r ) => { codegenExp ( l ) ++ "Push\n" ++ codegenExp ( r ) ++ s"${ pad }Div\n" } case Negate ( e ) => "..." } } def codegenM ( p : Program ) : String = { p match { case Seq ( l, r ) => { codegenM ( l ) ++ codegenM ( r ) } case Assign ( x, e ) => { codegenExp ( e ) ++ s"${ pad }Store ${ x }\n" } case For ( x, lo, hi, body ) => { val check = freshLabel ( "check" ) val loopExit = freshLabel ( "exit" ) codegenExp ( lo ) ++ s"${ pad }Store ${ x }\n" ++ s"${ check }:\n" ++ codegenExp ( hi ) ++ s"${ pad }Push\n" ++ s"${ pad }Load ${ x }\n" ++ s"${ pad }CompGreaterThan \n" ++ s"${ pad }JumpTrue ${ loopExit }\n" ++ codegenM ( body ) ++ s"${ pad }Load ${ x }\n" ++ s"${ pad }LoadImm 1\n" ++ s"${ pad }PlusStack \n" ++ s"${ pad }Store ${ x }\n" ++ s"${ pad }Jump ${ check }\n" ++ s"${ loopExit }:\n" } } }