public FunctionContext( TranslationContext translationContext, GimpleFunction gimpleFunction, JimpleMethodBuilder builder) { this.gimpleFunction = gimpleFunction; this.translationContext = translationContext; this.builder = builder; VarUsageInspector varUsage = new VarUsageInspector(gimpleFunction); for (GimpleVarDecl decl : gimpleFunction.getVariableDeclarations()) { Variable localVariable = translationContext .resolveType(decl.getType()) .createLocalVariable(this, decl.getName(), varUsage.getUsage(decl.getId())); symbolTable.put(decl.getId(), localVariable); } for (GimpleParameter param : gimpleFunction.getParameters()) { ImType type = translationContext.resolveType(param.getType()); builder.addParameter(type.paramType(), "p_" + param.getName()); ImExpr paramExpr = JvmExprs.toExpr(this, new JimpleExpr("p_" + param.getName()), type.paramType(), true); Variable variable = type.createLocalVariable(this, param.getName(), varUsage.getUsage(param.getId())); variable.writeAssignment(this, paramExpr); symbolTable.put(param.getId(), variable); } }
static JsExpression getRTTClassId( TranslationContext translationContext, ClassElement classElement) { JsName classJsName = translationContext.getNames().getName(classElement); JsProgram program = translationContext.getProgram(); JsStringLiteral clsid = program.getStringLiteral(classJsName.getShortIdent()); return call(null, nameref(null, "$cls"), clsid); }
private JsExpression generateRawInterfaceTypeComparison( JsExpression lhs, DartTypeNode typeNode, SourceInfo src) { ClassElement element = (ClassElement) typeNode.getType().getElement(); if (element.equals(typeProvider.getObjectType().getElement())) { // Everything is an object, including null return this.translationContext.getProgram().getTrueLiteral(); } String builtin = builtInTypeChecks.get(element); if (builtin != null) { return call(src, nameref(src, builtin), lhs); } // Due to implementing implied interfaces of classes, we always have to // use $implements$ rather than using JS instanceof for classes. // Inject: !!(tmp = target, tmp && tmp.$implements$type) JsProgram program = translationContext.getProgram(); JsName tmp = context.createTemporary(); String mangledClass = translationContext.getMangler().mangleClassName(element); return not( src, not( src, comma( src, assign(src, tmp.makeRef(), lhs), and( src, neq(src, tmp.makeRef().setSourceRef(src), program.getNullLiteral()), nameref(src, tmp, "$implements$" + mangledClass))))); }
public ImExpr lookupVar(GimpleExpr gimpleExpr) { if (gimpleExpr instanceof SymbolRef) { SymbolRef symbol = (SymbolRef) gimpleExpr; ImExpr variable = symbolTable.get(symbol.getId()); if (variable != null) { return variable; } if (symbol.getName() != null) { variable = translationContext.findGlobal(symbol.getName()); } if (variable == null) { throw new IllegalArgumentException( "No such variable '" + gimpleExpr + "' (id=" + symbol.getId() + ")"); } return variable; } else { throw new UnsupportedOperationException( "Expected GimpleVar, got: " + gimpleExpr + " [" + gimpleExpr.getClass().getSimpleName() + "]"); } }
public ImExpr resolveExpr(GimpleExpr gimpleExpr) { if (gimpleExpr instanceof GimpleMemRef) { return resolveExpr(((GimpleMemRef) gimpleExpr).getPointer()).memref(); } else if (gimpleExpr instanceof SymbolRef) { return lookupVar(gimpleExpr); } else if (gimpleExpr instanceof GimpleStringConstant) { return new ImStringConstant((GimpleStringConstant) gimpleExpr); } else if (gimpleExpr instanceof GimpleConstant) { return new ImPrimitiveConstant(this, (GimpleConstant) gimpleExpr); } else if (gimpleExpr instanceof GimpleAddressOf) { return resolveExpr(((GimpleAddressOf) gimpleExpr).getValue()).addressOf(); } else if (gimpleExpr instanceof GimpleFunctionRef) { return new ImFunctionExpr( translationContext.resolveMethod(((GimpleFunctionRef) gimpleExpr).getName())); } else if (gimpleExpr instanceof GimpleArrayRef) { GimpleArrayRef arrayRef = (GimpleArrayRef) gimpleExpr; return resolveExpr(arrayRef.getArray()).elementAt(resolveExpr(arrayRef.getIndex())); } else if (gimpleExpr instanceof GimpleComponentRef) { GimpleComponentRef componentRef = (GimpleComponentRef) gimpleExpr; return resolveExpr(componentRef.getValue()).member(componentRef.getMember()); } else if (gimpleExpr instanceof GimpleConstantRef) { return resolveExpr(((GimpleConstantRef) gimpleExpr).getValue()); } throw new UnsupportedOperationException(gimpleExpr.toString()); }
private void injectInterfaceMarkers(ClassElement classElement, SourceInfo srcRef) { JsProgram program = translationContext.getProgram(); JsName classJsName = translationContext.getNames().getName(classElement); for (InterfaceType iface : getAllInterfaces(classElement)) { JsStatement assignment = (JsStatement) newAssignment( newNameRef( newNameRef(new JsNameRef(classJsName), "prototype"), "$implements$" + translationContext .getMangler() .mangleClassName(iface.getElement())), program.getNumberLiteral(1)) .makeStmt() .setSourceRef(srcRef); globalBlock.getStatements().add(assignment); } }
RuntimeTypeInjector( TraversalContextProvider context, CoreTypeProvider typeProvider, TranslationContext translationContext, boolean emitTypeChecks) { this.context = context; this.translationContext = translationContext; JsProgram program = translationContext.getProgram(); this.globalBlock = program.getGlobalBlock(); this.globalScope = program.getScope(); this.builtInTypeChecks = makeBuiltinTypes(typeProvider); this.typeProvider = typeProvider; this.emitTypeChecks = emitTypeChecks; }
/** @return a JsArrayLiteral listing the type arguments for the interface instance. */ private JsExpression buildTypeArgsForFactory( FunctionType functionType, InterfaceType instanceType, List<? extends Type> listTypeVars, JsExpression contextTypeArgs) { if (functionType.getTypeVariables().size() == 0) { return null; } if (instanceType.hasDynamicTypeArgs()) { return translationContext.getProgram().getNullLiteral(); } JsArrayLiteral arr = new JsArrayLiteral(); for (Type type : instanceType.getArguments()) { JsExpression typeExpr = buildTypeLookupExpression(type, listTypeVars, contextTypeArgs); arr.getExpressions().add(typeExpr); } return arr; }
/** @return a JsArrayLiteral listing the type arguments for the interface instance. */ private JsExpression buildTypeArgs( InterfaceType instanceType, List<? extends Type> listTypeVars, JsExpression contextTypeArgs) { ClassElement classElement = instanceType.getElement(); if (!hasTypeParameters(classElement)) { return null; } if (instanceType.hasDynamicTypeArgs()) { JsProgram program = translationContext.getProgram(); return program.getNullLiteral(); } JsArrayLiteral arr = new JsArrayLiteral(); assert instanceType.getArguments().size() > 0; for (Type type : instanceType.getArguments()) { JsExpression typeExpr = buildTypeLookupExpression(type, listTypeVars, contextTypeArgs); arr.getExpressions().add(typeExpr); } return arr; }
/** @return js The expression used to lookup the RTT for the given type. */ private JsExpression buildTypeLookupExpression( Type type, List<? extends Type> list, JsExpression contextTypeArgs) { switch (TypeKind.of(type)) { case INTERFACE: InterfaceType interfaceType = (InterfaceType) type; JsInvocation callLookup = call(null, getRTTLookupMethodName(interfaceType.getElement())); if (hasTypeParameters(interfaceType.getElement()) && !interfaceType.hasDynamicTypeArgs()) { JsArrayLiteral typeArgs = new JsArrayLiteral(); for (Type arg : interfaceType.getArguments()) { typeArgs.getExpressions().add(buildTypeLookupExpression(arg, list, contextTypeArgs)); } callLookup.getArguments().add(typeArgs); } return callLookup; case FUNCTION_ALIAS: // TODO(johnlenz): implement this return newQualifiedNameRef("RTT.placeholderType"); case VARIABLE: TypeVariable var = (TypeVariable) type; JsProgram program = translationContext.getProgram(); int varIndex = 0; for (Type t : list) { if (t.equals(type)) { return call( null, newQualifiedNameRef("RTT.getTypeArg"), Cloner.clone(contextTypeArgs), program.getNumberLiteral(varIndex)); } varIndex++; } throw new AssertionError("unresolved type variable:" + var); default: throw new AssertionError("unexpected type kind:" + type.getKind()); } }
private void generateRTTLookupMethod(DartClass x) { ClassElement classElement = x.getSymbol(); boolean hasTypeParams = hasTypeParameters(classElement); // 1) create static type information construction function // function Foo$lookupOrCreateRTT(typeargs) { // return $createRTT(name, Foo$RTTimplements, typeargs) ; // } // Build the function JsFunction lookupFn = new JsFunction(globalScope); lookupFn.setBody(new JsBlock()); List<JsStatement> body = lookupFn.getBody().getStatements(); JsScope scope = new JsScope(globalScope, "temp"); JsProgram program = translationContext.getProgram(); JsInvocation invokeCreate = call(null, newQualifiedNameRef("RTT.create"), getRTTClassId(classElement)); List<JsExpression> callArgs = invokeCreate.getArguments(); if (hasRTTImplements(classElement)) { callArgs.add(getRTTImplementsMethodName(classElement)); } else if (hasTypeParams) { // need a placeholder param if the typeArgs are needed. callArgs.add(program.getNullLiteral()); } if (hasTypeParams) { JsName typeArgs = scope.declareName("typeArgs"); lookupFn.getParameters().add(new JsParameter(typeArgs)); callArgs.add(typeArgs.makeRef()); } body.add(new JsReturn(invokeCreate)); // Finally, Add the function JsExpression fnDecl = assign(null, getRTTLookupMethodName(classElement), lookupFn); globalBlock.getStatements().add(fnDecl.makeStmt()); }
/** @return an expression that implements a runtime "is" operation */ JsExpression generateInstanceOfComparison( ClassElement enclosingClass, JsExpression lhs, DartTypeNode typeNode, SourceInfo src) { ClassElement currentClass = enclosingClass; Type type = typeNode.getType(); switch (TypeKind.of(type)) { case INTERFACE: InterfaceType interfaceType = (InterfaceType) type; if (hasTypeParameters(interfaceType.getElement()) && !interfaceType.hasDynamicTypeArgs()) { return generateRefiedInterfaceTypeComparison(lhs, interfaceType, currentClass, src); } else { // TODO(johnlenz): special case "is Object"? return generateRawInterfaceTypeComparison(lhs, typeNode, src); } case VARIABLE: TypeVariable typeVar = (TypeVariable) type; return generateRefiedTypeVariableComparison(lhs, typeVar, currentClass, src); case DYNAMIC: JsProgram program = translationContext.getProgram(); return program.getTrueLiteral(); default: throw new IllegalStateException("unexpected"); } }
public MethodRef resolveMethod(GimpleCall call) { return translationContext.resolveMethod(call, getCallingConvention()); }
private JsNameRef getRTTAddToMethodName(ClassElement classElement) { return nameref(null, translationContext.getNames().getName(classElement), "$addTo"); }
private JsNameRef getRTTImplementsMethodName(ClassElement classElement) { return nameref(null, translationContext.getNames().getName(classElement), "$RTTimplements"); }
private JsNameRef getRTTLookupMethodName(ClassElement classElement) { return nameref(null, translationContext.getNames().getName(classElement), "$lookupRTT"); }