Search in sources :

Example 1 with BaseMemberExpression

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;
}
Also used : SpecifierExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.SpecifierExpression) DeferredSpecification(org.eclipse.ceylon.compiler.java.codegen.StatementTransformer.DeferredSpecification) ArrayList(java.util.ArrayList) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) Function(org.eclipse.ceylon.model.typechecker.model.Function) JCPrimitiveTypeTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) ArrayList(java.util.ArrayList) AnnotationList(org.eclipse.ceylon.compiler.typechecker.tree.Tree.AnnotationList) List(org.eclipse.ceylon.langtools.tools.javac.util.List) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) MethodDeclaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) FunctionArgument(org.eclipse.ceylon.compiler.typechecker.tree.Tree.FunctionArgument) BaseMemberExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression) MethodDeclaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) MethodDeclaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) BaseMemberExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression) SpecifierExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.SpecifierExpression) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Value(org.eclipse.ceylon.model.typechecker.model.Value) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) JavaBeanValue(org.eclipse.ceylon.model.loader.model.JavaBeanValue) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) BaseMemberExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression)

Example 2 with BaseMemberExpression

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);
    }
}
Also used : QualifiedMemberExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.QualifiedMemberExpression) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) Term(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term) BaseMemberExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression)

Example 3 with BaseMemberExpression

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(";");
        }
    }
}
Also used : Term(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) Function(org.eclipse.ceylon.model.typechecker.model.Function) IntersectionType(org.eclipse.ceylon.model.typechecker.model.IntersectionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) ExtendedType(org.eclipse.ceylon.compiler.typechecker.tree.Tree.ExtendedType) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) StaticMemberOrTypeExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.StaticMemberOrTypeExpression) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) Value(org.eclipse.ceylon.model.typechecker.model.Value) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) List(java.util.List) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) BaseMemberExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) AttributeDeclaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration) LazySpecifierExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 4 with BaseMemberExpression

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;
}
Also used : IntersectionType(org.eclipse.ceylon.model.typechecker.model.IntersectionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) ExtendedType(org.eclipse.ceylon.compiler.typechecker.tree.Tree.ExtendedType) QualifiedMemberExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.QualifiedMemberExpression) Term(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term) BaseMemberExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) AttributeDeclaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration)

Example 5 with BaseMemberExpression

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.");
    }
}
Also used : QualifiedMemberExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.QualifiedMemberExpression) Term(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) Term(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term) BaseMemberExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) AttributeDeclaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration)

Aggregations

BaseMemberExpression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression)6 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)5 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)5 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)5 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)5 AttributeDeclaration (org.eclipse.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration)4 QualifiedMemberExpression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.QualifiedMemberExpression)4 Term (org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term)4 ArrayList (java.util.ArrayList)2 ExtendedType (org.eclipse.ceylon.compiler.typechecker.tree.Tree.ExtendedType)2 StaticMemberOrTypeExpression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.StaticMemberOrTypeExpression)2 Function (org.eclipse.ceylon.model.typechecker.model.Function)2 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)2 IntersectionType (org.eclipse.ceylon.model.typechecker.model.IntersectionType)2 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)2 ParameterList (org.eclipse.ceylon.model.typechecker.model.ParameterList)2 Type (org.eclipse.ceylon.model.typechecker.model.Type)2 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)2 Value (org.eclipse.ceylon.model.typechecker.model.Value)2 LinkedList (java.util.LinkedList)1