use of org.eclipse.ceylon.langtools.tools.javac.code.Type.MethodType in project ceylon by eclipse.
the class LambdaToMethod method visitLambda.
/**
* Translate a lambda into a method to be inserted into the class.
* Then replace the lambda site with an invokedynamic call of to lambda
* meta-factory, which will use the lambda method.
* @param tree
*/
@Override
public void visitLambda(JCLambda tree) {
LambdaAnalyzerPreprocessor.LambdaTranslationContext localContext = (LambdaAnalyzerPreprocessor.LambdaTranslationContext) context;
MethodSymbol sym = localContext.translatedSym;
MethodType lambdaType = (MethodType) sym.type;
{
Symbol owner = localContext.owner;
ListBuffer<Attribute.TypeCompound> ownerTypeAnnos = new ListBuffer<Attribute.TypeCompound>();
ListBuffer<Attribute.TypeCompound> lambdaTypeAnnos = new ListBuffer<Attribute.TypeCompound>();
for (Attribute.TypeCompound tc : owner.getRawTypeAttributes()) {
if (tc.position.onLambda == tree) {
lambdaTypeAnnos.append(tc);
} else {
ownerTypeAnnos.append(tc);
}
}
if (lambdaTypeAnnos.nonEmpty()) {
owner.setTypeAttributes(ownerTypeAnnos.toList());
sym.setTypeAttributes(lambdaTypeAnnos.toList());
}
}
// create the method declaration hoisting the lambda body
JCMethodDecl lambdaDecl = make.MethodDef(make.Modifiers(sym.flags_field), sym.name, make.QualIdent(lambdaType.getReturnType().tsym), List.<JCTypeParameter>nil(), localContext.syntheticParams, lambdaType.getThrownTypes() == null ? List.<JCExpression>nil() : make.Types(lambdaType.getThrownTypes()), null, null);
lambdaDecl.sym = sym;
lambdaDecl.type = lambdaType;
// translate lambda body
// As the lambda body is translated, all references to lambda locals,
// captured variables, enclosing members are adjusted accordingly
// to refer to the static method parameters (rather than i.e. acessing to
// captured members directly).
lambdaDecl.body = translate(makeLambdaBody(tree, lambdaDecl));
// Add the method to the list of methods to be added to this class.
kInfo.addMethod(lambdaDecl);
// now that we have generated a method for the lambda expression,
// we can translate the lambda into a method reference pointing to the newly
// created method.
//
// Note that we need to adjust the method handle so that it will match the
// signature of the SAM descriptor - this means that the method reference
// should be added the following synthetic arguments:
//
// * the "this" argument if it is an instance method
// * enclosing locals captured by the lambda expression
ListBuffer<JCExpression> syntheticInits = new ListBuffer<>();
if (localContext.methodReferenceReceiver != null) {
syntheticInits.append(localContext.methodReferenceReceiver);
} else if (!sym.isStatic()) {
syntheticInits.append(makeThis(sym.owner.enclClass().asType(), localContext.owner.enclClass()));
}
// add captured locals
for (Symbol fv : localContext.getSymbolMap(CAPTURED_VAR).keySet()) {
if (fv != localContext.self) {
JCTree captured_local = make.Ident(fv).setType(fv.type);
syntheticInits.append((JCExpression) captured_local);
}
}
// then, determine the arguments to the indy call
List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev);
// build a sam instance using an indy call to the meta-factory
int refKind = referenceKind(sym);
// convert to an invokedynamic call
result = makeMetafactoryIndyCall(context, refKind, sym, indy_args);
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Type.MethodType in project ceylon by eclipse.
the class LambdaToMethod method addDeserializationCase.
private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym, DiagnosticPosition pos, List<Object> staticArgs, MethodType indyType) {
String functionalInterfaceClass = classSig(targetType);
String functionalInterfaceMethodName = samSym.getSimpleName().toString();
String functionalInterfaceMethodSignature = typeSig(types.erasure(samSym.type));
String implClass = classSig(types.erasure(refSym.owner.type));
String implMethodName = refSym.getQualifiedName().toString();
String implMethodSignature = typeSig(types.erasure(refSym.type));
JCExpression kindTest = eqTest(syms.intType, deserGetter("getImplMethodKind", syms.intType), make.Literal(implMethodKind));
ListBuffer<JCExpression> serArgs = new ListBuffer<>();
int i = 0;
for (Type t : indyType.getParameterTypes()) {
List<JCExpression> indexAsArg = new ListBuffer<JCExpression>().append(make.Literal(i)).toList();
List<Type> argTypes = new ListBuffer<Type>().append(syms.intType).toList();
serArgs.add(make.TypeCast(types.erasure(t), deserGetter("getCapturedArg", syms.objectType, argTypes, indexAsArg)));
++i;
}
JCStatement stmt = make.If(deserTest(deserTest(deserTest(deserTest(deserTest(kindTest, "getFunctionalInterfaceClass", functionalInterfaceClass), "getFunctionalInterfaceMethodName", functionalInterfaceMethodName), "getFunctionalInterfaceMethodSignature", functionalInterfaceMethodSignature), "getImplClass", implClass), "getImplMethodSignature", implMethodSignature), make.Return(makeIndyCall(pos, syms.lambdaMetafactory, names.altMetafactory, staticArgs, indyType, serArgs.toList(), samSym.name)), null);
ListBuffer<JCStatement> stmts = kInfo.deserializeCases.get(implMethodName);
if (stmts == null) {
stmts = new ListBuffer<>();
kInfo.deserializeCases.put(implMethodName, stmts);
}
/**
**
* System.err.printf("+++++++++++++++++\n");
* System.err.printf("*functionalInterfaceClass: '%s'\n", functionalInterfaceClass);
* System.err.printf("*functionalInterfaceMethodName: '%s'\n", functionalInterfaceMethodName);
* System.err.printf("*functionalInterfaceMethodSignature: '%s'\n", functionalInterfaceMethodSignature);
* System.err.printf("*implMethodKind: %d\n", implMethodKind);
* System.err.printf("*implClass: '%s'\n", implClass);
* System.err.printf("*implMethodName: '%s'\n", implMethodName);
* System.err.printf("*implMethodSignature: '%s'\n", implMethodSignature);
***
*/
stmts.append(stmt);
}
use of org.eclipse.ceylon.langtools.tools.javac.code.Type.MethodType in project ceylon by eclipse.
the class CeylonModelLoader method isFunctionalInterfaceType.
@Override
protected boolean isFunctionalInterfaceType(TypeMirror typeMirror) {
if (typeMirror.getKind() != TypeKind.DECLARED)
return false;
// FIXME: possibly apply other optimisations to lighten the lookup cost? see what javac does
Type type = ((JavacType) typeMirror).type;
try {
Type descriptorType = types.findDescriptorType(type);
// Let's be honest I've no idea what this means, but it happens and Javac seems to refuse it too
if (descriptorType.hasTag(TypeTag.FORALL))
return false;
MethodType methodDescriptorType = (MethodType) descriptorType;
MethodSymbol methodSymbol = (MethodSymbol) types.findDescriptorSymbol(type.tsym);
// make sure we can load them
methodDescriptorType.complete();
methodSymbol.complete();
return true;
} catch (Symbol.CompletionFailure err) {
// bad luck
return false;
} catch (FunctionDescriptorLookupError err) {
return false;
}
}
Aggregations