Search in sources :

Example 76 with TypedDeclaration

use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.

the class StatementTransformer method transformCaseMatch.

private JCStatement transformCaseMatch(Naming.SyntheticName selectorAlias, Tree.SwitchClause switchClause, Tree.CaseClause caseClause, String tmpVar, Tree.Term outerExpression, Type expectedType, Tree.MatchCase matchCase, JCStatement last, Type switchType, boolean primitiveSelector) {
    at(matchCase);
    JCVariableDecl decl2 = null;
    Substitution prevSubst2 = null;
    if (matchCase.getVariable() != null) {
        // Use the type of the variable, which is more precise than the type we test for.
        Type varType = matchCase.getVariable().getDeclarationModel().getType();
        String name = matchCase.getVariable().getIdentifier().getText();
        TypedDeclaration varDecl = matchCase.getVariable().getDeclarationModel();
        Naming.SyntheticName tmpVarName = selectorAlias;
        Name substVarName = naming.aliasName(name);
        // Want raw type for instanceof since it can't be used with generic types
        JCExpression rawToTypeExpr = makeJavaType(varType, JT_NO_PRIMITIVES | JT_RAW);
        // Substitute variable with the correct type to use in the rest of the code block
        JCExpression tmpVarExpr = at(matchCase).TypeCast(rawToTypeExpr, tmpVarName.makeIdent());
        JCExpression toTypeExpr;
        if (isCeylonBasicType(varType) && varDecl.getUnboxed() == true) {
            toTypeExpr = makeJavaType(varType);
            tmpVarExpr = unboxType(tmpVarExpr, varType);
        } else {
            toTypeExpr = makeJavaType(varType, JT_NO_PRIMITIVES);
        }
        // The variable holding the result for the code inside the code block
        decl2 = at(matchCase).VarDef(make().Modifiers(FINAL), substVarName, toTypeExpr, tmpVarExpr);
        // Prepare for variable substitution in the following code block
        prevSubst2 = naming.addVariableSubst(varDecl, substVarName.toString());
    }
    JCExpression tests = null;
    java.util.List<Tree.Expression> expressions = matchCase.getExpressionList().getExpressions();
    for (Tree.Expression expr : expressions) {
        Tree.Term term = ExpressionTransformer.eliminateParens(expr.getTerm());
        boolean unboxedEquality = primitiveSelector || isCeylonBasicType(typeFact().getDefiniteType(switchType));
        Type type = term.getTypeModel();
        JCExpression transformedExpression = expressionGen().transformExpression(term, unboxedEquality ? BoxingStrategy.UNBOXED : BoxingStrategy.BOXED, type);
        JCExpression test;
        if (term instanceof Tree.Literal || term instanceof Tree.NegativeOp) {
            if (unboxedEquality) {
                if (term instanceof Tree.StringLiteral) {
                    test = make().Apply(null, makeSelect(unboxType(selectorAlias.makeIdent(), type), "equals"), List.<JCExpression>of(transformedExpression));
                } else {
                    test = make().Binary(JCTree.Tag.EQ, primitiveSelector ? selectorAlias.makeIdent() : unboxType(selectorAlias.makeIdent(), type), transformedExpression);
                }
            } else {
                test = make().Apply(null, makeSelect(selectorAlias.makeIdent(), "equals"), List.<JCExpression>of(transformedExpression));
            }
            if (isOptional(switchType)) {
                test = make().Binary(JCTree.Tag.AND, make().Binary(JCTree.Tag.NE, selectorAlias.makeIdent(), makeNull()), test);
            }
        } else {
            JCExpression selectorExpr;
            if (!primitiveSelector && isCeylonBasicType(typeFact().getDefiniteType(switchType))) {
                selectorExpr = unboxType(selectorAlias.makeIdent(), type);
            } else {
                selectorExpr = selectorAlias.makeIdent();
            }
            if (term instanceof Tree.Tuple) {
                if (type.isEmpty()) {
                    test = make().TypeTest(selectorAlias.makeIdent(), makeJavaType(typeFact().getEmptyType(), JT_RAW));
                } else {
                    test = make().Apply(null, makeSelect(selectorExpr, "equals"), List.<JCExpression>of(transformedExpression));
                    test = make().Binary(Tag.AND, make().TypeTest(selectorAlias.makeIdent(), make().QualIdent(syms().ceylonTupleType.tsym)), test);
                }
            } else if (type.isString()) {
                test = make().Apply(null, makeSelect(selectorExpr, "equals"), List.<JCExpression>of(transformedExpression));
            } else {
                test = make().Binary(JCTree.Tag.EQ, selectorExpr, transformedExpression);
            }
        }
        if (tests == null) {
            tests = test;
        } else if (isNull(type)) {
            // ensure we do any null check as the first operation in the ||-ed expression
            tests = make().Binary(JCTree.Tag.OR, test, tests);
        } else {
            tests = make().Binary(JCTree.Tag.OR, tests, test);
        }
    }
    java.util.List<Tree.Type> types = matchCase.getExpressionList().getTypes();
    for (Tree.Type caseType : types) {
        // note: There's no point using makeOptimizedTypeTest() because cases are disjoint
        // anyway and the cheap cases get evaluated first.
        Type type = caseType.getTypeModel();
        JCExpression cond = makeTypeTest(null, selectorAlias, type, type);
        if (tests == null) {
            tests = cond;
        } else if (isNull(type)) {
            // ensure we do any null check as the first operation in the ||-ed expression
            tests = make().Binary(JCTree.Tag.OR, cond, tests);
        } else {
            tests = make().Binary(JCTree.Tag.OR, tests, cond);
        }
    }
    Substitution prevSubst = null;
    if (switchClause.getSwitched().getVariable() != null) {
        // Prepare for variable substitution in the following code block
        prevSubst = naming.addVariableSubst(switchClause.getSwitched().getVariable().getDeclarationModel(), selectorAlias.toString());
    }
    JCBlock block;
    if (decl2 != null) {
        List<JCStatement> stats = List.<JCStatement>of(decl2);
        stats = stats.appendList(transformCaseClause(caseClause, tmpVar, outerExpression, expectedType));
        block = at(matchCase).Block(0, stats);
    } else {
        block = transformCaseClauseBlock(caseClause, tmpVar, outerExpression, expectedType);
    }
    if (prevSubst2 != null) {
        // Deactivate the above variable substitution
        prevSubst2.close();
    }
    if (prevSubst != null) {
        // Deactivate the above variable substitution
        prevSubst.close();
    }
    return at(caseClause).If(tests, block, last);
}
Also used : JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) Name(org.eclipse.ceylon.langtools.tools.javac.util.Name) CName(org.eclipse.ceylon.compiler.java.codegen.Naming.CName) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName) Substitution(org.eclipse.ceylon.compiler.java.codegen.Naming.Substitution) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) JCBlock(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCBlock) Term(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Term) JCVariableDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) SpecifierOrInitializerExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.SpecifierOrInitializerExpression) Expression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Expression) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName)

