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.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 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[], Context context);
If a Java program holds a reference to PnutsFunction object, the function can be called directly by the following instance methods.
import pnuts.lang.*; class Foo { public static void main(String arg[]){ Context context = new Context(); Pnuts.eval("function foo() 100", context); ... System.out.println(PnutsFunction.call("foo", new Object[]{}, context)); } }
- public Object call(Object[] args, Context context);
import pnuts.lang.*; class Foo { public static void main(String arg[]){ Context context = new Context(); PnutsFunction func = (PnutsFunction)Pnuts.eval("function foo() 100", context); ... System.out.println(func.call(new Object[]{}, context)); } }
The following methods retrieve the function definition from a PnutsFunction object.
- public String unparse(int narg);
- The body of function definition.
- public String[] getImportEnv(int narg);
- Array of imported Java package names and class names
- public Package getPackage();
- Package in which the function is defined.
function f(n) n * n f.unparse(1) ==> "function f(n) n * n" f.getPackage() ==> package "" f.getImportEnv(1) ==> ["java.lang.*", "*"]
Package is a name space which can be used to prevent name conficts among scripts. Package can also be used to define a module, which is a set of re-usable functions.
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.
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 static Package getPackage(String pkgName);
- public Package();
Hierarchy of Packages can be made by specifying the parent package to the following constructor. The global package is the default parameter.
- public Package(String name, Package parent);
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 );
A Context represents an internal state in the Pnuts runtime environment. It holds the following information.
A Context object need to be created when evaluating a script.
- public Context();
- public Context(Package pkg);
- public Context(String pkgName);
- public Context(Context template);
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.
One Context object can be passed among several interpreters. 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 );
When eval(),load(), or loadFile() is called from a script, a clone of the Context being used is made and passed to the function. A clone of a context can be made by calling Context.clone() method directly.
Some of the attributes are shared among the clones, and some of them are copied.
Attributes What happened when a clone is made OutputStream for messages copied Context-local Variables copied Class Loader shared PnutsImpl object copied Modules added by use() shared Symbols registered by autoload() shared The list of files loaded by load() shared Imported Java package list copied
If all attributes need to be copied, use the constructor Context(Context) instead of clone().
As shown below, three kinds of output stream can be specified for a Context.
- public PrintWriter getOutputStream ();
- public void setOutputStream (Writer out);
- public void setOutputStream (OutputStream out);
- public PrintWriter getErrorStream ();
- public void setErrorStream (OutputStream out );
- public void setErrorStream (Writer out );
- public PrintWriter getTerminalStream ();
- public void setTerminalStream (OutputStream out );
- public void setTerminalStream (Writer out );
Context-local variable is a kind of environment variable bound to a context.
- public void set (String key , Object value);
- public Object get (String key );
A class loader can be associated with the context. It is used to resolve class names, and finds scripts when load() function is used.
- public void setClassLoader (ClassLoader loader );
- public ClassLoader getClassLoader ();
See "On-the-fly Compiler and Pure Interpreter".
- public void setPnutsImpl (PnutsImpl impl );
- public PnutsImpl getPnutsImpl ();
use() function registers a module to the executing context. The registered modules are managed and shared by a family of Context clones.
- public void usePackage (String name );
- public String[] usedPackages ();
usePackage() registers a module to the context. usedPackages() returns the list of registered module names.
- 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.
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); } } } }