Pregunta

I would like to write a compiler for a toy-language for Java. I would like to generate runnable .class files. I was wondering what is the best library or tool available for doing this? I know I could learn the binary format for all the instructions and build my own constant pool etc, but that seems like work that ought to have been already done: no point reinventing the wheel, right?

Searching online I've found two different Java Assembly languages, Jasmin and Jamaica, however only Jasmin looks somewhat maintained.

Is there a Java library for writing byte codes to a stream? Is this what the Apache BCEL is?

Is their a tool for this that is the "standard" for byte-code generation, like Antlr is for parsing?


PS- The toy language is Brainf***, I wanted something where I could have a simple "grammar" so I could focus on the generation aspect and not the parsing part... that will come later on the next step.

¿Fue útil?

Solución

ASM and BCEL do basically similar things. I'd recommend ASM as it's much more supported, much smaller, and is up to date JDK-wise.

Otros consejos

It sounds like you're looking for Apache BCEL:

The Byte Code Engineering Library (Apache Commons BCEL™) is intended to give users a convenient way to analyze, create, and manipulate (binary) Java class files (those ending with .class).

JDK 1.6 has the ability to dynamically compile Java classes (see getSystemJavaCompiler). This can be used to compile Java from source without byte code manipulation or temporary files. We're doing this as a way to improve the performance of some reflection API code, but it will just as easily serve your purpose as well.

Create a Java source file from a string containing the code:

   public class JavaSourceFromString extends SimpleJavaFileObject {
       final String code;

       JavaSourceFromString(String name, String code) {
           super(URI.create("string:///"
                            + name.replace('.','/')
                            + Kind.SOURCE.extension),
                 Kind.SOURCE);
           this.code = code;
       }

       @Override
       public CharSequence getCharContent(boolean ignoreEncodingErrors) {
           return code;
       }
   }

// Use your favorite template language here, like FreeMarker
static final String sourceCode = ""
        + "import org.example.MySomethingObject;"
        // DynamicStringGetter would define getString as a standard way to get
        // a String from an object
        + "public class GetStringDynamic implements DynamicStringGetter {\n" 
        + "    public String getString(Object o) {\n"
        + "        MySomethingObject obj = (MySomethingObject) o;\n"
        + "        return o.getSomething();\n"
        + "    }\n"
        + "}\n";

   JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
   StandardJavaFileManager fileManager = 
       compiler.getStandardFileManager(null, null, null);

   List<JavaFileObject> files = new ArrayList<JavaFileObject>();
   files.add(new JavaSourceFromString("org.example.DynamicClass", sourceCode));

   compiler.getTask(null, fileManager, null, null, null, files).call();

Then you load the newly created class files dynamically.

Alternatively, use byte code manipulation (such as ASM) to create classes on the fly.

As another alternative, there is the Scala CAFEBABE bytecode compilation library. I have not used it personally, but it seems geared more towards creating a new JVM language.

As far as the parsing portion goes, Antlr should serve.

Easiest would be to translate your toy-language into valid .java source code using a preprocessor and then just compile it with javac. That's also the way Processing works.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top