use of org.eclipse.ceylon.model.typechecker.model.Reference in project ceylon by eclipse.
the class ExpressionVisitor method inferParameterTypesDirectly.
/**
* Infer parameter types of anonymous function arguments
* in a direct invocation with named arguments.
*
* Also sets references from arguments back to parameters
* by side effect.
*/
private void inferParameterTypesDirectly(Tree.NamedArgumentList nal, Tree.MemberOrTypeExpression mte, Declaration dec) {
Reference reference = getInvokedProducedReference(dec, mte);
Functional fun = (Functional) dec;
List<ParameterList> pls = fun.getParameterLists();
if (!pls.isEmpty()) {
Set<Parameter> foundParameters = new HashSet<Parameter>();
ParameterList pl = pls.get(0);
List<Tree.NamedArgument> args = nal.getNamedArguments();
for (int i = 0; i < args.size(); i++) {
Tree.NamedArgument arg = args.get(i);
Parameter param = getMatchingParameter(pl, arg, foundParameters);
if (param != null) {
foundParameters.add(param);
arg.setParameter(param);
if (arg instanceof Tree.SpecifiedArgument) {
Tree.SpecifiedArgument sa = (Tree.SpecifiedArgument) arg;
Tree.SpecifierExpression se = sa.getSpecifierExpression();
if (se != null) {
setupTargetParameters(reference, param, se.getExpression());
inferParameterTypes(reference, param, se.getExpression(), false, true);
}
}
}
}
Tree.SequencedArgument sa = nal.getSequencedArgument();
if (sa != null) {
Parameter param = getUnspecifiedParameter(reference, pl, foundParameters);
if (param != null) {
sa.setParameter(param);
for (Tree.PositionalArgument pa : sa.getPositionalArguments()) {
if (pa instanceof Tree.ListedArgument) {
Tree.ListedArgument la = (Tree.ListedArgument) pa;
la.setParameter(param);
setupTargetParameters(reference, param, la.getExpression());
inferParameterTypes(reference, param, la.getExpression(), true, true);
}
}
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Reference in project ceylon by eclipse.
the class ExpressionVisitor method refineMethod.
private void refineMethod(Tree.SpecifierStatement that) {
Function refinedMethod = (Function) that.getRefined();
Function method = (Function) that.getDeclaration();
ClassOrInterface ci = (ClassOrInterface) method.getContainer();
Declaration root = method.getRefinedDeclaration();
TypeDeclaration td = (TypeDeclaration) root.getContainer();
List<Declaration> interveningRefinements = getInterveningRefinements(method, root, ci, td);
if (interveningRefinements.isEmpty()) {
that.getBaseMemberExpression().addError("shortcut refinement does not exactly refine any overloaded inherited member");
} else {
Reference refinedProducedReference = accountForIntermediateRefinements(that, refinedMethod, method, ci, interveningRefinements);
List<Tree.ParameterList> parameterLists;
Tree.Term me = that.getBaseMemberExpression();
if (me instanceof Tree.ParameterizedExpression) {
Tree.ParameterizedExpression pe = (Tree.ParameterizedExpression) me;
parameterLists = pe.getParameterLists();
} else {
parameterLists = emptyList();
}
List<ParameterList> refinedParamLists = refinedMethod.getParameterLists();
List<ParameterList> methodParamLists = method.getParameterLists();
Map<TypeParameter, Type> subs = substitutions(refinedMethod, method);
for (int i = 0; i < refinedParamLists.size() && i < methodParamLists.size(); i++) {
ParameterList refinedParameters = refinedParamLists.get(i);
ParameterList parameters = methodParamLists.get(i);
Tree.ParameterList parameterList = parameterLists.size() <= i ? null : parameterLists.get(i);
List<Parameter> rps = refinedParameters.getParameters();
for (int j = 0; j < rps.size(); j++) {
Parameter refinedParameter = rps.get(j);
Type refinedParameterType = refinedProducedReference.getTypedParameter(refinedParameter).getFullType().substitute(subs, null);
Parameter parameter;
if (parameterList == null || parameterList.getParameters().size() <= j) {
parameter = parameters.getParameters().get(j);
parameter.getModel().setType(refinedParameterType);
parameter.setSequenced(refinedParameter.isSequenced());
} else {
Tree.Parameter param = parameterList.getParameters().get(j);
parameter = param.getParameterModel();
Type parameterType = parameter.getModel().getTypedReference().getFullType();
Node typeNode = param;
if (param instanceof Tree.ParameterDeclaration) {
Tree.ParameterDeclaration pd = (Tree.ParameterDeclaration) param;
Tree.Type type = pd.getTypedDeclaration().getType();
if (type != null) {
typeNode = type;
}
}
checkIsExactlyIgnoringNull(refinedParameters.isNamedParametersSupported(), parameterType, refinedParameterType, typeNode, "type of parameter '" + parameter.getName() + "' of '" + method.getName() + "' declared by '" + ci.getName() + "' is different to type of corresponding parameter " + message(refinedMethod, refinedParameter), 9200);
if (refinedParameter.isSequenced() && !parameter.isSequenced()) {
param.addError("parameter must be variadic: parameter " + message(refinedMethod, refinedParameter) + " is variadic");
}
if (!refinedParameter.isSequenced() && parameter.isSequenced()) {
param.addError("parameter may not be variadic: parameter " + message(refinedMethod, refinedParameter) + " is not variadic");
}
}
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Reference in project ceylon by eclipse.
the class ExpressionVisitor method accountForStaticReferenceReceiverType.
private Type accountForStaticReferenceReceiverType(Tree.QualifiedMemberOrTypeExpression that, Type receivingType) {
if (that.getStaticMethodReference()) {
Tree.MemberOrTypeExpression primary = (Tree.MemberOrTypeExpression) that.getPrimary();
Reference target = primary.getTarget();
return target == null ? unit.getUnknownType() : target.getType();
} else {
return receivingType;
}
}
use of org.eclipse.ceylon.model.typechecker.model.Reference in project ceylon by eclipse.
the class ExpressionVisitor method setupTargetParametersDirectly.
/**
* Sets references from arguments back to parameters
* in a direct invocation with positional arguments,
* special casing "coercion points" generated by the
* model loader.
*/
private void setupTargetParametersDirectly(Tree.PositionalArgumentList pal, Tree.MemberOrTypeExpression mte, Declaration dec, boolean error) {
// coercion point and use that instead
if (!error && isOverloadedVersion(dec) && !dec.isCoercionPoint()) {
Declaration abstraction = dec.getContainer().getDirectMember(dec.getName(), null, false);
if (abstraction.isAbstraction()) {
List<Declaration> overloads = abstraction.getOverloads();
if (overloads.size() == 2) {
for (Declaration overload : overloads) {
if (overload.isCoercionPoint()) {
dec = overload;
break;
}
}
}
}
}
List<Tree.PositionalArgument> args = pal.getPositionalArguments();
int argCount = args.size();
Functional fun = (Functional) dec;
List<ParameterList> pls = fun.getParameterLists();
if (!pls.isEmpty()) {
List<Parameter> params = pls.get(0).getParameters();
Reference reference = getInvokedProducedReference(dec, mte);
int paramsSize = params.size();
for (int i = 0, j = 0; i < argCount && j < paramsSize; i++) {
Parameter param = params.get(j);
Tree.PositionalArgument arg = args.get(i);
arg.setParameter(param);
if (arg instanceof Tree.ListedArgument) {
Tree.ListedArgument la = (Tree.ListedArgument) arg;
setupTargetParameters(reference, param, la.getExpression());
}
if (!param.isSequenced()) {
j++;
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Reference in project ceylon by eclipse.
the class ClassTransformer method transformSpecifiedMethodBody.
List<JCStatement> transformSpecifiedMethodBody(Tree.MethodDeclaration def, SpecifierExpression specifierExpression) {
final Function model = def.getDeclarationModel();
Tree.MethodDeclaration methodDecl = def;
boolean isLazy = specifierExpression instanceof Tree.LazySpecifierExpression;
boolean returnNull = false;
JCExpression bodyExpr;
Tree.Term term = null;
if (specifierExpression != null && specifierExpression.getExpression() != null) {
term = Decl.unwrapExpressionsUntilTerm(specifierExpression.getExpression());
HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(term);
if (error != null) {
return List.<JCStatement>of(this.makeThrowUnresolvedCompilationError(error));
}
}
if (!isLazy && term instanceof Tree.FunctionArgument) {
// Function specified with lambda: Don't bother generating a
// Callable, just transform the expr to use as the method body.
Tree.FunctionArgument fa = (Tree.FunctionArgument) term;
Type resultType = model.getType();
returnNull = Decl.isUnboxedVoid(model);
final java.util.List<Tree.Parameter> lambdaParams = fa.getParameterLists().get(0).getParameters();
final java.util.List<Tree.Parameter> defParams = def.getParameterLists().get(0).getParameters();
List<Substitution> substitutions = List.nil();
for (int ii = 0; ii < lambdaParams.size(); ii++) {
substitutions = substitutions.append(naming.addVariableSubst((TypedDeclaration) lambdaParams.get(ii).getParameterModel().getModel(), defParams.get(ii).getParameterModel().getName()));
}
List<JCStatement> body = null;
if (fa.getExpression() != null)
bodyExpr = gen().expressionGen().transformExpression(fa.getExpression(), returnNull ? BoxingStrategy.INDIFFERENT : CodegenUtil.getBoxingStrategy(model), resultType);
else {
body = gen().statementGen().transformBlock(fa.getBlock());
// useless but satisfies branch checking
bodyExpr = null;
}
for (Substitution subs : substitutions) {
subs.close();
}
// if we have a whole body we're done
if (body != null)
return body;
} else if (!isLazy && typeFact().isCallableType(term.getTypeModel())) {
returnNull = isAnything(term.getTypeModel()) && term.getUnboxed();
Function method = methodDecl.getDeclarationModel();
boolean lazy = specifierExpression instanceof Tree.LazySpecifierExpression;
boolean inlined = CodegenUtil.canOptimiseMethodSpecifier(term, method);
Invocation invocation;
if ((lazy || inlined) && term instanceof Tree.MemberOrTypeExpression && ((Tree.MemberOrTypeExpression) term).getDeclaration() instanceof Functional) {
Declaration primaryDeclaration = ((Tree.MemberOrTypeExpression) term).getDeclaration();
Reference producedReference = ((Tree.MemberOrTypeExpression) term).getTarget();
invocation = new MethodReferenceSpecifierInvocation(this, (Tree.MemberOrTypeExpression) term, primaryDeclaration, producedReference, method, specifierExpression);
} else if (!lazy && !inlined) {
// must be a callable we stored
String name = naming.getMethodSpecifierAttributeName(method);
invocation = new CallableSpecifierInvocation(this, method, naming.makeUnquotedIdent(name), term, term);
} else if (isCeylonCallableSubtype(term.getTypeModel())) {
invocation = new CallableSpecifierInvocation(this, method, expressionGen().transformExpression(term), term, term);
} else {
throw new BugException(term, "unhandled primary: " + term == null ? "null" : term.getNodeType());
}
invocation.handleBoxing(true);
invocation.setErased(CodegenUtil.hasTypeErased(term) || getReturnTypeOfCallable(term.getTypeModel()).isNothing());
bodyExpr = expressionGen().transformInvocation(invocation);
} else {
Substitution substitution = null;
JCStatement varDef = null;
// Handle implementations of Java variadic methods
Parameter lastParameter = Decl.getLastParameterFromFirstParameterList(model);
if (lastParameter != null && Decl.isJavaVariadicIncludingInheritance(lastParameter)) {
SyntheticName alias = naming.alias(lastParameter.getName());
substitution = naming.addVariableSubst(lastParameter.getModel(), alias.getName());
varDef = substituteSequentialForJavaVariadic(alias, lastParameter);
}
bodyExpr = expressionGen().transformExpression(model, term);
if (varDef != null) {
// Turn into Let for java variadic methods
bodyExpr = make().LetExpr(List.of(varDef), bodyExpr);
substitution.close();
}
// The innermost of an MPL method declared void needs to return null
returnNull = Decl.isUnboxedVoid(model) && Decl.isMpl(model);
}
if (CodegenUtil.downcastForSmall(term, model)) {
bodyExpr = expressionGen().applyErasureAndBoxing(bodyExpr, term.getTypeModel(), false, !CodegenUtil.isUnBoxed(term), CodegenUtil.getBoxingStrategy(model), model.getType(), ExpressionTransformer.EXPR_UNSAFE_PRIMITIVE_TYPECAST_OK);
}
List<JCStatement> body;
if (!Decl.isUnboxedVoid(model) || Decl.isMpl(model) || Strategy.useBoxedVoid(model)) {
if (returnNull) {
body = List.<JCStatement>of(make().Exec(bodyExpr), make().Return(makeNull()));
} else {
body = List.<JCStatement>of(make().Return(bodyExpr));
}
} else {
body = List.<JCStatement>of(make().Exec(bodyExpr));
}
return body;
}
Aggregations