User's Guide - Using the translator as a Compiler

NetRexx User's Guide, version 2.02 Copyright (c) IBM Corporation, 2001. All rights reserved. © | Draft of 22 May 2001
[previous | contents | next]

## Using the translator as a Compiler

The installation instructions for the NetRexx translator describe how to use the package to compile and run a simple NetRexx program (`hello.nrx`). When using the translator in this way (as a compiler), the translator parses and checks the NetRexx source code, and if no errors were found then generates Java source code. This Java code (which is known to be correct) is then compiled into bytecodes (`.class` files) using a Java compiler. By default, the `javac` compiler in the Java toolkit is used.

This section explains more of the options available to you when using the translator as a compiler.

#### The translator command

The translator is invoked by running a Java program (class) which is called `COM.ibm.netrexx.process.NetRexxC` (‘`NetRexxC`’, for short). This can be run by using the Java interpreter, for example, by the command:

      java COM.ibm.netrexx.process.NetRexxC

or by using a system-specific script (such as `NetRexxC.cmd`. or `nrc.bat`). In either case, the compiler invocation is followed by one or more file specifications (these are the names of the files containing the NetRexx source code for the programs to be compiled).

File specifications may include a path; if no path is given then NetRexxC will look in the current (working) directory for the file. NetRexxC will add the extension `.nrx` to input program names (file specifications) if no extension was given.

So, for example, to compile `hello.nrx` in the current directory, you could use any of:

      java COM.ibm.netrexx.process.NetRexxC hello
      java COM.ibm.netrexx.process.NetRexxC hello.nrx
      NetRexxC hello.nrx
      nrc hello

(the first two should always work, the last two require that the system-specific script be available). The resulting `.class` file is placed in the current directory, and the `.crossref` (cross-reference) file is placed in the same directory as the source file (if there are any variables and the compilation has no errors).

Here's an example of compiling two programs, one of which is in the directory `D:\myprograms`:

      nrc hello d:\myprograms\test2.nrx

In this case, again, the `.class` file for each program is placed in the current directory.

Note that when more than one program is specified, they are all compiled within the same class context. That is, they can ‘see’ the classes, properties, and methods of the other programs being compiled, much as though they were all in one file.[1] This allows mutually interdependent programs and classes to be compiled in a single operation. Note that if you use the package instruction you should also read the more detailed Compiling multiple programs section.

On completion, the NetRexxC class will exit with one of three return values: 0 if the compilation of all programs was successful, 1 if there were one or more Warnings, but no errors, and 2 if there were one or more Errors.

As well as file names, you can also specify various option words, which are distinguished by the word being prefixed with ‘`-`’. These flagged words (or ‘flags’) may be any of the option words allowed on the NetRexx options instruction (see the NetRexx language documentation). These options words can be freely mixed with file specifications. To see a full list of options, execute the NetRexxC command without specifying any files.

The translator also implements some additional option words, which control compilation features. These cannot be used on the options instruction, and are:

`-keep`

  keep the intermediate `.java` file for each program. It is kept in the same directory as the NetRexx source file as `xxx.java.keep`, where `xxx` is the source file name. The file will also be kept automatically if the `javac` compilation fails for any reason.

`-nocompile`

  do not compile (just translate). Use this option when you want to use a different Java compiler. The `.java` file for each program is kept in the same directory as the NetRexx source file, as the file `xxx.java.keep` (where `xxx` is the source file name).

`-noconsole`

  do not display compiler messages on the console (command display screen). This is usually used with the `savelog` option.

`-savelog`

  write compiler messages to the file `NetRexxC.log`, in the current directory. This is often used with the `noconsole` option.

`-time`

  display translation, `javac` compile, and total times (for the sum of all programs processed).

`-run`

  run the resulting Java class as a stand-alone application, provided that the compilation had no errors. (See note below.)

Here are some examples:

      java COM.ibm.netrexx.process.NetRexxC hello -keep -strictargs
      java COM.ibm.netrexx.process.NetRexxC -keep hello wordclock
      java COM.ibm.netrexx.process.NetRexxC hello wordclock -nocompile
      nrc hello
      nrc hello.nrx
      nrc -run hello
      nrc -run Spectrum -keep
      nrc hello -binary -verbose1
      nrc hello -noconsole -savelog -format -keep

Option words may be specified in lowercase, mixed case, or uppercase. File specifications are platform-dependent and may be case sensitive, though NetRexxC will always prefer an exact case match over a mismatch.

