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))))); }
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()); }
@Nullable public JsPropertyInitializer translate( @NotNull JetClassOrObject declaration, TranslationContext context) { ClassDescriptor descriptor = getClassDescriptor(context().bindingContext(), declaration); JsExpression value; if (descriptor.getModality() == Modality.FINAL) { value = new ClassTranslator(declaration, classDescriptorToQualifiedLabel, context).translate(); } else { String label = createNameForClass(descriptor); JsName name = dummyFunction.getScope().declareName(label); JsNameRef qualifiedLabel = openClassDescriptorToQualifiedLabel.get(descriptor); if (qualifiedLabel == null) { qualifiedLabel = new JsNameRef(name); openClassDescriptorToQualifiedLabel.put(descriptor, qualifiedLabel); } else { qualifiedLabel.resolve(name); } qualifiedLabel.setQualifier(declarationsObjectRef); OpenClassInfo item = new OpenClassInfo((JetClass) declaration, descriptor, name.makeRef()); openList.add(item); openClassDescriptorToItem.put(descriptor, item); value = qualifiedLabel; // not public api classes referenced to internal var _c if (!descriptor.getVisibility().isPublicAPI()) { return null; } } return InitializerUtils.createPropertyInitializer(descriptor, value, context()); }
public ClassDeclarationTranslator(@NotNull TranslationContext context) { super(context); dummyFunction = new JsFunction(context.scope()); JsName declarationsObject = context().scope().declareName(Namer.nameForClassesVariable()); classesVar = new JsVars.JsVar(declarationsObject); declarationsObjectRef = declarationsObject.makeRef(); }
/** Add the appropriate code to a class's constructing factory, if necessary. */ void maybeAddClassRuntimeTypeToConstructor( ClassElement classElement, JsFunction factory, JsExpression thisRef) { // TODO(johnlenz):in optimized mode, only add this where it is needed. JsScope factoryScope = factory.getScope(); JsExpression typeInfo; if (hasTypeParameters(classElement)) { JsName typeinfoParameter = factoryScope.declareName("$rtt"); factory.getParameters().add(0, new JsParameter(typeinfoParameter)); typeInfo = typeinfoParameter.makeRef(); } else { // TODO(johnlenz): this is a constant value, it only needs to be evaluated once. typeInfo = generateRawRTTLookup(classElement); } JsExpression setTypeInfo = assign(null, nameref(null, Cloner.clone(thisRef), "$typeInfo"), typeInfo); factory.getBody().getStatements().add(0, setTypeInfo.makeStmt()); }
@Nullable private JsNameRef getTargetLabel(@NotNull Node statementWithLabel) { int type = statementWithLabel.getType(); if (type != TokenStream.BREAK && type != TokenStream.CONTINUE) { String tokenTypeName = TokenStream.tokenToName(statementWithLabel.getType()); throw new AssertionError("Unexpected node type with label: " + tokenTypeName); } Node label = statementWithLabel.getFirstChild(); if (label == null) return null; String identifier = label.getString(); assert identifier != null : "If label exists identifier should not be null"; JsName labelName = scopeContext.labelFor(identifier); assert labelName != null : "Unknown label name: " + identifier; return labelName.makeRef(); }
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()); }
@NotNull public JsPropertyInitializer getDeclarationAsInitializer() { return new JsPropertyInitializer(namespaceName.makeRef(), getNamespaceDeclaration()); }
@NotNull public JsNameRef nameReference() { return variableName.makeRef(); }
/*package*/ TemporaryVariable( @NotNull JsName temporaryName, @NotNull JsExpression initExpression) { this.variableName = temporaryName; this.assignmentExpression = AstUtil.newAssignment(variableName.makeRef(), initExpression); }
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()); }