public JsFunction mapFunction(Node fnNode) throws JsParserException { int nodeType = fnNode.getType(); assert nodeType == TokenStream.FUNCTION : "Expected function node, got: " + TokenStream.tokenToName(nodeType); Node fromFnNameNode = fnNode.getFirstChild(); Node fromParamNode = fnNode.getFirstChild().getNext().getFirstChild(); Node fromBodyNode = fnNode.getFirstChild().getNext().getNext(); JsFunction toFn = scopeContext.enterFunction(); // Decide the function's name, if any. // String fnNameIdent = fromFnNameNode.getString(); if (fnNameIdent != null && fnNameIdent.length() > 0) { scopeContext.globalNameFor(fnNameIdent); } while (fromParamNode != null) { String fromParamName = fromParamNode.getString(); JsName name = scopeContext.localNameFor(fromParamName); toFn.getParameters().add(new JsParameter(name)); fromParamNode = fromParamNode.getNext(); } // Map the function's body. // JsBlock toBody = mapBlock(fromBodyNode); toFn.setBody(toBody); scopeContext.exitFunction(); return toFn; }
/** Add a type arguments parameter to a factory method, if necessary. */ void maybeAddTypeParameterToFactory(DartMethodDefinition method, JsFunction factory) { // TODO(johnlenz):in optimized mode, only add this where it is needed. if (isParameterizedFactoryMethod(method)) { JsScope scope = factory.getScope(); JsName typeArgs = scope.declareName("$typeArgs"); factory.getParameters().add(0, new JsParameter(typeArgs)); } }
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()); }
@NotNull @Override public JsFunction deepCopy() { JsFunction functionCopy = new JsFunction(scope.getParent(), scope.getDescription(), name); functionCopy.getScope().copyOwnNames(scope); functionCopy.setBody(body.deepCopy()); functionCopy.params = AstUtil.deepCopy(params); return functionCopy.withMetadataFrom(this); }
@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()); }
/** 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()); }
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()); }
public void generateDeclarations() { List<JsVar> vars = new SmartList<JsVar>(); List<JsPropertyInitializer> propertyInitializers = new SmartList<JsPropertyInitializer>(); generateOpenClassDeclarations(vars, propertyInitializers); fixUnresolvedClassReferences(); if (vars.isEmpty()) { if (!propertyInitializers.isEmpty()) { classesVar.setInitExpression(new JsObjectLiteral(propertyInitializers, true)); } return; } dummyFunction.setBody( new JsBlock( new JsVars(vars, true), new JsReturn(new JsObjectLiteral(propertyInitializers)))); classesVar.setInitExpression(new JsInvocation(dummyFunction)); }
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()); }