Note: The `-run` option is implemented by a script (such as `nrc.bat` or `NetRexxC.cmd`), not by the translator; some scripts (such as the `.bat` scripts) may require that the `-run` be the first word of the command arguments, and/or be in lowercase. They may also require that only the name of the file be given if the `-run` option is used. Check the commentary at the beginning of the script for details.

#### Compiling multiple programs and using packages

When you specify more than one program for NetRexxC to compile, they are all compiled within the same class context: that is, they can ‘see’ the classes, properties, and methods of the other programs being compiled, much as though they were all in one file.

This allows mutually interdependent programs and classes to be compiled in a single operation. For example, consider the following two programs (assumed to be in your current directory, as the files `X.nrx` and `Y.nrx`):

      /* X.nrx */
      class X
        why=Y null

      /* Y.nrx */
      class Y
        exe=X null

Each contains a reference to the other, so neither can be compiled in isolation. However, if you compile them together, using the command:

      nrc X Y

then the cross-references will be resolved correctly.

The total elapsed time will be significantly less, too, as the classes on the CLASSPATH need to be located only once, and the class files used by the NetRexxC compiler or the programs themselves will also only be loaded (and JIT-compiled) once.

This example works as you would expect for programs that are not in packages. There's a restriction, though, if the classes you are compiling are in packages (that is, they include a package instruction). Currently, NetRexxC uses the `javac` compiler to generate the `.class` files, and for mutually-dependent files like these, `javac` requires that the source files be in the Java CLASSPATH, in the sub-directory described by the package instruction.

So, for example, if your project is based on the tree:

      D:\myproject

then if the two programs above specified a package, thus:

      /* X.nrx */
      package foo.bar
      class X
        why=Y null

      /* Y.nrx */
      package foo.bar
      class Y
        exe=X null

then:

1. You should put these source files in the directory: `D:\myproject\foo\bar`
2. The directory `D:\myproject` should appear in your CLASSPATH setting (if you don't do this, `javac` will complain that it cannot find one or other of the classes).
3. You should then make the current directory be `D:\myproject\foo\bar` and then compile the programs using the command ‘`nrc X Y`’, as above.

With this procedure, you should end up with the `.class` files in the same directory as the `.nrx` (source) files, and therefore also on the CLASSPATH and immediately usable by other packages. In general, this arrangement is recommended whenever you are writing programs that reside in packages.

Notes:

1. When `javac` is used to generate the `.class` files, no new `.class` files will be created if any of the programs being compiled together had errors – this avoids accidentally generating mixtures of new and old `.class` files that cannot work with each other.
2. If a class is abstract or is an adapter class then it should be placed in the list before any classes that extend it (as otherwise any automatically generated methods will not be visible to the subclasses).

#### Compiling from another program

The translator may be called from a NetRexx or Java program directly, by invoking the `main` method in the `COM.ibm.netrexx.process.NetRexxC` class described as follows:

      method main(arg=Rexx, log=PrintWriter null) static returns int

The `Rexx` string passed to the method can be any combination of program names and options (except `-run`), as described above. Program names may optionally be enclosed in double-quote characters (and must be if the name includes any blanks in its specification).

A sample NetRexx program that invokes the NetRexx compiler to compile a program called `test` is:

      /* compiletest.nrx */
      s='test -keep -verbose4 -utf8'
      say COM.ibm.netrexx.process.NetRexxC.main(s)

Alternatively, the compiler may be called using the method:

      method main2(arg=String[], log=PrintWriter null) static returns int

in which case each element of the `arg` array must contain either a name or an option (except `-run`, as before). In this case, names must not be enclosed in double-quote characters, and may contain blanks.

For both methods, the returned `int` value will be one of the return values described above, and the second argument to the method is an optional `PrintWriter` stream. If the `PrintWriter` stream is provided, translator messages will be written to that stream (in addition to displaying them on the console, unless `-noconsole` is specified). It is the responsibility of the caller to create the stream (autoflush is recommended) and to close it after calling the compiler. The `-savelog` compiler option is ignored if a `PrintWriter` is provided (the `-savelog` option normally creates a `PrintWriter` for the file `NetRexxC.log`).

Note: NetRexxC is thread-safe (the only static properties are constants), but it is not known whether `javac` is thread-safe. Hence the invocation of multiple instances of NetRexxC on different threads should probably specify `-nocompile`, for safety.

Footnotes:

[1] | The programs do, however, maintain their independence (that is, they may have different options, import, and package instructions).

[previous | contents | next]