Search in sources :

Example 16 with Expression

use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression in project ceylon by eclipse.

the class ExpressionTransformer method transformStringExpression.

public JCExpression transformStringExpression(Tree.StringTemplate expr) {
    at(expr);
    JCExpression builder;
    builder = make().NewClass(null, null, naming.makeFQIdent("java", "lang", "StringBuilder"), List.<JCExpression>nil(), null);
    java.util.List<Tree.StringLiteral> literals = expr.getStringLiterals();
    java.util.List<Tree.Expression> expressions = expr.getExpressions();
    for (int ii = 0; ii < literals.size(); ii += 1) {
        Tree.StringLiteral literal = literals.get(ii);
        if (!literal.getText().isEmpty()) {
            // ignore empty string literals
            at(literal);
            builder = make().Apply(null, makeSelect(builder, "append"), List.<JCExpression>of(transform(literal)));
        }
        if (ii == expressions.size()) {
            // after that because we've already exhausted all the expressions
            break;
        }
        Tree.Expression expression = expressions.get(ii);
        at(expression);
        // Here in both cases we don't need a type cast for erasure
        if (isCeylonBasicType(expression.getTypeModel()) && expression.getUnboxed()) {
            // TODO: Test should be erases to String, long, int, boolean, char, byte, float, double
            // If erases to a Java primitive just call append, don't box it just to call format.
            String method = isCeylonCharacter(expression.getTypeModel()) ? "appendCodePoint" : "append";
            builder = make().Apply(null, makeSelect(builder, method), List.<JCExpression>of(transformExpression(expression, BoxingStrategy.UNBOXED, null)));
        } else {
            JCMethodInvocation formatted = make().Apply(null, makeSelect(transformExpression(expression), "toString"), List.<JCExpression>nil());
            builder = make().Apply(null, makeSelect(builder, "append"), List.<JCExpression>of(formatted));
        }
    }
    return make().Apply(null, makeSelect(builder, "toString"), List.<JCExpression>nil());
}
Also used : JCMethodInvocation(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCMethodInvocation) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) LetExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.LetExpression) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree)

Example 17 with Expression

use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression in project ceylon by eclipse.

the class CeylonDocTool method warningMissingThrows.

protected void warningMissingThrows(Declaration d) {
    if (ignoreMissingThrows) {
        return;
    }
    final Scope scope = d.getScope();
    final PhasedUnit unit = getUnit(d);
    final Node node = getNode(d);
    if (scope == null || unit == null || unit.getUnit() == null || node == null || !(d instanceof FunctionOrValue)) {
        return;
    }
    List<Type> documentedExceptions = new ArrayList<Type>();
    for (Annotation annotation : d.getAnnotations()) {
        if (annotation.getName().equals("throws")) {
            String exceptionName = annotation.getPositionalArguments().get(0);
            Declaration exceptionDecl = scope.getMemberOrParameter(unit.getUnit(), exceptionName, null, false);
            if (exceptionDecl instanceof TypeDeclaration) {
                documentedExceptions.add(((TypeDeclaration) exceptionDecl).getType());
            }
        }
    }
    final List<Type> thrownExceptions = new ArrayList<Type>();
    node.visitChildren(new Visitor() {

        @Override
        public void visit(Tree.Throw that) {
            Expression expression = that.getExpression();
            if (expression != null) {
                thrownExceptions.add(expression.getTypeModel());
            } else {
                thrownExceptions.add(unit.getUnit().getExceptionType());
            }
        }

        @Override
        public void visit(Tree.Declaration that) {
        // the end of searching
        }
    });
    for (Type thrownException : thrownExceptions) {
        boolean isDocumented = false;
        for (Type documentedException : documentedExceptions) {
            if (thrownException.isSubtypeOf(documentedException)) {
                isDocumented = true;
                break;
            }
        }
        if (!isDocumented) {
            richLog.warning(CeylondMessages.msg("warn.missingThrows", thrownException.asString(), getWhere(d), getPosition(getNode(d))));
        }
    }
}
Also used : Visitor(org.eclipse.ceylon.compiler.typechecker.tree.Visitor) AssertionVisitor(org.eclipse.ceylon.compiler.typechecker.util.AssertionVisitor) Node(org.eclipse.ceylon.compiler.typechecker.tree.Node) ArrayList(java.util.ArrayList) Annotation(org.eclipse.ceylon.model.typechecker.model.Annotation) PhasedUnit(org.eclipse.ceylon.compiler.typechecker.context.PhasedUnit) NothingType(org.eclipse.ceylon.model.typechecker.model.NothingType) Type(org.eclipse.ceylon.model.typechecker.model.Type) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 18 with Expression

use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression in project ceylon by eclipse.

the class ConditionGenerator method caseClause.

/**
 * Generates code for a case clause, as part of a switch statement. Each case
 * is rendered as an if.
 */
private void caseClause(final Tree.CaseClause cc, String expvar, final Tree.Term switchTerm) {
    gen.out("if(");
    final Tree.CaseItem item = cc.getCaseItem();
    Tree.Variable caseVar = null;
    Value caseDec = null;
    if (item instanceof IsCase) {
        IsCase isCaseItem = (IsCase) item;
        gen.generateIsOfType(item, expvar, isCaseItem.getType().getTypeModel(), null, false, false);
        caseVar = isCaseItem.getVariable();
        if (caseVar != null) {
            caseDec = caseVar.getDeclarationModel();
            directAccess.add(caseDec);
            names.forceName(caseDec, expvar);
        }
    } else if (item instanceof Tree.SatisfiesCase) {
        item.addError("case(satisfies) not yet supported", Backend.JavaScript);
        gen.out("true");
    } else if (item instanceof MatchCase) {
        final boolean isNull = switchTerm.getTypeModel().covers(switchTerm.getUnit().getNullType());
        boolean first = true;
        MatchCase matchCaseItem = (MatchCase) item;
        Tree.MatchList matchList = matchCaseItem.getExpressionList();
        if (!matchList.getTypes().isEmpty()) {
            first = false;
            List<Type> union = new ArrayList<Type>();
            for (Tree.Type type : matchList.getTypes()) {
                ModelUtil.addToUnion(union, type.getTypeModel());
            }
            gen.generateIsOfType(item, expvar, ModelUtil.union(union, matchList.getUnit()), null, false, false);
        }
        for (Expression exp : matchList.getExpressions()) {
            if (!first)
                gen.out(" || ");
            final Tree.Term term = exp.getTerm();
            if (term instanceof Tree.StringLiteral || term instanceof Tree.NaturalLiteral) {
                if (isNull) {
                    gen.out(gen.getClAlias(), "nn$(", expvar, ")&&");
                }
                exp.visit(gen);
                gen.out(".equals(", expvar, ")");
            } else if (ModelUtil.isTypeUnknown(switchTerm.getTypeModel())) {
                gen.out(expvar, "===");
                if (!gen.isNaturalLiteral(term)) {
                    exp.visit(gen);
                }
            } else if (term instanceof Tree.Literal) {
                if (switchTerm.getUnit().isOptionalType(switchTerm.getTypeModel())) {
                    gen.out(expvar, "!==null&&");
                }
                gen.out(expvar, ".equals(");
                exp.visit(gen);
                gen.out(")");
            } else if (term instanceof Tree.Tuple) {
                if (((Tree.Tuple) term).getSequencedArgument() == null) {
                    gen.out(expvar, "===", gen.getClAlias(), "empty()");
                } else {
                    gen.out(gen.getClAlias(), "is$(", expvar, ",{t:", gen.getClAlias(), "Tuple})&&", expvar, ".equals(");
                    exp.visit(gen);
                    gen.out(")");
                }
            } else {
                gen.out(expvar, "===");
                exp.visit(gen);
            }
            first = false;
        }
        caseVar = matchCaseItem.getVariable();
        if (caseVar != null) {
            caseDec = caseVar.getDeclarationModel();
            directAccess.add(caseDec);
            names.forceName(caseDec, expvar);
        }
    } else {
        cc.addUnexpectedError("support for case of type " + cc.getClass().getSimpleName() + " not yet implemented", Backend.JavaScript);
    }
    gen.out(")");
    if (cc.getBlock() == null) {
        gen.out("return ");
        cc.getExpression().visit(gen);
        gen.out(";");
    } else {
        gen.out(" ");
        Set<Value> cap = caseDec != null && caseDec.isJsCaptured() ? Collections.singleton(caseDec) : null;
        gen.encloseBlockInFunction(cc.getBlock(), true, cap);
    }
    if (caseDec != null) {
        directAccess.remove(caseDec);
        names.forceName(caseDec, null);
    }
}
Also used : ArrayList(java.util.ArrayList) Type(org.eclipse.ceylon.model.typechecker.model.Type) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) MatchCase(org.eclipse.ceylon.compiler.typechecker.tree.Tree.MatchCase) Value(org.eclipse.ceylon.model.typechecker.model.Value) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) IsCase(org.eclipse.ceylon.compiler.typechecker.tree.Tree.IsCase)

Example 19 with Expression

use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression 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);
            }
        }
    }
}
Also used : Functional(org.eclipse.ceylon.model.typechecker.model.Functional) LazySpecifierExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Value(org.eclipse.ceylon.model.typechecker.model.Value) LazySpecifierExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression)

Aggregations

Expression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression)19 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)17 JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)9 JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)8 Type (org.eclipse.ceylon.model.typechecker.model.Type)8 CustomTree (org.eclipse.ceylon.compiler.typechecker.tree.CustomTree)7 JCStatement (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement)7 SpecifierOrInitializerExpression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.SpecifierOrInitializerExpression)6 Term (org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term)5 ArrayList (java.util.ArrayList)4 JCVariableDecl (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl)4 Value (org.eclipse.ceylon.model.typechecker.model.Value)4 SyntheticName (org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName)3 LazySpecifierExpression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression)3 StaticMemberOrTypeExpression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.StaticMemberOrTypeExpression)3 JCBlock (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCBlock)3 CName (org.eclipse.ceylon.compiler.java.codegen.Naming.CName)2 BaseMemberExpression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression)2 LetExpression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.LetExpression)2 QualifiedMemberExpression (org.eclipse.ceylon.compiler.typechecker.tree.Tree.QualifiedMemberExpression)2