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());
}
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;
}
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);
}
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);
}
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;
}
Aggregations