Skip to content
Snippets Groups Projects
Commit 9b5556ac authored by Philippe Suter's avatar Philippe Suter
Browse files

Case class generation works (use doesn't yet).

parent 7394fad6
No related branches found
No related tags found
No related merge requests found
......@@ -15,15 +15,16 @@ object CodeGenPhase extends LeonPhase[Program,CompilationResult] {
def run(ctx : LeonContext)(p : Program) : CompilationResult = {
import CodeGeneration._
// This sets up an environment where all classes and all functions have names.
implicit val env = CompilationEnvironment.fromProgram(p)
val cName = programToClassName(p)
for((p,cs) <- p.algebraicDataTypes) {
// val acf = new ClassFile(p....
for((parent,children) <- p.algebraicDataTypes) {
val acf = compileAbstractClassDef(p, parent)
val ccfs = children.map(c => compileCaseClassDef(p, c))
}
val cf = new ClassFile(cName, None)
val mainClassName = defToJVMName(p, p.mainObject)
val cf = new ClassFile(mainClassName, None)
cf.addDefaultConstructor
cf.setFlags((
......@@ -51,7 +52,7 @@ object CodeGenPhase extends LeonPhase[Program,CompilationResult] {
CodeGeneration.compileFunDef(funDef, m.codeHandler)
}
cf.writeToFile(cName + ".class")
cf.writeToFile(mainClassName + ".class")
CompilationResult(successful = true)
}
......
......@@ -7,15 +7,22 @@ import purescala.Trees._
import purescala.TypeTrees._
import cafebabe._
import cafebabe.ByteCodes._
import cafebabe.AbstractByteCodes._
import cafebabe.ByteCodes._
import cafebabe.ClassFileTypes._
import cafebabe.Flags._
object CodeGeneration {
def programToClassName(p : Program) : String = "Leon$CodeGen$" + p.mainObject.id.uniqueName
def defToJVMName(p : Program, d : Definition) : String = "Leon$CodeGen$" + d.id.uniqueName
def typeToJVM(tpe : TypeTree)(implicit env : CompilationEnvironment) : String = tpe match {
case Int32Type => "I"
case BooleanType => "Z"
case c : ClassType =>
env.classDefToName(c.classDef).map(n => "L" + n + ";").getOrElse("Unsupported class " + c.id)
case _ => throw CompilationException("Unsupported type : " + tpe)
}
......@@ -170,4 +177,68 @@ object CodeGeneration {
throw CompilationException("Unknown variable : " + id)
}
}
def compileAbstractClassDef(p : Program, acd : AbstractClassDef)(implicit env : CompilationEnvironment) : ClassFile = {
val cName = defToJVMName(p, acd)
val cf = new ClassFile(cName, None)
cf.setFlags((
CLASS_ACC_SUPER |
CLASS_ACC_PUBLIC |
CLASS_ACC_ABSTRACT
).asInstanceOf[U2])
cf.addDefaultConstructor
//cf.writeToFile(cName + ".class")
cf
}
def compileCaseClassDef(p : Program, ccd : CaseClassDef)(implicit env : CompilationEnvironment) : ClassFile = {
assert(ccd.hasParent)
val cName = defToJVMName(p, ccd)
val pName = defToJVMName(p, ccd.parent.get)
val cf = new ClassFile(cName, Some(pName))
cf.setFlags((
CLASS_ACC_SUPER |
CLASS_ACC_PUBLIC |
CLASS_ACC_FINAL
).asInstanceOf[U2])
if(ccd.fields.isEmpty) {
cf.addDefaultConstructor
} else {
val namesTypes = ccd.fields.map { vd => (vd.id.name, typeToJVM(vd.tpe)) }
for((nme, jvmt) <- namesTypes) {
val fh = cf.addField(jvmt, nme)
fh.setFlags((
FIELD_ACC_PUBLIC |
FIELD_ACC_FINAL
).asInstanceOf[U2])
}
val cmh = cf.addConstructor(namesTypes.map(_._2).toList).codeHandler
cmh << ALoad(0) << InvokeSpecial(pName, cafebabe.Defaults.constructorName, "()V")
var c = 1
for((nme, jvmt) <- namesTypes) {
cmh << ALoad(0)
cmh << (jvmt match {
case "I" | "Z" => ILoad(c)
case _ => ALoad(c)
})
cmh << PutField(cName, nme, jvmt)
c += 1
}
cmh << RETURN
cmh.freeze
}
//cf.writeToFile(cName + ".class")
cf
}
}
......@@ -10,6 +10,8 @@ abstract class CompilationEnvironment() {
// - a mapping of function defs to class + method name
// - a mapping of class defs to class names
// - a mapping of class fields to fields
def classDefToName(classDef : ClassTypeDef) : Option[String]
def funDefToMethod(funDef : FunDef) : Option[(String,String,String)]
......@@ -18,6 +20,7 @@ abstract class CompilationEnvironment() {
/** Augment the environment with new local var. mappings. */
def withVars(pairs : Map[Identifier,Int]) = {
new CompilationEnvironment {
def classDefToName(classDef : ClassTypeDef) = self.classDefToName(classDef)
def funDefToMethod(funDef : FunDef) = self.funDefToMethod(funDef)
def varToLocal(v : Identifier) = pairs.get(v).orElse(self.varToLocal(v))
}
......@@ -25,20 +28,21 @@ abstract class CompilationEnvironment() {
}
object CompilationEnvironment {
lazy val empty = new CompilationEnvironment {
def funDefToMethod(funDef : FunDef) = None
def varToLocal(v : Identifier) = None
}
def fromProgram(p : Program) : CompilationEnvironment = {
import CodeGeneration.typeToJVM
// This should change: it should contain the case classes before
// we go and generate function signatures.
implicit val env = empty
implicit val initial = new CompilationEnvironment {
private val cNames : Map[ClassTypeDef,String] =
p.definedClasses.map(c => (c, CodeGeneration.defToJVMName(p, c))).toMap
val className = CodeGeneration.programToClassName(p)
def classDefToName(classDef : ClassTypeDef) = cNames.get(classDef)
def funDefToMethod(funDef : FunDef) = None
def varToLocal(v : Identifier) = None
}
val className = CodeGeneration.defToJVMName(p, p.mainObject)
val fs = p.definedFunctions.filter(_.hasImplementation)
......@@ -49,8 +53,8 @@ object CompilationEnvironment {
}).toMap
new CompilationEnvironment {
def classDefToName(classDef : ClassTypeDef) = initial.classDefToName(classDef)
def funDefToMethod(funDef : FunDef) = fMap.get(funDef)
def varToLocal(v : Identifier) = None
}
}
......
No preview for this file type
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment