use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression in project ceylon by eclipse.
the class GenerateJsVisitor method specifierStatement.
private void specifierStatement(final TypeDeclaration outer, final Tree.SpecifierStatement specStmt) {
final Tree.Expression expr = specStmt.getSpecifierExpression().getExpression();
final Tree.Term term = specStmt.getBaseMemberExpression();
final Tree.StaticMemberOrTypeExpression smte = term instanceof Tree.StaticMemberOrTypeExpression ? (Tree.StaticMemberOrTypeExpression) term : null;
if (isInDynamicBlock() && ModelUtil.isTypeUnknown(term.getTypeModel())) {
if (smte != null && smte.getDeclaration() == null) {
out(smte.getIdentifier().getText());
} else {
term.visit(this);
if (term instanceof BaseMemberExpression) {
Declaration dec = ((BaseMemberExpression) term).getDeclaration();
if (dec instanceof Value) {
Value v = (Value) dec;
if (v.isMember()) {
// Assignment to dynamic member
out("_");
}
}
}
}
out("=");
int box = boxUnboxStart(expr, term);
expr.visit(this);
if (box == 4)
out("/*TODO: callable targs 6.1*/");
boxUnboxEnd(box);
out(";");
return;
}
if (smte != null) {
final Declaration bmeDecl = smte.getDeclaration();
if (specStmt.getSpecifierExpression() instanceof LazySpecifierExpression) {
// attr => expr;
final boolean property = AttributeGenerator.defineAsProperty(bmeDecl);
if (property) {
defineAttribute(qualifiedPath(specStmt, bmeDecl), names.name(bmeDecl));
} else {
if (bmeDecl.isMember()) {
qualify(specStmt, bmeDecl);
} else {
out("var ");
}
out(names.getter(bmeDecl, false), "=function()");
}
beginBlock();
if (outer != null) {
initSelf(specStmt);
}
out("return ");
if (!isNaturalLiteral(specStmt.getSpecifierExpression().getExpression().getTerm())) {
specStmt.getSpecifierExpression().visit(this);
}
out(";");
endBlock();
if (property) {
out(",undefined,");
TypeUtils.encodeForRuntime(specStmt, bmeDecl, this);
out(")");
}
endLine(true);
directAccess.remove(bmeDecl);
} else if (outer != null) {
// since #451 we now generate an attribute here
if (outer instanceof Constructor || bmeDecl.isMember() && bmeDecl instanceof Value && bmeDecl.isActual()) {
assignment(outer, bmeDecl, expr);
}
} else if (bmeDecl instanceof FunctionOrValue) {
// "attr = expr;" in an initializer or method
final FunctionOrValue moval = (FunctionOrValue) bmeDecl;
if (moval.isVariable() || moval.isLate()) {
// simple assignment to a variable attribute
BmeGenerator.generateMemberAccess(smte, new GenerateCallback() {
@Override
public void generateValue() {
int boxType = boxUnboxStart(expr.getTerm(), moval);
if (isInDynamicBlock() && !ModelUtil.isTypeUnknown(moval.getType()) && ModelUtil.isTypeUnknown(expr.getTypeModel())) {
TypeUtils.generateDynamicCheck(expr, moval.getType(), GenerateJsVisitor.this, false, expr.getTypeModel().getTypeArguments());
} else {
expr.visit(GenerateJsVisitor.this);
}
if (boxType == 4) {
out(",");
if (moval instanceof Function) {
// Add parameters
TypeUtils.encodeParameterListForRuntime(true, specStmt, ((Function) moval).getFirstParameterList(), GenerateJsVisitor.this);
out(",");
} else {
// TODO extract parameters from Value
final Type ps = moval.getUnit().getCallableTuple(moval.getType());
if (ps == null || ps.isSubtypeOf(moval.getUnit().getEmptyType())) {
out("[],");
} else {
out("[/*VALUE Callable params ", ps.asString() + "*/],");
}
}
TypeUtils.printTypeArguments(expr, expr.getTypeModel().getTypeArguments(), GenerateJsVisitor.this, false, expr.getTypeModel().getVarianceOverrides());
}
boxUnboxEnd(boxType);
}
}, qualifiedPath(smte, moval), this);
out(";");
} else if (moval.isMember()) {
if (moval instanceof Function) {
// same as fat arrow
qualify(specStmt, bmeDecl);
if (expr.getTerm() instanceof Tree.FunctionArgument) {
((Tree.FunctionArgument) expr.getTerm()).getDeclarationModel().setRefinedDeclaration(moval);
out(names.name(moval), "=");
specStmt.getSpecifierExpression().visit(this);
out(";");
} else {
out(names.name(moval), "=function ", names.name(moval), "(");
// Build the parameter list, we'll use it several times
final StringBuilder paramNames = new StringBuilder();
final List<Parameter> params = ((Function) moval).getFirstParameterList().getParameters();
for (Parameter p : params) {
if (paramNames.length() > 0)
paramNames.append(",");
paramNames.append(names.name(p));
}
out(paramNames.toString());
out("){");
for (Parameter p : params) {
if (p.isDefaulted()) {
out("if(", names.name(p), "===undefined)", names.name(p), "=");
qualify(specStmt, moval);
out(names.name(moval), "$defs$", p.getName(), "(", paramNames.toString(), ")");
endLine(true);
}
}
out("return ");
if (!isNaturalLiteral(specStmt.getSpecifierExpression().getExpression().getTerm())) {
specStmt.getSpecifierExpression().visit(this);
}
out("(", paramNames.toString(), ");}");
endLine(true);
}
} else {
// declaration itself can be omitted), so generate the attribute.
if (opts.isOptimize()) {
// #451
out(names.self(ModelUtil.getContainingClassOrInterface(moval.getScope())), ".", names.valueName(moval), "=");
specStmt.getSpecifierExpression().visit(this);
endLine(true);
} else {
AttributeGenerator.generateAttributeGetter(null, moval, specStmt.getSpecifierExpression(), null, this, directAccess, verboseStitcher);
}
}
} else {
// Specifier for some other attribute, or for a method.
if (opts.isOptimize() || bmeDecl.isMember() && bmeDecl instanceof Function) {
qualify(specStmt, bmeDecl);
}
out(names.name(bmeDecl), "=");
if (isInDynamicBlock() && ModelUtil.isTypeUnknown(expr.getTypeModel()) && !ModelUtil.isTypeUnknown(((FunctionOrValue) bmeDecl).getType())) {
TypeUtils.generateDynamicCheck(expr, ((FunctionOrValue) bmeDecl).getType(), this, false, expr.getTypeModel().getTypeArguments());
} else {
if (expr.getTerm() instanceof Tree.FunctionArgument) {
Function fun = ((Tree.FunctionArgument) expr.getTerm()).getDeclarationModel();
if (fun.isAnonymous()) {
fun.setRefinedDeclaration(moval);
}
}
specStmt.getSpecifierExpression().visit(this);
}
out(";");
}
}
} else if ((term instanceof Tree.ParameterizedExpression) && (specStmt.getSpecifierExpression() != null)) {
final Tree.ParameterizedExpression paramExpr = (Tree.ParameterizedExpression) term;
if (paramExpr.getPrimary() instanceof BaseMemberExpression) {
// func(params) => expr;
final BaseMemberExpression bme2 = (BaseMemberExpression) paramExpr.getPrimary();
final Declaration bmeDecl = bme2.getDeclaration();
if (bmeDecl.isMember()) {
qualify(specStmt, bmeDecl);
} else {
out("var ");
}
out(names.name(bmeDecl), "=");
FunctionHelper.singleExprFunction(paramExpr.getParameterLists(), expr, bmeDecl instanceof Scope ? (Scope) bmeDecl : null, true, true, this);
out(";");
}
}
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression in project ceylon by eclipse.
the class BoxingDeclarationVisitor method visit.
@Override
public void visit(SpecifierStatement that) {
TypedDeclaration declaration = that.getDeclaration();
Function optimisedDeclaration = null;
// make sure we detect the shortcut refinement inlining cases
if (declaration instanceof Function) {
if (that.getSpecifierExpression() != null && that.getSpecifierExpression() instanceof LazySpecifierExpression == false) {
Tree.Term term = Decl.unwrapExpressionsUntilTerm(that.getSpecifierExpression().getExpression());
if (term != null && term instanceof Tree.FunctionArgument) {
optimisedDeclaration = ((Tree.FunctionArgument) term).getDeclarationModel();
this.optimisedMethodSpecifiersToMethods.put(optimisedDeclaration, (Function) declaration);
}
}
}
try {
super.visit(that);
} finally {
if (optimisedDeclaration != null)
this.optimisedMethodSpecifiersToMethods.remove(optimisedDeclaration);
}
if (declaration == null)
return;
if (declaration instanceof Function) {
visitMethod((Function) declaration, that);
} else if (declaration instanceof Value)
visitAttributeOrParameter(declaration, that);
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression 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.LazySpecifierExpression in project ceylon by eclipse.
the class AttributeGenerator method addGetterAndSetterToPrototype.
static void addGetterAndSetterToPrototype(final TypeDeclaration outer, final Tree.AttributeDeclaration that, final GenerateJsVisitor gen, final boolean verboseStitcher) {
final Value d = that.getDeclarationModel();
if (!gen.opts.isOptimize() || d.isToplevel())
return;
gen.comment(that);
final String atname = gen.getNames().valueName(d);
final String outerName = d.isStatic() ? gen.getNames().name(outer) + ".$st$" : gen.getNames().self(outer);
if (d.isFormal()) {
generateAttributeMetamodel(that, false, false, gen);
} else if (that.getSpecifierOrInitializerExpression() == null) {
gen.defineAttribute(outerName, gen.getNames().name(d));
gen.out("{");
if (TypeUtils.isNativeExternal(d)) {
// this is for native member attribute declaration with no value
gen.stitchNative(d, that);
} else {
if (d.isStatic()) {
if (d.isLate()) {
gen.generateUnitializedAttributeReadCheck(outerName + "." + atname, gen.getNames().name(d), that.getSpecifierOrInitializerExpression());
gen.out("return ", outerName, ".", atname, ";");
} else {
gen.out("return ");
that.getSpecifierOrInitializerExpression().visit(gen);
gen.out(";");
}
} else {
if (d.isLate()) {
// Just return the private value #451
gen.generateUnitializedAttributeReadCheck("this." + atname, gen.getNames().name(d), that.getSpecifierOrInitializerExpression());
}
gen.out("return this.", atname, ";");
}
}
gen.out("},");
Tree.AttributeSetterDefinition setterDef = null;
boolean setterDefined = false;
if (d.isVariable() || d.isLate()) {
setterDef = gen.associatedSetterDefinition(d);
if (setterDef == null) {
setterDefined = true;
final String par = gen.getNames().createTempVariable();
gen.out("function(", par, "){");
gen.generateImmutableAttributeReassignmentCheck(d, "this." + atname, gen.getNames().name(d));
gen.out("return this.", atname, "=", par, ";}");
} else if (!gen.stitchNative(setterDef.getDeclarationModel(), that)) {
gen.out("function(", gen.getNames().name(setterDef.getDeclarationModel().getParameter()), ")");
setter(setterDef, gen);
setterDefined = true;
}
}
if (!setterDefined) {
gen.out("undefined");
}
gen.out(",");
TypeUtils.encodeForRuntime(that, that.getDeclarationModel(), that.getAnnotationList(), gen);
if (setterDef != null) {
gen.out(",");
TypeUtils.encodeForRuntime(setterDef, setterDef.getDeclarationModel(), that.getAnnotationList(), gen);
}
gen.out(")");
gen.endLine(true);
} else {
org.eclipse.ceylon.model.typechecker.model.Parameter param = null;
if (d.isParameter()) {
param = ((Functional) d.getContainer()).getParameter(d.getName());
}
if ((that.getSpecifierOrInitializerExpression() != null) || d.isVariable() || param != null || d.isLate() || TypeUtils.isNativeExternal(d)) {
if (that.getSpecifierOrInitializerExpression() instanceof LazySpecifierExpression) {
// attribute is defined by a lazy expression ("=>" syntax)
gen.defineAttribute(outerName, gen.getNames().name(d));
gen.beginBlock();
gen.initSelf(that);
boolean stitch = TypeUtils.isNativeExternal(d);
if (stitch) {
stitch = gen.stitchNative(d, that);
if (stitch && verboseStitcher) {
gen.spitOut("Stitching in native getter " + d.getQualifiedNameString() + ", ignoring Ceylon declaration");
}
}
if (!stitch) {
final Expression expr = that.getSpecifierOrInitializerExpression().getExpression();
gen.out("return ");
if (!gen.isNaturalLiteral(expr.getTerm())) {
gen.visitSingleExpression(expr);
}
}
gen.endBlock();
Tree.AttributeSetterDefinition setterDef = null;
if (d.isVariable()) {
setterDef = gen.associatedSetterDefinition(d);
if (setterDef != null) {
gen.out(",function(", gen.getNames().name(setterDef.getDeclarationModel().getParameter()), ")");
setter(setterDef, gen);
}
}
if (setterDef == null) {
gen.out(",undefined");
}
gen.out(",");
TypeUtils.encodeForRuntime(that, that.getDeclarationModel(), that.getAnnotationList(), gen);
if (setterDef != null) {
gen.out(",");
TypeUtils.encodeForRuntime(setterDef, setterDef.getDeclarationModel(), that.getAnnotationList(), gen);
}
gen.out(")");
gen.endLine(true);
} else {
final String privname = param == null ? gen.getNames().privateName(d) : gen.getNames().name(param) + "_";
gen.defineAttribute(outerName, gen.getNames().name(d));
gen.out("{");
if (d.isLate()) {
gen.generateUnitializedAttributeReadCheck("this." + privname, gen.getNames().name(d), that.getSpecifierOrInitializerExpression());
}
if (TypeUtils.isNativeExternal(d)) {
if (gen.stitchNative(d, that)) {
if (verboseStitcher) {
gen.spitOut("Stitching in native getter " + d.getQualifiedNameString() + ", ignoring Ceylon declaration");
}
} else {
gen.out("return ");
gen.visitSingleExpression(that.getSpecifierOrInitializerExpression().getExpression());
}
gen.out("}");
} else {
if (d.isStatic()) {
gen.out("return ");
gen.visitSingleExpression(that.getSpecifierOrInitializerExpression().getExpression());
gen.out("}");
} else {
gen.out("return this.", privname, ";}");
}
}
if (d.isVariable() || d.isLate()) {
final String pname = gen.getNames().createTempVariable();
gen.out(",function(", pname, "){");
gen.generateImmutableAttributeReassignmentCheck(d, "this." + privname, gen.getNames().name(d));
gen.out("return this.", privname, "=", pname, ";}");
} else {
gen.out(",undefined");
}
gen.out(",");
TypeUtils.encodeForRuntime(that, that.getDeclarationModel(), that.getAnnotationList(), gen);
gen.out(")");
gen.endLine(true);
}
}
}
}
Aggregations