Compiling Scripts from Java

1. Compiling Scripted Classes

Scripted classes are usually compiled and loaded by PnutsClassLoader, but sometimes they need to be compiled manually. pnuts.compiler.Compiler class provides a way to compile scripted classes.

pnuts.compiler.Compiler

public Object compileClassScript(Reader reader, Object scriptSource, ClassFileHandler handler) throws ParseException

compileClassScript() compiles a script read from reader, then let handler handle the result.

pnuts.compiler.ClassFileHandler is an abstract interface to get a result of compilation. Two concrete classes of ClassFileHandler are provided: pnuts.compiler.FileWriterHandler and pnuts.compiler.ZipWriterHandler. The following example compiles mymap class and saves as "e:\tmp\mymap.class".

import pnuts.compiler.FileWriterHandler;
import pnuts.compiler.Compiler;
import pnuts.lang.ParseException;
import java.io.File;
import java.io.Reader;
import java.io.FileReader;

public class CompileTest {
    public static void main(String[] args){
	try {
	    File file = new File("mymap.pnc");
	    Reader reader = new FileReader(file);
	    Compiler compiler = new Compiler();
	    compiler.compileClassScript(reader, file.toURL(), new FileWriterHandler(new File("e:\\tmp")));
	} catch (Exception e){
	    e.printStackTrace();
	}
    }
}

2. Compiling Executable Scripts

pnuts.compiler.CompilerPnutsImpl can be used to execute Pnuts scripts with on-the-fly compilation. On the other hand, pnuts.compiler.Compiler class is used to compile scripts without executing.

import pnuts.lang.*;

public void compile(PnutsFunction function, Context context)
public Pnuts compile(String expr, Context context)
public Pnuts compile(Pnuts pnuts, Context context)

pnuts.compiler.Compiler class provides these public methods to compile functions, expressions, and parsed scripts. java.lang.ClassFormatError may occur when its compilation fails.

e.g.
import pnuts.lang.*;
import pnuts.compiler.*;

class CompileTest {
  public Object compileAndRun(InputStream in, Context context) throws ParseException {
    Compiler compiler = new Compiler();
    Pnuts pn = null;
    try {
      pn = Pnuts.parse(in);
      pn = compiler.compile(pn, context);
      return pn.run(context);
    } catch (ParseException pe){
      throw pe;
    } catch (ClassFormatError cfe){
      return pn.accept(new PnutsInterpreter(), context);
    }
  }
  ...
}
import pnuts.lang.*;

public Object compile(PnutsFunction function, ClassFileHandler handler)
public Object compile(String expr, ClassFileHandler handler)
public Object compile(Pnuts pnuts, ClassFileHandler handler)

The class also provides public methods to define how generated class files are processed. pnuts.compiler.ClassFileHandler is an abstract interface to get a result of compilation.

Two concrete classes of ClassFileHandler are provided: pnuts.compiler.FileWriterHandler and pnuts.compiler.ZipWriterHandler. The following code compiles the expression 1+2 and saves the result in "e:\tmp\test.class".

e.g.
String expression = "1 + 2";
Compiler compiler = new Compiler("test");
try {
    compiler.compile(Pnuts.parse(expression), new FileWriterHandler(new File("e:\\tmp")));
} catch (ParseException pe){
} catch (ClassFormatError cfe){
    ...
}

There are two ways to load a compiled script:

  1. Set the property 'pnuts.compiled.script.prefix' to the package name of the generated class, then call load().
    load("test")
    
  2. Call Executable.run(Context) method on an instance of the generated class.

    test().run(getContext())
    

See also 'Compiling Scripts from Command Line'.