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);
}
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, "();");
}
}
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);
}
Aggregations