use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.
the class AbstractTransformer method makeGetterBlock.
JCBlock makeGetterBlock(TypedDeclaration declarationModel, final Tree.Block block, final Tree.SpecifierOrInitializerExpression expression) {
List<JCStatement> stats;
if (block != null) {
stats = statementGen().transformBlock(block);
} else {
BoxingStrategy boxing = CodegenUtil.getBoxingStrategy(declarationModel);
Type type = declarationModel.getType();
JCStatement transStat;
HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(expression.getExpression());
if (error != null) {
transStat = this.makeThrowUnresolvedCompilationError(error);
} else {
transStat = make().Return(expressionGen().transformExpression(expression.getExpression(), boxing, type));
}
stats = List.<JCStatement>of(transStat);
}
JCBlock getterBlock = make().Block(0, stats);
return getterBlock;
}
use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.
the class AbstractTransformer method makeLetExpr.
private JCExpression makeLetExpr(String varBaseName, List<JCStatement> statements, JCExpression... args) {
String varName = null;
ListBuffer<JCStatement> decls = ListBuffer.lb();
int i;
for (i = 0; (i + 1) < args.length; i += 2) {
JCExpression typeExpr = args[i];
JCExpression valueExpr = args[i + 1];
varName = varBaseName + ((args.length > 3) ? "$" + i : "");
JCVariableDecl varDecl = makeVar(varName, typeExpr, valueExpr);
decls.append(varDecl);
}
JCExpression result;
if (i == args.length) {
result = makeUnquotedIdent(varName);
} else {
result = args[i];
}
if (statements != null) {
decls.appendList(statements);
}
return make().LetExpr(decls.toList(), result);
}
use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.
the class ClassTransformer method addRefinedThrowerAttribute.
/**
* Adds a getter (and possibly a setter) to {@code classBuilder}
* which throws
* @param classBuilder The class builder to add the method to
* @param error The message
* @param classModel The class which doesn't refine {@code formalAttribute}
* @param formalAttribute The formal attribute that hasn't been refined in {@code classModel}
*/
private void addRefinedThrowerAttribute(ClassDefinitionBuilder classBuilder, String error, ClassOrInterface classModel, Value formalAttribute) {
Value refined = refineValue(formalAttribute, formalAttribute.appliedTypedReference(null, null), classModel, classModel.getUnit());
AttributeDefinitionBuilder getterBuilder = AttributeDefinitionBuilder.getter(this, refined.getName(), refined);
getterBuilder.skipField();
getterBuilder.modifiers(transformAttributeGetSetDeclFlags(refined, false));
getterBuilder.getterBlock(make().Block(0, List.<JCStatement>of(makeThrowUnresolvedCompilationError(error))));
classBuilder.attribute(getterBuilder);
if (formalAttribute.isVariable()) {
AttributeDefinitionBuilder setterBuilder = AttributeDefinitionBuilder.setter(this, refined.getName(), refined);
setterBuilder.skipField();
setterBuilder.modifiers(transformAttributeGetSetDeclFlags(refined, false));
setterBuilder.setterBlock(make().Block(0, List.<JCStatement>of(makeThrowUnresolvedCompilationError(error))));
classBuilder.attribute(setterBuilder);
}
}
use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.
the class ClassTransformer method serializationGet.
private void serializationGet(Class model, ClassDefinitionBuilder classBuilder) {
MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, Unfix.$get$.toString());
mdb.isOverride(true);
mdb.ignoreModelAnnotations();
mdb.modifiers(PUBLIC);
ParameterDefinitionBuilder pdb = ParameterDefinitionBuilder.systemParameter(this, Unfix.reference.toString());
pdb.modifiers(FINAL);
pdb.type(make().Type(syms().ceylonReachableReferenceType), null);
mdb.parameter(pdb);
mdb.resultType(null, make().Type(syms().objectType));
/*
* public void $set$(Object reference, Object instance) {
* switch((String)reference) {
* case ("attr1")
* return ...;
* // ... other fields of this class
* case ("lateAttr1")
* if (!$init$lateAttr1) {
* return ceylon.language.serialization.uninitializedLateValue.get_();
* }
* return ...;
* case (null):
* return Outer.this;
* default:
* return super.get(reference);
*/
ListBuffer<JCCase> cases = ListBuffer.<JCCase>lb();
boolean[] needsLookup = new boolean[] { false };
for (Declaration member : model.getMembers()) {
if (hasField(member)) {
if (member instanceof Function)
// TODO: This class is not serializable
continue;
ListBuffer<JCStatement> caseStmts = ListBuffer.<JCStatement>lb();
if (member instanceof Value && ((Value) member).isLate()) {
// TODO this should be encapsulated so the ADB and this
// code can just call something common
JCExpression test;
if (CodegenUtil.needsLateInitField((Value) member, typeFact())) {
test = make().Unary(JCTree.NOT, naming.makeUnquotedIdent(Naming.getInitializationFieldName(member.getName())));
} else {
test = make().Binary(JCTree.EQ, naming.makeQualifiedName(naming.makeThis(), (Value) member, Naming.NA_IDENT), makeNull());
}
caseStmts.add(make().If(test, make().Return(makeLanguageSerializationValue("uninitializedLateValue")), null));
}
caseStmts.add(make().Return(makeSerializationGetter((Value) member)));
cases.add(make().Case(make().Literal(member.getQualifiedNameString()), caseStmts.toList()));
}
}
SyntheticName reference = naming.synthetic(Unfix.reference);
ListBuffer<JCStatement> defaultCase = ListBuffer.lb();
if (extendsSerializable(model)) {
// super.get(reference);
defaultCase.add(make().Return(make().Apply(null, naming.makeQualIdent(naming.makeSuper(), Unfix.$get$.toString()), List.<JCExpression>of(reference.makeIdent()))));
} else {
// throw (or pass to something else to throw, based on policy)
defaultCase.add(make().Throw(make().NewClass(null, null, naming.makeQuotedFQIdent("java.lang.RuntimeException"), List.<JCExpression>of(make().Literal("unknown attribute")), null)));
}
cases.add(make().Case(null, defaultCase.toList()));
ListBuffer<JCStatement> stmts = ListBuffer.<JCStatement>lb();
if (needsLookup[0]) {
// if we needed to use a lookup object to reset final fields,
// prepend that variable
stmts.add(makeVar(FINAL, "lookup", naming.makeQualIdent(make().Type(syms().methodHandlesType), "Lookup"), make().Apply(null, naming.makeQuotedFQIdent("java.lang.invoke.MethodHandles.lookup"), List.<JCExpression>nil())));
}
JCSwitch swtch = make().Switch(make().Apply(null, naming.makeSelect(make().Apply(null, naming.makeSelect(make().TypeCast(make().Type(syms().ceylonMemberType), reference.makeIdent()), "getAttribute"), List.<JCExpression>nil()), "getQualifiedName"), List.<JCExpression>nil()), cases.toList());
if (model.isMember() && !model.getExtendedType().getDeclaration().isMember()) {
stmts.add(make().If(make().TypeTest(reference.makeIdent(), make().Type(syms().ceylonOuterType)), make().Return(expressionGen().makeOuterExpr(((TypeDeclaration) model.getContainer()).getType())), swtch));
} else {
stmts.add(swtch);
}
mdb.body(stmts.toList());
classBuilder.method(mdb);
}
use of com.sun.tools.javac.tree.JCTree.JCStatement in project ceylon-compiler by ceylon.
the class ClassTransformer method transformMethodBody.
private List<JCStatement> transformMethodBody(Tree.AnyMethod def) {
List<JCStatement> body = null;
final Function model = def.getDeclarationModel();
if (model.isDeferred()) {
// Uninitialized or deferred initialized method => Make a Callable field
String fieldName = naming.selector(model);
final Parameter initializingParameter = CodegenUtil.findParamForDecl(def);
int mods = PRIVATE;
JCExpression initialValue;
if (initializingParameter != null) {
mods |= FINAL;
initialValue = makeUnquotedIdent(Naming.getAliasedParameterName(initializingParameter));
} else {
// The field isn't initialized by a parameter, but later in the block
initialValue = makeNull();
}
Type callableType = model.getReference().getFullType();
current().field(mods, fieldName, makeJavaType(callableType), initialValue, false);
Invocation invocation = new CallableSpecifierInvocation(this, model, makeUnquotedIdent(fieldName), // but with deferred methods we can't define them so that they are erased so we're good
null, def);
invocation.handleBoxing(true);
JCExpression call = expressionGen().transformInvocation(invocation);
JCStatement stmt;
if (!isVoid(def) || !Decl.isUnboxedVoid(model) || Strategy.useBoxedVoid((Function) model)) {
stmt = make().Return(call);
} else {
stmt = make().Exec(call);
}
JCStatement result;
if (initializingParameter == null) {
// If the field isn't initialized by a parameter we have to
// cope with the possibility that it's never initialized
final JCBinary cond = make().Binary(JCTree.EQ, makeUnquotedIdent(fieldName), makeNull());
final JCStatement throw_ = make().Throw(make().NewClass(null, null, makeIdent(syms().ceylonUninitializedMethodErrorType), List.<JCExpression>nil(), null));
result = make().If(cond, throw_, stmt);
} else {
result = stmt;
}
return List.<JCStatement>of(result);
} else if (def instanceof Tree.MethodDefinition) {
body = transformMethodBlock((Tree.MethodDefinition) def);
} else if (def instanceof MethodDeclaration && ((MethodDeclaration) def).getSpecifierExpression() != null) {
body = transformSpecifiedMethodBody((MethodDeclaration) def, ((MethodDeclaration) def).getSpecifierExpression());
}
return body;
}
Aggregations