Pnuts API Overview

Introduction

Pnuts API is a set of classes that provides methods to use the scripting functionalities of Pnuts. There is no initialization procedure to use the API and it can be called at any place in a Java program. Pnuts interpreter shares the thread resource and the object space with the Java program that call the API.

Pnuts

pnuts.lang.Pnuts class has static methods which starts an interpreter. Pnuts.eval() and Pnuts.load() are two of the most important methods to call Pnuts script from Java.

public static Object eval( String exp, Context context );
public static Object load( InputStream in , Context context );
public static Object load ( Reader in , Context context );
public static Object load( URL scriptURL , Context context );
public static Object load( String rsrc , Context context ) throws FileNotFoundException;

The following example illustrates a simple usage of Pnuts.eval() method.

import pnuts.lang.*;
import java.math.*;

class Foo {
   public static void main(String arg[]){
       Context context = new Context();
       BigInteger bint = (BigInteger)Pnuts.eval("1<<100", context);
       ...
   }
}

pnuts.lang.Pnuts class can be instantiated only by Pnuts::parse(InputStream/Reader) methods. The instance of pnuts.lang.Pnuts can be executed by run() method.

public static Pnuts parse( InputStream in ) throws ParseException;
public static Pnuts parse( Reader in ) throws ParseException;
public Object run(Context context);

The following program illustrates how to parse a Pnuts script first and execute it later.

import pnuts.lang.*;
import java.io.*;

class ParseTest {
  public static void main(String a[]){
     Pnuts p = null;
     try {
        p = Pnuts.parse(new FileInputStream(a[0]));
     } catch (ParseException e1){
        ...
     } catch (IOException e2){
        ...
     }
     ...
     p.run(new Context());
  }
}

PnutsFunction

PnutsFunction is another entry point into the Pnuts interpreter. It is used to call a Pnuts function from Java.

public static Object call(String name, Object args[]);
public static Object call(String name, Object args[], String pkg);
public static Object call(String name, Object args[], Context context);
import pnuts.lang.*;

class Foo {
   public static void main(String arg[]){
       Pnuts.eval("function foo() 100");
       ...
       System.out.println(PnutsFunction.call("foo", new Object[]{}));
   }
}
If a Java program holds a reference to PnutsFunction object, the function can be called directly by the following instance methods.
public Object call(Object[] args);
public Object call(Object[] args, Context context);
import pnuts.lang.*;

class Foo {
   public static void main(String arg[]){
       PnutsFunction func = (PnutsFunction)Pnuts.eval("function foo() 100");
       ...
       System.out.println(func.call(new Object[]{}));
   }
}

The following methods retrieve the function definition from a PnutsFunction object.

public String unparse(int narg);
The body of function definition.
public Package getPackage(int narg);
Package in which the function is defined.
public String[] getImportEnv(int narg);
Array of imported Java package names and class names
function f(n) n * n

f.unparse(1) ==> "function f(n) n * n"
f.getPackage(1) ==> package ""
f.getImportEnv(1) ==> ["java.lang.*", "*"]

Package

Package provides separate name spaces for an interpreter to make extensibility of the scripting environment. The name spaces prevent name conflicts among the scripts.

Also, Package provides separate name spaces used by several interpreters. If each interpreter uses a unique Package, they will not interfere with each other in their execution.

Packages are identified by the name and the Package name can not be changed after it is created. Usually Packages are managed in a static hashtable and it is garranteed that their names are unique.

To create a Package use the following method. If Package with the name pkgName does not exists it creates the Package.

public static Package getPackage(String pkgName);

The default constructor of pnuts.lang.Package also makes a new Package but the name is initialized to null. In this case, the created Package is not managed by the hashtable, which means that the Package can never conflict but the names in the Package can not be refered by other Packages.

public Package();

The following methods are access methods to symbols in the Package. See apidoc for details.

public Object get(String symbol , Context context );
public void set(String symbol, Object value , Context context );
public boolean defined(String symbol , Context context );
public void clear(String symbol , Context context );

Context

As noted previously, a Context represents an internal state in the Pnuts runtime environment. It holds the following information.

The default constructor of Context creates a Context object with the global Package. The constructors Context(String pkgName) and Context(Package anPackage) create a Context and set the default Package. If Package with the name pkgName does not exists it creates the Package.

public Context();
public Context(Package pkg);
public Context(String pkgName);

One Context object can be passed among several interpreters by specifying in Pnuts.eval() and load() method. Also a context can be used from different threads at the same time.

public static Object eval( String exp, Context context );
public static Object load ( String rsrc , Context context );
public static Object load ( InputStream in , Context context );
public static Object load ( Reader in , Context context );
public static Object load ( InputStream in , boolean interactive , Context context );
public static Object load ( Reader in , boolean interactive , Context context );

The following method creates a Context which has package "pkg" by default, then evaluates str.

public static Object eval (String str, String pkg)

The following two statements are equivalent.

Pnuts.eval(str, "pkg");
Pnuts.eval(str, new Context("pkg"));

Message

As shown below, three kinds of output stream can be specified for a Context.

Difference between eval() and Pnuts::eval()

eval(expr)
Evaluates expr with a copy of the current Context
eval(expr, context)
Evaluates expr with a copy of context
Pnuts::eval(expr)
Evaluates expr with a newly created Context
same as Pnuts::eval(expr, Context())
Pnuts::eval(expr, context)
Evaluates expr with context

When a Context object is passed to Pnuts::eval(expr, context), import() and some other functions can modify the caller's context. On the other hand, the original Context object can not be modified by primitive function eval(), because it uses a copy of a Context.

Exception handling

When an exception is thrown during executing script through Pnuts.eval(), Pnuts.load(), or Pnuts.loadFile() method, the exception is propagated to the caller of the methods.

The exception is encapsulated in a pnuts.lang.PnutsException object and can be retrieved with the PnutsException.getThrowable() method.

public Throwable getThrowable();
import pnuts.lang.*;
import java.io.*;

class Foo {
   public static void main(String arg[]){
      try {
         Object ret = Pnuts.eval(arg[0], new Context());
	 System.out.println("ret = " + ret);
      } catch (PnuteException e){
	 if (e.getThrowable() instanceof IOException){
	   e.printStackTrace();
	 } else {
	   System.out.println("caught: " + e);
	 }
      }
   }
}

Back