Search in sources :

Example 1 with SuperVisitor

use of org.eclipse.ceylon.compiler.js.GenerateJsVisitor.SuperVisitor in project ceylon by eclipse.

the class TypeGenerator method interfaceDefinition.

static void interfaceDefinition(final Tree.InterfaceDefinition that, final GenerateJsVisitor gen, InitDeferrer initDeferrer) {
    // Don't even bother with nodes that have errors
    if (errVisitor.hasErrors(that))
        return;
    final Interface d = that.getDeclarationModel();
    // If it's inside a dynamic interface, don't generate anything
    if (d.isClassOrInterfaceMember() && ((ClassOrInterface) d.getContainer()).isDynamic())
        return;
    final Interface natd = (Interface) ModelUtil.getNativeDeclaration(d, Backend.JavaScript);
    final boolean headerWithoutBackend = NativeUtil.isHeaderWithoutBackend(that, Backend.JavaScript);
    if (natd != null && (headerWithoutBackend || NativeUtil.isNativeHeader(that))) {
        // It's a native header, remember it for later when we deal with its implementation
        gen.saveNativeHeader(that);
        return;
    }
    if (!(NativeUtil.isForBackend(that, Backend.JavaScript) || headerWithoutBackend)) {
        return;
    }
    gen.comment(that);
    gen.out(GenerateJsVisitor.function, gen.getNames().name(d));
    final boolean withTargs = generateParameters(that.getTypeParameterList(), null, d, gen);
    gen.beginBlock();
    final List<Declaration> superDecs = new ArrayList<>(3);
    if (!gen.opts.isOptimize()) {
        new SuperVisitor(superDecs).visit(that.getInterfaceBody());
    }
    final Tree.SatisfiedTypes sats = that.getSatisfiedTypes();
    if (withTargs) {
        gen.out(gen.getClAlias(), "set_type_args(", gen.getNames().self(d), ",$$targs$$,", gen.getNames().name(d), ")");
        gen.endLine(true);
    }
    callSupertypes(sats == null ? null : TypeUtils.getTypes(sats.getTypes()), null, d, that, superDecs, null, null, gen);
    if (!d.isToplevel() && d.getContainer() instanceof Function && !((Function) d.getContainer()).getTypeParameters().isEmpty()) {
        gen.out(gen.getClAlias(), "set_type_args(", gen.getNames().self(d), ",", gen.getNames().typeArgsParamName((Function) d.getContainer()), ",", gen.getNames().name(d), ")");
        gen.endLine(true);
    }
    final List<Tree.Statement> stmts;
    if (NativeUtil.isForBackend(d, Backend.JavaScript)) {
        Tree.Declaration nh = gen.getNativeHeader(d);
        if (nh == null && NativeUtil.hasNativeMembers(d)) {
            nh = that;
        }
        stmts = NativeUtil.mergeStatements(that.getInterfaceBody(), nh, Backend.JavaScript);
    } else {
        stmts = that.getInterfaceBody().getStatements();
    }
    gen.visitStatements(stmts);
    // returnSelf(d);
    gen.endBlockNewLine();
    if (d.isDynamic()) {
        // Add the list of expected members here
        final List<Declaration> members = d.getMembers();
        gen.out(gen.getNames().name(d), ".dynmem$=[");
        if (members.isEmpty()) {
            gen.out("];");
        } else {
            gen.out("'");
            boolean first = true;
            for (Declaration m : members) {
                if (first)
                    first = false;
                else
                    gen.out("','");
                gen.out(gen.getNames().name(m));
            }
            gen.out("'];");
        }
    }
    // Add reference to metamodel
    gen.out(gen.getNames().name(d), ".$crtmm$=");
    TypeUtils.encodeForRuntime(that, d, that.getAnnotationList(), gen);
    gen.endLine(true);
    gen.share(d);
    initializeType(that, gen, initDeferrer);
}
Also used : Function(org.eclipse.ceylon.model.typechecker.model.Function) SuperVisitor(org.eclipse.ceylon.compiler.js.GenerateJsVisitor.SuperVisitor) ArrayList(java.util.ArrayList) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)

Example 2 with SuperVisitor

use of org.eclipse.ceylon.compiler.js.GenerateJsVisitor.SuperVisitor in project ceylon by eclipse.

the class Singletons method defineObject.

/**
 * Generate an object definition, that is, define an anonymous class and then a function
 * to return a single instance of it.
 * @param that The node with the definition (can be ObjectDefinition, ObjectExpression, ObjectArgument)
 * @param d The Value declaration for the object
 * @param sats The list of satisfied types of the anonymous class
 * @param superType The supertype of the anonymous class
 * @param superCall The invocation of the supertype (object bla extends Foo(x))
 * @param body The object definition's body
 * @param annots The annotations (in case of ObjectDefinition)
 * @param gen The main visitor/generator.
 */