Example 77 with TypedDeclaration

use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.

the class StatementTransformer method transformCaseIs.

/**
 * Transform a "case(is ...)"
 * @param selectorAlias
 * @param caseClause
 * @param isCase
 * @param last
 * @return
 */
private JCStatement transformCaseIs(Naming.SyntheticName selectorAlias, Tree.CaseClause caseClause, String tmpVar, Tree.Term outerExpression, Type expectedType, Tree.IsCase isCase, JCStatement last, Type expressionType) {
    at(isCase);
    // Use the type of the variable, which is more precise than the type we test for.
    Type varType = isCase.getVariable().getDeclarationModel().getType();
    Type caseType = getIsCaseType(isCase);
    // note: There's no point using makeOptimizedTypeTest() because cases are disjoint
    // anyway and the cheap cases get evaluated first.
    JCExpression cond = makeTypeTest(null, selectorAlias, caseType, expressionType);
    String name = isCase.getVariable().getIdentifier().getText();
    TypedDeclaration varDecl = isCase.getVariable().getDeclarationModel();
    Naming.SyntheticName tmpVarName = selectorAlias;
    Name substVarName = naming.aliasName(name);
    // Want raw type for instanceof since it can't be used with generic types
    JCExpression rawToTypeExpr = makeJavaType(varType, JT_NO_PRIMITIVES | JT_RAW);
    // Substitute variable with the correct type to use in the rest of the code block
    JCExpression tmpVarExpr = at(isCase).TypeCast(rawToTypeExpr, tmpVarName.makeIdent());
    JCExpression toTypeExpr;
    if (isCeylonBasicType(varType) && varDecl.getUnboxed() == true) {
        toTypeExpr = makeJavaType(varType);
        tmpVarExpr = unboxType(tmpVarExpr, varType);
    } else {
        toTypeExpr = makeJavaType(varType, JT_NO_PRIMITIVES);
    }
    // The variable holding the result for the code inside the code block
    JCVariableDecl decl2 = at(isCase).VarDef(make().Modifiers(FINAL), substVarName, toTypeExpr, tmpVarExpr);
    // Prepare for variable substitution in the following code block
    Substitution prevSubst = naming.addVariableSubst(varDecl, substVarName.toString());
    List<JCStatement> stats = List.<JCStatement>of(decl2);
    stats = stats.appendList(transformCaseClause(caseClause, tmpVar, outerExpression, expectedType));
    JCBlock block = at(isCase).Block(0, stats);
    // Deactivate the above variable substitution
    prevSubst.close();
    last = make().If(cond, block, last);
    return last;
}
Also used : TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCBlock(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCBlock) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Substitution(org.eclipse.ceylon.compiler.java.codegen.Naming.Substitution) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) JCVariableDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl) Name(org.eclipse.ceylon.langtools.tools.javac.util.Name) CName(org.eclipse.ceylon.compiler.java.codegen.Naming.CName) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName)

