use of com.sun.tools.javac.tree.JCTree.JCExpression in project ceylon-compiler by ceylon.
the class CallableBuilder method build.
public JCExpression build() {
// Generate a subclass of Callable
ListBuffer<JCTree> classBody = new ListBuffer<JCTree>();
gen.at(node);
if (parameterDefaultValueMethods != null) {
for (MethodDefinitionBuilder mdb : parameterDefaultValueMethods) {
classBody.append(mdb.build());
}
}
transformation.appendMethods(classBody);
JCClassDecl classDef = gen.make().AnonymousClassDef(gen.make().Modifiers(0, annotations != null ? annotations : List.<JCAnnotation>nil()), classBody.toList());
int variadicIndex = isVariadic ? numParams - 1 : -1;
Type callableType;
if (typeModel.isTypeConstructor()) {
callableType = typeModel.getDeclaration().getExtendedType();
} else {
callableType = typeModel;
}
JCNewClass callableInstance = gen.make().NewClass(null, null, gen.makeJavaType(callableType, JT_EXTENDS | JT_CLASS_NEW), List.<JCExpression>of(gen.makeReifiedTypeArgument(callableType.getTypeArgumentList().get(0)), gen.makeReifiedTypeArgument(callableType.getTypeArgumentList().get(1)), gen.make().Literal(callableType.asString(true)), gen.make().TypeCast(gen.syms().shortType, gen.makeInteger(variadicIndex))), classDef);
JCExpression result;
if (typeModel.isTypeConstructor()) {
result = buildTypeConstructor(callableType, callableInstance);
} else {
result = callableInstance;
}
gen.at(null);
if (instanceSubstitution != null) {
instanceSubstitution.close();
}
return result;
}
use of com.sun.tools.javac.tree.JCTree.JCExpression 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.JCExpression 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.JCExpression 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.JCExpression 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);
}
Aggregations