genicode.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 1,653 行 · 第 1/5 页

SCALA
1,653
字号
            ctx1.bb.emit(CALL_PRIMITIVE(ArrayLength(DOUBLE)), tree.pos)          case OARRAY_LENGTH =>            ctx1.bb.emit(CALL_PRIMITIVE(ArrayLength(ANY_REF_CLASS)), tree.pos)          case ZARRAY_GET =>            ctx1.bb.emit(LOAD_ARRAY_ITEM(BOOL), tree.pos)          case BARRAY_GET =>            ctx1.bb.emit(LOAD_ARRAY_ITEM(BYTE), tree.pos)          case SARRAY_GET =>            ctx1.bb.emit(LOAD_ARRAY_ITEM(SHORT), tree.pos)          case CARRAY_GET =>            ctx1.bb.emit(LOAD_ARRAY_ITEM(CHAR), tree.pos)          case IARRAY_GET =>            ctx1.bb.emit(LOAD_ARRAY_ITEM(INT), tree.pos)          case LARRAY_GET =>            ctx1.bb.emit(LOAD_ARRAY_ITEM(LONG), tree.pos)          case FARRAY_GET =>            ctx1.bb.emit(LOAD_ARRAY_ITEM(FLOAT), tree.pos)          case DARRAY_GET =>            ctx1.bb.emit(LOAD_ARRAY_ITEM(DOUBLE), tree.pos)          case OARRAY_GET =>            ctx1.bb.emit(LOAD_ARRAY_ITEM(ANY_REF_CLASS), tree.pos)          case ZARRAY_SET =>            ctx1.bb.emit(STORE_ARRAY_ITEM(BOOL), tree.pos)          case BARRAY_SET =>            ctx1.bb.emit(STORE_ARRAY_ITEM(BYTE), tree.pos)          case SARRAY_SET =>            ctx1.bb.emit(STORE_ARRAY_ITEM(SHORT), tree.pos)          case CARRAY_SET =>            ctx1.bb.emit(STORE_ARRAY_ITEM(CHAR), tree.pos)          case IARRAY_SET =>            ctx1.bb.emit(STORE_ARRAY_ITEM(INT), tree.pos)          case LARRAY_SET =>            ctx1.bb.emit(STORE_ARRAY_ITEM(LONG), tree.pos)          case FARRAY_SET =>            ctx1.bb.emit(STORE_ARRAY_ITEM(FLOAT), tree.pos)          case DARRAY_SET =>            ctx1.bb.emit(STORE_ARRAY_ITEM(DOUBLE), tree.pos)          case OARRAY_SET =>            ctx1.bb.emit(STORE_ARRAY_ITEM(ANY_REF_CLASS), tree.pos)          case _ =>            abort("Unknown operation on arrays: " + tree + " code: " + code)        }        ctx1      }      // genLoad      val resCtx: Context = tree match {        case LabelDef(name, params, rhs) =>          val ctx1 = ctx.newBlock          if (isLoopHeaderLabel(name))            ctx1.bb.loopHeader = true;          ctx1.labels.get(tree.symbol) match {            case Some(label) =>              label.anchor(ctx1.bb)              label.patch(ctx.method.code)            case None =>              ctx1.labels += (tree.symbol -> (new Label(tree.symbol) anchor ctx1.bb setParams (params map (_.symbol))));              ctx.method.addLocals(params map (p => new Local(p.symbol, toTypeKind(p.symbol.info), false)));              if (settings.debug.value)                log("Adding label " + tree.symbol);          }          ctx.bb.emit(JUMP(ctx1.bb), tree.pos)          ctx.bb.close          genLoad(rhs, ctx1, expectedType /*toTypeKind(tree.symbol.info.resultType)*/)        case ValDef(_, nme.THIS, _, _) =>          if (settings.debug.value) log("skipping trivial assign to _$this: " + tree)          ctx        case ValDef(_, _, _, rhs) =>          val sym = tree.symbol          val local = ctx.method.addLocal(new Local(sym, toTypeKind(sym.info), false))          ctx.scope.add(local)          ctx.bb.emit(SCOPE_ENTER(local))          if (rhs == EmptyTree) {            if (settings.debug.value)              log("Uninitialized variable " + tree + " at: " + (tree.pos));            ctx.bb.emit(getZeroOf(local.kind))          }          var ctx1 = ctx          if (rhs != EmptyTree)            ctx1 = genLoad(rhs, ctx, local.kind);          ctx1.bb.emit(STORE_LOCAL(local), tree.pos)          generatedType = UNIT          ctx1        case If(cond, thenp, elsep) =>          var thenCtx = ctx.newBlock          var elseCtx = ctx.newBlock          val contCtx = ctx.newBlock            genCond(cond, ctx, thenCtx, elseCtx)          val ifKind = toTypeKind(tree.tpe)          val thenKind = toTypeKind(thenp.tpe)          val elseKind = if (elsep == EmptyTree) UNIT else toTypeKind(elsep.tpe)          generatedType = ifKind          // we need to drop unneeded results, if one branch gives          // unit and the other gives something on the stack, because          // the type of 'if' is scala.Any, and its erasure would be Object.          // But unboxed units are not Objects...          if (thenKind == UNIT || elseKind == UNIT) {            if (settings.debug.value)              log("Will drop result from an if branch");            thenCtx = genLoad(thenp, thenCtx, UNIT)            elseCtx = genLoad(elsep, elseCtx, UNIT)            if (settings.debug.value)              assert(expectedType == UNIT,                     "I produce UNIT in a context where " +                     expectedType + " is expected!")            generatedType = UNIT          } else {            thenCtx = genLoad(thenp, thenCtx, ifKind)            elseCtx = genLoad(elsep, elseCtx, ifKind)          }          thenCtx.bb.emit(JUMP(contCtx.bb))          thenCtx.bb.close          if (elsep == EmptyTree)            elseCtx.bb.emit(JUMP(contCtx.bb), tree.pos)          else            elseCtx.bb.emit(JUMP(contCtx.bb))          elseCtx.bb.close          contCtx        case Return(expr) =>          val returnedKind = toTypeKind(expr.tpe)          var ctx1 = genLoad(expr, ctx, returnedKind)          val oldcleanups = ctx1.cleanups          lazy val tmp = ctx1.makeLocal(tree.pos, expr.tpe, "tmp")          var saved = false                    for (op <- ctx1.cleanups) op match {            case MonitorRelease(m) =>              if (settings.debug.value) log("removing " + m + " from cleanups: " + ctx1.cleanups)              ctx1.bb.emit(LOAD_LOCAL(m))              ctx1.bb.emit(MONITOR_EXIT())              ctx1.exitSynchronized(m)            case Finalizer(f) =>              if (settings.debug.value) log("removing " + f + " from cleanups: " + ctx1.cleanups)              if (returnedKind != UNIT && mayCleanStack(f) && !saved) {                ctx1.bb.emit(STORE_LOCAL(tmp))                saved = true              }              // we have to run this without the same finalizer in              // the list, otherwise infinite recursion happens for              // finalizers that contain 'return'              ctx1 = genLoad(f, ctx1.removeFinalizer(f), UNIT)          }          ctx1.cleanups = oldcleanups          if (saved) ctx1.bb.emit(LOAD_LOCAL(tmp))          ctx1.bb.emit(RETURN(returnedKind), tree.pos)          ctx1.bb.enterIgnoreMode          generatedType = expectedType          ctx1        case Try(block, catches, finalizer) =>          val kind = toTypeKind(tree.tpe)          var tmp: Local = null          val guardResult = kind != UNIT && mayCleanStack(finalizer)           if (guardResult) {            tmp = ctx.makeLocal(tree.pos, tree.tpe, "tmp")          }                    var handlers = for (CaseDef(pat, _, body) <- catches.reverse)            yield pat match {              case Typed(Ident(nme.WILDCARD), tpt) => (tpt.tpe.typeSymbol, kind, {                ctx: Context =>                  ctx.bb.emit(DROP(REFERENCE(tpt.tpe.typeSymbol)));                  val ctx1 = genLoad(body, ctx, kind);                  if (guardResult) {                    ctx1.bb.emit(STORE_LOCAL(tmp))                    val ctx2 = genLoad(finalizer, ctx1, UNIT)                    ctx2.bb.emit(LOAD_LOCAL(tmp))                    ctx2                  } else                    genLoad(finalizer, ctx1, UNIT);                })              case Ident(nme.WILDCARD) => (definitions.ThrowableClass, kind, {                ctx: Context =>                  ctx.bb.emit(DROP(REFERENCE(definitions.ThrowableClass)))                  val ctx1 = genLoad(body, ctx, kind)                  if (guardResult) {                    ctx1.bb.emit(STORE_LOCAL(tmp))                    val ctx2 = genLoad(finalizer, ctx1, UNIT)                    ctx2.bb.emit(LOAD_LOCAL(tmp))                    ctx2                  } else                    genLoad(finalizer, ctx1, UNIT)                })              case Bind(name, _) =>                val exception = ctx.method.addLocal(new Local(pat.symbol, toTypeKind(pat.symbol.tpe), false))                (pat.symbol.tpe.typeSymbol, kind, {                  ctx: Context =>                    ctx.bb.emit(STORE_LOCAL(exception), pat.pos);                    val ctx1 = genLoad(body, ctx, kind);                    if (guardResult) {                      ctx1.bb.emit(STORE_LOCAL(tmp))                      val ctx2 = genLoad(finalizer, ctx1, UNIT)                      ctx2.bb.emit(LOAD_LOCAL(tmp))                      ctx2                    } else                      genLoad(finalizer, ctx1, UNIT);                })            }          val duppedFinalizer = (new DuplicateLabels(ctx.labels.keySet))(ctx, finalizer)          if (settings.debug.value)            log("Duplicated finalizer: " + duppedFinalizer)          ctx.Try(            bodyCtx => {              generatedType = kind; //toTypeKind(block.tpe);              val ctx1 = genLoad(block, bodyCtx, generatedType);              if (guardResult) {                val tmp = ctx1.makeLocal(tree.pos, tree.tpe, "tmp")                ctx1.bb.emit(STORE_LOCAL(tmp))                val ctx2 = genLoad(duppedFinalizer, ctx1, UNIT)                ctx2.bb.emit(LOAD_LOCAL(tmp))                ctx2              } else                genLoad(duppedFinalizer, ctx1, UNIT)            },            handlers,            finalizer)        case Throw(expr) =>          val ctx1 = genLoad(expr, ctx, THROWABLE)          ctx1.bb.emit(THROW(), tree.pos)          ctx1.bb.enterIgnoreMode          generatedType = SCALA_ALL          ctx1        case New(tpt) =>          abort("Unexpected New")        case Apply(TypeApply(fun, targs), _) =>          val sym = fun.symbol          var ctx1 = ctx          var cast = false          if (sym == definitions.Object_isInstanceOf)             cast = false          else if (sym == definitions.Object_asInstanceOf)            cast = true          else            abort("Unexpected type application " + fun + "[sym: " + sym.fullNameString + "]" + " in: " + tree)          val Select(obj, _) = fun          val l = toTypeKind(obj.tpe)          val r = toTypeKind(targs.head.tpe)          ctx1 = genLoadQualifier(fun, ctx)          if (l.isValueType && r.isValueType)            genConversion(l, r, ctx1, cast)          else if (l.isValueType) {            ctx1.bb.emit(DROP(l), fun.pos)            if (cast) {              ctx1.bb.emit(NEW(REFERENCE(definitions.getClass("ClassCastException"))))              ctx1.bb.emit(DUP(ANY_REF_CLASS))              ctx1.bb.emit(THROW())            } else              ctx1.bb.emit(CONSTANT(Constant(false)))          }          else if (r.isValueType && cast) {            assert(false) /* Erasure should have added an unboxing operation to prevent that. */          }          else if (r.isValueType)            ctx.bb.emit(IS_INSTANCE(REFERENCE(definitions.boxedClass(r.toType.typeSymbol))))          else            genCast(l, r, ctx1, cast);          generatedType = if (cast) r else BOOL;          ctx1        // 'super' call: Note: since constructors are supposed to         // return an instance of what they construct, we have to take        // special care. On JVM they are 'void', and Scala forbids (syntactically)        // to call super constructors explicitly and/or use their 'returned' value.        // therefore, we can ignore this fact, and generate code that leaves nothing        // on the stack (contrary to what the type in the AST says).        case Apply(fun @ Select(Super(_, mix), _), args) =>          if (settings.debug.value)            log("Call to super: " + tree);          val invokeStyle = SuperCall(mix)//            if (fun.symbol.isConstructor) Static(true) else SuperCall(mix);          ctx.bb.emit(THIS(ctx.clazz.symbol), tree.pos)          val ctx1 = genLoadArguments(args, fun.symbol.info.paramTypes, ctx)          ctx1.bb.emit(CALL_METHOD(fun.symbol, invokeStyle), tree.pos)          generatedType =            if (fun.symbol.isConstructor) UNIT            else toTypeKind(fun.symbol.info.resultType)          ctx1        // 'new' constructor call: Note: since constructors are        // thought to return an instance of what they construct,        // we have to 'simulate' it by DUPlicating the freshly created        // instance (on JVM, <init> methods return VOID).        case Apply(fun @ Select(New(tpt), nme.CONSTRUCTOR), args) =>          val ctor = fun.symbol          if (settings.debug.value)            assert(ctor.isClassConstructor,                   "'new' call to non-constructor: " + ctor.name)          generatedType = toTypeKind(fun.tpe.resultType)          if (settings.debug.value)            assert(generatedType.isReferenceType || generatedType.isArrayType,                 "Non reference type cannot be instantiated: " + generatedType)          var ctx1 = ctx          generatedType match {            case arr @ ARRAY(elem) =>              ctx1 = genLoadArguments(args, ctor.info.paramTypes, ctx)

⌨️ 快捷键说明

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