Example 78 with TypedDeclaration

use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.

the class MethodOrValueReferenceVisitor method capture.

private void capture(Tree.Primary that, boolean methodSpecifier) {
    if (that instanceof Tree.MemberOrTypeExpression) {
        final Declaration decl = ((Tree.MemberOrTypeExpression) that).getDeclaration();
        if (!(decl instanceof TypedDeclaration)) {
            return;
        }
        TypedDeclaration d = (TypedDeclaration) decl;
        if (Decl.equal(d, declaration) || (d.isNativeHeader() && d.getOverloads().contains(declaration))) {
            d = declaration;
            if (Decl.isParameter(d)) {
                // a reference from a default argument
                // expression of the same parameter
                // list does not capture a parameter
                Scope s = that.getScope();
                boolean sameScope = d.getContainer().equals(s) || (s instanceof Declaration && (Decl.isParameter((Declaration) s) || (s instanceof Value && !((Value) s).isTransient())) && d.getContainer().equals(s.getScope()));
                if (!sameScope || methodSpecifier || inLazySpecifierExpression) {
                    ((FunctionOrValue) d).setCaptured(true);
                }
                // Accessing another instance's member passed to a class initializer
                if (that instanceof Tree.QualifiedMemberExpression) {
                    if (d instanceof TypedDeclaration && ((TypedDeclaration) d).getOtherInstanceAccess()) {
                        ((FunctionOrValue) d).setCaptured(true);
                    }
                }
                if (isCapturableMplParameter(d)) {
                    ((FunctionOrValue) d).setCaptured(true);
                }
            } else if (Decl.isValue(d) || Decl.isGetter(d)) {
                Value v = (Value) d;
                v.setCaptured(true);
                if (Decl.isObjectValue(d)) {
                    v.setSelfCaptured(isSelfCaptured(that, d));
                }
                if (v.getSetter() != null) {
                    v.getSetter().setCaptured(true);
                }
            } else if (d instanceof Function) {
                ((Function) d).setCaptured(true);
            }
        /*if (d.isVariable() && !d.isClassMember() && !d.isToplevel()) {
                    that.addError("access to variable local from capturing scope: " + declaration.getName());
                }*/
        }
    }
}
Also used : TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) Function(org.eclipse.ceylon.model.typechecker.model.Function) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Value(org.eclipse.ceylon.model.typechecker.model.Value) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 79 with TypedDeclaration

