Search in sources :

Example 31 with JCStatement

use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.

the class CallableBuilder method methodReference.

/**
     * Constructs an {@code AbstractCallable} suitable for wrapping a 
     * method reference. For example:
     * <pre>
     *   void someMethod() { ... }
     *   Anything() ref = someMethod;
     * </pre>
     */
public static JCExpression methodReference(CeylonTransformer gen, final Tree.StaticMemberOrTypeExpression forwardCallTo, ParameterList parameterList) {
    ListBuffer<JCStatement> letStmts = ListBuffer.<JCTree.JCStatement>lb();
    CallableBuilder cb = new CallableBuilder(gen, forwardCallTo, forwardCallTo.getTypeModel(), parameterList);
    cb.parameterTypes = cb.getParameterTypesFromCallableModel();
    Naming.SyntheticName instanceFieldName;
    boolean instanceFieldIsBoxed = false;
    if (forwardCallTo instanceof Tree.QualifiedMemberOrTypeExpression && !ExpressionTransformer.isSuperOrSuperOf(((Tree.QualifiedMemberOrTypeExpression) forwardCallTo).getPrimary()) && !ExpressionTransformer.isPackageQualified((Tree.QualifiedMemberOrTypeExpression) forwardCallTo)) {
        if ((((Tree.QualifiedMemberOrTypeExpression) forwardCallTo).getMemberOperator() instanceof Tree.SpreadOp)) {
            instanceFieldIsBoxed = true;
            instanceFieldName = null;
        } else {
            Tree.QualifiedMemberOrTypeExpression qmte = (Tree.QualifiedMemberOrTypeExpression) forwardCallTo;
            boolean prevCallableInv = gen.expressionGen().withinSyntheticClassBody(true);
            try {
                instanceFieldName = gen.naming.synthetic(Unfix.$instance$);
                int varTypeFlags = Decl.isPrivateAccessRequiringCompanion(qmte) ? JT_COMPANION : 0;
                Type primaryType;
                if (Decl.isValueTypeDecl(qmte.getPrimary().getTypeModel())) {
                    primaryType = qmte.getPrimary().getTypeModel();
                } else {
                    primaryType = qmte.getTarget().getQualifyingType();
                }
                if (((Tree.QualifiedMemberOrTypeExpression) forwardCallTo).getMemberOperator() instanceof Tree.SafeMemberOp) {
                    primaryType = gen.typeFact().getOptionalType(primaryType);
                }
                JCExpression primaryExpr = gen.expressionGen().transformQualifiedMemberPrimary(qmte);
                if (Decl.isPrivateAccessRequiringCompanion(qmte)) {
                    primaryExpr = gen.naming.makeCompanionAccessorCall(primaryExpr, (Interface) qmte.getDeclaration().getContainer());
                }
                Type varType = qmte.getDeclaration().isShared() ? primaryType : Decl.getPrivateAccessType(qmte);
                if (qmte.getPrimary().getUnboxed() == false) {
                    varTypeFlags |= JT_NO_PRIMITIVES;
                    instanceFieldIsBoxed = true;
                }
                letStmts.add(gen.makeVar(Flags.FINAL, instanceFieldName, gen.makeJavaType(varType, varTypeFlags), primaryExpr));
                if (qmte.getPrimary() instanceof Tree.MemberOrTypeExpression && ((Tree.MemberOrTypeExpression) qmte.getPrimary()).getDeclaration() instanceof TypedDeclaration) {
                    cb.instanceSubstitution = gen.naming.addVariableSubst((TypedDeclaration) ((Tree.MemberOrTypeExpression) qmte.getPrimary()).getDeclaration(), instanceFieldName.getName());
                }
            } finally {
                gen.expressionGen().withinSyntheticClassBody(prevCallableInv);
            }
        }
    } else {
        instanceFieldName = null;
    }
    CallableTransformation tx;
    cb.defaultValueCall = new DefaultValueMethodTransformation() {

        @Override
        public JCExpression makeDefaultValueMethod(AbstractTransformer gen, Parameter defaultedParam, List<JCExpression> defaultMethodArgs) {
            JCExpression fn = null;
            if (forwardCallTo instanceof Tree.BaseMemberOrTypeExpression) {
                fn = gen.naming.makeDefaultedParamMethod(null, defaultedParam);
            } else if (forwardCallTo instanceof Tree.QualifiedMemberOrTypeExpression) {
                JCExpression qualifier = gen.expressionGen().transformTermForInvocation(((Tree.QualifiedMemberOrTypeExpression) forwardCallTo).getPrimary(), null);
                fn = gen.naming.makeDefaultedParamMethod(qualifier, defaultedParam);
            }
            return gen.make().Apply(null, fn, defaultMethodArgs);
        }
    };
    if (cb.isVariadic) {
        tx = cb.new VariadicCallableTransformation(cb.new CallMethodWithForwardedBody(instanceFieldName, instanceFieldIsBoxed, forwardCallTo, false));
    } else {
        tx = cb.new FixedArityCallableTransformation(cb.new CallMethodWithForwardedBody(instanceFieldName, instanceFieldIsBoxed, forwardCallTo, true), null);
    }
    cb.useTransformation(tx);
    return letStmts.isEmpty() ? cb.build() : gen.make().LetExpr(letStmts.toList(), cb.build());
}
Also used : JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Type(com.redhat.ceylon.model.typechecker.model.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) Parameter(com.redhat.ceylon.model.typechecker.model.Parameter) JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) SyntheticName(com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName) Interface(com.redhat.ceylon.model.typechecker.model.Interface)

Example 32 with JCStatement

use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.

the class AttributeDefinitionBuilder method generateDefaultGetterBlock.

private JCTree.JCBlock generateDefaultGetterBlock() {
    JCTree.JCExpression returnExpr = owner.makeQuotedIdent(fieldName);
    // make sure we turn hash long to int properly
    if (isHash)
        returnExpr = owner.convertToIntForHashAttribute(returnExpr);
    JCReturn returnValue = owner.make().Return(returnExpr);
    List<JCStatement> stmts;
    stmts = List.<JCTree.JCStatement>of(returnValue);
    JCTree.JCBlock block;
    if (toplevel || late) {
        JCExpression msg = owner.make().Literal(late ? "Accessing uninitialized 'late' attribute '" + attrName + "'" : "Cyclic initialization trying to read the value of '" + attrName + "' before it was set");
        JCTree.JCThrow throwStmt = owner.make().Throw(owner.makeNewClass(owner.makeIdent(owner.syms().ceylonInitializationErrorType), List.<JCExpression>of(msg)));
        List<JCStatement> catchStmts;
        if (isDeferredInitError()) {
            JCStatement rethrow = owner.make().Exec(owner.utilInvocation().rethrow(owner.makeUnquotedIdent(Naming.getToplevelAttributeSavedExceptionName())));
            // rethrow the init exception if we have one
            JCIf ifThrow = owner.make().If(owner.make().Binary(JCTree.NE, owner.makeUnquotedIdent(Naming.getToplevelAttributeSavedExceptionName()), owner.makeNull()), rethrow, null);
            catchStmts = List.<JCTree.JCStatement>of(ifThrow, throwStmt);
        } else {
            catchStmts = List.<JCTree.JCStatement>of(throwStmt);
        }
        block = owner.make().Block(0L, List.<JCTree.JCStatement>of(owner.make().If(makeInitFlagExpr(true), owner.make().Block(0, stmts), owner.make().Block(0, catchStmts))));
    } else {
        block = owner.make().Block(0L, stmts);
    }
    return block;
}
Also used : JCReturn(com.sun.tools.javac.tree.JCTree.JCReturn) JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCIf(com.sun.tools.javac.tree.JCTree.JCIf) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCTree(com.sun.tools.javac.tree.JCTree) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement)

Example 33 with JCStatement

use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.

the class AttributeDefinitionBuilder method generateDefaultSetterBlock.

