Support for main() Functions

After running module initialization code (top-level statements in modules), a Chapel program will start executing from the entry point, a function named main(). Chapel's main() function has typically taken no arguments and had no return type. This README describes initial support for returning a status value and making main() take arbitrary command-line arguments.

Returning a status value

Traditionally, the only way to return a nonzero exit value from a Chapel program has been to call exit(). Optionally, main() can be declared to return an integer in which case the value returned serves as the status value.

Having main() accept command-line arguments

Overview

Because Chapel programs have traditionally accepted a number of "built-in" flags and configuration variables, there has been no way to create a Chapel program that accepts arguments like an arbitrary list of filenames or flags that might conflict with built-in capabilities. For most uses, Chapel's existing config variable support is useful and easy; occasionally, however, one wants to fully control argument processing.

If a program's main() function is declared to take no arguments, Chapel will behave as it traditionally has -- built-in flags and config settings will be handled and unrecognized flags will trigger an error.

Alternatively, a main() function can be declared to take an array of strings as an argument. By doing so, the program opts-in to explicit argument handling, described in the remainder of this README.

Usage

To use this feature, declare main as follows:

proc main(args: [] string) {
  // ...body...
}

When main is so declared, Chapel's default command line argument processing changes. Rather than generate an error message when an unknown argument is encountered, that argument will instead be passed on to this main(args) function. Arguments corresponding to config variables or Chapel's predefined flags (like -nl, -b, etc) will still be processed and will not be passed on to the main(args) function.

To be clear, the arguments that would be handled without using this feature will continue to behave as usual. The difference is that other arguments will be passed to main(args) rather than generating an error message. The only exception to this, is --help and -h.

Prior to this feature, a Chapel program would always exit immediately after printing the help message. A programmer might want to print other information explaining what non-config-var command line arguments are available and what they might do. For this reason, when a Chapel program includes a main declared to take arguments, --help and -h will be passed on to the main(args) function. The function Help.printUsage() will print out the familiar config var table.

To gain access to this new function requires a module:

use Help;

From that module, the function printDefaultUsage() is available. For example, consider the following program:

use Help;

proc main(args: [] string) {
  for a in args {
    if a=="--help" {
      printUsage();
      writeln("\nEXTRA ARGUMENTS:");
      writeln(  "================");
      writeln("You can provide an arbitrary list of filenames.");
      exit(0);
    }
  }
}

This program scans its argument list for --help, and if found, it prints the standard usage message as well as some additional text explaining the purpose of the extra arguments. Note that this could be used by a program which simply wants to add explanatory text to the --help output without actually handling any additional arguments.

Finally, as is common in GNU programs, there is a way to suspend argument processing when main is declared to take arguments. Suppose you are writing rm in Chapel and need to delete a file named --memTrack=true. Your program will consume this flag during startup, rather than passing it on to the declared main function. However, placing the argument -- in the argument list will cause all following arguments to be passed to the declared main function and will suspend handling of any builtin command line arguments. Specifically, if a.out is a Chapel program which has declared main to take arguments:

./a.out -- --memTrack=true

will result in the program receiving --memTrack=true as the first argument after the executable name.