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

No commit message

No commit message
parent cd8784ac
No related branches found
No related tags found
No related merge requests found
...@@ -7,7 +7,6 @@ import purescala.Definitions._ ...@@ -7,7 +7,6 @@ import purescala.Definitions._
import purescala.Trees._ import purescala.Trees._
import purescala.TypeTrees._ import purescala.TypeTrees._
import purescala.Common._ import purescala.Common._
import purescala.Symbols._
trait CodeExtraction extends Extractors { trait CodeExtraction extends Extractors {
self: AnalysisComponent => self: AnalysisComponent =>
...@@ -20,93 +19,85 @@ trait CodeExtraction extends Extractors { ...@@ -20,93 +19,85 @@ trait CodeExtraction extends Extractors {
import scala.collection.mutable.HashMap import scala.collection.mutable.HashMap
// register where the symbols where extracted from // register where the symbols where extracted from
val symbolDefMap = new HashMap[Symbol,Tree] val symbolDefMap = new HashMap[purescala.Symbols.Symbol,Tree]
def s2ps(tree: Tree): Expr = toPureScala(unit)(tree) match { def s2ps(tree: Tree): Expr = toPureScala(unit)(tree) match {
case Some(ex) => ex case Some(ex) => ex
case None => stopIfErrors; throw new Error("unreachable") case None => stopIfErrors; throw new Error("unreachable?")
} }
// def trav(tree: Tree): Unit = tree match { /** Populates the symbolDefMap with object and class symbols, and returns
// case t : Tree if t.symbol != null && t.symbol.hasFlag(symtab.Flags.SYNTHETIC) => { * the symbol corresponding to the expected single top-level object. */
// println("Synth! " + t) def extractClassSymbols: purescala.Symbols.ObjectSymbol = {
// } val top = unit.body match {
// case d @ DefDef(mods, name, tparams, vparamss, tpt, body) if !(d.symbol.hasFlag(symtab.Flags.SYNTHETIC) || d.symbol.isConstructor) => { case p @ PackageDef(name, lst) if lst.size == 0 => {
// println("In: " + name) unit.error(p.pos, "No top-level definition found.")
// println(d.symbol) None
// println(d.mods) }
//
// toPureScala(unit)(body) match {
// case Some(t) => println(" the body was extracted as: " + t)
// case None => println(" the body could not be extracted. Is it pure Scala?")
// }
// }
// case _ => ;
// }
/** Populates the symbolDefMap and returns the symbol corresponding to
* the expected single top-level object. */
def extractSymbols: ObjectSymbol = {
null
}
def extractObject(name: Identifier, tmpl: Template): ObjectDef = {
var funDefs: List[FunDef] = Nil
var valDefs: List[ValDef] = Nil
var asserts: List[Expr] = Nil
val tTrees: List[Tree] = tmpl.body
println(tTrees) case PackageDef(name, lst) if lst.size > 1 => {
unit.error(lst(1).pos, "Too many top-level definitions.")
None
}
tTrees.foreach(tree => tree match { case PackageDef(name, lst) => {
case cd @ ClassDef(_, name, tparams, impl) => { assert(lst.size == 1)
println("--- " + name.toString) lst(0) match {
println(cd.symbol.info) case ExObjectDef(n, templ) => Some(extractObjectSym(n.toString, templ))
println(cd.symbol.info.parents) case other @ _ => unit.error(other.pos, "Expected: top-level single object.")
None
}
} }
case _ => ; }
})
ObjectDef(name, Nil, Nil) stopIfErrors
top.get
} }
// Extraction of the definitions. def extractObjectSym(name: Identifier, tmpl: Template): purescala.Symbols.ObjectSymbol = {
val program = unit.body match { // we assume that the template actually corresponds to an object
case p @ PackageDef(name, lst) if lst.size == 0 => { // definition. Typically it should have been obtained from the proper
unit.error(p.pos, "No top-level definition found.") // extractor (ExObjectDef)
None
}
case PackageDef(name, lst) if lst.size > 1 => {
unit.error(lst(1).pos, "Too many top-level definitions.")
None
}
case PackageDef(name, lst) => { var classSyms: List[purescala.Symbols.ClassSymbol] = Nil
assert(lst.size == 1) var objectSyms: List[purescala.Symbols.ObjectSymbol] = Nil
lst(0) match {
case ExObjectDef(n, templ) => Some(Program(name.toString, extractObject(n.toString, templ)))
case other @ _ => unit.error(other.pos, "Expected: top-level single object.")
None
}
}
}
// Extraction of the expressions. tmpl.body.foreach(tree => tree match {
case ExObjectDef(o2, t2) => { objectSyms = extractObjectSym(o2, t2) :: objectSyms }
case ExAbstractClass(o2) => ;
case _ => ;
})
// (new ForeachTreeTraverser(trav)).traverse(unit.body) val theSym = new purescala.Symbols.ObjectSymbol(name, classSyms.reverse, objectSyms.reverse)
// we register the tree associated to the symbol to be able to fill in
// the rest later
symbolDefMap(theSym) = tmpl
theSym
}
// Step-by-step algo: // Step-by-step:
// 1) extract class and object symbols (will already be nested) // 1) extract class and object symbols recursively (objects can have
// 2) extract function and val symbols (can now have a type, since we // objects as members)
// 2) set parents for classes
// 3) extract function and val symbols (can now have a type, since we
// have full class hierarchy) // have full class hierarchy)
// 3) extract val and function bodies (can do it, since we have all // 4) extract val and function bodies (can do it, since we have all
// definitions, hence we can resolve all symbols) // definitions, hence we can resolve all symbols)
// This extracts the class and object symbols recursively.
val topLevelObjSym: purescala.Symbols.ObjectSymbol = extractClassSymbols
stopIfErrors stopIfErrors
program.get val programName: Identifier = unit.body match {
case PackageDef(name, _) => name.toString
case _ => "<program>"
}
println("Top level sym:")
println(topLevelObjSym)
Program(programName, ObjectDef("Object", Nil, Nil))
} }
/** An exception thrown when non-purescala compatible code is encountered. */ /** An exception thrown when non-purescala compatible code is encountered. */
......
...@@ -51,26 +51,30 @@ trait Extractors { ...@@ -51,26 +51,30 @@ trait Extractors {
object ExObjectDef { object ExObjectDef {
/** Matches an object with no type parameters, and regardless of its /** Matches an object with no type parameters, and regardless of its
* visibility. */ * visibility. Does not match on the automatically generated companion
* objects of case classes (or any synthetic class). */
def unapply(cd: ClassDef): Option[(String,Template)] = cd match { def unapply(cd: ClassDef): Option[(String,Template)] = cd match {
case ClassDef(_, name, tparams, impl) if (cd.symbol.isModuleClass && tparams.isEmpty) => Some((name.toString, impl)) case ClassDef(_, name, tparams, impl) if (cd.symbol.isModuleClass && tparams.isEmpty && !cd.symbol.hasFlag(symtab.Flags.SYNTHETIC)) => {
Some((name.toString, impl))
}
case _ => None case _ => None
} }
} }
object ExAbstractClass { object ExAbstractClass {
/** Matches an abstract class with no type parameters, no constructor /** Matches an abstract class or a trait with no type parameters, no
* arguments, at most one parent class and an empty template. (Does _not_ * constrctor args (in the case of a class), no implementation details,
* match such a trait). */ * no abstract members. */
def unapply(cd: ClassDef): Option[(String)] = cd match { def unapply(cd: ClassDef): Option[(String)] = cd match {
case ClassDef(_, name, tparams, impl) if (cd.symbol.isTrait && tparams.isEmpty && impl.body.length == 2) => {
println(name + " seems to be a cool trait")
Some(name.toString)
}
case _ => None case _ => None
} }
} }
object ExCaseClass { object ExCaseClass {
/** Matches a case class definition with no type parameters, at most one
* parent class and an empty template. */
} }
......
...@@ -28,25 +28,72 @@ object Symbols { ...@@ -28,25 +28,72 @@ object Symbols {
def getType = tpe def getType = tpe
} }
// The object and class members have to be known at construction time. The
// typed members can be added anytime.
class ObjectSymbol( class ObjectSymbol(
val id: Identifier, val id: Identifier,
val fields: Seq[VariableSymbol],
val functions: Seq[FunctionSymbol],
val classes: Seq[ClassSymbol], val classes: Seq[ClassSymbol],
val objects: Seq[ObjectSymbol]) extends Symbol val objects: Seq[ObjectSymbol]) extends Symbol {
sealed abstract class ClassSymbol { private var _fields: List[VariableSymbol] = Nil
private var _functions: List[FunctionSymbol] = Nil
def fields: Seq[VariableSymbol] = _fields
def functions: Seq[FunctionSymbol] = _functions
def registerField(f: VariableSymbol): ObjectSymbol = {
_fields = _fields ::: List(f)
this
}
def registerFunction(f: FunctionSymbol): ObjectSymbol = {
_functions = _functions ::: List(f)
this
}
override def toString: String = withInc(0)
private def withInc(inc: Int): String = {
val ii: String = " " * inc
ii + "[object: " + id + "\n" +
(if(!fields.isEmpty) {
ii + " fields: " + fields.map(_.toString).mkString("{ ", ", ", " }") + "\n"
} else { "" }) +
(if(!functions.isEmpty) {
ii + " functions: " + functions.map(_.toString).mkString("{ ", ", ", " }") + "\n"
} else { "" }) +
(if(!classes.isEmpty) {
ii + " classes: " + classes.map(_.toString).mkString("{ ", ", ", " }") + "\n"
} else { "" }) +
(if(!objects.isEmpty) {
ii + " objects: " + objects.map(_.withInc(inc+1)).mkString("{\n", ",\n", "\n" + ii + " }") + "\n"
} else { "" }) +
ii + "]"
}
}
sealed abstract class ClassSymbol extends Symbol {
val parents: Seq[AbstractClassSymbol] val parents: Seq[AbstractClassSymbol]
protected val _pfx: String
override def toString = "[" + _pfx + ": " + id + (if (!parents.isEmpty) { " extends " + parents.mkString(", ") } else { "" }) + "]"
} }
/** Symbols for abstract classes (or traits) */ /** Symbols for abstract classes (or traits) */
class AbstractClassSymbol(val id: Identifier, val parents: Seq[AbstractClassSymbol]) extends ClassSymbol class AbstractClassSymbol(val id: Identifier, val parents: Seq[AbstractClassSymbol]) extends ClassSymbol {
override protected val _pfx = "abstract class"
}
/** Symbols for "regular" (= non-abstract, non-case) classes */ /** Symbols for "regular" (= non-abstract, non-case) classes */
class RefClassSymbol(val id: Identifier, val parents: Seq[AbstractClassSymbol]) extends ClassSymbol class RefClassSymbol(val id: Identifier, val parents: Seq[AbstractClassSymbol]) extends ClassSymbol {
override protected val _pfx = "class"
}
/** Symbols for case classes. */ /** Symbols for case classes. */
class CaseClassSymbol(val id: Identifier, val parents: Seq[AbstractClassSymbol]) extends ClassSymbol class CaseClassSymbol(val id: Identifier, val parents: Seq[AbstractClassSymbol]) extends ClassSymbol {
override protected val _pfx = "case class"
}
class FunctionSymbol(val id: Identifier, val params: Seq[VariableSymbol], val returnType: TypeTree) extends Typed { class FunctionSymbol(val id: Identifier, val params: Seq[VariableSymbol], val returnType: TypeTree) extends Typed {
def getType = returnType def getType = returnType
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment