Search in sources :

Example 1 with Substitution

use of com.redhat.ceylon.compiler.java.codegen.Naming.Substitution in project ceylon-compiler by ceylon.

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);
    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));
        JCExpression transformedExpression = expressionGen().transformExpression(term, unboxedEquality ? BoxingStrategy.UNBOXED : BoxingStrategy.BOXED, term.getTypeModel());
        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(), term.getTypeModel()), "equals"), List.<JCExpression>of(transformedExpression));
                } else {
                    test = make().Binary(JCTree.EQ, primitiveSelector ? selectorAlias.makeIdent() : unboxType(selectorAlias.makeIdent(), term.getTypeModel()), transformedExpression);
                }
            } else {
                test = make().Apply(null, makeSelect(selectorAlias.makeIdent(), "equals"), List.<JCExpression>of(transformedExpression));
            }
            if (isOptional(switchType)) {
                test = make().Binary(JCTree.AND, make().Binary(JCTree.NE, selectorAlias.makeIdent(), makeNull()), test);
            }
        } else {
            JCExpression selectorExpr;
            if (!primitiveSelector && isCeylonBasicType(typeFact().getDefiniteType(switchType))) {
                selectorExpr = unboxType(selectorAlias.makeIdent(), term.getTypeModel());
            } else {
                selectorExpr = selectorAlias.makeIdent();
            }
            test = make().Binary(JCTree.EQ, selectorExpr, transformedExpression);
        }
        if (tests == null)
            tests = test;
        else if (isNull(term.getTypeModel())) {
            // ensure we do any null check as the first operation in the ||-ed expression
            tests = make().Binary(JCTree.OR, test, tests);
        } else {
            tests = make().Binary(JCTree.OR, tests, test);
        }
    }
    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 = transformCaseClauseBlock(caseClause, tmpVar, outerExpression, expectedType);
    if (prevSubst != null) {
        // Deactivate the above variable substitution
        prevSubst.close();
    }
    return at(caseClause).If(tests, block, last);
}
Also used : JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) Term(com.redhat.ceylon.compiler.typechecker.tree.Tree.Term) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) Substitution(com.redhat.ceylon.compiler.java.codegen.Naming.Substitution) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) SpecifierOrInitializerExpression(com.redhat.ceylon.compiler.typechecker.tree.Tree.SpecifierOrInitializerExpression) Expression(com.redhat.ceylon.compiler.typechecker.tree.Tree.Expression) Expression(com.redhat.ceylon.compiler.typechecker.tree.Tree.Expression) CustomTree(com.redhat.ceylon.compiler.typechecker.tree.CustomTree) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree)

Example 2 with Substitution

use of com.redhat.ceylon.compiler.java.codegen.Naming.Substitution in project ceylon-compiler by ceylon.

the class ClassTransformer method transformSpecifiedMethodBody.