use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.

the class MethodDefinitionBuilder method getFirstRefinedDeclaration.

private Declaration getFirstRefinedDeclaration(TypedDeclaration member) {
    if (!member.isActual() || Decl.equal(member, member.getRefinedDeclaration()))
        return null;
    // Taken pretty much straight from RefinementVisitor
    ClassOrInterface type = (ClassOrInterface) member.getContainer();
    java.util.List<Type> signature = ModelUtil.getSignature(member);
    boolean variadic = ModelUtil.isVariadic(member);
    Declaration root = type.getRefinedMember(name, signature, variadic);
    if (root == null)
        return null;
    TypeDeclaration rootType = (TypeDeclaration) root.getContainer();
    java.util.List<Declaration> interveningRefinements = getInterveningRefinements(member, root, type, rootType);
    for (Declaration refined : interveningRefinements) {
        TypeDeclaration interveningType = (TypeDeclaration) refined.getContainer();
        if (getInterveningRefinements(member, root, type, interveningType).size() > 1) {
            continue;
        }
        // first?
        return refined;
    }
    return null;
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) Type(org.eclipse.ceylon.model.typechecker.model.Type) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 80 with TypedDeclaration

use of org.eclipse.ceylon.model.typechecker.model.TypedDeclaration in project ceylon by eclipse.

the class Naming method getMethodNameInternal.

private static String getMethodNameInternal(TypedDeclaration decl) {
    String name;
    if (decl.isClassOrInterfaceMember() && decl instanceof Function) {
        Declaration refined = decl.getRefinedDeclaration();
        if (refined instanceof JavaMethod) {
            return ((JavaMethod) refined).getRealName();
        }
        name = quoteMethodNameIfProperty((Function) decl);
    } else {
        name = decl.getName();
    }
    if (decl.isClassMember() && "readResolve".equals(name) && Strategy.addReadResolve((Class) decl.getContainer())) {
        return quote(name);
    }
    if (decl.isClassMember() && "writeReplace".equals(name) && Strategy.useSerializationProxy((Class) decl.getContainer())) {
        return quote(name);
    }
    // ERASURE
    if (QUOTABLE_METHOD_NAMES.contains(name)) {
        return quote(name);
    } else {
        return quoteIfJavaKeyword(name);
    }
}
Also used : Function(org.eclipse.ceylon.model.typechecker.model.Function) LazyFunction(org.eclipse.ceylon.model.loader.model.LazyFunction) JavaMethod(org.eclipse.ceylon.model.loader.model.JavaMethod) LazyClass(org.eclipse.ceylon.model.loader.model.LazyClass) Class(org.eclipse.ceylon.model.typechecker.model.Class) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration)

Aggregations

TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)110 Type (org.eclipse.ceylon.model.typechecker.model.Type)58 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)51 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)50 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)47 Function (org.eclipse.ceylon.model.typechecker.model.Function)34 Value (org.eclipse.ceylon.model.typechecker.model.Value)28 Class (org.eclipse.ceylon.model.typechecker.model.Class)26 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)26 AnalyzerUtil.getTypedDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration)25 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)22 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)21 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)21 AnalyzerUtil.getPackageTypedDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypedDeclaration)20 Scope (org.eclipse.ceylon.model.typechecker.model.Scope)19 JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)18 JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)17 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)17 Constructor (org.eclipse.ceylon.model.typechecker.model.Constructor)16 CustomTree (org.eclipse.ceylon.compiler.typechecker.tree.CustomTree)15