public static void compileToArray(Expression[] args, Compilation comp) { CodeAttr code = comp.getCode(); if (args.length == 0) { code.emitGetStatic(Compilation.noArgsField); return; } code.emitPushInt(args.length); code.emitNewArray(Type.pointer_type); for (int i = 0; i < args.length; ++i) { Expression arg = args[i]; if (comp.usingCPStyle() && !(arg instanceof QuoteExp) && !(arg instanceof ReferenceExp)) { // If the argument involves a CPStyle function call, we will // have to save and restore anything on the JVM stack into // fields in the CallFrame. This is expensive, so defer // pushing the duplicated argument array and the index // until *after* we've calculated the argument. The downside // is that we have to do some extra stack operations. // However, these are cheap (and get compiled away when // compiling to native code). arg.compileWithPosition(comp, Target.pushObject); code.emitSwap(); code.emitDup(1, 1); code.emitSwap(); code.emitPushInt(i); code.emitSwap(); } else { code.emitDup(Compilation.objArrayType); code.emitPushInt(i); arg.compileWithPosition(comp, Target.pushObject); } code.emitArrayStore(Type.pointer_type); } }
public void setLine(Compilation paramCompilation) { int i = paramCompilation.getLineNumber(); if (i > 0) { setFile(paramCompilation.getFileName()); setLine(i, paramCompilation.getColumnNumber()); } }
public final void compileNotePosition( Compilation paramCompilation, Target paramTarget, Expression paramExpression) { String str = paramCompilation.getFileName(); int i = paramCompilation.getLineNumber(); int j = paramCompilation.getColumnNumber(); paramCompilation.setLine(paramExpression); compile(paramCompilation, paramTarget); paramCompilation.setLine(str, i, j); }
public void emitTestIf(Variable incoming, Declaration decl, Compilation comp) { CodeAttr code = comp.getCode(); if (incoming != null) code.emitLoad(incoming); if (decl != null) { code.emitDup(); decl.compileStore(comp); } comp.compileConstant(this); code.emitSwap(); code.emitInvokeVirtual(isInstanceMethod); code.emitIfIntNotZero(); }
public ProcInitializer(LambdaExp paramLambdaExp, Compilation paramCompilation, Field paramField) { this.field = paramField; this.proc = paramLambdaExp; if (paramField.getStaticFlag()) {} for (paramLambdaExp = paramCompilation.getModule(); ((paramLambdaExp instanceof ModuleExp)) && (paramCompilation.isStatic()); paramLambdaExp = paramLambdaExp.getOwningLambda()) { this.next = paramCompilation.clinitChain; paramCompilation.clinitChain = this; return; } this.next = paramLambdaExp.initChain; paramLambdaExp.initChain = this; }
public final void compileWithPosition(Compilation paramCompilation, Target paramTarget) { int i = getLineNumber(); if (i > 0) { paramCompilation.getCode().putLineNumber(getFileName(), i); compileNotePosition(paramCompilation, paramTarget, this); return; } compile(paramCompilation, paramTarget); }
@Test public void testCompile() throws Exception { Compilation compilation = Compile.compile( IO.load("test1.java"), IO.load("mixin.java"), "public class Book { String title; int x = 1234; } class Foo {}", "public class Bar extends Foo {}", "public class Fg extends Foo {}"); Set<Class<?>> classes = compilation.loadClasses(); eq(classes.size(), 10); Set<String> classNames = compilation.getClassNames(); D.print(classNames); eq(Cls.classMap(classes).get("Main").getAnnotations().length, 2); Set<String> expectedClasses = U.set( "abc.Main", "abc.Main$1", "abc.Person", "abc.Person$Insider", "abc.PersonService", "Book", "Foo", "Bar", "Fg", "mixo.Mixin"); eq(classNames, expectedClasses); for (String clsName : expectedClasses) { Class<?> cls = compilation.loadClass(clsName); notNull(cls); eq(cls.getName(), clsName); } Class<?> mainClass = compilation.loadClass("abc.Main"); Method main = Cls.getMethod(mainClass, "main", String[].class); Cls.invoke(main, null, new Object[] {new String[] {}}); }
public void compile(Compilation compilation, Target target) { compilation.getCode(); if (result == null) { target = QuoteExp.voidExp; } else { target = result; } target.compileWithPosition(compilation, block.exitTarget); block.exitableBlock.exit(); }
public static Expression makeWhile( Object paramObject1, Object paramObject2, Compilation paramCompilation) { Expression[] arrayOfExpression = new Expression[1]; LetExp localLetExp = new LetExp(arrayOfExpression); Declaration localDeclaration = localLetExp.addDeclaration("%do%loop"); ApplyExp localApplyExp = new ApplyExp(new ReferenceExp(localDeclaration), noExpressions); LambdaExp localLambdaExp = new LambdaExp(); paramCompilation.push(localLambdaExp); localLambdaExp.body = new IfExp( paramCompilation.parse(paramObject1), new BeginExp(paramCompilation.parse(paramObject2), localApplyExp), QuoteExp.voidExp); localLambdaExp.setName("%do%loop"); paramCompilation.pop(localLambdaExp); arrayOfExpression[0] = localLambdaExp; localDeclaration.noteValue(localLambdaExp); localLetExp.setBody(new ApplyExp(new ReferenceExp(localDeclaration), noExpressions)); return localLetExp; }
public void emit(Compilation paramCompilation) { CodeAttr localCodeAttr = paramCompilation.getCode(); if (!this.field.getStaticFlag()) { localCodeAttr.emitPushThis(); } emitLoadModuleMethod(this.proc, paramCompilation); if (this.field.getStaticFlag()) { localCodeAttr.emitPutStatic(this.field); return; } localCodeAttr.emitPutField(this.field); }
public void reportError(String paramString, Compilation paramCompilation) { String str1 = paramCompilation.getFileName(); int i = paramCompilation.getLineNumber(); int j = paramCompilation.getColumnNumber(); paramCompilation.setLocation(this.proc); String str2 = this.proc.getName(); paramString = new StringBuffer(paramString); if (str2 == null) { paramString.append("unnamed procedure"); } for (;;) { paramCompilation.error('e', paramString.toString()); paramCompilation.setLine(str1, i, j); return; paramString.append("procedure "); paramString.append(str2); } }
public static void emitLoadModuleMethod(LambdaExp paramLambdaExp, Compilation paramCompilation) { Object localObject3 = paramLambdaExp.nameDecl; Object localObject1; CodeAttr localCodeAttr; Object localObject2; label61: label129: label150: label178: int i; if (localObject3 == null) { localObject1 = paramLambdaExp.getName(); localCodeAttr = null; localObject2 = localCodeAttr; if (paramCompilation.immediate) { localObject2 = localCodeAttr; if (localObject1 != null) { localObject2 = localCodeAttr; if (localObject3 != null) { localObject3 = Environment.getCurrent(); if (!(localObject1 instanceof Symbol)) { break label353; } localObject2 = (Symbol)localObject1; localObject3 = ((Environment)localObject3).get((Symbol)localObject2, paramCompilation.getLanguage().getEnvPropertyFor(paramLambdaExp.nameDecl), null); localObject2 = localCodeAttr; if ((localObject3 instanceof ModuleMethod)) { localObject2 = (ModuleMethod)localObject3; } } } } localCodeAttr = paramCompilation.getCode(); localObject3 = Compilation.typeModuleMethod; if (localObject2 != null) { break label369; } localCodeAttr.emitNew((ClassType)localObject3); localCodeAttr.emitDup(1); localObject2 = "<init>"; localObject3 = ((ClassType)localObject3).getDeclaredMethod((String)localObject2, 4); if (!paramLambdaExp.getNeedsClosureEnv()) { break label385; } localObject2 = paramLambdaExp.getOwningLambda(); if ((!(localObject2 instanceof ClassExp)) || (((LambdaExp)localObject2).staticLinkField == null)) { break label393; } localCodeAttr.emitLoad(localCodeAttr.getCurrentScope().getVariable(1)); localCodeAttr.emitPushInt(paramLambdaExp.getSelectorValue(paramCompilation)); paramCompilation.compileConstant(localObject1, Target.pushObject); int j = paramLambdaExp.min_args; if (paramLambdaExp.keywords != null) { break label583; } i = paramLambdaExp.max_args; label215: localCodeAttr.emitPushInt(i << 12 | j); localCodeAttr.emitInvoke((Method)localObject3); if (paramLambdaExp.properties == null) { return; } j = paramLambdaExp.properties.length; i = 0; label252: if (i >= j) { return; } localObject2 = paramLambdaExp.properties[i]; if ((localObject2 != null) && (localObject2 != PropertySet.nameKey)) { localObject1 = paramLambdaExp.properties[(i + 1)]; localCodeAttr.emitDup(1); paramCompilation.compileConstant(localObject2); localObject2 = Target.pushObject; if (!(localObject1 instanceof Expression)) { break label589; } ((Expression)localObject1).compile(paramCompilation, (Target)localObject2); } } for (;;) { localCodeAttr.emitInvokeVirtual(ClassType.make("gnu.mapping.PropertySet").getDeclaredMethod("setProperty", 2)); i += 2; break label252; localObject1 = ((Declaration)localObject3).getSymbol(); break; label353: localObject2 = Symbol.make("", localObject1.toString().intern()); break label61; label369: paramCompilation.compileConstant(localObject2, Target.pushValue((Type)localObject3)); localObject2 = "init"; break label129; label385: localObject2 = paramCompilation.getModule(); break label150; label393: if ((!(localObject2 instanceof ModuleExp)) || ((paramCompilation.moduleClass == paramCompilation.mainClass) && (!paramCompilation.method.getStaticFlag()))) { localCodeAttr.emitPushThis(); break label178; } if (paramCompilation.moduleInstanceVar == null) { paramCompilation.moduleInstanceVar = localCodeAttr.locals.current_scope.addVariable(localCodeAttr, paramCompilation.moduleClass, "$instance"); if ((paramCompilation.moduleClass == paramCompilation.mainClass) || (paramCompilation.isStatic())) { break label571; } localCodeAttr.emitNew(paramCompilation.moduleClass); localCodeAttr.emitDup(paramCompilation.moduleClass); localCodeAttr.emitInvokeSpecial(paramCompilation.moduleClass.constructor); paramCompilation.moduleInstanceMainField = paramCompilation.moduleClass.addField("$main", paramCompilation.mainClass, 0); localCodeAttr.emitDup(paramCompilation.moduleClass); localCodeAttr.emitPushThis(); localCodeAttr.emitPutField(paramCompilation.moduleInstanceMainField); } for (;;) { localCodeAttr.emitStore(paramCompilation.moduleInstanceVar); localCodeAttr.emitLoad(paramCompilation.moduleInstanceVar); break; label571: localCodeAttr.emitGetStatic(paramCompilation.moduleInstanceMainField); } label583: i = -1; break label215; label589: paramCompilation.compileConstant(localObject1, (Target)localObject2); } }
static void compile(ApplyExp exp, Compilation comp, Target target, boolean checkInlineable) { int args_length = exp.args.length; Expression exp_func = exp.func; LambdaExp func_lambda = null; String func_name = null; Declaration owner = null; Object quotedValue = null; if (exp_func instanceof LambdaExp) { func_lambda = (LambdaExp) exp_func; func_name = func_lambda.getName(); if (func_name == null) func_name = "<lambda>"; } else if (exp_func instanceof ReferenceExp) { ReferenceExp func_ref = (ReferenceExp) exp_func; owner = func_ref.contextDecl(); Declaration func_decl = func_ref.binding; while (func_decl != null && func_decl.isAlias() && func_decl.value instanceof ReferenceExp) { func_ref = (ReferenceExp) func_decl.value; if (owner != null || func_decl.needsContext() || func_ref.binding == null) break; func_decl = func_ref.binding; owner = func_ref.contextDecl(); } if (!func_decl.getFlag(Declaration.IS_UNKNOWN)) { Expression value = func_decl.getValue(); func_name = func_decl.getName(); if (value != null && value instanceof LambdaExp) func_lambda = (LambdaExp) value; if (value != null && value instanceof QuoteExp) quotedValue = ((QuoteExp) value).getValue(); } } else if (exp_func instanceof QuoteExp) { quotedValue = ((QuoteExp) exp_func).getValue(); } if (checkInlineable && quotedValue instanceof Procedure) { Procedure proc = (Procedure) quotedValue; if (target instanceof IgnoreTarget && proc.isSideEffectFree()) { for (int i = 0; i < args_length; i++) exp.args[i].compile(comp, target); return; } try { if (inlineCompile(proc, exp, comp, target)) return; } catch (Throwable ex) { comp.getMessages() .error('e', "caught exception in inline-compiler for " + quotedValue + " - " + ex, ex); return; } } gnu.bytecode.CodeAttr code = comp.getCode(); Method method; if (func_lambda != null) { if ((func_lambda.max_args >= 0 && args_length > func_lambda.max_args) || args_length < func_lambda.min_args) // This is supposed to get caught by InlineCalls. throw new Error("internal error - wrong number of parameters for " + func_lambda); int conv = func_lambda.getCallConvention(); // Mostly duplicates logic with LambdaExp.validateApply. // See comment there. if (comp.inlineOk(func_lambda) && (conv <= Compilation.CALL_WITH_CONSUMER || (conv == Compilation.CALL_WITH_TAILCALLS && !exp.isTailCall())) && (method = func_lambda.getMethod(args_length)) != null) { PrimProcedure pproc = new PrimProcedure(method, func_lambda); boolean is_static = method.getStaticFlag(); boolean extraArg = false; // ?? Procedure.checkArgCount(this, args.length); // FIXME if (!is_static || func_lambda.declareClosureEnv() != null) { if (is_static) extraArg = true; if (comp.curLambda == func_lambda) // Recursive call. code.emitLoad( func_lambda.closureEnv != null ? func_lambda.closureEnv : func_lambda.thisVariable); else if (owner != null) owner.load(null, 0, comp, Target.pushObject); else func_lambda.getOwningLambda().loadHeapFrame(comp); } pproc.compile(extraArg ? Type.voidType : null, exp, comp, target); return; } } /* if (comp.usingCPStyle()) { { Label l = new Label(code); gnu.bytecode.SwitchState fswitch = comp.fswitch; int pc = fswitch.getMaxValue() + 1; fswitch.addCase(pc, code, l); exp_func.compile(comp, new StackTarget(Compilation.typeProcedure)); comp.loadCallContext(); // Emit: context->pc = pc. comp.loadCallContext(); code.emitPushInt(pc); code.emitPutField(Compilation.pcCallContextField); code.emitInvokeVirtual(Compilation.applyCpsMethod); // emit[save java stack, if needed] Type[] stackTypes = code.saveStackTypeState(false); java.util.Stack stackFields = new java.util.Stack(); if (stackTypes != null) { for (int i = stackTypes.length; --i >= 0; ) { Field fld = comp.allocLocalField (stackTypes[i], null); code.emitPushThis(); code.emitSwap(); code.emitPutField(fld); stackFields.push(fld); } } code.emitReturn(); l.define(code); // emit[restore java stack, if needed] if (stackTypes != null) { for (int i = stackTypes.length; --i >= 0; ) { Field fld = (Field) stackFields.pop(); code.emitPushThis(); code.emitGetField(fld); comp.freeLocalField(fld); } } // FIXME // Load result from stack.value to target. comp.loadCallContext(); code.emitGetField(comp.valueCallContextField); target.compileFromStack(comp, Type.pointer_type); } return; } */ // Check for tail-recursion. boolean tail_recurse = exp.isTailCall() && func_lambda != null && func_lambda == comp.curLambda; if (func_lambda != null && func_lambda.getInlineOnly() && !tail_recurse && func_lambda.min_args == args_length) { pushArgs(func_lambda, exp.args, null, comp); if (func_lambda.getFlag(LambdaExp.METHODS_COMPILED)) { popParams(code, func_lambda, null, false); code.emitTailCall(false, func_lambda.getVarScope()); return; } func_lambda.flags |= LambdaExp.METHODS_COMPILED; LambdaExp saveLambda = comp.curLambda; comp.curLambda = func_lambda; func_lambda.allocChildClasses(comp); func_lambda.allocParameters(comp); popParams(code, func_lambda, null, false); func_lambda.enterFunction(comp); func_lambda.body.compileWithPosition(comp, target); func_lambda.compileEnd(comp); func_lambda.generateApplyMethods(comp); code.popScope(); comp.curLambda = saveLambda; return; } if (comp.curLambda.isHandlingTailCalls() && (exp.isTailCall() || target instanceof ConsumerTarget) && !comp.curLambda.getInlineOnly()) { ClassType typeContext = Compilation.typeCallContext; exp_func.compile(comp, new StackTarget(Compilation.typeProcedure)); // evaluate args to frame-locals vars; // may recurse! if (args_length <= 4) { for (int i = 0; i < args_length; ++i) exp.args[i].compileWithPosition(comp, Target.pushObject); comp.loadCallContext(); code.emitInvoke( Compilation.typeProcedure.getDeclaredMethod("check" + args_length, args_length + 1)); } else { compileToArray(exp.args, comp); comp.loadCallContext(); code.emitInvoke(Compilation.typeProcedure.getDeclaredMethod("checkN", 2)); } if (exp.isTailCall()) { code.emitReturn(); } else if (((ConsumerTarget) target).isContextTarget()) { comp.loadCallContext(); code.emitInvoke(typeContext.getDeclaredMethod("runUntilDone", 0)); } else { comp.loadCallContext(); code.emitLoad(((ConsumerTarget) target).getConsumerVariable()); code.emitInvoke(typeContext.getDeclaredMethod("runUntilValue", 1)); } return; } if (!tail_recurse) exp_func.compile(comp, new StackTarget(Compilation.typeProcedure)); boolean toArray = (tail_recurse ? func_lambda.min_args != func_lambda.max_args : args_length > 4); int[] incValues = null; // Increments if we can use iinc. if (toArray) { compileToArray(exp.args, comp); method = Compilation.applyNmethod; } else if (tail_recurse) { incValues = new int[exp.args.length]; pushArgs(func_lambda, exp.args, incValues, comp); method = null; } else { for (int i = 0; i < args_length; ++i) { exp.args[i].compileWithPosition(comp, Target.pushObject); if (!code.reachableHere()) break; } method = Compilation.applymethods[args_length]; } if (!code.reachableHere()) { comp.error('e', "unreachable code"); return; } if (tail_recurse) { popParams(code, func_lambda, incValues, toArray); code.emitTailCall(false, func_lambda.getVarScope()); return; } code.emitInvokeVirtual(method); target.compileFromStack(comp, Type.pointer_type); }
public void compileFromStack(Compilation comp, Type stackType) { if (!stackType.isVoid()) comp.getCode().emitPop(1); }