progs/fun-bare.scala
changeset 639 217e66d7aeff
parent 628 8067d0a8ba04
child 695 484b74bc057e
equal deleted inserted replaced
638:0367aa7c764b 639:217e66d7aeff
     1 // A Small Compiler for a Simple Functional Language
     1 // A Small Compiler for a Simple Functional Language
     2 // (it does not include a parser and lexer)
     2 // (it does not include a parser and lexer)
     3 
     3 
     4 // Abstract syntax trees
     4 // abstract syntax trees
     5 abstract class Exp
     5 abstract class Exp
     6 abstract class BExp 
     6 abstract class BExp 
     7 abstract class Decl
     7 abstract class Decl
     8 
     8 
     9 // function declarations
     9 // functions and declarations
    10 case class Def(name: String, args: List[String], body: Exp) extends Decl
    10 case class Def(name: String, args: List[String], body: Exp) extends Decl
    11 case class Main(e: Exp) extends Decl
    11 case class Main(e: Exp) extends Decl
    12 
    12 
    13 // expressions
    13 // expressions
    14 case class Call(name: String, args: List[Exp]) extends Exp
    14 case class Call(name: String, args: List[Exp]) extends Exp
    73 // convenient string interpolations for
    73 // convenient string interpolations for
    74 // generating instructions, labels etc
    74 // generating instructions, labels etc
    75 import scala.language.implicitConversions
    75 import scala.language.implicitConversions
    76 import scala.language.reflectiveCalls
    76 import scala.language.reflectiveCalls
    77 
    77 
       
    78 // convenience for code-generation (string interpolations)
    78 implicit def sring_inters(sc: StringContext) = new {
    79 implicit def sring_inters(sc: StringContext) = new {
    79   def i(args: Any*): String = "   " ++ sc.s(args:_*) ++ "\n"
    80   def i(args: Any*): String = "   " ++ sc.s(args:_*) ++ "\n"  // instructions
    80   def l(args: Any*): String = sc.s(args:_*) ++ ":\n"
    81   def l(args: Any*): String = sc.s(args:_*) ++ ":\n"          // labels
    81   def m(args: Any*): String = sc.s(args:_*) ++ "\n"
    82   def m(args: Any*): String = sc.s(args:_*) ++ "\n"           // methods
    82 }
    83 }
    83 
    84 
    84 // variable / index environments
    85 // variable / index environments
    85 type Env = Map[String, Int]
    86 type Env = Map[String, Int]
    86 
    87 
   128     compile_exp(a1, env) ++ compile_exp(a2, env) ++ i"if_icmpge $jmp"
   129     compile_exp(a1, env) ++ compile_exp(a2, env) ++ i"if_icmpge $jmp"
   129   case Bop("<=", a1, a2) => 
   130   case Bop("<=", a1, a2) => 
   130     compile_exp(a1, env) ++ compile_exp(a2, env) ++ i"if_icmpgt $jmp"
   131     compile_exp(a1, env) ++ compile_exp(a2, env) ++ i"if_icmpgt $jmp"
   131 }
   132 }
   132 
   133 
   133 // compile function for declarations and main
   134 // compile functions and declarations
   134 def compile_decl(d: Decl) : String = d match {
   135 def compile_decl(d: Decl) : String = d match {
   135   case Def(name, args, a) => { 
   136   case Def(name, args, a) => { 
   136     val env = args.zipWithIndex.toMap
   137     val env = args.zipWithIndex.toMap
   137     val is = "I" * args.length
   138     val is = "I" * args.length
   138     m".method public static $name($is)I" ++
   139     m".method public static $name($is)I" ++
   162 
   163 
   163 
   164 
   164 
   165 
   165 
   166 
   166 // An example program (factorials)
   167 // An example program (factorials)
       
   168 //
       
   169 // def fact(n) = if n == 0 then 1 else n * fact(n - 1);
       
   170 // def facT(n, acc) = if n == 0 then acc else facT(n - 1, n * acc);
       
   171 // 
       
   172 // fact(10) ; facT(15, 1)
       
   173 // 
       
   174 
   167 
   175 
   168 val test_prog = 
   176 val test_prog = 
   169   List(Def("fact", List("n"),
   177   List(Def("fact", List("n"),
   170          If(Bop("==",Var("n"),Num(0)),
   178          If(Bop("==",Var("n"),Num(0)),
   171             Num(1),
   179             Num(1),