Skip to content

Commit

Permalink
jast2bc changes to actually emit jars
Browse files Browse the repository at this point in the history
  • Loading branch information
sorear committed Jun 21, 2013
1 parent f394bee commit 76b8dc0
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 17 deletions.
2 changes: 1 addition & 1 deletion src/vm/jvm/HLL/Backend.nqp
Expand Up @@ -40,7 +40,7 @@ class HLL::Backend::JVM {
}

method is_precomp_stage($stage) {
$stage eq 'classfile'
$stage eq 'classfile' || $stage eq 'jar'
}

method is_textual_stage($stage) {
Expand Down
53 changes: 45 additions & 8 deletions src/vm/jvm/runtime/org/perl6/nqp/jast2bc/JASTToJVMBytecode.java
Expand Up @@ -8,12 +8,17 @@
import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassWriter;
Expand All @@ -23,6 +28,8 @@
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import org.perl6.nqp.runtime.Base64;

public class JASTToJVMBytecode {
public static void main(String[] argv)
{
Expand Down Expand Up @@ -61,9 +68,30 @@ public static void writeClassFromString(String in, String filename) {
try {
BufferedReader br = new BufferedReader(new StringReader(in));
JavaClass c = buildClassFrom(br);

FileOutputStream fos = new FileOutputStream(filename);
fos.write(c.bytes);
fos.close();
if (c.serialized == null) {
// we're writing a plain java class

fos.write(c.bytes);
fos.close();
} else {
// writing a jar
Manifest mf = new Manifest();

mf.getMainAttributes().put( Attributes.Name.MANIFEST_VERSION, "1.0" );
if (c.hasMain)
mf.getMainAttributes().put( Attributes.Name.MAIN_CLASS, c.name );

JarOutputStream jos = new JarOutputStream(fos, mf);

jos.putNextEntry(new JarEntry(c.name.replace('.','/') + ".class"));
jos.write(c.bytes);
jos.putNextEntry(new JarEntry(c.name.replace('.','/') + ".serialized"));
jos.write(c.serialized);

jos.close();
}
}
catch (Exception e) {
throw new RuntimeException(e);
Expand All @@ -72,16 +100,23 @@ public static void writeClassFromString(String in, String filename) {

private static JavaClass buildClassFrom(BufferedReader in) throws Exception
{
JavaClass c = new JavaClass();
// Read in class name, superclass and any fields.
String curLine, className = null, superName = null, fileName = null;
byte[] serData = null;
List<String> fieldLines = new ArrayList<String>();
while ((curLine = in.readLine()) != null) {
if (curLine.startsWith("+ class ")) {
className = curLine.substring("+ class ".length());
className = c.name = curLine.substring("+ class ".length());
}
else if (curLine.startsWith("+ super ")) {
superName = curLine.substring("+ super ".length());
}
else if (curLine.startsWith("+ serialized ")) {
ByteBuffer sbuf = Base64.decode(curLine.substring("+ serialized ".length()));
c.serialized = new byte[sbuf.remaining()];
sbuf.get(c.serialized);
}
else if (curLine.startsWith("+ filename ")) {
fileName = curLine.substring("+ filename ".length());
}
Expand Down Expand Up @@ -122,7 +157,7 @@ else if (curLine.equals("+ method")) {
// Process all of the methods.
if (!curLine.equals("+ method"))
throw new Exception("Expected method after class configuration");
while (processMethod(in, cw, className))
while (processMethod(c, in, cw, className))
;

// Add empty constructor.
Expand All @@ -136,8 +171,8 @@ else if (curLine.equals("+ method")) {
constructor.visitEnd();

cw.visitEnd();

JavaClass c = new JavaClass(className, cw.toByteArray());
c.bytes = cw.toByteArray();

return c;
}

Expand All @@ -146,7 +181,7 @@ private static class LabelInfo {
public boolean defined;
}

private static boolean processMethod(BufferedReader in, ClassWriter c, String className) throws Exception {
private static boolean processMethod(JavaClass jcout, BufferedReader in, ClassWriter c, String className) throws Exception {
String curLine, methodName = null, returnType = null, desc = null;
String crName = null, crCuid = null, crOuter = null;
int crOuterIx = -2; // not coderef
Expand Down Expand Up @@ -238,7 +273,9 @@ else if (curLine.startsWith("++ handlers ")) {
if (inMethodHeader) {
// Transition to instructions mode.
inMethodHeader = false;


if (methodName.equals("main")) jcout.hasMain = true;

// Create method object.
desc = Type.getMethodDescriptor(processType(returnType), argTypes.toArray(new Type[0]));
m = c.visitMethod(
Expand Down
12 changes: 4 additions & 8 deletions src/vm/jvm/runtime/org/perl6/nqp/jast2bc/JavaClass.java
@@ -1,12 +1,8 @@
package org.perl6.nqp.jast2bc;

public class JavaClass {

public final String name;
public final byte[] bytes;

public JavaClass(String name, byte[] bytes) {
this.name = name;
this.bytes = bytes;
}
public String name;
public byte[] bytes;
public byte[] serialized;
public boolean hasMain;
}

0 comments on commit 76b8dc0

Please sign in to comment.