patternnodes.scala

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

SCALA
245
字号
/* NSC -- new Scala compiler * Copyright 2005-2007 LAMP/EPFL * @author Burak Emir */// $Id: PatternNodes.scala 14520 2008-04-07 04:10:08Z emir $package scala.tools.nsc.matchingimport scala.tools.nsc.util.{Position, NoPosition}/** *  @author Burak Emir */trait PatternNodes { self: transform.ExplicitOuter =>  import global._                      object TagIndexPair {    /** inserts tag and index, maintaining relative order of tags */  def insert(current: TagIndexPair, tag: Int, index: Int): TagIndexPair = {    if (current eq null)      new TagIndexPair(tag, index, null)    else if (tag > current.tag)       new TagIndexPair(current.tag, current.index, insert(current.next, tag, index))    else      new TagIndexPair(tag, index, current)    }  }   /** sorted, null-terminated list of (int,int) pairs */  class TagIndexPair(val tag: Int, val index: Int, val next: TagIndexPair) {    def find(tag: Int): Int =      if (this.tag == tag) index      else next.find(tag) // assumes argument can always be found  }  // --- misc methods  private val dummy1 = EmptyTree :: Nil  private val dummy2 = EmptyTree :: dummy1  private val dummy3 = EmptyTree :: dummy2  private val dummy4 = EmptyTree :: dummy3  private val dummy5 = EmptyTree :: dummy4  private val dummy6 = EmptyTree :: dummy5  private val dummy7 = EmptyTree :: dummy6  final def getDummies(i:Int): List[Tree] = i match {    case 0 => Nil    case 1 => dummy1    case 2 => dummy2    case 3 => dummy3    case 4 => dummy4    case 5 => dummy5    case 6 => dummy6    case 7 => dummy7    case n => EmptyTree::getDummies(i-1)  }  def makeBind(vs:SymList, pat:Tree): Tree =     if(vs eq Nil) pat else Bind(vs.head, makeBind(vs.tail, pat)) setType pat.tpe  def normalizedListPattern(pats:List[Tree], tptArg:Type): Tree = pats match {    case Nil   => gen.mkAttributedRef(definitions.NilModule)    case sp::xs if strip2(sp).isInstanceOf[Star] =>       makeBind(definedVars(sp), Ident(nme.WILDCARD) setType sp.tpe)    case x::xs =>       var resType: Type = null;      val consType: Type = definitions.ConsClass.primaryConstructor.tpe match {        case mt @ MethodType(args, res @ TypeRef(pre,sym,origArgs)) =>          val listType = TypeRef(pre, definitions.ListClass, List(tptArg))               resType = TypeRef(pre, sym                  , List(tptArg))                  MethodType(List(tptArg, listType), resType)      }      Apply(TypeTree(consType),List(x,normalizedListPattern(xs,tptArg))).setType(resType)  }  object Apply_Value {    def unapply(x:Apply) = if (!x.fun.isType && x.args.isEmpty) Some(x.tpe.prefix, x.symbol) else None  }                     object Apply_CaseClass_NoArgs {    def unapply(x:Apply) = if (x.fun.isType && x.args.isEmpty) Some(x.tpe) else None  }  object Apply_CaseClass_WithArgs {    def unapply(x:Apply) = x.fun.isType  }  object __UnApply {    def unapply(x:Tree) = strip(x) match {      case (vs, UnApply(Apply(fn, _), args)) =>         val argtpe = fn.tpe.asInstanceOf[MethodType].paramTypes.head        Some(Tuple3(vs,argtpe,args))      case _                      => None    }  }/*  object ArrayValueFixed {    def unapply(x:Tree):Option[List[Tree]] = x match {      case ArrayValue(_,xs) => if(isDefaultPattern(xs.last)) Some(xs) else None    }  }  object ArrayValueStar {    def unapply(x:Tree): Option[(List[Tree],Tree)] = x match {      case ArrayValue(_,xs) =>         val ys = xs.drop(xs.length-1)         val p = xs.last        if(!isDefaultPattern(p)) Some(ys,p) else None    }  }*/  /* equality checks for named constant patterns like "Foo()" are encoded as "_:<equals>[Foo().type]"   * and later compiled to "if(Foo() == scrutinee) ...". This method extracts type information from   * such an encoded type, which is used in optimization. If the argument is not an encoded equals   *  test, it is returned as is.   */  def patternType_wrtEquals(pattpe:Type) = pattpe match {    case TypeRef(_,sym,arg::Nil) if sym eq definitions.EqualsPatternClass =>       arg    case x => x  }  /** returns if pattern can be considered a no-op test ??for expected type?? */  final def isDefaultPattern(pattern:Tree): Boolean = pattern match {    case Bind(_, p)            => isDefaultPattern(p)    case EmptyTree             => true // dummy    case Ident(nme.WILDCARD)   => true    case _                     => false// -- what about the following? still have to test "ne null" :///  case Typed(nme.WILDCARD,_) => pattern.tpe <:< scrutinee.tpe  }  final def DBG(x:String) { if (settings_debug) Console.println(x) }  /** returns all variables that are binding the given pattern    *  @param   x a pattern   *  @return  vs variables bound, p pattern proper   */  final def strip(x: Tree): (Set[Symbol], Tree) = x match {    case b @ Bind(_,pat) => val (vs, p) = strip(pat); (vs + b.symbol, p)    case z               => (emptySymbolSet,z)  }  final def strip1(x: Tree): Set[Symbol] = x match { // same as strip(x)._1    case b @ Bind(_,pat) => strip1(pat) + b.symbol    case z               => emptySymbolSet  }  final def strip2(x: Tree): Tree = x match {        // same as strip(x)._2    case     Bind(_,pat) => strip2(pat)    case z               => z  }  final def isCaseClass(tpe: Type): Boolean =     tpe match {      case TypeRef(_, sym, _) =>        if(!sym.isAliasType)           sym.hasFlag(symtab.Flags.CASE)        else          tpe.normalize.typeSymbol.hasFlag(symtab.Flags.CASE)      case _ => false    }   final def isEqualsPattern(tpe: Type): Boolean =     tpe match {      case TypeRef(_, sym, _) => sym eq definitions.EqualsPatternClass      case _                  => false    }  //  this method obtains tag method in a defensive way  final def getCaseTag(x:Type): Int = { x.typeSymbol.tag }  final def definedVars(x:Tree): SymList = {    var vs = new collection.mutable.ListBuffer[Symbol]    def definedVars1(x:Tree): Unit = x match {      case Alternative(bs) => ; // must not have any variables      case Apply(_, args)  => definedVars2(args)      case b @ Bind(_,p)   => vs += b.symbol; definedVars1(p)       case Ident(_)        => ;      case Literal(_)      => ;      case Select(_,_)     => ;      case Typed(p,_)      => definedVars1(p) //otherwise x @ (_:T)      case UnApply(_,args) => definedVars2(args)            // regexp specific      case ArrayValue(_,xs)=> definedVars2(xs)      case Star(p)         => ; // must not have variables    }    def definedVars2(args:List[Tree]): Unit = {      var xs = args; while(xs ne Nil) { definedVars1(xs.head); xs = xs.tail };    }    definedVars1(x);    vs.toList  }  // insert in sorted list, larger items first  final def insertSorted(tag: Int, xs:List[Int]):List[Int] = xs match {     case y::ys if y > tag => y::insertSorted(tag, ys)    case ys               => tag :: ys  }   // find taag in sorted list  final def findSorted(Tag: Int, xs:List[Int]): Boolean = xs match {     case Tag::_             => true    case   y::ys if y > Tag => findSorted(Tag,ys)    case _                  => false  }   /** pvar: the symbol of the pattern variable   *  temp: the temp variable that holds the actual value   *  next: next binding   */  case class Binding(pvar:Symbol, temp:Symbol, next: Binding) {    def add(vs:Iterator[Symbol], temp:Symbol): Binding = {      var b = this; while(vs.hasNext){        b = Binding(vs.next, temp, b)      }      return b    }    /** this is just to produce debug output, ListBuffer needs an equals method?! */    override def equals(x:Any) = {      x match {        case NoBinding               => false        case Binding(pv2,tmp2,next2) => (pvar eq pv2) && (temp eq tmp2) && (next==next2)      }    }    def apply(v:Symbol): Ident = {      //Console.println(this.toString()+" apply ("+v+"), eq?"+(v eq pvar))      if(v eq pvar) {Ident(temp).setType(v.tpe)} else next(v)    }  }  object NoBinding extends Binding(null,null,null) {    override def apply(v:Symbol) = null // not found, means bound elsewhere (x @ unapply-call)    override def toString = "."    override def equals(x:Any) = x.isInstanceOf[Binding] && (x.asInstanceOf[Binding] eq this)  }  // misc methods END ---  type SymSet  = collection.immutable.Set[Symbol]  type SymList = List[Symbol]}

⌨️ 快捷键说明

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