List<JCStatement> transformSpecifiedMethodBody(Tree.MethodDeclaration def, SpecifierExpression specifierExpression) {
    final Function model = def.getDeclarationModel();
    List<JCStatement> body;
    Tree.MethodDeclaration methodDecl = def;
    boolean isLazy = specifierExpression instanceof Tree.LazySpecifierExpression;
    boolean returnNull = false;
    JCExpression bodyExpr;
    Tree.Term term = null;
    if (specifierExpression != null && specifierExpression.getExpression() != null) {
        term = Decl.unwrapExpressionsUntilTerm(specifierExpression.getExpression());
        HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(term);
        if (error != null) {
            return List.<JCStatement>of(this.makeThrowUnresolvedCompilationError(error));
        }
    }
    if (!isLazy && term instanceof Tree.FunctionArgument) {
        // Function specified with lambda: Don't bother generating a
        // Callable, just transform the expr to use as the method body.
        Tree.FunctionArgument fa = (Tree.FunctionArgument) term;
        Type resultType = model.getType();
        returnNull = isAnything(resultType) && fa.getExpression().getUnboxed();
        final java.util.List<Tree.Parameter> lambdaParams = fa.getParameterLists().get(0).getParameters();
        final java.util.List<Tree.Parameter> defParams = def.getParameterLists().get(0).getParameters();
        List<Substitution> substitutions = List.nil();
        for (int ii = 0; ii < lambdaParams.size(); ii++) {
            substitutions = substitutions.append(naming.addVariableSubst((TypedDeclaration) lambdaParams.get(ii).getParameterModel().getModel(), defParams.get(ii).getParameterModel().getName()));
        }
        bodyExpr = gen().expressionGen().transformExpression(fa.getExpression(), returnNull ? BoxingStrategy.INDIFFERENT : CodegenUtil.getBoxingStrategy(model), resultType);
        for (Substitution subs : substitutions) {
            subs.close();
        }
    } else if (!isLazy && typeFact().isCallableType(term.getTypeModel())) {
        returnNull = isAnything(term.getTypeModel()) && term.getUnboxed();
        Function method = methodDecl.getDeclarationModel();
        boolean lazy = specifierExpression instanceof Tree.LazySpecifierExpression;
        boolean inlined = CodegenUtil.canOptimiseMethodSpecifier(term, method);
        Invocation invocation;
        if ((lazy || inlined) && term instanceof Tree.MemberOrTypeExpression && ((Tree.MemberOrTypeExpression) term).getDeclaration() instanceof Functional) {
            Declaration primaryDeclaration = ((Tree.MemberOrTypeExpression) term).getDeclaration();
            Reference producedReference = ((Tree.MemberOrTypeExpression) term).getTarget();
            invocation = new MethodReferenceSpecifierInvocation(this, (Tree.MemberOrTypeExpression) term, primaryDeclaration, producedReference, method, specifierExpression);
        } else if (!lazy && !inlined) {
            // must be a callable we stored
            String name = naming.getMethodSpecifierAttributeName(method);
            invocation = new CallableSpecifierInvocation(this, method, naming.makeUnquotedIdent(name), term, term);
        } else if (isCeylonCallableSubtype(term.getTypeModel())) {
            invocation = new CallableSpecifierInvocation(this, method, expressionGen().transformExpression(term), term, term);
        } else {
            throw new BugException(term, "unhandled primary: " + term == null ? "null" : term.getNodeType());
        }
        invocation.handleBoxing(true);
        invocation.setErased(CodegenUtil.hasTypeErased(term) || getReturnTypeOfCallable(term.getTypeModel()).isNothing());
        bodyExpr = expressionGen().transformInvocation(invocation);
    } else {
        bodyExpr = expressionGen().transformExpression(model, term);
        // The innermost of an MPL method declared void needs to return null
        returnNull = Decl.isUnboxedVoid(model) && Decl.isMpl(model);
    }
    if (!Decl.isUnboxedVoid(model) || Decl.isMpl(model) || Strategy.useBoxedVoid(model)) {
        if (returnNull) {
            body = List.<JCStatement>of(make().Exec(bodyExpr), make().Return(makeNull()));
        } else {
            body = List.<JCStatement>of(make().Return(bodyExpr));
        }
    } else {
        body = List.<JCStatement>of(make().Exec(bodyExpr));
    }
    return body;
}
Also used : JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) Function(com.redhat.ceylon.model.typechecker.model.Function) FunctionArgument(com.redhat.ceylon.compiler.typechecker.tree.Tree.FunctionArgument) Substitution(com.redhat.ceylon.compiler.java.codegen.Naming.Substitution) JCPrimitiveTypeTree(com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) MethodDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) AttributeDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration) FunctionArgument(com.redhat.ceylon.compiler.typechecker.tree.Tree.FunctionArgument) LazySpecifierExpression(com.redhat.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression) Reference(com.redhat.ceylon.model.typechecker.model.Reference) TypedReference(com.redhat.ceylon.model.typechecker.model.TypedReference) MethodDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) Functional(com.redhat.ceylon.model.typechecker.model.Functional) Type(com.redhat.ceylon.model.typechecker.model.Type) LazySpecifierExpression(com.redhat.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) HasErrorException(com.redhat.ceylon.compiler.java.codegen.recovery.HasErrorException) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) Parameter(com.redhat.ceylon.model.typechecker.model.Parameter)

Example 3 with Substitution

use of com.redhat.ceylon.compiler.java.codegen.Naming.Substitution in project ceylon-compiler by ceylon.

the class StatementTransformer method transform.

