PSVM generation works
This commit is contained in:
@@ -1,9 +1,13 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import org.jetbrains.jet.lang.psi.JetClass;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.psi.JetFunction;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetNamespace;
|
|
||||||
import org.objectweb.asm.ClassVisitor;
|
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.Method;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author max
|
* @author max
|
||||||
@@ -16,7 +20,42 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void gen(JetFunction f, JetNamespace owner) {
|
public void gen(JetFunction f, JetNamespace owner) {
|
||||||
|
final List<JetParameter> parameters = f.getValueParameters();
|
||||||
|
Type[] parameterTypes = new Type[parameters.size()];
|
||||||
|
for (int i = 0; i < parameters.size(); i++) {
|
||||||
|
parameterTypes[i] = mapTypeReference(parameters.get(i).getTypeReference());
|
||||||
|
}
|
||||||
|
Method method = new Method(f.getName(), Type.VOID_TYPE, parameterTypes);
|
||||||
|
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
|
||||||
|
method.getName(), method.getDescriptor(), null, null);
|
||||||
|
mv.visitCode();
|
||||||
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Type mapTypeReference(JetTypeReference typeRef) {
|
||||||
|
if (typeRef == null) {
|
||||||
|
throw new UnsupportedOperationException("Cannot evaluate type for parameter with no type ref");
|
||||||
|
}
|
||||||
|
final JetTypeElement typeElement = typeRef.getTypeElement();
|
||||||
|
if (typeElement instanceof JetUserType) {
|
||||||
|
final String referencedName = ((JetUserType) typeElement).getReferencedName();
|
||||||
|
if ("Array".equals(referencedName)) {
|
||||||
|
final List<JetTypeProjection> typeArguments = ((JetUserType) typeElement).getTypeArguments();
|
||||||
|
if (typeArguments.size() != 1) {
|
||||||
|
throw new UnsupportedOperationException("arrays must have one type argument");
|
||||||
|
}
|
||||||
|
final JetTypeReference elementTypeRef = typeArguments.get(0).getTypeReference();
|
||||||
|
Type elementType = mapTypeReference(elementTypeRef);
|
||||||
|
return Type.getType("[" + elementType.getDescriptor());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("String".equals(referencedName)) {
|
||||||
|
return Type.getType(String.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new UnsupportedOperationException("Unknown type " + typeRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void gen(JetFunction f, JetClass owner) {
|
public void gen(JetFunction f, JetClass owner) {
|
||||||
|
|||||||
@@ -19,9 +19,10 @@ public class NamespaceCodegen {
|
|||||||
final FunctionCodegen functionCodegen = new FunctionCodegen(v);
|
final FunctionCodegen functionCodegen = new FunctionCodegen(v);
|
||||||
v.visit(Opcodes.V1_6,
|
v.visit(Opcodes.V1_6,
|
||||||
Opcodes.ACC_PUBLIC,
|
Opcodes.ACC_PUBLIC,
|
||||||
namespace.getFQName().replace('.', '/') + "/namespace",
|
getJVMClassName(namespace),
|
||||||
null,
|
null,
|
||||||
"jet/lang/Namespace",
|
//"jet/lang/Namespace",
|
||||||
|
"java/lang/Object",
|
||||||
new String[0]
|
new String[0]
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -37,4 +38,8 @@ public class NamespaceCodegen {
|
|||||||
|
|
||||||
v.visitEnd();
|
v.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getJVMClassName(JetNamespace namespace) {
|
||||||
|
return namespace.getFQName().replace('.', '/') + "/namespace";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,21 +4,60 @@ import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
|||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
import org.jetbrains.jet.lang.psi.JetNamespace;
|
import org.jetbrains.jet.lang.psi.JetNamespace;
|
||||||
import org.jetbrains.jet.parsing.JetParsingTest;
|
import org.jetbrains.jet.parsing.JetParsingTest;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
import org.objectweb.asm.util.TraceClassVisitor;
|
import org.objectweb.asm.util.TraceClassVisitor;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yole
|
* @author yole
|
||||||
*/
|
*/
|
||||||
public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
|
public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
|
||||||
public void testPSVM() {
|
public void testPSVM() throws InvocationTargetException, IllegalAccessException {
|
||||||
myFixture.configureByFile(JetParsingTest.getTestDataDir() + "/codegen/PSVM.jet");
|
myFixture.configureByFile(JetParsingTest.getTestDataDir() + "/codegen/PSVM.jet");
|
||||||
JetFile jetFile = (JetFile) myFixture.getFile();
|
JetFile jetFile = (JetFile) myFixture.getFile();
|
||||||
JetNamespace namespace = jetFile.getRootNamespace();
|
JetNamespace namespace = jetFile.getRootNamespace();
|
||||||
NamespaceCodegen codegen = new NamespaceCodegen();
|
NamespaceCodegen codegen = new NamespaceCodegen();
|
||||||
|
final String text = generateToText(namespace, codegen);
|
||||||
|
System.out.println(text);
|
||||||
|
|
||||||
|
final Class aClass = generateToClass(namespace, codegen);
|
||||||
|
final Method[] methods = aClass.getMethods();
|
||||||
|
final Method main = methods[0];
|
||||||
|
Object[] args = new Object[] { new String[0] };
|
||||||
|
main.invoke(null, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String generateToText(JetNamespace namespace, NamespaceCodegen codegen) {
|
||||||
StringWriter writer = new StringWriter();
|
StringWriter writer = new StringWriter();
|
||||||
codegen.generate(namespace, new TraceClassVisitor(new PrintWriter(writer)));
|
codegen.generate(namespace, new TraceClassVisitor(new PrintWriter(writer)));
|
||||||
|
return writer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Class generateToClass(JetNamespace namespace, NamespaceCodegen codegen) {
|
||||||
|
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||||
|
codegen.generate(namespace, writer);
|
||||||
|
final byte[] data = writer.toByteArray();
|
||||||
|
MyClassLoader classLoader = new MyClassLoader(NamespaceGenTest.class.getClassLoader());
|
||||||
|
final Class aClass = classLoader.doDefineClass(NamespaceCodegen.getJVMClassName(namespace).replace("/", "."), data);
|
||||||
|
return aClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MyClassLoader extends ClassLoader {
|
||||||
|
public MyClassLoader(ClassLoader parent) {
|
||||||
|
super(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class doDefineClass(String name, byte[] data) {
|
||||||
|
return defineClass(name, data, 0, data.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||||
|
return super.loadClass(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user