use of com.redhat.ceylon.model.typechecker.model.Parameter in project ceylon-compiler by ceylon.
the class CeylonVisitor method transformConstructor.
private void transformConstructor(Tree.Declaration ctor, Tree.ParameterList parameterList, Tree.DelegatedConstructor delegatedCtor, Tree.Block block, Constructor ctorModel, Map<Constructor, CtorDelegation> delegates) {
TransformationPlan plan = gen.errors().hasDeclarationAndMarkBrokenness(ctor);
if (plan instanceof Drop) {
return;
}
if (parameterList != null) {
for (Parameter param : parameterList.getModel().getParameters()) {
if (Naming.aliasConstructorParameterName(param.getModel())) {
gen.naming.addVariableSubst(param.getModel(), gen.naming.suffixName(Suffix.$param$, param.getName()));
}
}
}
final CtorDelegation delegation = delegates.get(ctorModel);
ListBuffer<JCStatement> stmts = ListBuffer.lb();
boolean delegatedTo = CtorDelegation.isDelegatedTo(delegates, ctorModel);
if (delegatedTo && !ctorModel.isAbstract()) {
Tree.InvocationExpression chainedCtorInvocation;
if (delegatedCtor != null) {
chainedCtorInvocation = delegatedCtor.getInvocationExpression();
} else {
chainedCtorInvocation = null;
}
// We need to generate $delegation$ delegation constructor
makeDelegationConstructor(ctor, parameterList, delegatedCtor, block, ctorModel, delegation, chainedCtorInvocation);
JCStatement delegateExpr;
if (chainedCtorInvocation != null) {
delegateExpr = gen.expressionGen().transformConstructorDelegation(chainedCtorInvocation, delegation.isSelfDelegation() ? delegation : new CtorDelegation(ctorModel, ctorModel), chainedCtorInvocation, classBuilder, !delegation.isSelfDelegation());
} else {
// In this case there is no extends clause in the source code
// so we have to construct the argument list "by hand".
ListBuffer<JCExpression> arguments = ListBuffer.<JCExpression>lb();
for (TypeParameter tp : ((Class) delegation.getConstructor().getContainer()).getTypeParameters()) {
arguments.add(gen.makeReifiedTypeArgument(tp.getType()));
}
arguments.add(gen.naming.makeNamedConstructorName(delegation.getConstructor(), true));
for (Parameter p : delegation.getConstructor().getFirstParameterList().getParameters()) {
arguments.add(gen.naming.makeName(p.getModel(), Naming.NA_IDENT));
}
delegateExpr = gen.make().Exec(gen.make().Apply(null, gen.naming.makeThis(), arguments.toList()));
}
stmts.add(delegateExpr);
} else if (delegatedCtor != null) {
stmts.add(gen.expressionGen().transformConstructorDelegation(delegatedCtor, delegation, delegatedCtor.getInvocationExpression(), classBuilder, false));
} else {
// no explicit extends clause
}
final boolean addBody;
if (delegatedTo && (delegation.isAbstractSelfOrSuperDelegation())) {
if (delegation.getConstructor().isAbstract()) {
stmts.addAll(classBuilder.getInitBuilder().copyStatementsBetween(null, ctorModel));
addBody = true;
} else if (delegation.getExtendingConstructor() != null && delegation.getExtendingConstructor().isAbstract()) {
stmts.addAll(classBuilder.getInitBuilder().copyStatementsBetween(delegation.getExtendingConstructor(), ctorModel));
addBody = true;
} else {
addBody = false;
}
} else if (delegation.isAbstractSelfDelegation()) {
// delegating to abstract
stmts.addAll(classBuilder.getInitBuilder().copyStatementsBetween(delegation.getExtendingConstructor(), ctorModel));
addBody = true;
} else if (delegation.isConcreteSelfDelegation()) {
stmts.addAll(classBuilder.getInitBuilder().copyStatementsBetween(delegation.getExtendingConstructor(), ctorModel));
addBody = true;
} else {
// super delegation
stmts.addAll(classBuilder.getInitBuilder().copyStatementsBetween(null, ctorModel));
addBody = true;
}
if (ctorModel.isAbstract() && !delegatedTo) {
stmts.add(gen.make().Throw(gen.make().NewClass(null, List.<JCExpression>nil(), gen.make().QualIdent(gen.syms().ceylonUninvokableErrorType.tsym), List.<JCExpression>nil(), null)));
}
List<JCStatement> following = ctorModel.isAbstract() ? List.<JCStatement>nil() : classBuilder.getInitBuilder().copyStatementsBetween(ctorModel, null);
if (addBody) {
if (following.isEmpty()) {
stmts.addAll(gen.statementGen().transformBlock(block));
} else {
Name label = gen.naming.aliasName(Naming.Unfix.$return$.toString());
Transformer<JCStatement, Return> prev = gen.statementGen().returnTransformer(gen.statementGen().new ConstructorReturnTransformer(label));
try {
stmts.add(gen.make().Labelled(label, gen.make().DoLoop(gen.make().Block(0, gen.statementGen().transformBlock(block, true)), gen.make().Literal(false))));
} finally {
gen.statementGen().returnTransformer(prev);
}
}
}
ThrowVisitor visitor = new ThrowVisitor();
block.visit(visitor);
if (!visitor.getDefinitelyReturnsViaThrow()) {
stmts.addAll(following);
}
String ctorName = !Decl.isDefaultConstructor(ctorModel) ? gen.naming.makeTypeDeclarationName(ctorModel) : null;
classBuilder.defs(gen.classGen().makeNamedConstructor(ctor, parameterList, ctorModel, classBuilder, Strategy.generateInstantiator(ctorModel), gen.classGen().transformConstructorDeclFlags(ctorModel), false, ctorName, stmts.toList(), DeclNameFlag.QUALIFIED));
}
use of com.redhat.ceylon.model.typechecker.model.Parameter in project ceylon-compiler by ceylon.
the class ClassTransformer method transformClassOrCtorParameters.
private void transformClassOrCtorParameters(Tree.AnyClass def, Class cls, Constructor constructor, Tree.Declaration node, Tree.ParameterList paramList, boolean delegationConstructor, ClassDefinitionBuilder classBuilder, ParameterizedBuilder<?> constructorBuilder, boolean generateInstantiator, ClassDefinitionBuilder instantiatorDeclCb, ClassDefinitionBuilder instantiatorImplCb) {
for (final Tree.Parameter param : paramList.getParameters()) {
// Overloaded instantiators
Parameter paramModel = param.getParameterModel();
Parameter refinedParam = CodegenUtil.findParamForDecl((TypedDeclaration) CodegenUtil.getTopmostRefinedDeclaration(param.getParameterModel().getModel()));
at(param);
Tree.TypedDeclaration member = def != null ? Decl.getMemberDeclaration(def, param) : null;
// transform the parameter and its annotations
transformParameter(constructorBuilder, param, paramModel, member);
if (Strategy.hasDefaultParameterValueMethod(paramModel) || Strategy.hasDefaultParameterOverload(paramModel) || (generateInstantiator && refinedParam != null && (Strategy.hasDefaultParameterValueMethod(refinedParam) || Strategy.hasDefaultParameterOverload(refinedParam)))) {
ClassDefinitionBuilder cbForDevaultValues;
ClassDefinitionBuilder cbForDevaultValuesDecls = null;
switch(Strategy.defaultParameterMethodOwner(constructor != null ? constructor : cls)) {
case STATIC:
cbForDevaultValues = classBuilder;
break;
case OUTER:
cbForDevaultValues = classBuilder.getContainingClassBuilder();
break;
case OUTER_COMPANION:
cbForDevaultValues = classBuilder.getContainingClassBuilder().getCompanionBuilder(Decl.getClassOrInterfaceContainer(cls, true));
if ((constructor == null || constructor.isShared()) && cls.isShared()) {
cbForDevaultValuesDecls = classBuilder.getContainingClassBuilder();
}
break;
default:
cbForDevaultValues = classBuilder.getCompanionBuilder(cls);
}
if (!delegationConstructor) {
if ((Strategy.hasDefaultParameterValueMethod(paramModel) || (refinedParam != null && Strategy.hasDefaultParameterValueMethod(refinedParam)))) {
if (!generateInstantiator || Decl.equal(refinedParam, paramModel)) {
// transform the default value into a method
cbForDevaultValues.method(makeParamDefaultValueMethod(false, constructor != null ? constructor : cls, paramList, param));
if (cbForDevaultValuesDecls != null) {
cbForDevaultValuesDecls.method(makeParamDefaultValueMethod(true, constructor != null ? constructor : cls, paramList, param));
}
} else if (Strategy.hasDelegatedDpm(cls) && cls.getContainer() instanceof Class) {
// generate a dpm which delegates to the companion
java.util.List<Parameter> parameters = paramList.getModel().getParameters();
MethodDefinitionBuilder mdb = makeDelegateToCompanion((Interface) cls.getRefinedDeclaration().getContainer(), paramModel.getModel().appliedTypedReference(cls.getType(), null), ((TypeDeclaration) cls.getContainer()).getType(), FINAL | (transformClassDeclFlags(cls) & ~ABSTRACT), List.<TypeParameter>nil(), Collections.<java.util.List<Type>>emptyList(), paramModel.getType().getFullType(), Naming.getDefaultedParamMethodName(cls, paramModel), parameters.subList(0, parameters.indexOf(paramModel)), false, Naming.getDefaultedParamMethodName(cls, paramModel), DelegateType.FOR_DEFAULT_VALUE);
cbForDevaultValues.method(mdb);
}
}
}
boolean addOverloadedConstructor = false;
if (generateInstantiator) {
if (Decl.withinInterface(cls)) {
MethodDefinitionBuilder instBuilder = new DefaultedArgumentInstantiator(daoAbstract, cls, constructor, instantiatorDeclCb.isCompanionBuilder()).makeOverload(paramList.getModel(), param.getParameterModel(), cls.getTypeParameters());
instantiatorDeclCb.method(instBuilder);
}
if (!Decl.withinInterface(cls) || !cls.isFormal()) {
MethodDefinitionBuilder instBuilder = new DefaultedArgumentInstantiator(new DaoThis(node, paramList), cls, constructor, instantiatorImplCb.isCompanionBuilder()).makeOverload(paramList.getModel(), param.getParameterModel(), cls.getTypeParameters());
instantiatorImplCb.method(instBuilder);
} else {
addOverloadedConstructor = true;
}
} else {
addOverloadedConstructor = true;
}
if (addOverloadedConstructor) {
// Add overloaded constructors for defaulted parameter
MethodDefinitionBuilder overloadBuilder;
DefaultedArgumentConstructor dac;
if (constructor != null) {
dac = new DefaultedArgumentConstructor(classBuilder.addConstructor(), constructor, node, paramList, delegationConstructor);
} else {
dac = new DefaultedArgumentConstructor(classBuilder.addConstructor(), cls, node, paramList, delegationConstructor);
}
overloadBuilder = dac.makeOverload(paramList.getModel(), param.getParameterModel(), cls.getTypeParameters());
}
}
}
}
use of com.redhat.ceylon.model.typechecker.model.Parameter in project ceylon-compiler by ceylon.
the class ClassTransformer method transformRefinementSpecifierStatement.
public List<JCStatement> transformRefinementSpecifierStatement(SpecifierStatement op, ClassDefinitionBuilder classBuilder) {
List<JCStatement> result = List.<JCStatement>nil();
// Check if this is a shortcut form of formal attribute refinement
if (op.getRefinement()) {
Tree.Term baseMemberTerm = op.getBaseMemberExpression();
if (baseMemberTerm instanceof Tree.ParameterizedExpression)
baseMemberTerm = ((Tree.ParameterizedExpression) baseMemberTerm).getPrimary();
Tree.BaseMemberExpression expr = (BaseMemberExpression) baseMemberTerm;
Declaration decl = expr.getDeclaration();
if (Decl.isValue(decl) || Decl.isGetter(decl)) {
// Now build a "fake" declaration for the attribute
Tree.AttributeDeclaration attrDecl = new Tree.AttributeDeclaration(null);
attrDecl.setDeclarationModel((Value) decl);
attrDecl.setIdentifier(expr.getIdentifier());
attrDecl.setScope(op.getScope());
attrDecl.setSpecifierOrInitializerExpression(op.getSpecifierExpression());
attrDecl.setAnnotationList(makeShortcutRefinementAnnotationTrees());
// Make sure the boxing information is set correctly
BoxingDeclarationVisitor v = new CompilerBoxingDeclarationVisitor(this);
v.visit(attrDecl);
// Generate the attribute
transform(attrDecl, classBuilder);
} else if (decl instanceof Function) {
// Now build a "fake" declaration for the method
Tree.MethodDeclaration methDecl = new Tree.MethodDeclaration(null);
Function m = (Function) decl;
methDecl.setDeclarationModel(m);
methDecl.setIdentifier(expr.getIdentifier());
methDecl.setScope(op.getScope());
methDecl.setAnnotationList(makeShortcutRefinementAnnotationTrees());
Tree.SpecifierExpression specifierExpression = op.getSpecifierExpression();
methDecl.setSpecifierExpression(specifierExpression);
if (specifierExpression instanceof Tree.LazySpecifierExpression == false) {
Tree.Expression expression = specifierExpression.getExpression();
Tree.Term expressionTerm = Decl.unwrapExpressionsUntilTerm(expression);
// we can optimise lambdas and static method calls
if (!CodegenUtil.canOptimiseMethodSpecifier(expressionTerm, m)) {
// we need a field to save the callable value
String name = naming.getMethodSpecifierAttributeName(m);
JCExpression specifierType = makeJavaType(expression.getTypeModel());
JCExpression specifier = expressionGen().transformExpression(expression);
classBuilder.field(PRIVATE | FINAL, name, specifierType, specifier, false);
}
}
java.util.List<Tree.ParameterList> parameterListTrees = null;
if (op.getBaseMemberExpression() instanceof Tree.ParameterizedExpression) {
parameterListTrees = new ArrayList<>(m.getParameterLists().size());
parameterListTrees.addAll(((Tree.ParameterizedExpression) op.getBaseMemberExpression()).getParameterLists());
Tree.Term term = specifierExpression.getExpression().getTerm();
// and give it the given block of expr as it's specifier
while (term instanceof Tree.FunctionArgument && m.getParameterLists().size() > 1) {
FunctionArgument functionArgument = (Tree.FunctionArgument) term;
specifierExpression.setExpression(functionArgument.getExpression());
parameterListTrees.addAll(functionArgument.getParameterLists());
term = functionArgument.getExpression().getTerm();
}
}
int plIndex = 0;
// copy from formal declaration
for (ParameterList pl : m.getParameterLists()) {
Tree.ParameterList parameterListTree = null;
if (parameterListTrees != null)
parameterListTree = parameterListTrees.get(plIndex++);
Tree.ParameterList tpl = new Tree.ParameterList(null);
tpl.setModel(pl);
int pIndex = 0;
for (Parameter p : pl.getParameters()) {
Tree.Parameter parameterTree = null;
if (parameterListTree != null)
parameterTree = parameterListTree.getParameters().get(pIndex++);
Tree.Parameter tp = null;
if (p.getModel() instanceof Value) {
Tree.ValueParameterDeclaration tvpd = new Tree.ValueParameterDeclaration(null);
if (parameterTree != null)
tvpd.setTypedDeclaration(((Tree.ParameterDeclaration) parameterTree).getTypedDeclaration());
tvpd.setParameterModel(p);
tp = tvpd;
} else if (p.getModel() instanceof Function) {
Tree.FunctionalParameterDeclaration tfpd = new Tree.FunctionalParameterDeclaration(null);
if (parameterTree != null)
tfpd.setTypedDeclaration(((Tree.ParameterDeclaration) parameterTree).getTypedDeclaration());
tfpd.setParameterModel(p);
tp = tfpd;
} else {
throw BugException.unhandledDeclarationCase(p.getModel());
}
tp.setScope(p.getDeclaration().getContainer());
//tp.setIdentifier(makeIdentifier(p.getName()));
tpl.addParameter(tp);
}
methDecl.addParameterList(tpl);
}
// Make sure the boxing information is set correctly
BoxingDeclarationVisitor v = new CompilerBoxingDeclarationVisitor(this);
v.visit(methDecl);
// Generate the method
classBuilder.method(methDecl, Errors.GENERATE);
}
} else {
// Normal case, just generate the specifier statement
result = result.append(expressionGen().transform(op));
}
Tree.Term term = op.getBaseMemberExpression();
if (term instanceof Tree.BaseMemberExpression) {
Tree.BaseMemberExpression bme = (Tree.BaseMemberExpression) term;
DeferredSpecification ds = statementGen().getDeferredSpecification(bme.getDeclaration());
if (ds != null && needsInnerSubstitution(term.getScope(), bme.getDeclaration())) {
result = result.append(ds.openInnerSubstitution());
}
}
return result;
}
use of com.redhat.ceylon.model.typechecker.model.Parameter in project ceylon-compiler by ceylon.
the class ClassTransformer method transform.
public void transform(AttributeDeclaration decl, ClassDefinitionBuilder classBuilder) {
final Value model = decl.getDeclarationModel();
boolean lazy = decl.getSpecifierOrInitializerExpression() instanceof LazySpecifierExpression;
boolean useField = Strategy.useField(model) && !lazy;
String attrName = decl.getIdentifier().getText();
// Only a non-formal or a concrete-non-lazy attribute has a corresponding field
// and if a captured class parameter exists with the same name we skip this part as well
Parameter parameter = CodegenUtil.findParamForDecl(decl);
boolean createField = Strategy.createField(parameter, model) && !lazy;
boolean concrete = Decl.withinInterface(decl) && decl.getSpecifierOrInitializerExpression() != null;
if (!lazy && (concrete || (!Decl.isFormal(decl) && createField))) {
TypedReference typedRef = getTypedReference(model);
TypedReference nonWideningTypedRef = nonWideningTypeDecl(typedRef);
Type nonWideningType = nonWideningType(typedRef, nonWideningTypedRef);
if (Decl.isIndirect(decl)) {
attrName = Naming.getAttrClassName(model, 0);
nonWideningType = getGetterInterfaceType(model);
}
JCExpression initialValue = null;
if (decl.getSpecifierOrInitializerExpression() != null) {
Value declarationModel = model;
initialValue = expressionGen().transformExpression(decl.getSpecifierOrInitializerExpression().getExpression(), CodegenUtil.getBoxingStrategy(declarationModel), nonWideningType);
}
int flags = 0;
if (!CodegenUtil.isUnBoxed(nonWideningTypedRef.getDeclaration())) {
flags |= JT_NO_PRIMITIVES;
}
JCExpression type = makeJavaType(nonWideningType, flags);
int modifiers = (useField) ? transformAttributeFieldDeclFlags(decl) : transformLocalDeclFlags(decl);
// does it in those cases)
if (parameter == null || parameter.isHidden()) {
if (concrete) {
classBuilder.getCompanionBuilder((TypeDeclaration) model.getContainer()).field(modifiers, attrName, type, initialValue, !useField);
} else {
List<JCAnnotation> annos = makeAtIgnore().prependList(expressionGen().transformAnnotations(OutputElement.FIELD, decl));
if (classBuilder.hasDelegatingConstructors()) {
annos = annos.prependList(makeAtNoInitCheck());
}
// fields should be ignored, they are accessed by the getters
classBuilder.field(modifiers, attrName, type, initialValue, !useField, annos);
if (model.isLate() && CodegenUtil.needsLateInitField(model, typeFact())) {
classBuilder.field(PRIVATE | Flags.VOLATILE | Flags.TRANSIENT, Naming.getInitializationFieldName(attrName), make().Type(syms().booleanType), make().Literal(false), false, makeAtIgnore());
}
}
}
// A shared attribute might be initialized in a for statement, so
// we might need a def-assignment subst for it
List<JCAnnotation> annots = makeJavaTypeAnnotations(decl.getDeclarationModel());
JCStatement outerSubs = statementGen().openOuterSubstitutionIfNeeded(decl.getDeclarationModel(), model.getType(), annots, 0);
if (outerSubs != null) {
classBuilder.getInitBuilder().init(outerSubs);
}
}
boolean withinInterface = Decl.withinInterface(decl);
if (useField || withinInterface || lazy) {
if (!withinInterface || model.isShared()) {
// Generate getter in main class or interface (when shared)
classBuilder.attribute(makeGetter(decl, false, lazy));
}
if (withinInterface && lazy) {
// Generate getter in companion class
classBuilder.getCompanionBuilder((Interface) decl.getDeclarationModel().getContainer()).attribute(makeGetter(decl, true, lazy));
}
if (Decl.isVariable(decl) || Decl.isLate(decl)) {
if (!withinInterface || model.isShared()) {
// Generate setter in main class or interface (when shared)
classBuilder.attribute(makeSetter(decl, false, lazy));
}
if (withinInterface && lazy) {
// Generate setter in companion class
classBuilder.getCompanionBuilder((Interface) decl.getDeclarationModel().getContainer()).attribute(makeSetter(decl, true, lazy));
}
}
}
}
use of com.redhat.ceylon.model.typechecker.model.Parameter in project ceylon-compiler by ceylon.
the class ClassTransformer method makeAttributeForValueParameter.
private void makeAttributeForValueParameter(ClassDefinitionBuilder classBuilder, Tree.Parameter parameterTree, Tree.TypedDeclaration memberTree) {
Parameter decl = parameterTree.getParameterModel();
if (!(decl.getModel() instanceof Value)) {
return;
}
final Value value = (Value) decl.getModel();
if (decl.getDeclaration() instanceof Constructor) {
classBuilder.field(PUBLIC | FINAL, decl.getName(), makeJavaType(decl.getType()), null, false, expressionGen().transformAnnotations(OutputElement.FIELD, memberTree));
classBuilder.getInitBuilder().init(make().Exec(make().Assign(naming.makeQualIdent(naming.makeThis(), decl.getName()), naming.makeName(value, Naming.NA_IDENT))));
} else if (parameterTree instanceof Tree.ValueParameterDeclaration && (value.isShared() || value.isCaptured())) {
makeFieldForParameter(classBuilder, decl, memberTree);
AttributeDefinitionBuilder adb = AttributeDefinitionBuilder.getter(this, decl.getName(), decl.getModel());
adb.modifiers(classGen().transformAttributeGetSetDeclFlags(decl.getModel(), false));
adb.userAnnotations(expressionGen().transformAnnotations(OutputElement.GETTER, memberTree));
classBuilder.attribute(adb);
if (value.isVariable()) {
AttributeDefinitionBuilder setter = AttributeDefinitionBuilder.setter(this, decl.getName(), decl.getModel());
setter.modifiers(classGen().transformAttributeGetSetDeclFlags(decl.getModel(), false));
//setter.userAnnotations(expressionGen().transform(AnnotationTarget.SETTER, memberTree.getAnnotationList()));
classBuilder.attribute(setter);
}
} else if (decl.isHidden() && // TODO Isn't this always true here? We know this is a parameter to a Class
(decl.getDeclaration() instanceof TypeDeclaration)) {
Declaration member = CodegenUtil.findMethodOrValueForParam(decl);
if (Strategy.createField(decl, (Value) member)) {
// The field itself is created by when we transform the AttributeDeclaration
// but it has to be initialized here so all the fields are initialized in parameter order
JCExpression parameterExpr = makeUnquotedIdent(Naming.getAliasedParameterName(decl));
TypedReference typedRef = getTypedReference(value);
TypedReference nonWideningTypedRef = nonWideningTypeDecl(typedRef);
Type paramType = nonWideningType(typedRef, nonWideningTypedRef);
if (!paramType.isExactly(decl.getType())) {
// The parameter type follows normal erasure rules, not affected by inheritance
// but the attribute respects non-widening rules, so we may need to cast
// the parameter to the field type (see #1728)
parameterExpr = make().TypeCast(classGen().transformClassParameterType(decl), parameterExpr);
}
classBuilder.getInitBuilder().init(make().Exec(make().Assign(naming.makeQualifiedName(naming.makeThis(), value, Naming.NA_IDENT), parameterExpr)));
}
}
}
Aggregations