@NotNull private JsInvocation getNamespaceDeclaration() { JsInvocation namespaceDeclaration = namespaceCreateMethodInvocation(); namespaceDeclaration.getArguments().add(translateNamespaceMemberDeclarations()); namespaceDeclaration.getArguments().add(getClassesAndNestedNamespaces()); return namespaceDeclaration; }
/** Add runtime type information to a "new" expression, if necessary. */ void mayAddRuntimeTypeToConstrutorOrFactoryCall( ClassElement enclosingClass, DartNewExpression x, JsInvocation invoke) { // TODO(johnlenz):in optimized mode, only add this where it is needed. InterfaceType instanceType = Types.constructorType(x); if (instanceType == null) { // TODO(johnlenz): HackHack. Currently the "new FallThroughError" injected by the // Normalizer does not have the instance type attached. But in this // case we know it does not have any type parameters. // reportError(x.getParent().getParent(), new AssertionError("missing type information")); assert typeProvider .getFallThroughError() .getElement() .lookupConstructor("") .equals(x.getSymbol()); } else if (constructorHasTypeParameters(x)) { ConstructorElement constructor = x.getSymbol(); ClassElement containingClassElement = enclosingClass; if (constructor.getModifiers().isFactory()) { // We are calling a factory, this is either in a class FunctionType functionType = (FunctionType) constructor.getType(); JsExpression typeArgs = generateTypeArgsArrayForFactory(functionType, instanceType, containingClassElement); assert typeArgs != null; invoke.getArguments().add(0, typeArgs); } else { ClassElement constructorClassElement = constructor.getConstructorType(); invoke .getArguments() .add( 0, generateRTTLookup(constructorClassElement, instanceType, containingClassElement)); } } }
private void generateRTTImplementsMethod(DartClass x) { ClassElement classElement = x.getSymbol(); // 1) create static type information construction function // function Foo$lookupOrCreateRTT(rtt, typeArgs) { // // // superclass // FooSuper$addTo(rtt, superTypeArg1, ...); // // interfaces // FooInterface1$addTo(rtt, interface1TypeArg1, ...); // // // fill in derived types // rtt.derivedTypes = [ // FirstRef$lookupOrCreateRTT(typearg1, ...), // ... // ] // } boolean hasTypeParams = classElement.getTypeParameters().size() > 0; // Build the function JsFunction implementsFn = new JsFunction(globalScope); implementsFn.setBody(new JsBlock()); List<JsStatement> body = implementsFn.getBody().getStatements(); JsScope scope = new JsScope(globalScope, "temp"); JsName rtt = scope.declareName("rtt"); implementsFn.getParameters().add(new JsParameter(rtt)); JsName typeArgs = null; if (hasTypeParams) { typeArgs = scope.declareName("typeArgs"); implementsFn.getParameters().add(new JsParameter(typeArgs)); } JsInvocation callAddTo = newInvocation(getRTTAddToMethodName(classElement), rtt.makeRef()); if (hasTypeParams) { typeArgs = scope.declareName("typeArgs"); callAddTo.getArguments().add(typeArgs.makeRef()); } body.add(callAddTo.makeStmt()); // Add the derived types if (hasTypeParams) { // Populated the list of derived types JsArrayLiteral derivedTypesArray = new JsArrayLiteral(); // TODO(johnlenz): Add needed types here. JsExpression addDerivedTypes = assign(null, nameref(null, rtt.makeRef(), "derivedTypes"), derivedTypesArray); body.add(addDerivedTypes.makeStmt()); } // Finally, Add the function JsExpression fnDecl = assign(null, getRTTImplementsMethodName(classElement), implementsFn); globalBlock.getStatements().add(fnDecl.makeStmt()); }
private JsExpression generateRTTLookup( ClassElement classElement, InterfaceType instanceType, ClassElement contextClassElement) { JsInvocation invokeLookup = call(null, getRTTLookupMethodName(classElement)); if (hasTypeParameters(instanceType.getElement()) && !instanceType.hasDynamicTypeArgs()) { JsExpression typeArgs = generateTypeArgsArray(instanceType, contextClassElement); assert typeArgs != null; invokeLookup.getArguments().add(typeArgs); } return invokeLookup; }
/** Add a runtime type information to a map literal, if necessary. */ void maybeAddRuntimeTypeToMapLiteralConstructor( ClassElement enclosingClass, DartMapLiteral x, JsInvocation invoke) { // TODO(johnlenz):in optimized mode, only add this where it is needed. // Fixup the type for map literal type to be the implementing type. List<? extends Type> typeArgs = x.getType().getArguments(); InterfaceType instanceType = typeProvider.getMapLiteralType(typeArgs.get(0), typeArgs.get(1)); JsExpression rtt = generateRTTLookup(instanceType, enclosingClass); invoke.getArguments().add(rtt); }
/** @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()); }
private void generateRTTAddToMethod(DartClass x) { ClassElement classElement = x.getSymbol(); // 2) create "addTo" method // Foo$Type$addTo(target, typeargs) { // var rtt = Foo$lookupOrCreateRTT(typeargs) // target.implementedTypes[rtt.classkey] = rtt; // } // Build the function JsFunction addToFn = new JsFunction(globalScope); addToFn.setBody(new JsBlock()); JsScope scope = new JsScope(globalScope, "temp"); JsName targetType = scope.declareName("target"); addToFn.getParameters().add(new JsParameter(targetType)); // Get the RTT info object JsName rtt = scope.declareName("rtt"); List<JsStatement> body = addToFn.getBody().getStatements(); JsInvocation callLookup = newInvocation(getRTTLookupMethodName(classElement)); if (hasTypeParameters(classElement)) { JsName typeArgs = scope.declareName("typeArgs"); addToFn.getParameters().add(new JsParameter(typeArgs)); callLookup.getArguments().add(new JsNameRef(typeArgs)); } JsStatement rttLookup = newVar((SourceInfo) null, rtt, callLookup); body.add(rttLookup); // store it. JsExpression addToTypes = newAssignment( new JsArrayAccess( newNameRef(targetType.makeRef(), "implementedTypes"), newNameRef(rtt.makeRef(), "classKey")), rtt.makeRef()); body.add(addToTypes.makeStmt()); InterfaceType superType = classElement.getSupertype(); if (superType != null && !superType.getElement().isObject()) { ClassElement interfaceElement = superType.getElement(); JsInvocation callAddTo = newInvocation(getRTTAddToMethodName(interfaceElement), targetType.makeRef()); if (hasTypeParameters(interfaceElement) && !superType.hasDynamicTypeArgs()) { JsArrayLiteral superTypeArgs = new JsArrayLiteral(); List<? extends Type> typeParams = classElement.getTypeParameters(); for (Type arg : superType.getArguments()) { superTypeArgs .getExpressions() .add( buildTypeLookupExpression( arg, typeParams, nameref(null, targetType.makeRef(), "typeArgs"))); } callAddTo.getArguments().add(superTypeArgs); } body.add(callAddTo.makeStmt()); } // Add the interfaces for (InterfaceType interfaceType : classElement.getInterfaces()) { ClassElement interfaceElement = interfaceType.getElement(); JsInvocation callAddTo = call(null, getRTTAddToMethodName(interfaceElement), targetType.makeRef()); if (hasTypeParameters(interfaceElement) && !interfaceType.hasDynamicTypeArgs()) { JsArrayLiteral interfaceTypeArgs = new JsArrayLiteral(); List<? extends Type> typeParams = classElement.getTypeParameters(); for (Type arg : interfaceType.getArguments()) { interfaceTypeArgs .getExpressions() .add( buildTypeLookupExpression( arg, typeParams, nameref(null, targetType.makeRef(), "typeArgs"))); } callAddTo.getArguments().add(interfaceTypeArgs); } body.add(callAddTo.makeStmt()); } // Add the function statement JsExpression fnDecl = newAssignment(getRTTAddToMethodName(classElement), addToFn); globalBlock.getStatements().add(fnDecl.makeStmt()); }