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]