first "OK" closure test.

This commit is contained in:
Maxim Shafirov
2011-06-22 18:46:56 +04:00
parent 760b643df9
commit 3619e411a7
23 changed files with 482 additions and 46 deletions
-3
View File
@@ -1,8 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DependencyValidationManager">
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</component>
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
@@ -19,14 +19,16 @@ public abstract class ClassBodyCodegen {
protected final BindingContext bindingContext;
protected final JetStandardLibrary stdlib;
protected final JetTypeMapper typeMapper;
protected final Codegens factory;
protected final JetClassOrObject myClass;
protected final OwnerKind kind;
protected final ClassDescriptor descriptor;
protected final ClassVisitor v;
public ClassBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass, OwnerKind kind, ClassVisitor v) {
public ClassBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass, OwnerKind kind, ClassVisitor v, Codegens factory) {
this.bindingContext = bindingContext;
this.stdlib = stdlib;
this.factory = factory;
this.typeMapper = new JetTypeMapper(stdlib, bindingContext);
descriptor = bindingContext.getClassDescriptor(aClass);
myClass = aClass;
@@ -50,7 +52,7 @@ public abstract class ClassBodyCodegen {
}
private void generateClassBody() {
final FunctionCodegen functionCodegen = new FunctionCodegen((JetDeclaration) myClass, v, stdlib, bindingContext);
final FunctionCodegen functionCodegen = new FunctionCodegen((JetDeclaration) myClass, v, stdlib, bindingContext, factory);
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, stdlib, bindingContext, functionCodegen);
for (JetDeclaration declaration : myClass.getDeclarations()) {
@@ -45,7 +45,7 @@ public class ClassCodegen {
private void generateInterface(JetClassOrObject aClass) {
final ClassVisitor visitor = factory.forClassInterface(bindingContext.getClassDescriptor(aClass));
new InterfaceBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, visitor).generate();
new InterfaceBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, visitor, factory).generate();
}
private void generateImplementation(JetClassOrObject aClass, OwnerKind kind) {
@@ -53,7 +53,7 @@ public class ClassCodegen {
ClassVisitor v = kind == OwnerKind.IMPLEMENTATION
? factory.forClassImplementation(descriptor)
: factory.forClassDelegatingImplementation(descriptor);
new ImplementationBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, kind, v).generate();
new ImplementationBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, kind, v, factory).generate();
}
@@ -0,0 +1,164 @@
/*
* @author max
*/
package org.jetbrains.jet.codegen;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.lang.types.JetType;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import org.objectweb.asm.commons.Method;
import org.objectweb.asm.signature.SignatureWriter;
import java.util.Arrays;
import java.util.List;
public class ClosureCodegen {
private final BindingContext bindingContext;
private final JetTypeMapper typeMapper;
private final Codegens factory;
public ClosureCodegen(BindingContext bindingContext, JetTypeMapper typeMapper, Codegens factory) {
this.bindingContext = bindingContext;
this.typeMapper = typeMapper;
this.factory = factory;
}
public static Method erasedInvokeSignature(FunctionDescriptor fd) {
boolean isExtensionFunction = fd.getReceiverType() != null;
int paramCount = fd.getUnsubstitutedValueParameters().size();
if (isExtensionFunction) {
paramCount++;
}
Type[] args = new Type[paramCount];
Arrays.fill(args, JetTypeMapper.TYPE_OBJECT);
return new Method("invoke", JetTypeMapper.TYPE_OBJECT, args);
}
public Method invokeSignature(FunctionDescriptor fd) {
return typeMapper.mapSignature("invoke", fd);
}
public GeneratedClosureDescriptor gen(JetFunctionLiteralExpression fun) {
JetNamedDeclaration container = PsiTreeUtil.getParentOfType(fun, JetNamespace.class, JetClass.class, JetObjectDeclaration.class);
final Pair<String, ClassVisitor> nameAndVisitor;
if (container instanceof JetNamespace) {
nameAndVisitor = factory.forClosureIn((JetNamespace) container);
}
else {
nameAndVisitor = factory.forClosureIn(bindingContext.getClassDescriptor((JetClassOrObject) container));
}
final FunctionDescriptor funDescriptor = (FunctionDescriptor) bindingContext.getDeclarationDescriptor(fun);
final ClassVisitor cv = nameAndVisitor.getSecond();
final String name = nameAndVisitor.getFirst();
SignatureWriter signatureWriter = new SignatureWriter();
final List<ValueParameterDescriptor> parameters = funDescriptor.getUnsubstitutedValueParameters();
final String funClass = getInternalClassName(funDescriptor);
signatureWriter.visitClassType(funClass);
for (ValueParameterDescriptor parameter : parameters) {
appendType(signatureWriter, parameter.getOutType(), '=');
}
appendType(signatureWriter, funDescriptor.getUnsubstitutedReturnType(), '=');
signatureWriter.visitEnd();
cv.visit(Opcodes.V1_6,
Opcodes.ACC_PUBLIC,
name,
null,
funClass,
new String[0]
);
final Method constructor = generateConstructor(cv, funClass);
generateBridge(name, funDescriptor, cv);
generateBody(name, funDescriptor, cv, container.getProject(), fun.getBody());
cv.visitEnd();
return new GeneratedClosureDescriptor(name, constructor);
}
private void generateBody(String className, FunctionDescriptor funDescriptor, ClassVisitor cv, Project project, List<JetElement> body) {
FunctionCodegen fc = new FunctionCodegen(null, cv, JetStandardLibrary.getJetStandardLibrary(project), bindingContext, factory);
fc.generatedMethod(body, OwnerKind.IMPLEMENTATION, invokeSignature(funDescriptor), null, funDescriptor.getUnsubstitutedValueParameters(), null);
}
private void generateBridge(String className, FunctionDescriptor funDescriptor, ClassVisitor cv) {
final Method bridge = erasedInvokeSignature(funDescriptor);
final MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "invoke", bridge.getDescriptor(), typeMapper.genericSignature(funDescriptor), new String[0]);
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, Type.getObjectType(className));
final List<ValueParameterDescriptor> params = funDescriptor.getUnsubstitutedValueParameters();
int count = 1;
for (ValueParameterDescriptor param : params) {
iv.load(count, JetTypeMapper.TYPE_OBJECT);
iv.checkcast(typeMapper.mapType(param.getOutType()));
count++;
}
iv.invokespecial(className, "invoke", invokeSignature(funDescriptor).getDescriptor());
iv.areturn(JetTypeMapper.TYPE_OBJECT);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
private Method generateConstructor(ClassVisitor cv, String funClass) {
final Method constructor = new Method("<init>", Type.VOID_TYPE, new Type[0]); // TODO:
final MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "<init>", constructor.getDescriptor(), null, new String[0]);
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
iv.load(0, Type.getObjectType(funClass));
iv.invokespecial(funClass, "<init>", "()V");
iv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
return constructor;
}
public static String getInternalClassName(FunctionDescriptor descriptor) {
final int paramCount = descriptor.getUnsubstitutedValueParameters().size();
if (descriptor.getReceiverType() != null) {
return "jet/ExtensionFunction" + paramCount;
}
else {
return "jet/Function" + paramCount;
}
}
private void appendType(SignatureWriter signatureWriter, JetType type, char variance) {
signatureWriter.visitTypeArgument(variance);
final Type rawRetType = typeMapper.boxType(typeMapper.mapType(type));
signatureWriter.visitClassType(rawRetType.getInternalName());
signatureWriter.visitEnd();
}
}
@@ -1,6 +1,7 @@
package org.jetbrains.jet.codegen;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.JetNamespace;
import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -20,6 +21,7 @@ public class Codegens {
private final boolean isText;
private final Map<String, NamespaceCodegen> ns2codegen = new HashMap<String, NamespaceCodegen>();
private final Map<String, ClassVisitor> generators = new LinkedHashMap<String, ClassVisitor>();
private final Map<String, Integer> closuresCount = new HashMap<String, Integer>();
private boolean isDone = false;
public Codegens(Project project, boolean text) {
@@ -56,6 +58,24 @@ public class Codegens {
return newVisitor(JetTypeMapper.jvmNameForDelegatingImplementation(aClass) + ".class");
}
public Pair<String, ClassVisitor> forClosureIn(ClassDescriptor aClass) {
return forClosureIn(JetTypeMapper.jvmNameForInterface(aClass));
}
public Pair<String, ClassVisitor> forClosureIn(JetNamespace namespace) {
return forClosureIn(NamespaceCodegen.getJVMClassName(namespace.getFQName()));
}
private Pair<String, ClassVisitor> forClosureIn(String baseName) {
Integer count = closuresCount.get(baseName);
if (count == null) count = 0;
closuresCount.put(baseName, count + 1);
final String className = baseName + "$" + (count + 1);
return new Pair<String, ClassVisitor>(className, newVisitor(className + ".class"));
}
public NamespaceCodegen forNamespace(JetNamespace namespace) {
assert !isDone : "Already done!";
String fqName = namespace.getFQName();
@@ -12,10 +12,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.resolve.DescriptorRenderer;
import org.objectweb.asm.Label;
@@ -64,6 +61,7 @@ public class ExpressionCodegen extends JetVisitor {
private final InstructionAdapter v;
private final FrameMap myMap;
private final JetTypeMapper typeMapper;
private final Codegens factory;
private final Type returnType;
private final DeclarationDescriptor contextType;
private final OwnerKind contextKind;
@@ -78,12 +76,14 @@ public class ExpressionCodegen extends JetVisitor {
Type returnType,
DeclarationDescriptor contextType,
OwnerKind contextKind,
@Nullable StackValue thisExpression) {
@Nullable StackValue thisExpression,
Codegens factory) {
this.myMap = myMap;
this.typeMapper = typeMapper;
this.returnType = returnType;
this.contextType = contextType;
this.contextKind = contextKind;
this.factory = factory;
this.v = new InstructionAdapter(v);
this.bindingContext = bindingContext;
this.thisExpression = thisExpression;
@@ -481,7 +481,10 @@ public class ExpressionCodegen extends JetVisitor {
generateBlock(expression.getBody());
}
else {
throw new UnsupportedOperationException("don't know how to generate non-block function literals");
final GeneratedClosureDescriptor closure = new ClosureCodegen(bindingContext, typeMapper, factory).gen(expression);
v.anew(Type.getObjectType(closure.getClassname()));
v.dup();
v.invokespecial(closure.getClassname(), "<init>", closure.getConstructor().getDescriptor());
}
}
@@ -543,7 +546,12 @@ public class ExpressionCodegen extends JetVisitor {
@Override
public void visitSimpleNameExpression(JetSimpleNameExpression expression) {
final DeclarationDescriptor descriptor = bindingContext.resolveReferenceExpression(expression);
DeclarationDescriptor descriptor = bindingContext.resolveReferenceExpression(expression);
if (descriptor instanceof VariableAsFunctionDescriptor) {
descriptor = ((VariableAsFunctionDescriptor) descriptor).getVariableDescriptor();
}
final DeclarationDescriptor container = descriptor.getContainingDeclaration();
if (descriptor instanceof VariableDescriptor) {
if (isClass(container, "Number")) {
@@ -702,13 +710,14 @@ public class ExpressionCodegen extends JetVisitor {
PsiElement declarationPsiElement = bindingContext.getDeclarationPsiElement(funDescriptor);
final FunctionDescriptor fd = (FunctionDescriptor) funDescriptor;
if (declarationPsiElement == null && isClass(functionParent, "String")) {
final Project project = expression.getProject();
PsiClass jlString = JavaPsiFacade.getInstance(project).findClass("java.lang.String",
ProjectScope.getAllScope(project));
// TODO better overload mapping
final PsiMethod[] methods = jlString.findMethodsByName(funDescriptor.getName(), false);
final int arity = ((FunctionDescriptor) funDescriptor).getUnsubstitutedValueParameters().size();
final int arity = fd.getUnsubstitutedValueParameters().size();
for (PsiMethod method : methods) {
if (method.getParameterList().getParametersCount() == arity) {
declarationPsiElement = method;
@@ -744,7 +753,7 @@ public class ExpressionCodegen extends JetVisitor {
methodDescriptor.getName(),
methodDescriptor.getDescriptor());
}
else {
else if(declarationPsiElement instanceof JetFunction) {
final JetFunction jetFunction = (JetFunction) declarationPsiElement;
methodDescriptor = typeMapper.mapSignature(jetFunction);
if (functionParent instanceof NamespaceDescriptorImpl) {
@@ -765,8 +774,25 @@ public class ExpressionCodegen extends JetVisitor {
throw new UnsupportedOperationException("don't know how to generate call to " + declarationPsiElement);
}
}
else {
gen(callee, Type.getObjectType(ClosureCodegen.getInternalClassName(fd)));
boolean isExtensionFunction = fd.getReceiverType() != null;
int paramCount = fd.getUnsubstitutedValueParameters().size();
if (isExtensionFunction) {
ensureReceiverOnStack(expression, null);
paramCount++;
}
methodDescriptor = ClosureCodegen.erasedInvokeSignature(fd);
pushMethodArguments(expression, methodDescriptor);
v.invokevirtual(ClosureCodegen.getInternalClassName(fd), "invoke", methodDescriptor.getDescriptor());
}
if (methodDescriptor.getReturnType() != Type.VOID_TYPE) {
myStack.push(StackValue.onStack(methodDescriptor.getReturnType()));
final Type retType = typeMapper.mapType(fd.getUnsubstitutedReturnType());
StackValue.onStack(methodDescriptor.getReturnType()).put(retType, v);
myStack.push(StackValue.onStack(retType));
}
}
else {
@@ -14,6 +14,7 @@ import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import org.objectweb.asm.commons.Method;
import java.util.Collections;
import java.util.List;
/**
@@ -24,11 +25,13 @@ public class FunctionCodegen {
private final ClassVisitor v;
private final BindingContext bindingContext;
private final JetTypeMapper typeMapper;
private final Codegens factory;
public FunctionCodegen(JetDeclaration owner, ClassVisitor v, JetStandardLibrary standardLibrary, BindingContext bindingContext) {
public FunctionCodegen(JetDeclaration owner, ClassVisitor v, JetStandardLibrary standardLibrary, BindingContext bindingContext, Codegens factory) {
this.owner = owner;
this.v = v;
this.bindingContext = bindingContext;
this.factory = factory;
typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
}
@@ -45,23 +48,33 @@ public class FunctionCodegen {
Method jvmSignature,
@Nullable JetType receiverType,
List<ValueParameterDescriptor> paramDescrs) {
final DeclarationDescriptor contextDesc = owner instanceof JetClassOrObject
? bindingContext.getClassDescriptor((JetClassOrObject) owner)
: bindingContext.getNamespaceDescriptor((JetNamespace) owner);
final JetExpression bodyExpression = f.getBodyExpression();
final List<JetElement> bodyExpressions = bodyExpression != null ? Collections.<JetElement>singletonList(bodyExpression) : null;
generatedMethod(bodyExpressions, kind, jvmSignature, receiverType, paramDescrs, contextDesc);
}
public void generatedMethod(List<JetElement> bodyExpressions,
OwnerKind kind,
Method jvmSignature,
JetType receiverType,
List<ValueParameterDescriptor> paramDescrs,
DeclarationDescriptor contextDesc)
{
int flags = Opcodes.ACC_PUBLIC; // TODO.
boolean isStatic = kind == OwnerKind.NAMESPACE;
if (isStatic) flags |= Opcodes.ACC_STATIC;
final JetExpression bodyExpression = f.getBodyExpression();
boolean isAbstract = kind == OwnerKind.INTERFACE || bodyExpression == null;
boolean isAbstract = kind == OwnerKind.INTERFACE || bodyExpressions == null;
if (isAbstract) flags |= Opcodes.ACC_ABSTRACT;
if (isAbstract && (kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.DELEGATING_IMPLEMENTATION)) {
return;
}
DeclarationDescriptor contextDescriptor = owner instanceof JetClassOrObject
? bindingContext.getClassDescriptor((JetClassOrObject) owner)
: bindingContext.getNamespaceDescriptor((JetNamespace) owner);
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
if (kind != OwnerKind.INTERFACE) {
mv.visitCode();
@@ -79,7 +92,7 @@ public class FunctionCodegen {
StackValue thisExpression = receiverType == null ? null : StackValue.local(0, typeMapper.mapType(receiverType));
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper,
jvmSignature.getReturnType(), contextDescriptor, kind, thisExpression);
jvmSignature.getReturnType(), contextDesc, kind, thisExpression, factory);
if (kind instanceof OwnerKind.DelegateKind) {
OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind;
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -93,15 +106,19 @@ public class FunctionCodegen {
iv.areturn(jvmSignature.getReturnType());
}
else if (!isAbstract) {
bodyExpression.accept(codegen);
generateReturn(mv, bodyExpression, codegen, jvmSignature);
JetElement last = null;
for (JetElement expression : bodyExpressions) {
expression.accept(codegen);
last = expression;
}
generateReturn(mv, last, codegen, jvmSignature);
}
mv.visitMaxs(0, 0);
mv.visitEnd();
}
}
private void generateReturn(MethodVisitor mv, JetExpression bodyExpression, ExpressionCodegen codegen, Method jvmSignature) {
private void generateReturn(MethodVisitor mv, JetElement bodyExpression, ExpressionCodegen codegen, Method jvmSignature) {
if (!endsWithReturn(bodyExpression)) {
if (jvmSignature.getReturnType() == Type.VOID_TYPE) {
mv.visitInsn(Opcodes.RETURN);
@@ -112,11 +129,12 @@ public class FunctionCodegen {
}
}
private static boolean endsWithReturn(JetExpression bodyExpression) {
private static boolean endsWithReturn(JetElement bodyExpression) {
if (bodyExpression instanceof JetBlockExpression) {
final List<JetElement> statements = ((JetBlockExpression) bodyExpression).getStatements();
return statements.size() > 0 && statements.get(statements.size()-1) instanceof JetReturnExpression;
}
return false;
return bodyExpression instanceof JetReturnExpression;
}
}
@@ -0,0 +1,24 @@
/*
* @author max
*/
package org.jetbrains.jet.codegen;
import org.objectweb.asm.commons.Method;
public class GeneratedClosureDescriptor {
private final String classname;
private Method constructor;
public GeneratedClosureDescriptor(String classname, Method constructor) {
this.classname = classname;
this.constructor = constructor;
}
public String getClassname() {
return classname;
}
public Method getConstructor() {
return constructor;
}
}
@@ -22,8 +22,8 @@ import java.util.*;
*/
public class ImplementationBodyCodegen extends ClassBodyCodegen {
public ImplementationBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass,
OwnerKind kind, ClassVisitor v) {
super(bindingContext, stdlib, aClass, kind, v);
OwnerKind kind, ClassVisitor v, Codegens factory) {
super(bindingContext, stdlib, aClass, kind, v, factory);
}
@Override
@@ -109,7 +109,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final InstructionAdapter iv = new InstructionAdapter(mv);
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, Type.VOID_TYPE,
descriptor, kind, StackValue.local(0, typeMapper.jvmType(descriptor, kind)));
descriptor, kind, StackValue.local(0, typeMapper.jvmType(descriptor, kind)), factory);
String classname = typeMapper.jvmName(descriptor, kind);
final Type classType = Type.getType("L" + classname + ";");
@@ -289,7 +289,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final InstructionAdapter iv = new InstructionAdapter(mv);
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, Type.VOID_TYPE,
descriptor, kind, StackValue.local(0, typeMapper.jvmType(descriptor, kind)));
descriptor, kind, StackValue.local(0, typeMapper.jvmType(descriptor, kind)), factory);
for (JetDelegationSpecifier initializer : constructor.getInitializers()) {
if (initializer instanceof JetDelegatorToThisCall) {
@@ -355,7 +355,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
protected void generateDelegates(JetClassOrObject inClass, JetClass toClass, OwnerKind kind, Set<FunctionDescriptor> overriden) {
final FunctionCodegen functionCodegen = new FunctionCodegen(toClass, v, stdlib, bindingContext);
final FunctionCodegen functionCodegen = new FunctionCodegen(toClass, v, stdlib, bindingContext, factory);
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, stdlib, bindingContext, functionCodegen);
for (JetDeclaration declaration : toClass.getDeclarations()) {
@@ -19,8 +19,8 @@ import java.util.Set;
* @author yole
*/
public class InterfaceBodyCodegen extends ClassBodyCodegen {
public InterfaceBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass, ClassVisitor v) {
super(bindingContext, stdlib, aClass, OwnerKind.INTERFACE, v);
public InterfaceBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass, ClassVisitor v, Codegens factory) {
super(bindingContext, stdlib, aClass, OwnerKind.INTERFACE, v, factory);
}
protected void generateDeclaration() {
@@ -219,6 +219,38 @@ public class JetTypeMapper {
throw new UnsupportedOperationException("Unknown type " + jetType);
}
public Type boxType(Type asmType) {
switch (asmType.getSort()) {
case Type.VOID:
return Type.getObjectType("java/lang/Void");
case Type.BYTE:
return Type.getObjectType("java/lang/Byte");
case Type.BOOLEAN:
return Type.getObjectType("java/lang/Boolean");
case Type.SHORT:
return Type.getObjectType("java/lang.Short");
case Type.CHAR:
return Type.getObjectType("java/lang/Character");
case Type.INT:
return Type.getObjectType("java/lang/Integer");
case Type.FLOAT:
return Type.getObjectType("java/lang/Float");
case Type.LONG:
return Type.getObjectType("java/lang/Long");
case Type.DOUBLE:
return Type.getObjectType("java/lang/Double");
}
return asmType;
}
private static Type getBoxedType(final Type type) {
switch (type.getSort()) {
}
return type;
}
public Method mapSignature(JetFunction f) {
final JetTypeReference receiverTypeRef = f.getReceiverTypeRef();
final JetType receiverType = receiverTypeRef == null ? null : bindingContext.resolveTypeReference(receiverTypeRef);
@@ -243,6 +275,50 @@ public class JetTypeMapper {
return new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
}
public Method mapSignature(String name, FunctionDescriptor f) {
final JetType receiverType = f.getReceiverType();
final List<ValueParameterDescriptor> parameters = f.getUnsubstitutedValueParameters();
List<Type> parameterTypes = new ArrayList<Type>();
if (receiverType != null) {
parameterTypes.add(mapType(receiverType));
}
for (ValueParameterDescriptor parameter : parameters) {
parameterTypes.add(mapType(parameter.getOutType()));
}
Type returnType = mapType(f.getUnsubstitutedReturnType());
return new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
}
public String genericSignature(FunctionDescriptor f) {
StringBuffer answer = new StringBuffer();
final List<TypeParameterDescriptor> typeParameters = f.getTypeParameters();
if (!typeParameters.isEmpty()) {
answer.append('<');
for (TypeParameterDescriptor p : typeParameters) {
appendTypeParameterSignature(answer, p);
}
answer.append('>');
}
answer.append('(');
for (ValueParameterDescriptor p : f.getUnsubstitutedValueParameters()) {
appendType(answer, p.getOutType());
}
answer.append(')');
appendType(answer, f.getUnsubstitutedReturnType());
return answer.toString();
}
private void appendType(StringBuffer answer, JetType type) {
answer.append(mapType(type).getDescriptor()); // TODO: type parameter references!
}
private void appendTypeParameterSignature(StringBuffer answer, TypeParameterDescriptor p) {
answer.append(p.getName()); // TODO: BOUND!
}
public Method mapGetterSignature(PropertyDescriptor descriptor) {
Type returnType = mapType(descriptor.getOutType());
return new Method(PropertyCodegen.getterName(descriptor.getName()), returnType, new Type[0]);
@@ -45,7 +45,7 @@ public class NamespaceCodegen {
AnalyzingUtils.applyHandler(ErrorHandler.THROW_EXCEPTION, bindingContext);
final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
final FunctionCodegen functionCodegen = new FunctionCodegen(namespace, v, standardLibrary, bindingContext);
final FunctionCodegen functionCodegen = new FunctionCodegen(namespace, v, standardLibrary, bindingContext, codegens);
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, standardLibrary, bindingContext, functionCodegen);
final ClassCodegen classCodegen = codegens.forClass(bindingContext);
@@ -81,7 +81,7 @@ public class NamespaceCodegen {
FrameMap frameMap = new FrameMap();
JetTypeMapper typeMapper = new JetTypeMapper(JetStandardLibrary.getJetStandardLibrary(namespace.getProject()), bindingContext);
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, Type.VOID_TYPE, null, OwnerKind.NAMESPACE, null);
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, Type.VOID_TYPE, null, OwnerKind.NAMESPACE, null, codegens);
for (JetDeclaration declaration : namespace.getDeclarations()) {
if (declaration instanceof JetProperty) {
@@ -131,13 +131,18 @@ public abstract class StackValue {
}
protected void coerce(Type type, InstructionAdapter v) {
if (type.getSort() == Type.OBJECT) {
if (type.equals(this.type)) return;
if (type.getSort() == Type.OBJECT && this.type.getSort() == Type.OBJECT) {
v.checkcast(type);
}
else if (type.getSort() == Type.OBJECT) {
box(this.type, type, v);
}
else if (this.type.getSort() == Type.OBJECT && type.getSort() <= Type.DOUBLE) {
unbox(type, v);
}
else if (type != this.type) {
else {
v.cast(this.type, type);
}
}
@@ -1,7 +1,7 @@
fun box() : String {
return if (invoker({49}) == 49) "OK" else "fail"
return invoker( {"OK"} )
}
fun invoker(gen : {() : Int}) : Int {
fun invoker(gen : {() : String}) : String {
return gen()
}
}
@@ -71,9 +71,9 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
} catch (NoClassDefFoundError e) {
System.out.println(generateToText());
throw e;
} catch (Exception e) {
} catch (Throwable e) {
System.out.println(generateToText());
throw e;
throw new RuntimeException(e);
}
assertEquals("OK", actual);
}
+13
View File
@@ -0,0 +1,13 @@
/*
* @author max
*/
package jet;
public abstract class ExtensionFunction0<E, R> {
public abstract R invoke(E receiver);
@Override
public String toString() {
return "{E.() : R}";
}
}
+13
View File
@@ -0,0 +1,13 @@
/*
* @author max
*/
package jet;
public abstract class ExtensionFunction1<E, D, R> {
public abstract R invoke(E receiver, D d);
@Override
public String toString() {
return "{E.(d: D) : R}";
}
}
+13
View File
@@ -0,0 +1,13 @@
/*
* @author max
*/
package jet;
public abstract class ExtensionFunction2<E, D1, D2, R> {
public abstract R invoke(E receiver, D1 d1, D2 d2);
@Override
public String toString() {
return "{E.(d1: D1, d2: D2) : R}";
}
}
+13
View File
@@ -0,0 +1,13 @@
/*
* @author max
*/
package jet;
public abstract class ExtensionFunction3<E, D1, D2, D3, R> {
public abstract R invoke(E receiver, D1 d1, D2 d2, D3 d3);
@Override
public String toString() {
return "{E.(d1: D1, d2: D2, d3: D3) : R}";
}
}
+13
View File
@@ -0,0 +1,13 @@
/*
* @author max
*/
package jet;
public abstract class Function0<R> {
public abstract R invoke();
@Override
public String toString() {
return "{() : R}";
}
}
+13
View File
@@ -0,0 +1,13 @@
/*
* @author max
*/
package jet;
public abstract class Function1<D, R> {
public abstract R invoke(D d);
@Override
public String toString() {
return "{(d: D) : R}";
}
}
+13
View File
@@ -0,0 +1,13 @@
/*
* @author max
*/
package jet;
public abstract class Function2<D1, D2, R> {
public abstract R invoke(D1 d1, D2 d2);
@Override
public String toString() {
return "{(d1: D1, d2: D2) : R}";
}
}
+13
View File
@@ -0,0 +1,13 @@
/*
* @author max
*/
package jet;
public abstract class Function3<D1, D2, D3, R> {
public abstract R invoke(D1 d1, D2 d2, D3 d3);
@Override
public String toString() {
return "{(d1: D1, d2: D2, d3: D3) : R}";
}
}