use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression in project ceylon by eclipse.
the class ClassTransformer method transformRefinementSpecifierStatement.
public List<JCStatement> transformRefinementSpecifierStatement(SpecifierStatement op, ClassDefinitionBuilder classBuilder) {
List<JCStatement> result = List.<JCStatement>nil();
// Check if this is a shortcut form of formal attribute refinement
if (op.getRefinement()) {
Tree.Term baseMemberTerm = op.getBaseMemberExpression();
if (baseMemberTerm instanceof Tree.ParameterizedExpression)
baseMemberTerm = ((Tree.ParameterizedExpression) baseMemberTerm).getPrimary();
Tree.BaseMemberExpression expr = (BaseMemberExpression) baseMemberTerm;
Declaration decl = expr.getDeclaration();
if (Decl.isValue(decl) || Decl.isGetter(decl)) {
// Now build a "fake" declaration for the attribute
Tree.AttributeDeclaration attrDecl = new Tree.AttributeDeclaration(null);
attrDecl.setDeclarationModel((Value) decl);
attrDecl.setIdentifier(expr.getIdentifier());
attrDecl.setScope(op.getScope());
attrDecl.setSpecifierOrInitializerExpression(op.getSpecifierExpression());
attrDecl.setAnnotationList(makeShortcutRefinementAnnotationTrees());
// Make sure the boxing information is set correctly
BoxingDeclarationVisitor v = new CompilerBoxingDeclarationVisitor(this);
v.visit(attrDecl);
// Generate the attribute
transform(attrDecl, classBuilder);
} else if (decl instanceof Function) {
// Now build a "fake" declaration for the method
Tree.MethodDeclaration methDecl = new Tree.MethodDeclaration(null);
Function m = (Function) decl;
methDecl.setDeclarationModel(m);
methDecl.setIdentifier(expr.getIdentifier());
methDecl.setScope(op.getScope());
methDecl.setAnnotationList(makeShortcutRefinementAnnotationTrees());
Tree.SpecifierExpression specifierExpression = op.getSpecifierExpression();
methDecl.setSpecifierExpression(specifierExpression);
if (specifierExpression instanceof Tree.LazySpecifierExpression == false) {
Tree.Expression expression = specifierExpression.getExpression();
Tree.Term expressionTerm = Decl.unwrapExpressionsUntilTerm(expression);
// we can optimise lambdas and static method calls
if (!CodegenUtil.canOptimiseMethodSpecifier(expressionTerm, m)) {
// we need a field to save the callable value
String name = naming.getMethodSpecifierAttributeName(m);
JCExpression specifierType = makeJavaType(expression.getTypeModel());
JCExpression specifier = expressionGen().transformExpression(expression);
classBuilder.field(PRIVATE | FINAL, name, specifierType, specifier, false);
}
}
java.util.List<Tree.ParameterList> parameterListTrees = null;
if (op.getBaseMemberExpression() instanceof Tree.ParameterizedExpression) {
parameterListTrees = new ArrayList<>(m.getParameterLists().size());
parameterListTrees.addAll(((Tree.ParameterizedExpression) op.getBaseMemberExpression()).getParameterLists());
Tree.Term term = specifierExpression.getExpression().getTerm();
// and give it the given block of expr as it's specifier
while (term instanceof Tree.FunctionArgument && m.getParameterLists().size() > 1) {
FunctionArgument functionArgument = (Tree.FunctionArgument) term;
specifierExpression.setExpression(functionArgument.getExpression());
parameterListTrees.addAll(functionArgument.getParameterLists());
term = functionArgument.getExpression().getTerm();
}
}
int plIndex = 0;
// copy from formal declaration
for (ParameterList pl : m.getParameterLists()) {
Tree.ParameterList parameterListTree = null;
if (parameterListTrees != null)
parameterListTree = parameterListTrees.get(plIndex++);
Tree.ParameterList tpl = new Tree.ParameterList(null);
tpl.setModel(pl);
int pIndex = 0;
for (Parameter p : pl.getParameters()) {
Tree.Parameter parameterTree = null;
if (parameterListTree != null)
parameterTree = parameterListTree.getParameters().get(pIndex++);
Tree.Parameter tp = null;
if (p.getModel() instanceof Value) {
Tree.ValueParameterDeclaration tvpd = new Tree.ValueParameterDeclaration(null);
if (parameterTree != null)
tvpd.setTypedDeclaration(((Tree.ParameterDeclaration) parameterTree).getTypedDeclaration());
tvpd.setParameterModel(p);
tp = tvpd;
} else if (p.getModel() instanceof Function) {
Tree.FunctionalParameterDeclaration tfpd = new Tree.FunctionalParameterDeclaration(null);
if (parameterTree != null)
tfpd.setTypedDeclaration(((Tree.ParameterDeclaration) parameterTree).getTypedDeclaration());
tfpd.setParameterModel(p);
tp = tfpd;
} else {
throw BugException.unhandledDeclarationCase(p.getModel());
}
tp.setScope(p.getDeclaration().getContainer());
// tp.setIdentifier(makeIdentifier(p.getName()));
tpl.addParameter(tp);
}
methDecl.addParameterList(tpl);
}
// Make sure the boxing information is set correctly
BoxingDeclarationVisitor v = new CompilerBoxingDeclarationVisitor(this);
v.visit(methDecl);
// Generate the method
classBuilder.method(methDecl, Errors.GENERATE);
}
} else {
// Normal case, just generate the specifier statement
result = result.append(expressionGen().transform(op));
}
Tree.Term term = op.getBaseMemberExpression();
if (term instanceof Tree.BaseMemberExpression) {
Tree.BaseMemberExpression bme = (Tree.BaseMemberExpression) term;
DeferredSpecification ds = statementGen().getDeferredSpecification(bme.getDeclaration());
if (ds != null && needsInnerSubstitution(term.getScope(), bme.getDeclaration())) {
result = result.append(ds.openInnerSubstitution());
}
}
return result;
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression in project ceylon by eclipse.
the class GenerateJsVisitor method visit.
@Override
public void visit(final Tree.NotOp that) {
final Term t = that.getTerm();
final boolean omitParens = t instanceof BaseMemberExpression || t instanceof QualifiedMemberExpression || t instanceof Tree.IsOp || t instanceof Tree.Exists || t instanceof Tree.IdenticalOp || t instanceof Tree.InOp || t instanceof Tree.Nonempty || (t instanceof Tree.InvocationExpression && ((Tree.InvocationExpression) t).getNamedArgumentList() == null);
if (omitParens) {
Operators.unaryOp(that, "!", null, this);
} else {
Operators.unaryOp(that, "(!", ")", this);
}
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression 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.BaseMemberExpression in project ceylon by eclipse.
the class GenerateJsVisitor method arithmeticAssignOp.
private boolean arithmeticAssignOp(final Tree.AssignmentOp that, final String operand) {
final Term lhs = that.getLeftTerm();
final Type ltype = lhs.getTypeModel();
final Type rtype = that.getRightTerm().getTypeModel();
final boolean oneFloat = ltype.isFloat() || rtype.isFloat();
if (TypeUtils.intsOrFloats(ltype, rtype)) {
if (lhs instanceof BaseMemberExpression) {
BaseMemberExpression lhsBME = (BaseMemberExpression) lhs;
Declaration lhsDecl = lhsBME.getDeclaration();
final String getLHS = memberAccess(lhsBME, null);
out("(");
BmeGenerator.generateMemberAccess(lhsBME, new GenerateCallback() {
@Override
public void generateValue() {
if (oneFloat) {
out(getClAlias(), "Float(");
}
out(getLHS, operand);
if (!isNaturalLiteral(that.getRightTerm())) {
that.getRightTerm().visit(GenerateJsVisitor.this);
}
if (oneFloat) {
out(")");
}
}
}, null, this);
if (!hasSimpleGetterSetter(lhsDecl)) {
out(",", getLHS);
}
out(")");
} else if (lhs instanceof QualifiedMemberExpression) {
QualifiedMemberExpression lhsQME = (QualifiedMemberExpression) lhs;
if (TypeUtils.isNativeJs(lhsQME)) {
// ($1.foo = Box($1.foo).operator($2))
final String tmp = names.createTempVariable();
final String dec = isInDynamicBlock() && lhsQME.getDeclaration() == null ? lhsQME.getIdentifier().getText() : lhsQME.getDeclaration().getName();
out("(", tmp, "=");
lhsQME.getPrimary().visit(this);
out(",", tmp, ".", dec, "=");
int boxType = boxStart(lhsQME);
out(tmp, ".", dec);
if (boxType == 4)
out("/*TODO: callable targs 8*/");
boxUnboxEnd(boxType);
out(operand);
if (!isNaturalLiteral(that.getRightTerm())) {
that.getRightTerm().visit(this);
}
out(")");
} else {
final String lhsPrimaryVar = createRetainedTempVar();
final String getLHS = memberAccess(lhsQME, lhsPrimaryVar);
out("(", lhsPrimaryVar, "=");
lhsQME.getPrimary().visit(this);
out(",");
BmeGenerator.generateMemberAccess(lhsQME, new GenerateCallback() {
@Override
public void generateValue() {
out(getLHS, operand);
if (!isNaturalLiteral(that.getRightTerm())) {
that.getRightTerm().visit(GenerateJsVisitor.this);
}
}
}, lhsPrimaryVar, this);
if (!hasSimpleGetterSetter(lhsQME.getDeclaration())) {
out(",", getLHS);
}
out(")");
}
} else if (lhs instanceof Tree.IndexExpression) {
lhs.addUnsupportedError("Index expressions are not supported in this kind of assignment.");
}
return true;
}
return false;
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression in project ceylon by eclipse.
the class GenerateJsVisitor method assignOp.
private void assignOp(final Tree.AssignmentOp that, final String functionName, final Map<TypeParameter, Type> targs) {
if (errVisitor.hasErrors(that))
return;
Term lhs = that.getLeftTerm();
final boolean isNative = "||".equals(functionName) || "&&".equals(functionName);
if (lhs instanceof BaseMemberExpression) {
BaseMemberExpression lhsBME = (BaseMemberExpression) lhs;
Declaration lhsDecl = lhsBME.getDeclaration();
final String getLHS = memberAccess(lhsBME, null);
out("(");
BmeGenerator.generateMemberAccess(lhsBME, new GenerateCallback() {
@Override
public void generateValue() {
if (isNative) {
out(getLHS, functionName);
} else {
out(getLHS, ".", functionName, "(");
}
if (!isNaturalLiteral(that.getRightTerm())) {
that.getRightTerm().visit(GenerateJsVisitor.this);
}
if (!isNative) {
if (targs != null) {
out(",");
TypeUtils.printTypeArguments(that, targs, GenerateJsVisitor.this, false, null);
}
out(")");
}
}
}, null, this);
if (!hasSimpleGetterSetter(lhsDecl)) {
out(",", getLHS);
}
out(")");
} else if (lhs instanceof QualifiedMemberExpression) {
QualifiedMemberExpression lhsQME = (QualifiedMemberExpression) lhs;
if (TypeUtils.isNativeJs(lhsQME)) {
// ($1.foo = Box($1.foo).operator($2))
final String tmp = names.createTempVariable();
final String dec = isInDynamicBlock() && lhsQME.getDeclaration() == null ? lhsQME.getIdentifier().getText() : lhsQME.getDeclaration().getName();
out("(", tmp, "=");
lhsQME.getPrimary().visit(this);
out(",", tmp, ".", dec, "=");
int boxType = boxStart(lhsQME);
out(tmp, ".", dec);
if (boxType == 4)
out("/*TODO: callable targs 8*/");
boxUnboxEnd(boxType);
out(".", functionName, "(");
if (!isNaturalLiteral(that.getRightTerm())) {
that.getRightTerm().visit(this);
}
out("))");
} else {
final String lhsPrimaryVar = createRetainedTempVar();
final String getLHS = memberAccess(lhsQME, lhsPrimaryVar);
out("(", lhsPrimaryVar, "=");
lhsQME.getPrimary().visit(this);
out(",");
BmeGenerator.generateMemberAccess(lhsQME, new GenerateCallback() {
@Override
public void generateValue() {
out(getLHS, ".", functionName, "(");
Tree.Term term = that.getRightTerm();
if (!isNaturalLiteral(term)) {
term.visit(GenerateJsVisitor.this);
}
out(")");
}
}, lhsPrimaryVar, this);
if (!hasSimpleGetterSetter(lhsQME.getDeclaration())) {
out(",", getLHS);
}
out(")");
}
} else if (lhs instanceof Tree.IndexExpression) {
lhs.addUnsupportedError("Index expressions are not supported in this kind of assignment.");
}
}
Aggregations