codefactory.scala

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

SCALA
338
字号
/* NSC -- new Scala compiler * Copyright 2005-2007 LAMP/EPFL * @author Burak Emir */// $Id: CodeFactory.scala 13401 2007-12-01 10:26:27Z emir $                                                                      package scala.tools.nsc.matchingimport scala.tools.nsc.util.Position/** contains many helper methods that build trees...some of these currently *  unused, since were for regexp matching. * *  @author Burak Emir */trait CodeFactory {   self: transform.ExplicitOuter with PatternNodes =>  import global._  import definitions._             // standard classes and methods  import typer.typed               // methods to type trees  import posAssigner.atPos         // for filling in tree positions   final def mkIdent(sym:Symbol) = Ident(sym) setType sym.tpe  final def typedValDef(x:Symbol, rhs:Tree) = {    //Console.println("1"+x.tpe)    x.tpe match {       case WildcardType => rhs.setType(null); val rhs1 = typed(rhs); x setInfo rhs1.tpe; typed{ValDef(x, rhs)}      case _ => typed{ValDef(x, typed(rhs, x.tpe))}    }      }  final def mk_(tpe:Type) = Ident(nme.WILDCARD) setType tpe  final def targetLabel(owner: Symbol, pos: Position, name:String, argtpes:List[Type], resultTpe: Type) =     owner.newLabel(pos, name).setInfo(new MethodType(argtpes, resultTpe))  final def targetParams(subst:Binding):List[ValDef] = if(subst eq NoBinding) Nil else subst match {    case Binding(v,t,n) => ValDef(v, {      //v.setFlag(symtab.Flags.TRANS_FLAG);       if(t.tpe <:< v.tpe) mkIdent(t)      else if(v.tpe <:< t.tpe) typed{gen.mkAsInstanceOf(mkIdent(t),v.tpe)} // refinement      else {        //Console.println("internal error, types don't match: pattern variable "+v+":"+v.tpe+" temp "+t+":"+t.tpe)        error("internal error, types don't match: pattern variable "+v+":"+v.tpe+" temp "+t+":"+t.tpe)        typed{gen.mkAsInstanceOf(mkIdent(t), v.tpe)} // refinement      }    })::targetParams(n)  }  /** returns  `List[ Tuple2[ scala.Int, <elemType> ] ]' */  final def SeqTraceType(elemType: Type): Type =    appliedType(definitions.ListClass.typeConstructor,                 List(pairType(definitions.IntClass.info,                              elemType)))  final def pairType(left: Type, right: Type) =    appliedType(definitions.TupleClass(2).typeConstructor,                List(left,right))  /**  returns `Iterator[ elemType ]' */  final def _seqIterType(elemType: Type): Type =    appliedType(definitions.IteratorClass.typeConstructor,                List(elemType))  /** returns A for T <: Sequence[ A ]   */  final def getElemType_Sequence(tpe: Type): Type = {    //System.err.println("getElemType_Sequence("+tpe.widen()+")")    val tpe1 = tpe.widen.baseType(definitions.SeqClass)    if (tpe1 == NoType)      Predef.error("arg " + tpe + " not subtype of Seq[A]")    tpe1.typeArgs(0)  }  final def emptynessCheck(vsym: Symbol) = {    if (vsym.tpe.typeSymbol == definitions.SomeClass)  // is Some[_]      Literal(Constant(true))    else                                          // is Option[_]      Not(Select(mkIdent(vsym), nme.isEmpty))  }  /** returns code `<seqObj>.elements' */  final def newIterator(seqObj: Tree): Tree =     Apply(Select(seqObj, newTermName("elements")), List())  /** `it.next()'     */  final def _next(iter: Tree) =    Apply(Select(iter, definitions.Iterator_next), List())  /** `it.hasNext()'  */  final def _hasNext(iter: Tree) =      Apply(Select(iter, definitions.Iterator_hasNext), List())  /** `!it.hasCur()'  */  final def _not_hasNext(iter: Tree) =     Apply(Select(_hasNext(iter), definitions.Boolean_not), List())  /** `trace.isEmpty' */  final def isEmpty( iter: Tree  ):  Tree =     Apply(Select(iter, definitions.List_isEmpty), List())   /** `arg.head' */  final def SeqList_head(arg: Tree) =     Apply(Select(arg, definitions.List_head), List())  final def Negate(tree: Tree) = tree match {    case Literal(Constant(value:Boolean))=>      Literal(Constant(!value))    case _ =>      Apply(Select(tree, definitions.Boolean_not), List());  }  /** for tree of sequence type, returns tree that drops first i elements */  final def seqDrop(sel:Tree, ix: Int) = if (ix == 0) sel else     typed { Apply(Select(Select(sel, nme.toList), nme.drop),                  List(Literal(Constant(ix)))) }  /** for tree of sequence type, returns tree that drops first i elements */  final def seqElement(sel:Tree, ix: Int) =     typed { Apply(Select(sel, sel.tpe.member(nme.apply)), List(Literal(Constant(ix)))) }    /** for tree of sequence type, returns boolean tree that has length i */  final def seqHasLength(sel: Tree, ntpe: Type, i: Int) =     typed(      Equals(        Apply(Select(sel, ntpe.member(nme.lengthCompare)), List(Literal(Constant(i)))),        Literal(Constant(0))      )    )/*defs.Seq_length ?*/  /** for tree of sequence type sel, returns boolean tree testing that length >= i   */  final def seqLongerThan(sel:Tree, tpe:Type, i:Int) =     GreaterThanOrEquals(      typed(Apply(Select(sel, tpe.member(nme.lengthCompare)), List(Literal(Constant(i))))),      typed(Literal(Constant(0))))      //defs.Seq_length instead of tpe.member ?  final def Not(arg:Tree) = arg match {    case Literal(Constant(true))  => Literal(Constant(false))    case Literal(Constant(false)) => Literal(Constant(true))    case t                        => Select(arg, definitions.Boolean_not)  }  /*protected*/ def And(left: Tree, right: Tree): Tree = left match {    case Literal(Constant(value: Boolean)) =>      if (value) right else left    case _ =>       right match {        case Literal(Constant(true)) =>	  left        case _ =>          Apply(Select(left, definitions.Boolean_and), List(right))      }  }  /*protected*/final def Or(left: Tree, right: Tree): Tree = {    left match {/*      case If(cond: Tree, thenp: Tree, Literal(Constant(false))) =>  // little opt, frequent special case        If(cond, thenp, right)*/      case Literal(Constant(value: Boolean))=>    	if(value) left else right      case _ =>        right match {          case Literal(Constant(false)) =>	    left          case _ =>            Apply(Select(left, definitions.Boolean_or), List(right));        }    }  }    final def Equals(left: Tree, right: Tree): Tree =    Apply(Select(left, nme.EQEQ), List(right))  final def Eq(left: Tree, right: Tree): Tree =    Apply(Select(left, nme.eq), List(right))  final def GreaterThanOrEquals(left: Tree, right: Tree): Tree =    Apply(Select(left, nme.GE), List(right))  final def ThrowMatchError(pos: Position, obj: Tree) =    atPos(pos) {      Throw(        New(          TypeTree(definitions.MatchErrorClass.tpe),          List(List(            obj          ))))    }  final def NotNull(tree:Tree) =     typed {      Apply(Select(tree, nme.ne), List(Literal(Constant(null))))    }  final def IsNull(tree:Tree) =     typed {      Apply(Select(tree, nme.eq), List(Literal(Constant(null))))    }    // statistics    var nremoved = 0    var nsubstituted = 0    var nstatic = 0  final def squeezedBlock(vds: List[Tree], exp: Tree)(implicit theOwner: Symbol): Tree =     if (settings_squeeze)      squeezedBlock1(vds, exp)    else      Block(vds,exp)    final def squeezedBlock1(vds: List[Tree], exp: Tree)(implicit theOwner: Symbol): Tree = {    val tpe = exp.tpe    class RefTraverser(sym: Symbol) extends Traverser {      var nref = 0      var nsafeRef = 0      override def traverse(tree: Tree) = tree match {        case t:Ident if t.symbol eq sym =>           nref += 1          if(sym.owner == currentOwner)  { // oldOwner should match currentOwner            nsafeRef += 1          } /*else if(nref == 1) {            Console.println("sym owner: "+sym.owner+" but currentOwner = "+currentOwner)          }*/        case LabelDef(_,args,rhs) =>          var args1 = args; while(args1 ne Nil) {            if(args1.head.symbol eq sym) {              nref += 2   // will abort traversal, cannot substitute this one              args1 = Nil // break            } else {              args1 = args1.tail            }          }          traverse(rhs)        case t if nref > 1 =>          // abort, no story to tell        case t =>          super.traverse(t)      }    }    class Subst(sym: Symbol, rhs: Tree) extends Transformer {      var stop = false      override def transform(tree: Tree) = tree match {        case t:Ident if t.symbol == sym =>           stop = true          rhs        case t if stop =>          t        case t =>           super.transform(t)      }    }    vds match {      case Nil =>        exp      case (vd:ValDef) :: rest =>        // recurse        val exp1 = squeezedBlock(rest, exp)        //Console.println("squeezedBlock for valdef "+vd)        val sym = vd.symbol        val rt = new RefTraverser(sym)        rt.atOwner (theOwner) (rt.traverse(exp1))      //Console.println("hello, ref count = "+rt.nref+"/"+rt.nsafeRef)        rt.nref match {          case 0 =>            nremoved = nremoved + 1            exp1          case 1 if rt.nsafeRef == 1 =>            nsubstituted += 1            new Subst(sym, vd.rhs).transform(exp1)          case _ =>             exp1 match {              case Block(vds2, exp2) => Block(vd::vds2, exp2)                case exp2              => Block(vd::Nil,  exp2)              }        }      case x::xs =>         squeezedBlock(xs, exp) match {          case Block(vds2, exp2) => Block(x::vds2, exp2)           case exp2              => Block(x::Nil,  exp2)         }    }  }  final def debugStrings(tps:List[Type]):String = tps.foldLeft("[")({ (x:String,y:Type) => x+","+debugString(y) })+"]"  final def debugString(tp:Type):String = tp match {    case ErrorType => "ErrorType"    // internal: error    case WildcardType => "WildcardType"    // internal: unknown    case NoType => "NoType"    case NoPrefix => "NoPrefix"    case ThisType(sym) => "ThisType("+sym.toString+")"    // sym.this.type    case SingleType(pre, sym) => "SingleType("+debugString(pre)+","+sym+")"    // pre.sym.type    case ConstantType(value) => "ConstantType("+value+")"    // int(2)    case TypeRef(pre, sym, args) => "TypeRef("+debugString(pre)+","+sym.getClass()+"(=="+sym+")"+","+ debugStrings(args)+")"    // pre.sym[targs]    case RefinedType(parents, defs) => "RefinedType("+debugStrings(parents)+","+defs+")"    // parent1 with ... with parentn { defs }    case AnnotatedType(attribs, tp, selfsym) => "AnnotatedType("+attribs+","+ debugString(tp)+","+ selfsym+")"    // tp @attribs    case p:Product => tp.getClass.toString+"(=="+tp.toString+")"+runtime.ScalaRunTime._toString(p)        case _ => tp.getClass.toString+"(=="+tp.toString+")"    /*     // the following are non-value types; you cannot write them down in Scala source.          case TypeBounds(lo, hi) =>       // >: lo <: hi     case ClassInfoType(parents, defs, clazz) =>     // same as RefinedType except as body of class     case MethodType(paramtypes, result) =>     // (paramtypes)result     case PolyType(tparams, result) =>     // [tparams]result where result is a MethodType or ClassInfoType     // or     // []T  for a eval-by-name type     case ExistentialType(tparams, result) =>     // exists[tparams]result     */  }}

⌨️ 快捷键说明

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