static void defineObject(final Node that, final Value d, final List<Type> sats, final Tree.SimpleType superType, final Tree.InvocationExpression superCall, final Tree.Body body, final Tree.AnnotationList annots, final GenerateJsVisitor gen, InitDeferrer initDeferrer) {
    final boolean addToPrototype = gen.opts.isOptimize() && d != null && d.isClassOrInterfaceMember();
    final boolean isObjExpr = that instanceof Tree.ObjectExpression;
    final TypeDeclaration _td = isObjExpr ? ((Tree.ObjectExpression) that).getAnonymousClass() : d.getTypeDeclaration();
    final Class c = (Class) (_td instanceof Constructor ? _td.getContainer() : _td);
    final String className = gen.getNames().name(c);
    final String objectName = gen.getNames().name(d);
    final String selfName = gen.getNames().self(c);
    final Value natd = d == null ? null : (Value) ModelUtil.getNativeDeclaration(d, Backend.JavaScript);
    if (that instanceof Tree.Declaration) {
        if (NativeUtil.isNativeHeader((Tree.Declaration) that) && natd != null) {
            // It's a native header, remember it for later when we deal with its implementation
            gen.saveNativeHeader((Tree.Declaration) that);
            return;
        }
        if (!(NativeUtil.isForBackend((Tree.Declaration) that, Backend.JavaScript) || NativeUtil.isHeaderWithoutBackend((Tree.Declaration) that, Backend.JavaScript))) {
            return;
        }
    }
    final List<Tree.Statement> stmts;
    if (d != null && NativeUtil.isForBackend(d, Backend.JavaScript)) {
        Tree.Declaration nh = gen.getNativeHeader(d);
        if (nh == null && NativeUtil.hasNativeMembers(c) && that instanceof Tree.Declaration) {
            nh = (Tree.Declaration) that;
        }
        stmts = NativeUtil.mergeStatements(body, nh, Backend.JavaScript);
    } else {
        stmts = body.getStatements();
    }
    Map<TypeParameter, Type> targs = new HashMap<>();
    if (sats != null) {
        for (Type st : sats) {
            Map<TypeParameter, Type> stargs = st.getTypeArguments();
            if (stargs != null && !stargs.isEmpty()) {
                targs.putAll(stargs);
            }
        }
    }
    gen.out(GenerateJsVisitor.function, className, targs.isEmpty() ? "()" : "($$targs$$)");
    gen.beginBlock();
    if (isObjExpr) {
        gen.out("var ", selfName, "=new ", className, ".$$;");
        final ClassOrInterface coi = ModelUtil.getContainingClassOrInterface(c.getContainer());
        if (coi != null) {
            gen.out(selfName, ".outer$=", gen.getNames().self(coi));
            gen.endLine(true);
        }
    } else {
        if (c.isMember() && !d.isStatic()) {
            gen.initSelf(that);
        }
        gen.instantiateSelf(c);
        gen.referenceOuter(c);
    }
    // TODO should we generate all this code for native headers?
    // Really we should merge the body of the header with that of the impl
    // It's the only way to make this shit work in lexical scope mode
    final List<Declaration> superDecs = new ArrayList<>();
    if (!gen.opts.isOptimize()) {
        final SuperVisitor superv = new SuperVisitor(superDecs);
        for (Tree.Statement st : stmts) {
            st.visit(superv);
        }
    }
    if (!targs.isEmpty()) {
        gen.out(selfName, ".$$targs$$=$$targs$$");
        gen.endLine(true);
    }
    TypeGenerator.callSupertypes(sats, superType, c, that, superDecs, superCall, superType == null ? null : ((Class) c.getExtendedType().getDeclaration()).getParameterList(), gen);
    gen.visitStatements(stmts);
    gen.out("return ", selfName, ";");
    gen.endBlock();
    gen.out(";", className, ".$crtmm$=");
    TypeUtils.encodeForRuntime(that, c, gen);
    gen.endLine(true);
    TypeGenerator.initializeType(that, gen, initDeferrer);
    final String objvar = (addToPrototype ? "this." : "") + gen.getNames().createTempVariable();
    if (d != null && !addToPrototype) {
        gen.out("var ", objvar);
        // If it's a property, create the object here
        if (AttributeGenerator.defineAsProperty(d)) {
            gen.out("=", className, "(");
            if (!targs.isEmpty()) {
                TypeUtils.printTypeArguments(that, targs, gen, false, null);
            }
            gen.out(")");
        }
        gen.endLine(true);
    }
    if (d != null && AttributeGenerator.defineAsProperty(d)) {
        gen.out(gen.getClAlias(), "atr$(");
        gen.outerSelf(d);
        gen.out(",'", objectName, "',function(){return ");
        if (addToPrototype) {
            gen.out("this.", gen.getNames().privateName(d));
        } else {
            gen.out(objvar);
        }
        gen.out(";},undefined,");
        TypeUtils.encodeForRuntime(that, d, annots, gen);
        gen.out(")");
        gen.endLine(true);
    } else if (d != null) {
        final String objectGetterName = gen.getNames().getter(d, false);
        gen.out(GenerateJsVisitor.function, objectGetterName, "()");
        gen.beginBlock();
        // Create the object lazily
        final String oname = gen.getNames().objectName(c);
        gen.out("if(", objvar, "===", gen.getClAlias(), "INIT$)");
        gen.generateThrow(gen.getClAlias() + "InitializationError", "Cyclic initialization trying to read the value of '" + d.getName() + "' before it was set", that);
        gen.endLine(true);
        gen.out("if(", objvar, "===undefined){", objvar, "=", gen.getClAlias(), "INIT$;", objvar, "=$init$", oname);
        if (!oname.endsWith("()")) {
            gen.out("()");
        }
        gen.out("(");
        if (!targs.isEmpty()) {
            TypeUtils.printTypeArguments(that, targs, gen, false, null);
        }
        gen.out(");", objvar, ".$crtmm$=", objectGetterName, ".$crtmm$;}");
        gen.endLine();
        gen.out("return ", objvar, ";");
        gen.endBlockNewLine();
        if (addToPrototype || d.isShared()) {
            gen.outerSelf(d);
            gen.out(".", objectGetterName, "=", objectGetterName);
            gen.endLine(true);
        }
        if (!d.isToplevel()) {
            if (gen.outerSelf(d))
                gen.out(".");
        }
        gen.out(objectGetterName, ".$crtmm$=");
        TypeUtils.encodeForRuntime(that, d, annots, gen);
        gen.endLine(true);
        gen.out(gen.getNames().getter(c, true), "=", objectGetterName);
        gen.endLine(true);
        if (d.isToplevel()) {
            final String objectGetterNameMM = gen.getNames().getter(d, true);
            gen.out("ex$.", objectGetterNameMM, "=", objectGetterNameMM);
            gen.endLine(true);
        }
    } else if (isObjExpr) {
        gen.out("return ", className, "();");
    }
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) SuperVisitor(org.eclipse.ceylon.compiler.js.GenerateJsVisitor.SuperVisitor) HashMap(java.util.HashMap) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) ArrayList(java.util.ArrayList) Type(org.eclipse.ceylon.model.typechecker.model.Type) Value(org.eclipse.ceylon.model.typechecker.model.Value) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) Class(org.eclipse.ceylon.model.typechecker.model.Class) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 3 with SuperVisitor

