This paper introduces a script language Pnuts which utilizes the functionalities of Java and can be easily used from Java programs. The language can be used to help Java programs be more flexible and simple.
The Java language is a compilation-based language, that is, you have to compile source code before an execution. Although we can write flexible Java programs combining object oriented techniques and class loader, Users still need to make programs more dynamic without re-compilation. The reason for this is that programs can just choose classes and methods dynamically with a bare Java environment. With a scripting language, it would be possible to define a new sequence of object manipulations at runtime.
If so, why is there a need for a new language? Someone may claim that the script language should not be a differrent language. Besides, there are many simple and dynamic languages used widely; e.g. Scheme, Perl, etc. Such languages could be used to access the Java API.
But the Java language is too complex to be used as a script language, while this script language is easy and simple to use and to learn. A good script language should not have too many functionalities in order to be easy to learn. Also, other dynamic languages were not designed to access the Java API. It is neccessary to introduce a new syntax (language) to enable brief description for access to the Java APIs. Coupled tightly with Java, it can keep the script language simple and easy to learn.
The script language has access to all public members and constructors of Java API; any Java API can be manipulated by the script. This is done by calling the Java Reflection API. Classes are represented as a Class object. Method call is to invoke on Method object.
The script language does not have the capability to define classes. This means that Pnuts is not a replacement of Java. They have a complementary relationship because Pnuts has the following features which are not included in Java.
The script language is expression-based. The script environment just evaluates an expression one by one and passes the last result to the Java environment. So scripts are evaluated interactively by the script interpreter.
Java has two types of data; primitive type and reference type. Pnuts integrates these data types so that the User does not have to care about the difference between them. Primitive data is automatically converted to a wrapper class such as java.lang.Integer. Arithmetic operations take such wrapper objects for their calculations.
In addition, multi-precision number which is provided by java.math package in JDK1.1 can be used transparently. In most cases, Users can manupilate numbers as if there is no distinction between BigInteger/BigDecimal and primitive data.
Pnuts has list notation which is a common feature of other languages such as Lisp and it's dialects. Actually, pseudo list is implemented as an array of objects. It means that it is simply a syntax sugar. But pseudo list can simplify the code, especially for nested array, so it encourages the User to use object arrays for their programs.
The script can have functions. The functions can take an arbitrary number of parameters and are identified by the name and the number of parameters. The parameters and results are passed as is, except for primitive type value which is wrapped by a Java object.
Functions are first class objects, which means that you can assign a function to a variable.
Function call and instance construction are denoted with a uniform syntax, e.g. func(...), class(...). So the User does not have to distinguish between function and class object calls. The User only has to make a call with some parameters. For a constructor, a Class object acts as a function that create a new object.
Variables have no type and do not have to be declared. When the interpreter reads an assignment statement, the variable is created automatically in it's scope and can bind any kind of object.
There are two types of scope, function scope and block scope. Function calls make the function scope. for/while/foreach-statement make the block scope. Basically the variable's scope is the surrounding scope. Reference resolution is made from the innermost scope to the surrounding function scope.
Packages provide naming scopes. Every functions and variables belongs to a package. Packages allow us to define function and variable without worrying about conflicts.
Both package and static class member make scopes for data and operations. So they have similar syntax; e.g. scope::member or scope::member(...)
The interpreter can help the repetitive execution process be much more efficient. Not only with the compilation itself, which is time consuming, but also with the initialization of Java VM and AWT which takes some time.
With the interpreter, you can try almost all of the functionalities of Java classes. This makes the interpreter extremely useful for debugging and prototyping.
The interpreter can be a traditional interpreter, such as on Lisp systems, or GUI environments like Emacs. In addition, the GUI environment can be Web based when the interpreter is an applet.
Some applications (or applets) want to give Users a chance to configure some portion of their behavior. Although Java programs can read property files or resources for this kind of configuration, it may not be flexible enough for certain situations. For example, if a User wants to configure the system with certain conditions. In this case, Java code can call a User's script to configure the application.
Generally, applications can be highly extensible with a scripting language. A good example is Emacs. In such a system, Users can write scripts to extend the system and realize their demand. Because Pnuts utilizes almost all functionalities of the Java API, it is powerful enough to make such extensible scripting environment based on Java.