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