use of com.redhat.ceylon.model.typechecker.model.Function in project ceylon-compiler by ceylon.
the class AbstractTransformer method makeJavaTypeAnnotations.
List<JCTree.JCAnnotation> makeJavaTypeAnnotations(TypedDeclaration decl, boolean handleFunctionalParameter) {
if (decl == null || decl.getType() == null)
return List.nil();
Type type;
if (decl instanceof Function && ((Function) decl).isParameter() && handleFunctionalParameter) {
type = getTypeForFunctionalParameter((Function) decl);
} else if (decl instanceof Functional && Decl.isMpl((Functional) decl)) {
type = getReturnTypeOfCallable(decl.appliedTypedReference(null, Collections.<Type>emptyList()).getFullType());
} else {
type = decl.getType();
}
boolean declaredVoid = decl instanceof Function && Strategy.useBoxedVoid((Function) decl) && Decl.isUnboxedVoid(decl);
return makeJavaTypeAnnotations(type, declaredVoid, CodegenUtil.hasTypeErased(decl), CodegenUtil.hasUntrustedType(decl), needsJavaTypeAnnotations(decl));
}
use of com.redhat.ceylon.model.typechecker.model.Function in project ceylon-compiler by ceylon.
the class AbstractTransformer method makeJavaType.
/**
* This function is used solely for method return types and parameters
*/
JCExpression makeJavaType(TypedDeclaration typeDecl, Type type, int flags) {
if (typeDecl instanceof Function && ((Function) typeDecl).isParameter()) {
Function p = (Function) typeDecl;
Type pt = type;
for (int ii = 1; ii < p.getParameterLists().size(); ii++) {
pt = typeFact().getCallableType(pt);
}
return makeJavaType(typeFact().getCallableType(pt), flags);
} else {
boolean usePrimitives = CodegenUtil.isUnBoxed(typeDecl);
return makeJavaType(type, flags | (usePrimitives ? 0 : AbstractTransformer.JT_NO_PRIMITIVES));
}
}
use of com.redhat.ceylon.model.typechecker.model.Function in project ceylon-compiler by ceylon.
the class ClassTransformer method refineMethod.
private Function refineMethod(Scope container, TypedReference pr, ClassOrInterface classModel, Function formalMethod, Unit unit) {
Function refined = new Function();
refined.setActual(true);
refined.setShared(formalMethod.isShared());
refined.setContainer(container);
// in case there are subclasses
refined.setDefault(true);
refined.setDeferred(false);
refined.setDeprecated(formalMethod.isDeprecated());
refined.setName(formalMethod.getName());
refined.setRefinedDeclaration(formalMethod.getRefinedDeclaration());
refined.setScope(container);
refined.setType(pr.getType());
refined.setUnit(unit);
refined.setUnboxed(formalMethod.getUnboxed());
refined.setUntrustedType(formalMethod.getUntrustedType());
refined.setTypeErased(formalMethod.getTypeErased());
ArrayList<TypeParameter> refinedTp = new ArrayList<TypeParameter>();
;
for (TypeParameter formalTp : formalMethod.getTypeParameters()) {
refinedTp.add(formalTp);
}
refined.setTypeParameters(refinedTp);
for (ParameterList formalPl : formalMethod.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.Function in project ceylon-compiler by ceylon.
the class ClassTransformer method transformSpecifiedMethodBody.
List<JCStatement> transformSpecifiedMethodBody(Tree.MethodDeclaration def, SpecifierExpression specifierExpression) {
final Function model = def.getDeclarationModel();
List<JCStatement> body;
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 = isAnything(resultType) && fa.getExpression().getUnboxed();
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()));
}
bodyExpr = gen().expressionGen().transformExpression(fa.getExpression(), returnNull ? BoxingStrategy.INDIFFERENT : CodegenUtil.getBoxingStrategy(model), resultType);
for (Substitution subs : substitutions) {
subs.close();
}
} 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 {
bodyExpr = expressionGen().transformExpression(model, term);
// The innermost of an MPL method declared void needs to return null
returnNull = Decl.isUnboxedVoid(model) && Decl.isMpl(model);
}
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;
}
use of com.redhat.ceylon.model.typechecker.model.Function in project ceylon-compiler by ceylon.
the class ClassTransformer method transformMethodBlock.
private List<JCStatement> transformMethodBlock(final Tree.MethodDefinition def) {
final Function model = def.getDeclarationModel();
final Tree.Block block = def.getBlock();
List<JCStatement> body;
boolean prevNoExpressionlessReturn = statementGen().noExpressionlessReturn;
try {
statementGen().noExpressionlessReturn = Decl.isMpl(model) || Strategy.useBoxedVoid(model);
body = statementGen().transformBlock(block);
} finally {
statementGen().noExpressionlessReturn = prevNoExpressionlessReturn;
}
// We void methods need to have their Callables return null
// so adjust here.
HasErrorException error = errors().getFirstErrorBlock(block);
if ((Decl.isMpl(model) || Strategy.useBoxedVoid(model)) && !block.getDefinitelyReturns() && error == null) {
if (Decl.isUnboxedVoid(model)) {
body = body.append(make().Return(makeNull()));
} else {
body = body.append(make().Return(makeErroneous(block, "compiler bug: non-void method doesn't definitely return")));
}
}
return body;
}
Aggregations