From b499d07e91b473d37ee51748c53f7b9903b0833c Mon Sep 17 00:00:00 2001 From: Gilles Dubochet Date: Tue, 14 Feb 2006 15:23:26 +0000 Subject: 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. --- .../scala/tools/nsc/typechecker/Codification.scala | 42 ++++++++++++++++++++-- src/library/scala/reflect/Code.scala | 6 +++- src/library/scala/reflect/Print.scala | 32 ++++++++++------- src/library/scala/reflect/Symbol.scala | 5 +++ 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 = ""; val tpe = NoPrefix } + +case class LabelSymbol(val name: String) extends Symbol { + val owner = NoSymbol; + val tpe = NamedType("scala.Unit") +} -- cgit v1.2.3