use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.SpecifierOrInitializerExpression in project ceylon by eclipse.
the class GenerateJsVisitor method visit.
@Override
public void visit(final Tree.AttributeDeclaration that) {
if (errVisitor.hasErrors(that) || !TypeUtils.acceptNative(that))
return;
final Value d = that.getDeclarationModel();
// Check if the attribute corresponds to a class parameter
// This is because of the new initializer syntax
final Parameter param = d.isParameter() ? ((Functional) d.getContainer()).getParameter(d.getName()) : null;
final boolean asprop = AttributeGenerator.defineAsProperty(d);
if (d.isFormal()) {
if (!opts.isOptimize()) {
comment(that);
AttributeGenerator.generateAttributeMetamodel(that, false, false, this);
}
} else if (!d.isStatic()) {
SpecifierOrInitializerExpression specInitExpr = that.getSpecifierOrInitializerExpression();
final boolean addGetter = specInitExpr != null || param != null || !d.isMember() || d.isVariable() || d.isLate();
boolean setterGend = false;
if (opts.isOptimize() && d.isClassOrInterfaceMember()) {
// Stitch native member attribute declaration with no value
final boolean eagerExpr = specInitExpr != null && !(specInitExpr instanceof LazySpecifierExpression);
if (eagerExpr && !TypeUtils.isNativeExternal(d)) {
comment(that);
outerSelf(d);
out(".", names.privateName(d), "=");
if (d.isLate()) {
out("undefined");
} else {
super.visit(specInitExpr);
}
endLine(true);
}
} else if (specInitExpr instanceof LazySpecifierExpression) {
comment(that);
if (asprop) {
defineAttribute(names.self((TypeDeclaration) d.getContainer()), names.name(d));
out("{");
} else {
out(function, names.getter(d, false), "(){");
}
initSelf(that);
boolean genatr = true;
if (TypeUtils.isNativeExternal(d)) {
if (stitchNative(d, that)) {
if (verboseStitcher) {
spitOut("Stitching in native attribute " + d.getQualifiedNameString() + ", ignoring Ceylon declaration");
}
genatr = false;
out(";};");
}
}
if (genatr) {
out("return ");
if (!isNaturalLiteral(specInitExpr.getExpression().getTerm())) {
visitSingleExpression(specInitExpr.getExpression());
}
out("}");
if (asprop) {
Tree.AttributeSetterDefinition setterDef = null;
if (d.isVariable()) {
setterDef = associatedSetterDefinition(d);
if (setterDef != null) {
out(",function(", names.name(setterDef.getDeclarationModel().getParameter()), ")");
AttributeGenerator.setter(setterDef, this);
}
}
if (setterDef == null) {
out(",undefined");
}
out(",");
TypeUtils.encodeForRuntime(that, that.getDeclarationModel(), that.getAnnotationList(), this);
if (setterDef != null) {
out(",");
TypeUtils.encodeForRuntime(setterDef, setterDef.getDeclarationModel(), setterDef.getAnnotationList(), this);
}
out(")");
endLine(true);
} else {
endLine(true);
shareGetter(d);
}
}
} else if (!(d.isParameter() && d.getContainer() instanceof Function)) {
if (addGetter) {
AttributeGenerator.generateAttributeGetter(that, d, specInitExpr, names.name(param), this, directAccess, verboseStitcher);
}
if ((d.isVariable() || d.isLate()) && !asprop) {
setterGend = AttributeGenerator.generateAttributeSetter(that, d, this);
}
}
boolean addMeta = !opts.isOptimize() || d.isToplevel();
if (!d.isToplevel()) {
addMeta |= ModelUtil.getContainingDeclaration(d).isAnonymous();
}
if (addMeta) {
AttributeGenerator.generateAttributeMetamodel(that, addGetter, setterGend, this);
}
}
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.SpecifierOrInitializerExpression in project ceylon by eclipse.
the class ClassGenerator method classDefinition.
static void classDefinition(final Tree.ClassDefinition that, final GenerateJsVisitor gen, InitDeferrer initDeferrer) {
// Don't even bother with nodes that have errors
if (TypeGenerator.errVisitor.hasErrors(that))
return;
final Class d = that.getDeclarationModel();
// If it's inside a dynamic interface, don't generate anything
if (d.isClassOrInterfaceMember() && ((ClassOrInterface) d.getContainer()).isDynamic())
return;
final Class natd = (Class) 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;
}
final Tree.ParameterList plist = that.getParameterList();
// final Tree.SatisfiedTypes sats = that.getSatisfiedTypes();
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.getClassBody(), nh, Backend.JavaScript);
} else {
stmts = that.getClassBody().getStatements();
}
// Find the constructors, if any
final List<Tree.Constructor> constructors;
Tree.Constructor defconstr = null;
final boolean hasConstructors = d.hasConstructors() || (natd != null && natd.hasConstructors());
final boolean hasEnumerated = d.hasEnumerated() || (natd != null && natd.hasEnumerated());
if (hasConstructors) {
constructors = new ArrayList<>(3);
for (Tree.Statement st : stmts) {
if (st instanceof Tree.Constructor) {
Tree.Constructor constr = (Tree.Constructor) st;
constructors.add(constr);
if (constr.getDeclarationModel().getName() == null) {
defconstr = constr;
}
}
}
} else {
constructors = null;
}
gen.comment(that);
final boolean isAbstractNative = d.isNativeHeader() && natd != null;
final String typeName = gen.getNames().name(d);
if (TypeUtils.isNativeExternal(d)) {
boolean bye = false;
if (hasConstructors && defconstr == null) {
gen.out(GenerateJsVisitor.function, typeName);
gen.out("(){");
gen.generateThrow("Exception", d.getQualifiedNameString() + " has no default constructor.", that);
gen.out(";}");
gen.endLine();
}
if (gen.stitchNative(d, that)) {
if (d.isShared()) {
gen.share(d);
}
TypeGenerator.initializeType(that, gen, initDeferrer);
bye = true;
}
if (hasConstructors) {
for (Tree.Constructor cnstr : constructors) {
Constructors.classConstructor(cnstr, that, constructors, gen);
}
}
if (bye)
return;
}
gen.out(GenerateJsVisitor.function, typeName);
// If there's a default constructor, create a different function with this code
if (hasConstructors || hasEnumerated) {
if (defconstr == null) {
gen.out("(){");
gen.generateThrow("Exception", d.getQualifiedNameString() + " has no default constructor.", that);
gen.out(";}");
gen.endLine();
gen.out(GenerateJsVisitor.function, typeName);
}
gen.out("$$c");
}
// counterparts
if (isAbstractNative) {
if (plist != null) {
for (Parameter p : d.getParameterList().getParameters()) {
gen.getNames().forceName(natd.getParameter(p.getName()).getModel(), gen.getNames().name(p));
}
}
for (Declaration hd : d.getMembers()) {
if (!hd.isShared()) {
gen.getNames().forceName(natd.getMember(hd.getName(), null, false), gen.getNames().name(hd));
}
}
}
final boolean withTargs = TypeGenerator.generateParameters(that.getTypeParameterList(), plist, d, gen);
gen.beginBlock();
if (!hasConstructors) {
// This takes care of top-level attributes defined before the class definition
gen.out("$init$", typeName, "();");
gen.endLine();
gen.declareSelf(d);
gen.referenceOuter(d);
}
final String me = gen.getNames().self(d);
if (withTargs) {
gen.out(gen.getClAlias(), "set_type_args(", me, ",$$targs$$);");
gen.endLine();
}
addFunctionTypeArguments(d, me, gen);
List<Tree.Parameter> defparams = null;
if (plist != null) {
defparams = gen.initParameters(plist, d, null);
}
callSupertypes(that, d, typeName, gen);
if (!gen.opts.isOptimize() && plist != null) {
// Fix #231 for lexical scope
for (Tree.Parameter p : plist.getParameters()) {
if (!p.getParameterModel().isHidden()) {
gen.generateAttributeForParameter(that, d, p.getParameterModel());
}
}
}
if (!hasConstructors) {
if (TypeUtils.isNativeExternal(d)) {
gen.stitchConstructorHelper(that, "_cons_before");
}
gen.visitStatements(stmts);
if (TypeUtils.isNativeExternal(d)) {
gen.stitchConstructorHelper(that, "_cons_after");
}
gen.out("return ", me, ";");
}
gen.endBlockNewLine();
if (defconstr != null) {
// Define a function as the class and call the default constructor in there
String _this = "undefined";
if (!d.isToplevel()) {
final ClassOrInterface coi = ModelUtil.getContainingClassOrInterface(d.getContainer());
if (coi != null) {
if (d.isClassOrInterfaceMember()) {
_this = "this";
} else {
_this = gen.getNames().self(coi);
}
}
}
gen.out(GenerateJsVisitor.function, typeName, "(){return ", typeName, gen.getNames().constructorSeparator(defconstr.getDeclarationModel()), gen.getNames().name(defconstr.getDeclarationModel()), ".apply(", _this, ",arguments);}");
gen.endLine();
}
if (hasConstructors) {
for (Tree.Constructor cnstr : constructors) {
Constructors.classConstructor(cnstr, that, constructors, gen);
}
}
if (hasEnumerated) {
for (Tree.Statement st : stmts) {
if (st instanceof Tree.Enumerated) {
Singletons.valueConstructor(that, (Tree.Enumerated) st, gen);
}
}
}
if (defparams != null) {
for (Tree.Parameter p : defparams) {
final SpecifierOrInitializerExpression expr = gen.getDefaultExpression(p);
if (expr != null) {
// Optimizing for certain expressions such as null and literals is tempting
// but we need to put them in functions if we want them to work in subtypes
gen.out(typeName, ".$defs$", p.getParameterModel().getName(), "=function(", me);
for (Parameter otherP : d.getParameterList().getParameters()) {
if (!otherP.equals(p.getParameterModel())) {
gen.out(",", gen.getNames().name(otherP));
}
}
gen.out("){return ");
gen.generateParameterExpression(p, expr, d);
gen.out("};");
}
}
}
// Add reference to metamodel
gen.out(typeName, ".$crtmm$=");
TypeUtils.encodeForRuntime(that, d, that.getAnnotationList(), gen);
gen.endLine(true);
if (!isAbstractNative) {
gen.share(d);
}
TypeGenerator.initializeType(that, gen, initDeferrer);
if (d.isSerializable()) {
SerializationHelper.addDeserializer(that, d, gen);
}
}
Aggregations