reifiers.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 324 行

SCALA
324
字号
package scala.tools.nsc.transformimport scala.tools.nsc.symtab.SymbolTableimport scala.reflectimport collection.mutable.HashMap/** Functions to reify (and un-reify) symbols, types, and trees. *  These can be used with only a symbol table; they do not *  need a full compiler. * *  @author Gilles Dubochet, Lex Spoon */trait Reifiers {  val symbols: SymbolTable  import symbols._  private def mkGlobalSymbol(fullname: String, sym: Symbol): reflect.Symbol =    if (sym.isClass) reflect.Class(fullname)    else if (sym.isType) reflect.TypeField(fullname, reify(sym.info))    else if (sym.isMethod) reflect.Method(fullname, reify(sym.info))    else reflect.Field(fullname, reify(sym.info));  def reify(sym: Symbol): reflect.Symbol = {    if (sym.isRoot || sym.isRootPackage || sym.isEmptyPackageClass || sym.isEmptyPackage)      reflect.RootSymbol    else if (sym.owner.isTerm)       reflect.NoSymbol    else reify(sym.owner) match {      case reflect.NoSymbol =>         reflect.NoSymbol;      case reflect.RootSymbol =>        mkGlobalSymbol(sym.name.toString(), sym)      case reflect.Class(ownername) =>        mkGlobalSymbol(ownername + "." + sym.name, sym)      case _ =>        reflect.NoSymbol    }  }  var _log_reify_type_ = false  def reify(tp: Type): reflect.Type = tp match {    case ErrorType =>      reflect.NoType    case WildcardType =>      if (_log_reify_type_) println("cannot handle WildcardType")    reflect.NoType    case NoType =>      reflect.NoType    case NoPrefix =>      reflect.NoType    case ThisType(sym) =>      val rsym = reify(sym)      reflect.ThisType(rsym)    case SingleType(pre, sym) =>      reflect.SingleType(reify(pre), reify(sym))    case ConstantType(value) =>      reify(value.tpe)    case TypeRef(pre, sym, args) =>      val rpre = reify(pre)      val rsym = reify(sym)      val rargs = args map reify      val beforeArgs = reflect.PrefixedType(rpre, rsym)      if(rargs.isEmpty)	beforeArgs      else if(beforeArgs == NoType)	beforeArgs      else	reflect.AppliedType(beforeArgs, rargs)    case TypeBounds(lo, hi) =>      reflect.TypeBounds(reify(lo), reify(hi))    case RefinedType(parents, defs) =>      if (_log_reify_type_) println("cannot handle RefinedType "+tp); reflect.NoType    case ClassInfoType(parents, defs, clazz) =>      if (_log_reify_type_) println("cannot handle ClassInfoType "+tp); reflect.NoType    case MethodType(paramtypes, result) =>      reflect.MethodType(paramtypes.map(reify), reify(result))    case PolyType(tparams, result) =>      val boundss =	for {	  param <- tparams	  TypeBounds(lo,hi) = param.info.bounds	} yield (reify(lo), reify(hi))	        reflect.PolyType(	tparams.map(reify),	boundss,	reify(result))      //todo: treat ExistentialType    case AnnotatedType(attribs, tp, _) =>      reify(tp)    case _ =>      println("could not reify: " + tp)      reflect.NoType  }  /** This is woefully incomplete.  It is barely enough   *  to process the types of Constant's .   */  def unreify(tpe: reflect.Type): Type =    tpe match {      case reflect.NoPrefix => NoPrefix      case reflect.NoType => NoType      case reflect.NamedType(fullname) =>	//NamedType(fullname)	println("NamedType: " + fullname)	NoType      case reflect.PrefixedType(_, reflect.Class("scala.Array")) =>        definitions.ArrayClass.tpe      case reflect.PrefixedType(_, reflect.Class("java.lang.String")) =>        definitions.StringClass.tpe      case reflect.PrefixedType(_, reflect.Class("scala.Unit")) =>        definitions.UnitClass.tpe      case reflect.PrefixedType(_, reflect.Class("scala.Boolean")) =>        definitions.BooleanClass.tpe      case reflect.PrefixedType(_, reflect.Class("scala.Byte")) =>        definitions.ByteClass.tpe      case reflect.PrefixedType(_, reflect.Class("scala.Short")) =>        definitions.ShortClass.tpe      case reflect.PrefixedType(_, reflect.Class("scala.Int")) =>        definitions.IntClass.tpe      case reflect.PrefixedType(_, reflect.Class("scala.Long")) =>        definitions.LongClass.tpe      case reflect.PrefixedType(_, reflect.Class("scala.Float")) =>        definitions.FloatClass.tpe      case reflect.PrefixedType(_, reflect.Class("scala.Double")) =>        definitions.DoubleClass.tpe      case reflect.PrefixedType(pre, sym) => 	NoType      case reflect.SingleType(pre, sym) => 	SingleType(unreify(pre), unreify(sym))      case reflect.ThisType(clazz) => 	ThisType(unreify(clazz))      case reflect.AppliedType(tpe, args) => 	val untpe = unreify(tpe)	if (untpe == NoType)	  NoType	else	  appliedType(untpe, args.map(unreify))      case reflect.TypeBounds(lo, hi) => 	TypeBounds(unreify(lo), unreify(hi))      case reflect.MethodType(formals, restpe) =>	MethodType(formals.map(unreify), unreify(restpe))      case reflect.PolyType(typeParams, typeBounds, resultType) =>	PolyType(typeParams.map(unreify), unreify(resultType))      //todo: treat ExistentialType      case _ => NoType    }  /** This is woefully incomplete.  It is barely enough   *  to process the types of Constant's .   */  def unreify(symbol: reflect.Symbol): Symbol =    symbol match {      case reflect.Class(fullname) => 	fullname match {	  case "scala.Unit" => definitions.UnitClass	  case "scala.Boolean" => definitions.BooleanClass	  case "scala.Byte" => definitions.ByteClass	  case "scala.Short" => definitions.ShortClass	  case "scala.Int" => definitions.IntClass	  case "scala.Long" => definitions.LongClass	  case "scala.Float" => definitions.FloatClass	  case "scala.Double" => definitions.DoubleClass	  case "scala.Array" => definitions.ArrayClass	  case _ => NoSymbol	}      case _ => NoSymbol    }  case class FreeValue(tree: Tree) extends reflect.Tree  class ReifyEnvironment extends HashMap[Symbol, reflect.Symbol] {    var targets = new HashMap[String, Option[reflect.LabelSymbol]]()    def addTarget(name: String, target: reflect.LabelSymbol): Unit =      targets.update(name, Some(target))    def getTarget(name: String): Option[reflect.LabelSymbol] =      targets.get(name) match {        case None =>          targets.update(name, None)          None        //case Some(None) => None //bq:redundant        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) =      super.update(sym,rsym)  }    class Reifier(env: ReifyEnvironment, currentOwner: reflect.Symbol)  {    def reify(tree: Tree): reflect.Tree = tree match {      case Ident(_) =>        val rsym = reify(tree.symbol);        //Console.println("LiftCode: seen ident")        if (rsym == reflect.NoSymbol) {          //Console.println("  free = "+tree)          FreeValue(tree)        } else {          //Console.println("  rsym = "+rsym)          reflect.Ident(rsym)        }      case Select(qual, _) =>        val rsym = reify(tree.symbol);        if (rsym == reflect.NoSymbol) throw new TypeError("cannot reify symbol: " + tree.symbol)        else reflect.Select(reify(qual), reify(tree.symbol))      case _ : StubTree => reflect.Literal(0)      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) =>        reflect.TypeApply(reify(fun), args map (_.tpe) map reify)      case Function(vparams, body) =>        var env1 = env        for (vparam <- vparams) {          val local = reflect.LocalValue(            currentOwner, vparam.symbol.name.toString(), reify(vparam.symbol.tpe));          env1.update(vparam.symbol, local);        }        reflect.Function(vparams map (_.symbol) map env1,                          new Reifier(env1, currentOwner).reify(body))      case tree@This(_) if tree.symbol.isModule =>        // there is no reflect node for a module's this, so        // represent it as a selection of the module	reify(	  Select(This(tree.symbol.owner), tree.symbol.name))      case This(_) =>         reflect.This(reify(tree.symbol))      case Block(stats, expr) =>         reflect.Block(stats.map(reify), reify(expr))      case New(clazz) if (clazz.isType) =>	val reifiedSymbol = reify(clazz.symbol)	reflect.New(reflect.Ident(reifiedSymbol))      case New(clazz) =>        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 vd @ ValDef(mods, name, tpt, rhs) =>        val rtpe = reify(vd.tpe) // will return null, currently?!        val sym  = reflect.LocalValue(currentOwner, name.toString(), rtpe)        env(vd.symbol) = sym // bq: despite Scala's scoping rules, this should work because references to vd.symbol were type checked.        val rhs_ = reify(rhs)        reflect.ValDef(sym, rhs_)      case cd @ ClassDef(mods, name, tparams, impl) =>         if(!tparams.isEmpty)           throw new TypeError("cannot handle polymorphic ClassDef ("+name+"): " + tparams)        val rsym = reify(cd.symbol)        val rimp = reify(impl)        val rtpe = reify(impl.self.tpt.tpe) //todo: update        reflect.ClassDef(rsym, rtpe, rimp.asInstanceOf[reflect.Template])      case tmpl @ Template(parents, self, body) =>        val rparents = for (p <- parents) yield { reify(p.tpe) }        //todo: add self to reified templates        reflect.Template(rparents, body.map(reify))      case dd @ DefDef(mods, name, tparams, vparamss, tpt, rhs) =>        if(!tparams.isEmpty)           throw new TypeError("cannot handle polymorphic DefDef ("+name+"): " + tparams)        val rsym   = reify(dd.symbol)        val rparss = vparamss map { x => x map (reify) }        val rret   = reify(tpt.tpe)        val rrhs   = reify(rhs)        reflect.DefDef(rsym, rparss, rret, rrhs)      case sp @ Super(qual: Name, mix: Name) =>        val rsym = reify(sp.symbol)        reflect.Super(rsym)      case _ =>        throw new TypeError("cannot reify tree ("+tree.getClass()+"): " + tree)    }    def reify(sym: Symbol): reflect.Symbol =      env.get(sym) match {	case Some(rsym) => 	  rsym	case None =>	  Reifiers.this.reify(sym)      }    def reify(tpe: Type): reflect.Type =      Reifiers.this.reify(tpe)  }  def reify(tree: Tree): reflect.Tree =    new Reifier(new ReifyEnvironment(), reflect.NoSymbol).reify(tree)}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?