use of org.eclipse.ceylon.compiler.js.GenerateJsVisitor.SuperVisitor in project ceylon by eclipse.

the class ClassGenerator method callSupertypes.

public static void callSupertypes(Tree.ClassDefinition that, Class d, String typeName, GenerateJsVisitor gen) {
    final List<Declaration> superDecs = new ArrayList<Declaration>(3);
    if (!gen.opts.isOptimize()) {
        that.getClassBody().visit(new SuperVisitor(superDecs));
    }
    final Tree.ExtendedType extendedType = that.getExtendedType();
    final Tree.SatisfiedTypes sats = that.getSatisfiedTypes();
    TypeGenerator.callSupertypes(sats == null ? null : TypeUtils.getTypes(sats.getTypes()), extendedType == null ? null : extendedType.getType(), d, that, superDecs, extendedType == null ? null : extendedType.getInvocationExpression(), extendedType == null ? null : ((Class) d.getExtendedType().getDeclaration()).getParameterList(), gen);
}
Also used : SuperVisitor(org.eclipse.ceylon.compiler.js.GenerateJsVisitor.SuperVisitor) ArrayList(java.util.ArrayList) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) Class(org.eclipse.ceylon.model.typechecker.model.Class) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration)

Aggregations

ArrayList (java.util.ArrayList)3 SuperVisitor (org.eclipse.ceylon.compiler.js.GenerateJsVisitor.SuperVisitor)3 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)3 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)3 Class (org.eclipse.ceylon.model.typechecker.model.Class)2 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)2 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)2 HashMap (java.util.HashMap)1 Constructor (org.eclipse.ceylon.model.typechecker.model.Constructor)1 Function (org.eclipse.ceylon.model.typechecker.model.Function)1 Interface (org.eclipse.ceylon.model.typechecker.model.Interface)1 Type (org.eclipse.ceylon.model.typechecker.model.Type)1 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)1 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)1 Value (org.eclipse.ceylon.model.typechecker.model.Value)1