use of org.eclipse.ceylon.model.typechecker.model.Parameter in project ceylon by eclipse.
the class ExpressionTransformer method transformArgumentsForCallableSpecifier.
private List<ExpressionAndType> transformArgumentsForCallableSpecifier(CallableSpecifierInvocation invocation) {
List<ExpressionAndType> result = List.<ExpressionAndType>nil();
int argIndex = 0;
for (Parameter parameter : invocation.getMethod().getFirstParameterList().getParameters()) {
Type exprType = expressionGen().getTypeForParameter(parameter, null, TP_TO_BOUND);
Parameter declaredParameter = invocation.getMethod().getFirstParameterList().getParameters().get(argIndex);
JCExpression arg = naming.makeName(parameter.getModel(), Naming.NA_IDENT);
arg = expressionGen().applyErasureAndBoxing(arg, exprType, !parameter.getModel().getUnboxed(), // Callables always have boxed params
BoxingStrategy.BOXED, declaredParameter.getType());
result = result.append(new ExpressionAndType(arg, makeJavaType(declaredParameter.getType())));
argIndex++;
}
return result;
}
use of org.eclipse.ceylon.model.typechecker.model.Parameter in project ceylon by eclipse.
the class ExpressionTransformer method transformArgumentsForSimpleInvocation.
private List<ExpressionAndType> transformArgumentsForSimpleInvocation(SimpleInvocation invocation, CallBuilder callBuilder) {
final Constructor superConstructor = invocation.getConstructor();
CtorDelegation constructorDelegation;
if (invocation instanceof SuperInvocation) {
constructorDelegation = ((SuperInvocation) invocation).getDelegation();
} else {
constructorDelegation = null;
}
List<ExpressionAndType> result = List.<ExpressionAndType>nil();
if (!(invocation instanceof SuperInvocation) || !((SuperInvocation) invocation).isDelegationDelegation()) {
int numArguments = invocation.getNumArguments();
if (invocation.getNumParameters() == 0) {
// skip transforming arguments
// (Usually, numArguments would already be null, but it's possible to call a
// parameterless function with a *[] argument - see #1593.)
numArguments = 0;
}
boolean wrapIntoArray = false;
ListBuffer<JCExpression> arrayWrap = new ListBuffer<JCExpression>();
for (int argIndex = 0; argIndex < numArguments; argIndex++) {
BoxingStrategy boxingStrategy = invocation.getParameterBoxingStrategy(argIndex);
Type parameterType = invocation.getParameterType(argIndex);
// to avoid ambiguity of foo(1,2) for foo(int...) and foo(Object...) methods
if (!wrapIntoArray && invocation.isParameterJavaVariadic(argIndex) && boxingStrategy == BoxingStrategy.UNBOXED && willEraseToPrimitive(typeFact().getDefiniteType(parameterType)) && !invocation.isSpread())
wrapIntoArray = true;
ExpressionAndType exprAndType;
if (invocation.isArgumentSpread(argIndex)) {
if (!invocation.isParameterSequenced(argIndex)) {
result = transformSpreadTupleArgument(invocation, callBuilder, result, argIndex);
break;
}
if (invocation.isJavaVariadicMethod()) {
// if it's a java method we need a special wrapping
exprAndType = transformSpreadArgument(invocation, numArguments, argIndex, boxingStrategy, parameterType);
argIndex = numArguments;
} else {
Type argType = invocation.getArgumentType(argIndex);
if (argType.getSupertype(typeFact().getSequentialDeclaration()) != null) {
exprAndType = transformArgument(invocation, argIndex, boxingStrategy);
} else if (argType.getSupertype(typeFact().getIterableDeclaration()) != null) {
exprAndType = transformArgument(invocation, argIndex, boxingStrategy);
JCExpression sequential = iterableToSequential(exprAndType.expression);
if (invocation.isParameterVariadicPlus(argIndex)) {
Type iteratedType = typeFact().getIteratedType(argType);
sequential = utilInvocation().castSequentialToSequence(sequential, iteratedType);
}
exprAndType = new ExpressionAndType(sequential, exprAndType.type);
} else if (typeFact().isJavaArrayType(argType)) {
exprAndType = transformArgument(invocation, argIndex, boxingStrategy);
JCExpression iterable;
if (typeFact().isJavaPrimitiveArrayType(argType)) {
iterable = utilInvocation().toIterable(exprAndType.expression);
} else {
Type elementType = typeFact().getJavaArrayElementType(argType);
iterable = utilInvocation().toIterable(makeJavaType(elementType, JT_TYPE_ARGUMENT), makeReifiedTypeArgument(elementType), exprAndType.expression);
}
exprAndType = new ExpressionAndType(make().Apply(null, makeSelect(iterable, "sequence"), List.<JCExpression>nil()), makeJavaType(argType));
} else if (typeFact().isJavaIterableType(argType)) {
exprAndType = transformArgument(invocation, argIndex, boxingStrategy);
Type elementType = typeFact().getJavaIteratedType(argType);
JCExpression iterable = utilInvocation().toIterable(makeJavaType(elementType, JT_TYPE_ARGUMENT), makeReifiedTypeArgument(elementType), exprAndType.expression);
exprAndType = new ExpressionAndType(make().Apply(null, makeSelect(iterable, "sequence"), List.<JCExpression>nil()), makeJavaType(argType));
} else {
exprAndType = new ExpressionAndType(makeErroneous(invocation.getNode(), "compiler bug: unexpected spread argument"), makeErroneous(invocation.getNode(), "compiler bug: unexpected spread argument"));
}
}
} else if (!invocation.isParameterSequenced(argIndex) || // if it's sequenced, Java and there's no spread at all, pass it along
(invocation.isParameterJavaVariadic(argIndex) && !invocation.isSpread())) {
exprAndType = transformArgument(invocation, argIndex, boxingStrategy);
// This is not required for primitive arrays since they are not Object[]
if (numArguments == 1 && invocation.isIndirect()) {
Type argumentType = invocation.getArgumentType(0);
if (isJavaObjectArray(argumentType) || isNull(argumentType)) {
exprAndType = new ExpressionAndType(make().TypeCast(makeJavaType(typeFact().getObjectType()), exprAndType.expression), exprAndType.type);
}
} else if (invocation.isParameterJavaVariadic(argIndex) && !invocation.isSpread()) {
// in fact, the very same problem happens when passing null or object arrays to a java variadic method
Type argumentType = invocation.getArgumentType(argIndex);
if (isJavaObjectArray(argumentType) || isNull(argumentType)) {
// remove any ambiguity
exprAndType = new ExpressionAndType(make().TypeCast(makeJavaType(parameterType), exprAndType.expression), exprAndType.type);
}
}
} else {
// we must have a sequenced param
if (invocation.isSpread()) {
exprAndType = transformSpreadArgument(invocation, numArguments, argIndex, boxingStrategy, parameterType);
argIndex = numArguments;
} else {
exprAndType = transformVariadicArgument(invocation, numArguments, argIndex, parameterType);
argIndex = numArguments;
}
}
if (!wrapIntoArray) {
if (argIndex == 0 && invocation.isCallable() && !invocation.isArgumentSpread(numArguments - 1)) {
exprAndType = new ExpressionAndType(make().TypeCast(make().Type(syms().objectType), exprAndType.expression), make().Type(syms().objectType));
}
result = result.append(exprAndType);
} else {
arrayWrap.append(exprAndType.expression);
}
}
if (invocation.isIndirect() && invocation.getNumParameters() > numArguments && invocation.isParameterSequenced(numArguments) && !invocation.isArgumentSpread(numArguments - 1)) {
// Calling convention for indirect variadic invocation's requires
// explicit variadic argument (can't use the overloading trick)
result = result.append(new ExpressionAndType(makeEmptyAsSequential(true), make().Erroneous()));
}
if (wrapIntoArray) {
// must have at least one arg, so take the last one
Type parameterType = invocation.getParameterType(numArguments - 1);
JCExpression arrayType = makeJavaType(parameterType, JT_RAW);
JCNewArray arrayExpr = make().NewArray(arrayType, List.<JCExpression>nil(), arrayWrap.toList());
JCExpression arrayTypeExpr = make().TypeArray(makeJavaType(parameterType, JT_RAW));
result = result.append(new ExpressionAndType(arrayExpr, arrayTypeExpr));
}
} else {
for (Parameter p : constructorDelegation.getConstructor().getParameterList().getParameters()) {
result = result.append(new ExpressionAndType(naming.makeName(p.getModel(), Naming.NA_IDENT | Naming.NA_ALIASED), null));
}
}
boolean concreteDelegation = invocation instanceof SuperInvocation && ((SuperInvocation) invocation).getDelegation().isConcreteSelfDelegation();
if (superConstructor == null && concreteDelegation) {
Constructor delegateTo = ((SuperInvocation) invocation).getDelegation().getConstructor();
result = result.prepend(new ExpressionAndType(naming.makeNamedConstructorName(delegateTo, true), naming.makeNamedConstructorType(delegateTo, true)));
} else if (superConstructor != null && constructorDelegation != null && constructorDelegation.isSelfDelegation()) {
result = result.prepend(new ExpressionAndType(naming.makeNamedConstructorName(constructorDelegation.getExtendingConstructor(), concreteDelegation), naming.makeNamedConstructorType(constructorDelegation.getExtendingConstructor(), concreteDelegation)));
} else if (superConstructor != null && !Decl.isDefaultConstructor(superConstructor) && !Decl.isJavaArrayWith(superConstructor) && (invocation.getQmePrimary() instanceof Tree.QualifiedTypeExpression == false || !isCeylonCallable(((Tree.QualifiedTypeExpression) invocation.getQmePrimary()).getPrimary().getTypeModel()))) {
result = result.prepend(new ExpressionAndType(naming.makeNamedConstructorName(superConstructor, concreteDelegation), naming.makeNamedConstructorType(superConstructor, concreteDelegation)));
}
return result;
}
use of org.eclipse.ceylon.model.typechecker.model.Parameter in project ceylon by eclipse.
the class StatementTransformer method transform.
// FIXME There is a similar implementation in ClassGen!
public List<JCStatement> transform(Tree.AttributeDeclaration decl) {
ListBuffer<JCStatement> result = new ListBuffer<JCStatement>();
// If the attribute is really from a parameter then don't generate a local variable
Parameter parameter = CodegenUtil.findParamForDecl(decl);
if (parameter == null) {
final Name attrName = names().fromString(naming.substitute(decl.getDeclarationModel()));
Type t = decl.getDeclarationModel().getType();
JCExpression initialValue = null;
SpecifierOrInitializerExpression initOrSpec = decl.getSpecifierOrInitializerExpression();
if (initOrSpec != null) {
HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(initOrSpec.getExpression().getTerm());
if (error != null) {
return List.<JCStatement>of(this.makeThrowUnresolvedCompilationError(error));
}
int flags = CodegenUtil.downcastForSmall(initOrSpec.getExpression(), decl.getDeclarationModel()) ? ExpressionTransformer.EXPR_UNSAFE_PRIMITIVE_TYPECAST_OK : 0;
flags |= decl.getDeclarationModel().hasUncheckedNullType() ? ExpressionTransformer.EXPR_TARGET_ACCEPTS_NULL : 0;
initialValue = expressionGen().transformExpression(initOrSpec.getExpression(), CodegenUtil.getBoxingStrategy(decl.getDeclarationModel()), decl.getDeclarationModel().getType(), flags);
} else if (decl.getDeclarationModel().isVariable()) {
// Java's definite initialization doesn't always work
// so give variable attribute declarations without
// initializers a default value. See #1153.
initialValue = makeDefaultExprForType(t);
if (CodegenUtil.getBoxingStrategy(decl.getDeclarationModel()) == BoxingStrategy.BOXED && canUnbox(t)) {
initialValue = boxType(initialValue, t);
}
}
List<JCAnnotation> annots = List.<JCAnnotation>nil();
int modifiers = transformLocalFieldDeclFlags(decl);
JCExpression typeExpr = makeJavaType(decl.getDeclarationModel(), t, modifiers);
result.append(at(decl.getIdentifier()).VarDef(at(decl.getIdentifier()).Modifiers(modifiers, annots), attrName, typeExpr, initialValue));
JCStatement outerSubs = openOuterSubstitutionIfNeeded(decl.getDeclarationModel(), t, modifiers);
if (outerSubs != null) {
result.append(outerSubs);
}
}
return result.toList();
}
use of org.eclipse.ceylon.model.typechecker.model.Parameter in project ceylon by eclipse.
the class Strategy method hasNoRequiredParameters.
/**
* Returns true if the given functional takes no parameters or accepts only defaulted params
*/
private static boolean hasNoRequiredParameters(Functional model) {
List<ParameterList> parameterLists = model.getParameterLists();
if (parameterLists == null || parameterLists.size() != 1)
return false;
ParameterList parameterList = parameterLists.get(0);
if (parameterList == null)
return false;
List<Parameter> parameters = parameterList.getParameters();
if (parameters == null)
return false;
if (parameters.isEmpty())
return true;
// if the first one is optional, all others have to be too
return parameters.get(0).isDefaulted();
}
use of org.eclipse.ceylon.model.typechecker.model.Parameter in project ceylon by eclipse.
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()) {
FunctionOrValue model = param.getModel();
if (Naming.aliasConstructorParameterName(model)) {
gen.naming.addVariableSubst(model, Naming.suffixName(Suffix.$param$, param.getName()));
}
}
}
final CtorDelegation delegation = delegates.get(ctorModel);
ListBuffer<JCStatement> stmts = new ListBuffer<JCStatement>();
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 = new ListBuffer<JCExpression>();
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().modifierTransformation().constructor(ctorModel), false, ctorName, stmts.toList(), DeclNameFlag.QUALIFIED));
}
Aggregations