use of com.redhat.ceylon.model.typechecker.model.ParameterList 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.ParameterList in project ceylon-compiler by ceylon.
the class ClassTransformer method refineClass.
private Class refineClass(Scope container, Reference pr, ClassOrInterface classModel, Class formalClass, Unit unit) {
Class refined = new Class();
refined.setActual(true);
refined.setShared(formalClass.isShared());
refined.setContainer(container);
refined.setExtendedType(formalClass.getType());
refined.setDeprecated(formalClass.isDeprecated());
refined.setName(formalClass.getName());
refined.setRefinedDeclaration(formalClass.getRefinedDeclaration());
refined.setScope(container);
// refined.setType(pr.getType());
refined.setUnit(unit);
for (ParameterList formalPl : formalClass.getParameterLists()) {
ParameterList refinedPl = new ParameterList();
for (Parameter formalP : formalPl.getParameters()) {
Parameter refinedP = new Parameter();
refinedP.setAtLeastOne(formalP.isAtLeastOne());
refinedP.setDeclaration(refined);
refinedP.setDefaulted(formalP.isDefaulted());
refinedP.setDeclaredAnything(formalP.isDeclaredAnything());
refinedP.setHidden(formalP.isHidden());
refinedP.setSequenced(formalP.isSequenced());
refinedP.setName(formalP.getName());
final TypedReference typedParameter = pr.getTypedParameter(formalP);
FunctionOrValue paramModel;
if (formalP.getModel() instanceof Value) {
Value paramValueModel = refineValue((Value) formalP.getModel(), typedParameter, refined, classModel.getUnit());
paramValueModel.setInitializerParameter(refinedP);
paramModel = paramValueModel;
} else {
Function paramFunctionModel = refineMethod(refined, typedParameter, classModel, (Function) formalP.getModel(), unit);
paramFunctionModel.setInitializerParameter(refinedP);
paramModel = paramFunctionModel;
}
refinedP.setModel(paramModel);
refinedPl.getParameters().add(refinedP);
}
refined.addParameterList(refinedPl);
}
return refined;
}
use of com.redhat.ceylon.model.typechecker.model.ParameterList in project ceylon-compiler by ceylon.
the class CallableBuilder method unboundFunctionalMemberReference.
/**
* Used for "static" method or class references. For example:
* <pre>
* value x = Integer.plus;
* value y = Foo.method;
* value z = Outer.Inner;
* </pre>
*/
public static CallableBuilder unboundFunctionalMemberReference(CeylonTransformer gen, Tree.QualifiedMemberOrTypeExpression qmte, Type typeModel, final Functional methodClassOrCtor, Reference producedReference) {
final ParameterList parameterList = methodClassOrCtor.getFirstParameterList();
Type type = typeModel;
JCExpression target;
boolean hasOuter = !(Decl.isConstructor((Declaration) methodClassOrCtor) && gen.getNumParameterLists(typeModel) == 1);
if (!hasOuter) {
type = typeModel;
target = null;
} else {
type = gen.getReturnTypeOfCallable(type);
Type qualifyingType = qmte.getTarget().getQualifyingType();
target = gen.naming.makeUnquotedIdent(Unfix.$instance$);
target = gen.expressionGen().applyErasureAndBoxing(target, producedReference.getQualifyingType(), true, BoxingStrategy.BOXED, qualifyingType);
}
CallableBuilder inner = new CallableBuilder(gen, null, type, parameterList);
// FromParameterModels();
inner.parameterTypes = inner.getParameterTypesFromCallableModel();
if (hasOuter) {
inner.defaultValueCall = inner.new MemberReferenceDefaultValueCall(methodClassOrCtor);
}
CallBuilder callBuilder = CallBuilder.instance(gen);
Type accessType = gen.getParameterTypeOfCallable(typeModel, 0);
if (Decl.isConstructor((Declaration) methodClassOrCtor)) {
Constructor ctor = Decl.getConstructor((Declaration) methodClassOrCtor);
Class cls = Decl.getConstructedClass(ctor);
if (Strategy.generateInstantiator(ctor)) {
callBuilder.invoke(gen.naming.makeInstantiatorMethodName(target, cls));
} else {
callBuilder.instantiate(gen.makeJavaType(gen.getReturnTypeOfCallable(typeModel), JT_CLASS_NEW));
if (!ctor.isShared()) {
accessType = Decl.getPrivateAccessType(qmte);
}
}
} else if (methodClassOrCtor instanceof Function && ((Function) methodClassOrCtor).isParameter()) {
callBuilder.invoke(gen.naming.makeQualifiedName(target, (Function) methodClassOrCtor, Naming.NA_MEMBER));
} else if (methodClassOrCtor instanceof Function) {
callBuilder.invoke(gen.naming.makeQualifiedName(target, (Function) methodClassOrCtor, Naming.NA_MEMBER));
if (!((TypedDeclaration) methodClassOrCtor).isShared()) {
accessType = Decl.getPrivateAccessType(qmte);
}
} else if (methodClassOrCtor instanceof Class) {
Class cls = (Class) methodClassOrCtor;
if (Strategy.generateInstantiator(cls)) {
callBuilder.invoke(gen.naming.makeInstantiatorMethodName(target, cls));
} else {
callBuilder.instantiate(new ExpressionAndType(target, null), gen.makeJavaType(cls.getType(), JT_CLASS_NEW | AbstractTransformer.JT_NON_QUALIFIED));
if (!cls.isShared()) {
accessType = Decl.getPrivateAccessType(qmte);
}
}
} else {
throw BugException.unhandledDeclarationCase((Declaration) methodClassOrCtor, qmte);
}
ListBuffer<ExpressionAndType> reified = ListBuffer.lb();
DirectInvocation.addReifiedArguments(gen, producedReference, reified);
for (ExpressionAndType reifiedArgument : reified) {
callBuilder.argument(reifiedArgument.expression);
}
if (Decl.isConstructor((Declaration) methodClassOrCtor) && !Decl.isDefaultConstructor(Decl.getConstructor((Declaration) methodClassOrCtor))) {
// invoke the param class ctor
Constructor ctor = Decl.getConstructor((Declaration) methodClassOrCtor);
callBuilder.argument(gen.naming.makeNamedConstructorName(ctor, false));
}
for (Parameter parameter : parameterList.getParameters()) {
callBuilder.argument(gen.naming.makeQuotedIdent(Naming.getAliasedParameterName(parameter)));
}
JCExpression innerInvocation = callBuilder.build();
// Need to worry about boxing for Function and FunctionalParameter
if (methodClassOrCtor instanceof TypedDeclaration && !Decl.isConstructor((Declaration) methodClassOrCtor)) {
// use the method return type since the function is actually applied
Type returnType = gen.getReturnTypeOfCallable(type);
innerInvocation = gen.expressionGen().applyErasureAndBoxing(innerInvocation, returnType, // expression is a Callable
CodegenUtil.hasTypeErased((TypedDeclaration) methodClassOrCtor), !CodegenUtil.isUnBoxed((TypedDeclaration) methodClassOrCtor), BoxingStrategy.BOXED, returnType, 0);
} else if (methodClassOrCtor instanceof Class && Strategy.isInstantiatorUntyped((Class) methodClassOrCtor)) {
// $new method declared to return Object, so needs typecast
innerInvocation = gen.make().TypeCast(gen.makeJavaType(((Class) methodClassOrCtor).getType()), innerInvocation);
}
List<JCStatement> innerBody = List.<JCStatement>of(gen.make().Return(innerInvocation));
inner.useDefaultTransformation(innerBody);
if (!hasOuter) {
return inner;
}
ParameterList outerPl = new ParameterList();
Parameter instanceParameter = new Parameter();
instanceParameter.setName(Naming.name(Unfix.$instance$));
Value valueModel = new Value();
instanceParameter.setModel(valueModel);
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> outerBody = List.<JCStatement>of(gen.make().Return(inner.build()));
outer.useDefaultTransformation(outerBody);
outer.companionAccess = Decl.isPrivateAccessRequiringCompanion(qmte);
return outer;
}
use of com.redhat.ceylon.model.typechecker.model.ParameterList in project ceylon-compiler by ceylon.
the class CallableBuilder method javaStaticMethodReference.
public static CallableBuilder javaStaticMethodReference(CeylonTransformer gen, Type typeModel, final Functional methodOrClass, Reference producedReference) {
final ParameterList parameterList = methodOrClass.getFirstParameterList();
CallableBuilder inner = new CallableBuilder(gen, null, typeModel, parameterList);
ArrayList<Type> pt = new ArrayList<>();
for (Parameter p : methodOrClass.getFirstParameterList().getParameters()) {
pt.add(p.getType());
}
inner.parameterTypes = pt;
inner.defaultValueCall = inner.new MemberReferenceDefaultValueCall(methodOrClass);
JCExpression innerInvocation = gen.expressionGen().makeJavaStaticInvocation(gen, methodOrClass, producedReference, parameterList);
// Need to worry about boxing for Function and FunctionalParameter
if (methodOrClass instanceof TypedDeclaration) {
innerInvocation = gen.expressionGen().applyErasureAndBoxing(innerInvocation, methodOrClass.getType(), !CodegenUtil.isUnBoxed((TypedDeclaration) methodOrClass), BoxingStrategy.BOXED, methodOrClass.getType());
} else if (Strategy.isInstantiatorUntyped((Class) methodOrClass)) {
// $new method declared to return Object, so needs typecast
innerInvocation = gen.make().TypeCast(gen.makeJavaType(((Class) methodOrClass).getType()), innerInvocation);
}
List<JCStatement> innerBody = List.<JCStatement>of(gen.make().Return(innerInvocation));
inner.useDefaultTransformation(innerBody);
return inner;
}
Aggregations