Joe Packages

A package is a collection of Joe functions and types intended to be added to a Joe interpreter as a unit. Joe's Standard Library is just such a package, as is the Test Tool API provided by joe test.

A package can be implemented in Java as a collection of native functions and registered types, or in Joe as a collection of Joe functions and classes, or as combination of the two.

Joe intentionally provides no means of installing a package at the script level; it is for the Java client to determine which packages it wishes to make available.1 Consequently, packages are usually defined at the Java level even when they are implemented primarily as Joe code.

Defining a Package

Defining a package is much like defining a registered type.

  • Subclass JoePackage
  • Give the package a name
  • Add content.

For example, the [Standard Library] package, joe, is defined like this:

public class StandardLibrary extends JoePackage {
    public static final StandardLibrary PACKAGE = new StandardLibrary();
    ...

    public StandardLibrary() {
        // Define the package name
        super("joe");

        // Add native functions
        globalFunction("catch", this::_catch);
        ...

        // Add native types
        type(BooleanProxy.TYPE);
        ...
        
        // Include script resources
        scriptResource(getClass(), "pkg.joe.joe");
    }
    ...
}

A global function is just a native function; when the package is installed, each defined global function will be installed automatically into the interpreter using Joe::installGlobalFunction. The function implementations are typically placed within the JoePackage subclass itself, as shown here.

The types are simply registered types; when the package is installed, each listed type will be installed automatically into the interpreter using Joe::installType. The actual proxies can be defined as nested classes in the JoePackage subclass, but are more typically defined in their own .java files.

Finally, a script resource is simply a Joe script found as a resource file in the project's jar file, usually adjacent to the package class that references it. At installation, the script resources will be loaded and executed after the global functions and native types.

Installing a Package

To install a package into an interpreter, use Joe::installPackage:

var joe = Joe();
joe.installPackage(new MyPackage());    // OR
joe.installPackage(MyPackage.PACKAGE);

Library Packages vs. Component Packages

Reusable libraries, such as Joe's standard library, are usually defined as JoePackage subclasses, as shown here.

Often, though, a particular component, e.g., joe test, will define a component-specific package of code, which is installed automatically by the component into the component's own instance of Joe. In this case the component might or might not define an explicit JoePackage subclass, as the JoePackage is primarily a convenient way for a client to install reusable bindings.

However, the component API should still be thought of as a package, and given a package name, as this is how distinct bindings are distinguished in the documentation produced by the joe doc tool.

1

Of course, a client could choose to provide a native function for importing its own packages....