public JCTree.JCBlock generateDefaultSetterBlock() {
    JCExpression fld = fld();
    JCExpressionStatement assign = owner.make().Exec(owner.make().Assign(fld, owner.makeQuotedIdent(attrName)));
    List<JCStatement> stmts = List.<JCTree.JCStatement>of(assign);
    if (late) {
        JCExpressionStatement makeInit = null;
        if (lateWithInit)
            makeInit = owner.make().Exec(owner.make().Assign(makeInitFlagExpr(true), owner.make().Literal(true)));
        if (variable) {
            if (makeInit != null)
                stmts = List.<JCStatement>of(assign, makeInit);
        //else stmts is already assign
        } else {
            List<JCStatement> then = List.<JCStatement>of(owner.make().Return(null));
            if (makeInit != null)
                then = then.prepend(makeInit);
            then = then.prepend(assign);
            stmts = List.of(owner.make().If(makeInitFlagExpr(false), owner.make().Block(0, then), null), owner.make().Throw(owner.makeNewClass(owner.make().Type(owner.syms().ceylonInitializationErrorType), List.<JCExpression>of(owner.make().Literal("Re-initialization of 'late' attribute")))));
        }
    }
    if (hasInitFlag() && isDeferredInitError()) {
        JCStatement rethrow = owner.make().Exec(owner.utilInvocation().rethrow(owner.makeUnquotedIdent(Naming.getToplevelAttributeSavedExceptionName())));
        // rethrow the init exception if we have one
        JCIf ifThrow = owner.make().If(owner.make().Binary(JCTree.NE, owner.makeUnquotedIdent(Naming.getToplevelAttributeSavedExceptionName()), owner.makeNull()), rethrow, null);
        stmts = stmts.prepend(ifThrow);
    }
    return owner.make().Block(0L, stmts);
}
Also used : JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCIf(com.sun.tools.javac.tree.JCTree.JCIf) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCExpressionStatement(com.sun.tools.javac.tree.JCTree.JCExpressionStatement)

Example 34 with JCStatement

use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.

the class AttributeDefinitionBuilder method generateFieldInit.

private JCTree generateFieldInit() {
    long flags = (modifiers & Flags.STATIC);
    JCTree.JCExpression varInit = variableInit;
    if (hasInitFlag()) {
        varInit = variableInit;
    }
    JCTree.JCAssign init = owner.make().Assign(owner.makeUnquotedIdent(Naming.quoteFieldName(fieldName)), varInit);
    List<JCStatement> stmts;
    if (isDeferredInitError()) {
        // surround the init expression with a try/catch that saves the exception
        // doesn't matter
        String exceptionName = "x";
        // $initException$ = x
        JCStatement saveException = owner.make().Exec(owner.make().Assign(owner.makeUnquotedIdent(Naming.getToplevelAttributeSavedExceptionName()), owner.makeUnquotedIdent(exceptionName)));
        // value = null
        JCStatement nullValue = owner.make().Exec(owner.make().Assign(owner.makeUnquotedIdent(fieldName), owner.makeDefaultExprForType(this.attrType)));
        // the catch statements
        JCStatement initFlagFalse = owner.make().Exec(owner.make().Assign(owner.naming.makeUnquotedIdent(Naming.getInitializationFieldName(fieldName)), owner.make().Literal(false)));
        JCBlock handlerBlock = owner.make().Block(0, List.<JCTree.JCStatement>of(saveException, nullValue, initFlagFalse));
        // the catch block
        JCExpression throwableType = owner.makeJavaType(owner.syms().throwableType.tsym);
        JCVariableDecl exceptionParam = owner.make().VarDef(owner.make().Modifiers(0), owner.naming.makeUnquotedName(exceptionName), throwableType, null);
        JCCatch catchers = owner.make().Catch(exceptionParam, handlerBlock);
        // $initException$ = null
        JCTree.JCAssign nullException = owner.make().Assign(owner.makeUnquotedIdent(Naming.getToplevelAttributeSavedExceptionName()), owner.makeNull());
        // $init$value = true;
        JCTree.JCAssign initFlagTrue = owner.make().Assign(owner.naming.makeUnquotedIdent(Naming.getInitializationFieldName(fieldName)), owner.make().Literal(true));
        // save the value, mark the exception as null
        List<JCStatement> body = List.<JCTree.JCStatement>of(owner.make().Exec(init), owner.make().Exec(nullException), owner.make().Exec(initFlagTrue));
        // the try/catch
        JCTree.JCTry try_ = owner.make().Try(owner.make().Block(0, body), List.<JCTree.JCCatch>of(catchers), null);
        stmts = List.<JCTree.JCStatement>of(try_);
    } else {
        stmts = List.<JCTree.JCStatement>of(owner.make().Exec(init));
    }
    return owner.make().Block(flags, stmts);
}
Also used : JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCTree(com.sun.tools.javac.tree.JCTree) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCCatch(com.sun.tools.javac.tree.JCTree.JCCatch) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl)

Example 35 with JCStatement

use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.

the class CallableBuilder method unboundValueMemberReference.

/**
     * Used for "static" value references. For example:
     * <pre>
     *     value x = Integer.plus;
     *     value y = Foo.method;
     *     value z = Outer.Inner;
     * </pre>
     */
public static CallableBuilder unboundValueMemberReference(CeylonTransformer gen, Tree.QualifiedMemberOrTypeExpression qmte, Type typeModel, final TypedDeclaration value) {
    CallBuilder callBuilder = CallBuilder.instance(gen);
    Type qualifyingType = qmte.getTarget().getQualifyingType();
    JCExpression target = gen.naming.makeUnquotedIdent(Unfix.$instance$);
    target = gen.expressionGen().applyErasureAndBoxing(target, qmte.getPrimary().getTypeModel(), true, BoxingStrategy.BOXED, qualifyingType);
    if (gen.expressionGen().isThrowableMessage(qmte)) {
        callBuilder.invoke(gen.utilInvocation().throwableMessage());
        callBuilder.argument(target);
    } else if (gen.expressionGen().isThrowableSuppressed(qmte)) {
        callBuilder.invoke(gen.utilInvocation().suppressedExceptions());
        callBuilder.argument(target);
    } else {
        JCExpression memberName = gen.naming.makeQualifiedName(target, value, Naming.NA_GETTER | Naming.NA_MEMBER);
        if (value instanceof FieldValue) {
            callBuilder.fieldRead(memberName);
        } else {
            callBuilder.invoke(memberName);
        }
    }
    JCExpression innerInvocation = callBuilder.build();
    // use the return type since the value is actually applied
    Type returnType = gen.getReturnTypeOfCallable(typeModel);
    innerInvocation = gen.expressionGen().applyErasureAndBoxing(innerInvocation, returnType, // expression is a Callable
    qmte.getTypeErased(), !CodegenUtil.isUnBoxed(value), BoxingStrategy.BOXED, returnType, 0);
    ParameterList outerPl = new ParameterList();
    Parameter instanceParameter = new Parameter();
    instanceParameter.setName(Naming.name(Unfix.$instance$));
    Value valueModel = new Value();
    instanceParameter.setModel(valueModel);
    Type accessType = gen.getParameterTypeOfCallable(typeModel, 0);
    ;
    if (!value.isShared()) {
        accessType = Decl.getPrivateAccessType(qmte);
    }
    valueModel.setName(instanceParameter.getName());
    valueModel.setInitializerParameter(instanceParameter);
    valueModel.setType(accessType);
    valueModel.setUnboxed(false);
    outerPl.getParameters().add(instanceParameter);
    CallableBuilder outer = new CallableBuilder(gen, null, typeModel, outerPl);
    outer.parameterTypes = outer.getParameterTypesFromParameterModels();
    List<JCStatement> innerBody = List.<JCStatement>of(gen.make().Return(innerInvocation));
    outer.useDefaultTransformation(innerBody);
    outer.companionAccess = Decl.isPrivateAccessRequiringCompanion(qmte);
    return outer;
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) FunctionOrValue(com.redhat.ceylon.model.typechecker.model.FunctionOrValue) FieldValue(com.redhat.ceylon.model.loader.model.FieldValue) Value(com.redhat.ceylon.model.typechecker.model.Value) ParameterList(com.redhat.ceylon.model.typechecker.model.ParameterList) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) Parameter(com.redhat.ceylon.model.typechecker.model.Parameter) JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) FieldValue(com.redhat.ceylon.model.loader.model.FieldValue) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement)

Aggregations

JCStatement (com.sun.tools.javac.tree.JCTree.JCStatement)112 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)82 JCVariableDecl (com.sun.tools.javac.tree.JCTree.JCVariableDecl)37 JCBlock (com.sun.tools.javac.tree.JCTree.JCBlock)33 JCTree (com.sun.tools.javac.tree.JCTree)32 Name (com.sun.tools.javac.util.Name)32 Type (com.redhat.ceylon.model.typechecker.model.Type)26 JCTypeParameter (com.sun.tools.javac.tree.JCTree.JCTypeParameter)26 ListBuffer (com.sun.tools.javac.util.ListBuffer)25 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)23 SyntheticName (com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName)18 JCMethodDecl (com.sun.tools.javac.tree.JCTree.JCMethodDecl)16 JavacTreeMaker (lombok.javac.JavacTreeMaker)16 TypeParameter (com.redhat.ceylon.model.typechecker.model.TypeParameter)14 JCModifiers (com.sun.tools.javac.tree.JCTree.JCModifiers)14 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)12 JCAnnotation (com.sun.tools.javac.tree.JCTree.JCAnnotation)12 JCPrimitiveTypeTree (com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree)12 Parameter (com.redhat.ceylon.model.typechecker.model.Parameter)11 HasErrorException (com.redhat.ceylon.compiler.java.codegen.recovery.HasErrorException)10