summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGilles Dubochet <gilles.dubochet@epfl.ch>2006-02-14 15:23:26 +0000
committerGilles Dubochet <gilles.dubochet@epfl.ch>2006-02-14 15:23:26 +0000
commitb499d07e91b473d37ee51748c53f7b9903b0833c (patch)
treed123fcc1b70f8a4b034c40677da65f3ca2ce95c0
parent28f84fae2b7514e95061ec86d0ea9910f9e62b2b (diff)
downloadscala-b499d07e91b473d37ee51748c53f7b9903b0833c.tar.gz
scala-b499d07e91b473d37ee51748c53f7b9903b0833c.tar.bz2
scala-b499d07e91b473d37ee51748c53f7b9903b0833c.zip
Expanded Codification to support loops, conditi...
Expanded Codification to support loops, conditions and assignation. Assignation is known to be highly instable and will change in the future: use at your own risks.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Codification.scala42
-rw-r--r--src/library/scala/reflect/Code.scala6
-rw-r--r--src/library/scala/reflect/Print.scala32
-rw-r--r--src/library/scala/reflect/Symbol.scala5
4 files changed, 70 insertions, 15 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Codification.scala b/src/compiler/scala/tools/nsc/typechecker/Codification.scala
index 9a79e2b3e8..f6af067609 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Codification.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Codification.scala
@@ -16,10 +16,30 @@ mixin class Codification requires Analyzer {
case class FreeValue(tree: Tree) extends reflect.Code;
- type ReifyEnvironment = ListMap[Symbol, reflect.Symbol];
+ class ReifyEnvironment extends ListMap[Symbol, reflect.Symbol] {
+ var targets = ListMap.Empty[String, Option[reflect.LabelSymbol]]
+ def addTarget(name: String, target: reflect.LabelSymbol): Unit =
+ targets = targets.update(name, Some(target))
+ def getTarget(name: String): Option[reflect.LabelSymbol] =
+ targets.get(name) match {
+ case None =>
+ targets = targets.update(name, None)
+ None
+ case Some(None) => None
+ case Some(tgt) => tgt
+ }
+ def hasAllTargets: Boolean =
+ targets.elements.map(._2).forall {
+ case Some(_) => true
+ case None => false
+ }
+ override def update(sym: Symbol, rsym: reflect.Symbol): ReifyEnvironment = this.update(sym,rsym)
+ }
class Reifier(env: ReifyEnvironment, currentOwner: reflect.Symbol) {
+ def testCompletion: Boolean = env.hasAllTargets
+
def reify(tree: Tree): reflect.Code = tree match {
case Ident(_) =>
val rsym = reify(tree.symbol);
@@ -31,6 +51,11 @@ mixin class Codification requires Analyzer {
else reflect.Select(reify(qual), reify(tree.symbol))
case Literal(constant) =>
reflect.Literal(constant.value)
+ case Apply(name, args) if name.toString().startsWith("label$") =>
+ env.getTarget(name.toString()) match {
+ case None => throw new TypeError("cannot reify tree (no forward jumps allowed): " + tree)
+ case Some(label) => reflect.Goto(label)
+ }
case Apply(fun, args) =>
reflect.Apply(reify(fun), args map reify)
case TypeApply(fun, args) =>
@@ -52,6 +77,13 @@ mixin class Codification requires Analyzer {
val reifiedClass = reify(clazz)
reflect.New(reifiedClass)
case Typed(t, _) => reify(t)
+ case If(cond, thenp, elsep) => reflect.If(reify(cond), reify(thenp), reify(elsep))
+ case Assign(lhs, rhs) => reflect.Assign(reify(lhs), reify(rhs))
+ case LabelDef(name, Nil, body) =>
+ val sym = new reflect.LabelSymbol(name.toString())
+ env.addTarget(name.toString(), sym)
+ val res = reflect.Target(sym, reify(body))
+ res
case _ =>
throw new TypeError("cannot reify tree: " + tree)
}
@@ -129,9 +161,14 @@ mixin class Codification requires Analyzer {
case reflect.TypeField(_, _) => "scala.reflect.TypeField"
case reflect.LocalValue(_, _, _) => "scala.reflect.LocalValue"
case reflect.LocalMethod(_, _, _) => "scala.reflect.LocalMethod"
+ case reflect.LabelSymbol(_) => "scala.reflect.LabelSymbol"
case reflect.This(_) => "scala.reflect.This"
case reflect.Block(_,_) => "scala.reflect.Block"
case reflect.New(_) => "scala.reflect.New"
+ case reflect.If(_,_,_) => "scala.reflect.If"
+ case reflect.Assign(_,_) => "scala.reflect.Assign"
+ case reflect.Target(_,_) => "scala.reflect.Target"
+ case reflect.Goto(_) => "scala.reflect.Goto"
case reflect.NamedType(_) => "scala.reflect.NamedType"
case reflect.PrefixedType(_, _) => "scala.reflect.PrefixedType"
case reflect.SingleType(_, _) => "scala.reflect.SingleType"
@@ -159,6 +196,7 @@ mixin class Codification requires Analyzer {
def inject(value: Any): Tree = value match {
case FreeValue(tree) =>
tree
+ case () => Literal(Constant(()))
case x: String => Literal(Constant(x))
case x: Boolean => Literal(Constant(x))
case x: Byte => Literal(Constant(x))
@@ -185,7 +223,7 @@ mixin class Codification requires Analyzer {
}
def reify(tree: Tree): reflect.Code =
- new Reifier(ListMap.Empty, reflect.NoSymbol).reify(tree);
+ new Reifier(new ReifyEnvironment(), reflect.NoSymbol).reify(tree);
def inject(code: reflect.Code): Tree =
new Injector(ListMap.Empty, new FreshNameCreator).inject(code);
diff --git a/src/library/scala/reflect/Code.scala b/src/library/scala/reflect/Code.scala
index 83aa81d03d..0458cb5341 100644
--- a/src/library/scala/reflect/Code.scala
+++ b/src/library/scala/reflect/Code.scala
@@ -20,4 +20,8 @@ case class TypeApply(fun: Code, args: List[Type]) extends Code;
case class Function(params: List[Symbol], body: Code) extends Code;
case class This(sym: Symbol) extends Code;
case class Block(stats: List[Code], expr: Code) extends Code;
-case class New(sym: Code) extends Code; \ No newline at end of file
+case class New(sym: Code) extends Code;
+case class If(condition: Code, trueCase: Code, falseCase: Code) extends Code;
+case class Assign(destination: Code, source: Code) extends Code;
+case class Target(sym: LabelSymbol, body: Code) extends Code;
+case class Goto(target: LabelSymbol) extends Code; \ No newline at end of file
diff --git a/src/library/scala/reflect/Print.scala b/src/library/scala/reflect/Print.scala
index 5d4cf45f62..cb74ac183f 100644
--- a/src/library/scala/reflect/Print.scala
+++ b/src/library/scala/reflect/Print.scala
@@ -29,26 +29,34 @@ object Print extends Function1[Any, String] {
def apply (code: Code): String = code match {
case reflect.Ident(sym) => Print(sym)
- case reflect.Select(qual, sym) => "(" + Print(qual) + "." + Print(sym) + ")"
- case reflect.Literal(value) => "(value: " + value.toString + ")"
+ case reflect.Select(qual, sym) => Print(qual) + "." + Print(sym)
+ case reflect.Literal(value) => value match {
+ case s:String => "\"" + s + "\""
+ case _ => value.toString
+ }
case reflect.Apply(fun, args) => Print(fun) + args.map(Print).mkString("(", ", ", ")")
case reflect.TypeApply(fun, args) => Print(fun) + args.map(Print).mkString("[", ", ", "]")
- case reflect.Function(params, body) => "(" + params.map(Print).mkString("(", ", ", ")") + " => " + Print(body) + ")"
- case reflect.This(sym) => "(" + Print(sym) + ".this)"
- case reflect.Block(stats, expr) => (stats ::: List(expr)).map(Print).mkString("{", ";\n", "}")
- case reflect.New(clazz) => "(new " + Print(clazz) + ")"
+ case reflect.Function(params, body) => params.map(Print).mkString("(", ", ", ")") + " => " + Print(body)
+ case reflect.This(sym) => Print(sym)
+ case reflect.Block(stats, expr) => (stats ::: List(expr)).map(Print).mkString("{\n", ";\n", "\n}")
+ case reflect.New(tpt) => "new " + Print(tpt)
+ case reflect.If(condition, trueCase, falseCase) => "if (" + Print(condition) + ") " + Print(trueCase) + " else " + Print(falseCase)
+ case reflect.Assign(destination: Code, source: Code) => Print(destination) + " = " + Print(source)
+ case reflect.Target(sym, body) => "target " + Print(sym) + " {\n" + Print(body) + "\n}"
+ case reflect.Goto(target) => "goto " + Print(target)
case _ => "???"
}
def apply (symbol: Symbol): String = symbol match {
- case reflect.Class(name) => "(class: " + name + ")"
- case reflect.Method(name, datatype) => "(method: " + name + ")" //+ ": " + datatype
- case reflect.Field(name, datatype) => "(field: " + name + ")" //+ ": " + datatype
- case reflect.TypeField(name, datatype) => "(typefield: " + name + ")" //+ ": " + datatype
- case reflect.LocalValue(owner, name, datatype) => "(lvalue: " + name + ")" //+ ": " + datatype
- case reflect.LocalMethod(owner, name, datatype) => "(lmethod: " + name + ")" //+ ": " + datatype
+ case reflect.Class(name) => name.substring(name.lastIndexOf('.')+1)
+ case reflect.Method(name, datatype) => name.substring(name.lastIndexOf('.')+1) //+ ": " + datatype
+ case reflect.Field(name, datatype) => name.substring(name.lastIndexOf('.')+1) //+ ": " + datatype
+ case reflect.TypeField(name, datatype) => name.substring(name.lastIndexOf('.')+1) //+ ": " + datatype
+ case reflect.LocalValue(owner, name, datatype) => name.substring(name.lastIndexOf('.')+1) //+ ": " + datatype
+ case reflect.LocalMethod(owner, name, datatype) => name.substring(name.lastIndexOf('.')+1) //+ ": " + datatype
case reflect.NoSymbol => "NoSymbol"
case reflect.RootSymbol => "RootSymbol"
+ case reflect.LabelSymbol(name) => name
case _ => "???"
}
diff --git a/src/library/scala/reflect/Symbol.scala b/src/library/scala/reflect/Symbol.scala
index 14be8e9317..6eedf34e17 100644
--- a/src/library/scala/reflect/Symbol.scala
+++ b/src/library/scala/reflect/Symbol.scala
@@ -49,3 +49,8 @@ case object RootSymbol extends Symbol {
val name = "<root>";
val tpe = NoPrefix
}
+
+case class LabelSymbol(val name: String) extends Symbol {
+ val owner = NoSymbol;
+ val tpe = NamedType("scala.Unit")
+}