public JCTree transform(CustomTree.GuardedVariable that) {
    BoxingStrategy boxingStrategy = CodegenUtil.getBoxingStrategy(that.getDeclarationModel());
    Tree.Expression expr = that.getSpecifierExpression().getExpression();
    Type fromType = expr.getTypeModel();
    Value newValue = that.getDeclarationModel();
    Type toType = newValue.getType();
    Tree.ConditionList conditionList = that.getConditionList();
    Tree.Condition condition = conditionList.getConditions().get(0);
    JCExpression val = expressionGen().transformExpression(expr);
    at(that);
    if (condition instanceof Tree.IsCondition) {
        if (!willEraseToObject(toType)) {
            // Want raw type for instanceof since it can't be used with generic types
            JCExpression rawToTypeExpr = makeJavaType(toType, JT_NO_PRIMITIVES | JT_RAW);
            // Substitute variable with the correct type to use in the rest of the code block
            val = make().TypeCast(rawToTypeExpr, val);
            if (CodegenUtil.isUnBoxed(newValue) && canUnbox(toType)) {
                val = unboxType(val, toType);
            }
        }
    } else if (condition instanceof Tree.ExistsCondition) {
        Type exprType = fromType;
        if (isOptional(exprType)) {
            exprType = typeFact().getDefiniteType(exprType);
        }
        val = expressionGen().applyErasureAndBoxing(val, exprType, CodegenUtil.hasTypeErased(expr), true, CodegenUtil.hasUntrustedType(expr), boxingStrategy, toType, 0);
    } else if (condition instanceof Tree.NonemptyCondition) {
        Type exprType = fromType;
        if (isOptional(exprType)) {
            exprType = typeFact().getDefiniteType(exprType);
        }
        val = expressionGen().applyErasureAndBoxing(val, exprType, false, true, BoxingStrategy.BOXED, toType, ExpressionTransformer.EXPR_DOWN_CAST);
    }
    SyntheticName alias = naming.alias(that.getIdentifier().getText());
    Substitution subst = naming.addVariableSubst(newValue, alias.getName());
    // FIXME: this is rubbish, but the same rubbish from assert. it's most likely wrong there too
    Scope scope = that.getScope().getScope();
    while (scope instanceof ConditionScope) {
        scope = scope.getScope();
    }
    subst.scopeClose(scope);
    JCExpression varType = makeJavaType(toType);
    return make().VarDef(make().Modifiers(FINAL), alias.asName(), varType, val);
}
Also used : SyntheticName(com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName) ConditionList(com.redhat.ceylon.compiler.typechecker.tree.Tree.ConditionList) Type(com.redhat.ceylon.model.typechecker.model.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) Substitution(com.redhat.ceylon.compiler.java.codegen.Naming.Substitution) ConditionScope(com.redhat.ceylon.model.typechecker.model.ConditionScope) Scope(com.redhat.ceylon.model.typechecker.model.Scope) ConditionScope(com.redhat.ceylon.model.typechecker.model.ConditionScope) Condition(com.redhat.ceylon.compiler.typechecker.tree.Tree.Condition) Expression(com.redhat.ceylon.compiler.typechecker.tree.Tree.Expression) Value(com.redhat.ceylon.model.typechecker.model.Value) CustomTree(com.redhat.ceylon.compiler.typechecker.tree.CustomTree) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) BoxingStrategy(com.redhat.ceylon.compiler.java.codegen.AbstractTransformer.BoxingStrategy)

Example 4 with Substitution

use of com.redhat.ceylon.compiler.java.codegen.Naming.Substitution in project ceylon-compiler by ceylon.

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 = isCase.getType().getTypeModel();
    // 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(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Type(com.redhat.ceylon.model.typechecker.model.Type) JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) Substitution(com.redhat.ceylon.compiler.java.codegen.Naming.Substitution) SyntheticName(com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) SyntheticName(com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName) CName(com.redhat.ceylon.compiler.java.codegen.Naming.CName) Name(com.sun.tools.javac.util.Name) OptionName(com.sun.tools.javac.main.OptionName)

Aggregations

Substitution (com.redhat.ceylon.compiler.java.codegen.Naming.Substitution)4 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)4 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)3 Type (com.redhat.ceylon.model.typechecker.model.Type)3 JCTree (com.sun.tools.javac.tree.JCTree)3 SyntheticName (com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName)2 CustomTree (com.redhat.ceylon.compiler.typechecker.tree.CustomTree)2 Expression (com.redhat.ceylon.compiler.typechecker.tree.Tree.Expression)2 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)2 JCBlock (com.sun.tools.javac.tree.JCTree.JCBlock)2 JCStatement (com.sun.tools.javac.tree.JCTree.JCStatement)2 BoxingStrategy (com.redhat.ceylon.compiler.java.codegen.AbstractTransformer.BoxingStrategy)1 CName (com.redhat.ceylon.compiler.java.codegen.Naming.CName)1 HasErrorException (com.redhat.ceylon.compiler.java.codegen.recovery.HasErrorException)1 AttributeDeclaration (com.redhat.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration)1 Condition (com.redhat.ceylon.compiler.typechecker.tree.Tree.Condition)1 ConditionList (com.redhat.ceylon.compiler.typechecker.tree.Tree.ConditionList)1 FunctionArgument (com.redhat.ceylon.compiler.typechecker.tree.Tree.FunctionArgument)1 LazySpecifierExpression (com.redhat.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression)1 MethodDeclaration (com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration)1