// 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 ( e : Exp, targetRegister : Int ) : String = { e match { case IntLit ( n ) => s"${ pad }LoadImm R${ targetRegister } ${ n }\n" case Var ( x ) => s"${ pad }Load R${ targetRegister } ${ x }\n" case Add ( l, r ) => { codegenExp ( l, targetRegister ) ++ codegenExp ( r, targetRegister+1 ) ++ s"${ pad }Plus R${ targetRegister } R${ targetRegister+1 }\n" } case Subt ( l, r ) => { codegenExp ( l, targetRegister ) ++ codegenExp ( r, targetRegister+1 ) ++ s"${ pad }Minus R${ targetRegister } R${ targetRegister+1 }\n" } case Mult ( l, r ) => { codegenExp ( l, targetRegister ) ++ codegenExp ( r, targetRegister+1 ) ++ s"${ pad }Times R${ targetRegister } R${ targetRegister+1 }\n" } case Div ( l, r ) => { codegenExp ( l, targetRegister ) ++ codegenExp ( r, targetRegister+1 ) ++ s"${ pad }Div R${ targetRegister } R${ targetRegister+1 }\n" } case Negate ( e ) => "..." } } def codegenM ( p : Program, targetRegister : Int ) : String = { p match { case Seq ( l, r ) => { codegenM ( l, targetRegister ) ++ codegenM ( r, targetRegister ) } case Assign ( x, e ) => { codegenExp ( e, targetRegister ) ++ s"${ pad }Store R${ targetRegister } ${ x }\n" } case For ( x, lo, hi, body ) => { val check = freshLabel ( "check" ) val loopExit = freshLabel ( "exit" ) codegenExp ( lo, targetRegister ) ++ s"${ pad }Store R${ targetRegister } ${ x }\n" ++ s"${ check }:\n" ++ s"${ pad }Load R${ targetRegister } ${ x }\n" ++ codegenExp ( hi, targetRegister+1 ) ++ s"${ pad }CompGreaterThan R${ targetRegister } R${ targetRegister+1 }\n" ++ s"${ pad }JumpTrue R${targetRegister} ${ loopExit }\n" ++ codegenM ( body, targetRegister+2 ) ++ s"${ pad }Load R${ targetRegister } ${ x }\n" ++ s"${ pad }LoadImm R${ targetRegister+2 } 1\n" ++ s"${ pad }Plus R${ targetRegister } R${ targetRegister+2 }\n" ++ s"${ pad }Store R${ targetRegister } ${ x }\n" ++ s"${ pad }Jump ${ check }\n" ++ s"${ loopExit }:\n" } } }