first "OK" closure test.
This commit is contained in:
Generated
-3
@@ -1,8 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="DependencyValidationManager">
|
|
||||||
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
|
|
||||||
</component>
|
|
||||||
<component name="EntryPointsManager">
|
<component name="EntryPointsManager">
|
||||||
<entry_points version="2.0" />
|
<entry_points version="2.0" />
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
@@ -19,14 +19,16 @@ public abstract class ClassBodyCodegen {
|
|||||||
protected final BindingContext bindingContext;
|
protected final BindingContext bindingContext;
|
||||||
protected final JetStandardLibrary stdlib;
|
protected final JetStandardLibrary stdlib;
|
||||||
protected final JetTypeMapper typeMapper;
|
protected final JetTypeMapper typeMapper;
|
||||||
|
protected final Codegens factory;
|
||||||
protected final JetClassOrObject myClass;
|
protected final JetClassOrObject myClass;
|
||||||
protected final OwnerKind kind;
|
protected final OwnerKind kind;
|
||||||
protected final ClassDescriptor descriptor;
|
protected final ClassDescriptor descriptor;
|
||||||
protected final ClassVisitor v;
|
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.bindingContext = bindingContext;
|
||||||
this.stdlib = stdlib;
|
this.stdlib = stdlib;
|
||||||
|
this.factory = factory;
|
||||||
this.typeMapper = new JetTypeMapper(stdlib, bindingContext);
|
this.typeMapper = new JetTypeMapper(stdlib, bindingContext);
|
||||||
descriptor = bindingContext.getClassDescriptor(aClass);
|
descriptor = bindingContext.getClassDescriptor(aClass);
|
||||||
myClass = aClass;
|
myClass = aClass;
|
||||||
@@ -50,7 +52,7 @@ public abstract class ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateClassBody() {
|
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);
|
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, stdlib, bindingContext, functionCodegen);
|
||||||
|
|
||||||
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class ClassCodegen {
|
|||||||
|
|
||||||
private void generateInterface(JetClassOrObject aClass) {
|
private void generateInterface(JetClassOrObject aClass) {
|
||||||
final ClassVisitor visitor = factory.forClassInterface(bindingContext.getClassDescriptor(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) {
|
private void generateImplementation(JetClassOrObject aClass, OwnerKind kind) {
|
||||||
@@ -53,7 +53,7 @@ public class ClassCodegen {
|
|||||||
ClassVisitor v = kind == OwnerKind.IMPLEMENTATION
|
ClassVisitor v = kind == OwnerKind.IMPLEMENTATION
|
||||||
? factory.forClassImplementation(descriptor)
|
? factory.forClassImplementation(descriptor)
|
||||||
: factory.forClassDelegatingImplementation(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;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.util.Pair;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetNamespace;
|
import org.jetbrains.jet.lang.psi.JetNamespace;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
@@ -20,6 +21,7 @@ public class Codegens {
|
|||||||
private final boolean isText;
|
private final boolean isText;
|
||||||
private final Map<String, NamespaceCodegen> ns2codegen = new HashMap<String, NamespaceCodegen>();
|
private final Map<String, NamespaceCodegen> ns2codegen = new HashMap<String, NamespaceCodegen>();
|
||||||
private final Map<String, ClassVisitor> generators = new LinkedHashMap<String, ClassVisitor>();
|
private final Map<String, ClassVisitor> generators = new LinkedHashMap<String, ClassVisitor>();
|
||||||
|
private final Map<String, Integer> closuresCount = new HashMap<String, Integer>();
|
||||||
private boolean isDone = false;
|
private boolean isDone = false;
|
||||||
|
|
||||||
public Codegens(Project project, boolean text) {
|
public Codegens(Project project, boolean text) {
|
||||||
@@ -56,6 +58,24 @@ public class Codegens {
|
|||||||
return newVisitor(JetTypeMapper.jvmNameForDelegatingImplementation(aClass) + ".class");
|
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) {
|
public NamespaceCodegen forNamespace(JetNamespace namespace) {
|
||||||
assert !isDone : "Already done!";
|
assert !isDone : "Already done!";
|
||||||
String fqName = namespace.getFQName();
|
String fqName = namespace.getFQName();
|
||||||
|
|||||||
@@ -12,10 +12,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
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.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||||
import org.objectweb.asm.Label;
|
import org.objectweb.asm.Label;
|
||||||
@@ -64,6 +61,7 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
private final InstructionAdapter v;
|
private final InstructionAdapter v;
|
||||||
private final FrameMap myMap;
|
private final FrameMap myMap;
|
||||||
private final JetTypeMapper typeMapper;
|
private final JetTypeMapper typeMapper;
|
||||||
|
private final Codegens factory;
|
||||||
private final Type returnType;
|
private final Type returnType;
|
||||||
private final DeclarationDescriptor contextType;
|
private final DeclarationDescriptor contextType;
|
||||||
private final OwnerKind contextKind;
|
private final OwnerKind contextKind;
|
||||||
@@ -78,12 +76,14 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
Type returnType,
|
Type returnType,
|
||||||
DeclarationDescriptor contextType,
|
DeclarationDescriptor contextType,
|
||||||
OwnerKind contextKind,
|
OwnerKind contextKind,
|
||||||
@Nullable StackValue thisExpression) {
|
@Nullable StackValue thisExpression,
|
||||||
|
Codegens factory) {
|
||||||
this.myMap = myMap;
|
this.myMap = myMap;
|
||||||
this.typeMapper = typeMapper;
|
this.typeMapper = typeMapper;
|
||||||
this.returnType = returnType;
|
this.returnType = returnType;
|
||||||
this.contextType = contextType;
|
this.contextType = contextType;
|
||||||
this.contextKind = contextKind;
|
this.contextKind = contextKind;
|
||||||
|
this.factory = factory;
|
||||||
this.v = new InstructionAdapter(v);
|
this.v = new InstructionAdapter(v);
|
||||||
this.bindingContext = bindingContext;
|
this.bindingContext = bindingContext;
|
||||||
this.thisExpression = thisExpression;
|
this.thisExpression = thisExpression;
|
||||||
@@ -481,7 +481,10 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
generateBlock(expression.getBody());
|
generateBlock(expression.getBody());
|
||||||
}
|
}
|
||||||
else {
|
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
|
@Override
|
||||||
public void visitSimpleNameExpression(JetSimpleNameExpression expression) {
|
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();
|
final DeclarationDescriptor container = descriptor.getContainingDeclaration();
|
||||||
if (descriptor instanceof VariableDescriptor) {
|
if (descriptor instanceof VariableDescriptor) {
|
||||||
if (isClass(container, "Number")) {
|
if (isClass(container, "Number")) {
|
||||||
@@ -702,13 +710,14 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
|
|
||||||
|
|
||||||
PsiElement declarationPsiElement = bindingContext.getDeclarationPsiElement(funDescriptor);
|
PsiElement declarationPsiElement = bindingContext.getDeclarationPsiElement(funDescriptor);
|
||||||
|
final FunctionDescriptor fd = (FunctionDescriptor) funDescriptor;
|
||||||
if (declarationPsiElement == null && isClass(functionParent, "String")) {
|
if (declarationPsiElement == null && isClass(functionParent, "String")) {
|
||||||
final Project project = expression.getProject();
|
final Project project = expression.getProject();
|
||||||
PsiClass jlString = JavaPsiFacade.getInstance(project).findClass("java.lang.String",
|
PsiClass jlString = JavaPsiFacade.getInstance(project).findClass("java.lang.String",
|
||||||
ProjectScope.getAllScope(project));
|
ProjectScope.getAllScope(project));
|
||||||
// TODO better overload mapping
|
// TODO better overload mapping
|
||||||
final PsiMethod[] methods = jlString.findMethodsByName(funDescriptor.getName(), false);
|
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) {
|
for (PsiMethod method : methods) {
|
||||||
if (method.getParameterList().getParametersCount() == arity) {
|
if (method.getParameterList().getParametersCount() == arity) {
|
||||||
declarationPsiElement = method;
|
declarationPsiElement = method;
|
||||||
@@ -744,7 +753,7 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
methodDescriptor.getName(),
|
methodDescriptor.getName(),
|
||||||
methodDescriptor.getDescriptor());
|
methodDescriptor.getDescriptor());
|
||||||
}
|
}
|
||||||
else {
|
else if(declarationPsiElement instanceof JetFunction) {
|
||||||
final JetFunction jetFunction = (JetFunction) declarationPsiElement;
|
final JetFunction jetFunction = (JetFunction) declarationPsiElement;
|
||||||
methodDescriptor = typeMapper.mapSignature(jetFunction);
|
methodDescriptor = typeMapper.mapSignature(jetFunction);
|
||||||
if (functionParent instanceof NamespaceDescriptorImpl) {
|
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);
|
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) {
|
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 {
|
else {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import org.objectweb.asm.Type;
|
|||||||
import org.objectweb.asm.commons.InstructionAdapter;
|
import org.objectweb.asm.commons.InstructionAdapter;
|
||||||
import org.objectweb.asm.commons.Method;
|
import org.objectweb.asm.commons.Method;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,11 +25,13 @@ public class FunctionCodegen {
|
|||||||
private final ClassVisitor v;
|
private final ClassVisitor v;
|
||||||
private final BindingContext bindingContext;
|
private final BindingContext bindingContext;
|
||||||
private final JetTypeMapper typeMapper;
|
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.owner = owner;
|
||||||
this.v = v;
|
this.v = v;
|
||||||
this.bindingContext = bindingContext;
|
this.bindingContext = bindingContext;
|
||||||
|
this.factory = factory;
|
||||||
typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
|
typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,23 +48,33 @@ public class FunctionCodegen {
|
|||||||
Method jvmSignature,
|
Method jvmSignature,
|
||||||
@Nullable JetType receiverType,
|
@Nullable JetType receiverType,
|
||||||
List<ValueParameterDescriptor> paramDescrs) {
|
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.
|
int flags = Opcodes.ACC_PUBLIC; // TODO.
|
||||||
|
|
||||||
boolean isStatic = kind == OwnerKind.NAMESPACE;
|
boolean isStatic = kind == OwnerKind.NAMESPACE;
|
||||||
if (isStatic) flags |= Opcodes.ACC_STATIC;
|
if (isStatic) flags |= Opcodes.ACC_STATIC;
|
||||||
|
|
||||||
final JetExpression bodyExpression = f.getBodyExpression();
|
boolean isAbstract = kind == OwnerKind.INTERFACE || bodyExpressions == null;
|
||||||
boolean isAbstract = kind == OwnerKind.INTERFACE || bodyExpression == null;
|
|
||||||
if (isAbstract) flags |= Opcodes.ACC_ABSTRACT;
|
if (isAbstract) flags |= Opcodes.ACC_ABSTRACT;
|
||||||
|
|
||||||
if (isAbstract && (kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.DELEGATING_IMPLEMENTATION)) {
|
if (isAbstract && (kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.DELEGATING_IMPLEMENTATION)) {
|
||||||
return;
|
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);
|
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
|
||||||
if (kind != OwnerKind.INTERFACE) {
|
if (kind != OwnerKind.INTERFACE) {
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
@@ -79,7 +92,7 @@ public class FunctionCodegen {
|
|||||||
|
|
||||||
StackValue thisExpression = receiverType == null ? null : StackValue.local(0, typeMapper.mapType(receiverType));
|
StackValue thisExpression = receiverType == null ? null : StackValue.local(0, typeMapper.mapType(receiverType));
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper,
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper,
|
||||||
jvmSignature.getReturnType(), contextDescriptor, kind, thisExpression);
|
jvmSignature.getReturnType(), contextDesc, kind, thisExpression, factory);
|
||||||
if (kind instanceof OwnerKind.DelegateKind) {
|
if (kind instanceof OwnerKind.DelegateKind) {
|
||||||
OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind;
|
OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind;
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
@@ -93,15 +106,19 @@ public class FunctionCodegen {
|
|||||||
iv.areturn(jvmSignature.getReturnType());
|
iv.areturn(jvmSignature.getReturnType());
|
||||||
}
|
}
|
||||||
else if (!isAbstract) {
|
else if (!isAbstract) {
|
||||||
bodyExpression.accept(codegen);
|
JetElement last = null;
|
||||||
generateReturn(mv, bodyExpression, codegen, jvmSignature);
|
for (JetElement expression : bodyExpressions) {
|
||||||
|
expression.accept(codegen);
|
||||||
|
last = expression;
|
||||||
|
}
|
||||||
|
generateReturn(mv, last, codegen, jvmSignature);
|
||||||
}
|
}
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
mv.visitEnd();
|
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 (!endsWithReturn(bodyExpression)) {
|
||||||
if (jvmSignature.getReturnType() == Type.VOID_TYPE) {
|
if (jvmSignature.getReturnType() == Type.VOID_TYPE) {
|
||||||
mv.visitInsn(Opcodes.RETURN);
|
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) {
|
if (bodyExpression instanceof JetBlockExpression) {
|
||||||
final List<JetElement> statements = ((JetBlockExpression) bodyExpression).getStatements();
|
final List<JetElement> statements = ((JetBlockExpression) bodyExpression).getStatements();
|
||||||
return statements.size() > 0 && statements.get(statements.size()-1) instanceof JetReturnExpression;
|
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 class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||||
public ImplementationBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass,
|
public ImplementationBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass,
|
||||||
OwnerKind kind, ClassVisitor v) {
|
OwnerKind kind, ClassVisitor v, Codegens factory) {
|
||||||
super(bindingContext, stdlib, aClass, kind, v);
|
super(bindingContext, stdlib, aClass, kind, v, factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -109,7 +109,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, Type.VOID_TYPE,
|
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);
|
String classname = typeMapper.jvmName(descriptor, kind);
|
||||||
final Type classType = Type.getType("L" + classname + ";");
|
final Type classType = Type.getType("L" + classname + ";");
|
||||||
@@ -289,7 +289,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, Type.VOID_TYPE,
|
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()) {
|
for (JetDelegationSpecifier initializer : constructor.getInitializers()) {
|
||||||
if (initializer instanceof JetDelegatorToThisCall) {
|
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) {
|
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);
|
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, stdlib, bindingContext, functionCodegen);
|
||||||
|
|
||||||
for (JetDeclaration declaration : toClass.getDeclarations()) {
|
for (JetDeclaration declaration : toClass.getDeclarations()) {
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ import java.util.Set;
|
|||||||
* @author yole
|
* @author yole
|
||||||
*/
|
*/
|
||||||
public class InterfaceBodyCodegen extends ClassBodyCodegen {
|
public class InterfaceBodyCodegen extends ClassBodyCodegen {
|
||||||
public InterfaceBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass, ClassVisitor v) {
|
public InterfaceBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass, ClassVisitor v, Codegens factory) {
|
||||||
super(bindingContext, stdlib, aClass, OwnerKind.INTERFACE, v);
|
super(bindingContext, stdlib, aClass, OwnerKind.INTERFACE, v, factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void generateDeclaration() {
|
protected void generateDeclaration() {
|
||||||
|
|||||||
@@ -219,6 +219,38 @@ public class JetTypeMapper {
|
|||||||
throw new UnsupportedOperationException("Unknown type " + jetType);
|
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) {
|
public Method mapSignature(JetFunction f) {
|
||||||
final JetTypeReference receiverTypeRef = f.getReceiverTypeRef();
|
final JetTypeReference receiverTypeRef = f.getReceiverTypeRef();
|
||||||
final JetType receiverType = receiverTypeRef == null ? null : bindingContext.resolveTypeReference(receiverTypeRef);
|
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()]));
|
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) {
|
public Method mapGetterSignature(PropertyDescriptor descriptor) {
|
||||||
Type returnType = mapType(descriptor.getOutType());
|
Type returnType = mapType(descriptor.getOutType());
|
||||||
return new Method(PropertyCodegen.getterName(descriptor.getName()), returnType, new Type[0]);
|
return new Method(PropertyCodegen.getterName(descriptor.getName()), returnType, new Type[0]);
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class NamespaceCodegen {
|
|||||||
AnalyzingUtils.applyHandler(ErrorHandler.THROW_EXCEPTION, bindingContext);
|
AnalyzingUtils.applyHandler(ErrorHandler.THROW_EXCEPTION, bindingContext);
|
||||||
|
|
||||||
final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
|
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 PropertyCodegen propertyCodegen = new PropertyCodegen(v, standardLibrary, bindingContext, functionCodegen);
|
||||||
final ClassCodegen classCodegen = codegens.forClass(bindingContext);
|
final ClassCodegen classCodegen = codegens.forClass(bindingContext);
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ public class NamespaceCodegen {
|
|||||||
|
|
||||||
FrameMap frameMap = new FrameMap();
|
FrameMap frameMap = new FrameMap();
|
||||||
JetTypeMapper typeMapper = new JetTypeMapper(JetStandardLibrary.getJetStandardLibrary(namespace.getProject()), bindingContext);
|
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()) {
|
for (JetDeclaration declaration : namespace.getDeclarations()) {
|
||||||
if (declaration instanceof JetProperty) {
|
if (declaration instanceof JetProperty) {
|
||||||
|
|||||||
@@ -131,13 +131,18 @@ public abstract class StackValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void coerce(Type type, InstructionAdapter v) {
|
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);
|
box(this.type, type, v);
|
||||||
}
|
}
|
||||||
else if (this.type.getSort() == Type.OBJECT && type.getSort() <= Type.DOUBLE) {
|
else if (this.type.getSort() == Type.OBJECT && type.getSort() <= Type.DOUBLE) {
|
||||||
unbox(type, v);
|
unbox(type, v);
|
||||||
}
|
}
|
||||||
else if (type != this.type) {
|
else {
|
||||||
v.cast(this.type, type);
|
v.cast(this.type, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
fun box() : String {
|
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()
|
return gen()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,9 +71,9 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
|
|||||||
} catch (NoClassDefFoundError e) {
|
} catch (NoClassDefFoundError e) {
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
throw e;
|
throw e;
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
throw e;
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
assertEquals("OK", actual);
|
assertEquals("OK", actual);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* @author max
|
||||||
|
*/
|
||||||
|
package jet;
|
||||||
|
|
||||||
|
public abstract class Function0<R> {
|
||||||
|
public abstract R invoke();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "{() : R}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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}";
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user