IO Support

Basic types and utilities in support of I/O operation.

Most of Chapel’s I/O support is within the IO module. This automatically included module provides several basic types and routines that support the IO module.

Writing and Reading

The writeln function allows for a simple implementation of a Hello World program:

writeln("Hello, World!");
// outputs
// Hello, World!

The read functions allow one to read values into variables as the following example demonstrates. It shows three ways to read values into a pair of variables x and y.

var x: int;
var y: real;

/* reading into variable expressions, returning
   true if the values were read, false on EOF */
var ok:bool = read(x, y);

/* reading via a single type argument */
x = read(int);
y = read(real);

/* reading via multiple type arguments */
(x, y) = read(int, real);

The write method on strings

The write method can also be called on strings to write the output to a string instead of a channel. The string will be appended to.

The readThis(), writeThis(), and readWriteThis() Methods

When programming the input and output method for a custom data type, it is often useful to define both the read and write routines at the same time. That is possible to do in a Chapel program by defining a readWriteThis method, which is a generic method expecting a single argument: either a Reader or a Writer.

In cases when the reading routine and the writing routine are more naturally separate, or in which only one should be defined, a Chapel program can define readThis (taking in a single argument of type Reader) and/or writeThis (taking in a single argument of type Writer).

If none of these routines are provided, a default version of readThis and writeThis will be generated by the compiler. If readWriteThis is defined, the compiler will generate readThis or writeThis methods - if they do not already exist - which call readWriteThis.

Objects of type Reader or Writer both support the following fields and methods:

Objects of type Reader also supports the following methods:

Objects of type Writer also support the following methods:

Note that objects of type Reader or Writer may represent a locked channel; as a result, using parallelism constructs to call methods on Reader or Writer may result in undefined behavior.

Note

In the future, we plan to merge Reader, Writer, and IO.channel in order to support calling IO.channel.readf and other I/O routines inside a readThis method.

Because it is often more convenient to use an operator for I/O, instead of writing

f.readwrite(x);
f.readwrite(y);

one can write

f <~> x <~> y;

Note that the types IO.ioLiteral and IO.ioNewline may be useful when using the <~> operator. IO.ioLiteral represents some string that must be read or written as-is (e.g. "," when working with a tuple), and IO.ioNewline will emit a newline when writing but skip to and consume a newline when reading.

This example defines a readWriteThis method and demonstrates how <~> will call the read or write routine, depending on the situation.

class IntPair {
  var x: int;
  var y: int;
  proc readWriteThis(f) {
    f <~> x <~> new ioLiteral(",") <~> y <~> new ioNewline();
  }
}
var ip = new IntPair(17,2);
write(ip);
// prints out
// 17,2

delete ip;

This example defines a only a writeThis method - so that there will be a function resolution error if the class NoRead is read.

class NoRead {
  var x: int;
  var y: int;
  proc writeThis(f:Writer) {
    f.writeln("hello");
  }
  // Note that no readThis function will be generated.
}
var nr = new NoRead();
write(nr);
// prints out
// hello

// Note that read(nr) will generate a compiler error.

delete nr;

Generalized write and writeln

The Writer class contains no fields and serves as a base class to allow user-defined classes to be written to. If a class is defined to be a subclass of Writer, it must override the Writer.writePrimitive method with any Chapel primitive type as an argument.

The following code defines a subclass of Writer that overrides the Writer.writePrimitive method to allow it to be written to. It also overrides the writeThis method to override the default way that it is written.

// A demonstration writer class that filters
// values printed to it by only printing the first
// character.
class C: Writer {
  // A variable to accumulate some writes.
  var data: string;

  // writePrimitive will be called when
  // c.write(...) is called
  proc writePrimitive(x) {
    var s = x:string;
    // only save the first letter
    data += s.substring(1);
  }

  // writeThis will be called when
  // e.g. stdout.write(c) is called
  proc writeThis(x: Writer) {
    x.write(data);
  }
}

var c = new C();
// c.write will invoke c.writePrimitive
// with each numeric value in turn
c.write(41, 32, 23, 14);
// writeln is stdout.writeln and will invoke
// c.writeThis.
writeln(c);
// prints out:
// 4321

delete c;

Default write and read Methods

Default write methods are created for all types for which a user-defined write method is not provided. They have the following semantics:

  • for an array argument: outputs the elements of the array in row-major order where rows are separated by line-feeds and blank lines are used to separate other dimensions.
  • for a domain argument: outputs the dimensions of the domain enclosed by [ and ].
  • for a range argument: output the lower bound of the range, output .., then output the upper bound of the range. If the stride of the range is not 1, output the word by and then the stride of the range.
  • for a tuples, outputs the components of the tuple in order delimited by ( and ), and separated by commas.
  • for a class: outputs the values within the fields of the class prefixed by the name of the field and the character =. Each field is separated by a comma. The output is delimited by { and }.
  • for a record: outputs the values within the fields of the class prefixed by the name of the field and the character =. Each field is separated by a comma. The output is delimited by ( and ).

Default read methods are created for all types for which a user-defined read method is not provided. The default read methods are defined to read in the output of the default write method.

Note

Note that it is not currently possible to read and write circular data structures with these mechanisms.

class Writer

An abstract base class type for classes that know how to write values.

proc writing param

returns true

proc binary(): bool

returns true if this Writer is configured for binary I/O.

proc error(): syserr

Return any saved error code. Subclasses should override this method.

proc setError(e: syserr)

Save an error code. Subclasses should override this method.

proc clearError()

Clear any saved error code. Subclasses should override this method.

proc writePrimitive(x)

Write a primitive type. Subclasses should override this method.

proc readwrite(x)

Write anything by calling writeThis methods or by using writePrimitive. Subclasses should not need to override this method.

proc write(args ...?k)

Write anything by calling writeThis methods or by using writePrimitive. Subclasses should not need to override this method.

proc writeln(args ...?k)

Write anything by calling writeThis methods or by using writePrimitive. Then write a newline character. Subclasses should not need to override this method.

proc writeln()

Write a newline character. Subclasses should not need to override this method.

class Reader

An abstract base class type for classes that know how to read values.

proc writing param

returns false

proc binary(): bool

returns true if this Reader is configured for binary I/O.

proc error(): syserr

Return any saved error code. Subclasses should override this method.

proc setError(e: syserr)

Save an error code. Subclasses should override this method.

proc clearError()

Clear any saved error code. Subclasses should override this method.

proc readPrimitive(ref x: ?t)

Read a primitive type. Subclasses should override this method.

proc readwrite(ref x)

Read anything by calling readThis methods or by using readPrimitive. Subclasses should not need to override this method.

proc read(ref args ...?k): bool

Read anything by calling readThis methods or by using readPrimitive. Subclasses should not need to override this method.

proc readln(ref args ...?k): bool

Read anything by calling readThis methods or by using readPrimitive. Then read and discard any input until a newline character is reached. Subclasses should not need to override this method.

proc readln(): bool

Read and discard any input until a newline character is reached. Subclasses should not need to override this method.

proc <~>(w: Writer, x): Writer

Call w.readwrite(x)

Returns:w so that <~> operators can be chained
proc <~>(r: Reader, ref x): Reader

Call r.readwrite(x)

Returns:r so that <~> operators can be chained
proc <~>(r: Reader, lit: ioLiteral): Reader

Overload to support reading an IO.ioLiteral without passing ioLiterals by reference, so that

reader <~> new ioLiteral("=")

works without requiring an explicit temporary value to store the ioLiteral.

proc <~>(r: Reader, nl: ioNewline): Reader

Overload to support reading an IO.ioNewline without passing ioNewline by reference, so that

reader <~> new ioNewline("=")

works without requiring an explicit temporary value to store the ioNewline.

proc Reader.readWriteLiteral(lit: string, ignoreWhiteSpace = true)

Explicit call for reading a literal as an alternative to using IO.ioLiteral.

proc Writer.readWriteLiteral(lit: string, ignoreWhiteSpace = true)

Explicit call for writing a literal as an alternative to using IO.ioLiteral.

proc Reader.readWriteNewline()

Explicit call for reading a newline as an alternative to using IO.ioNewline.

proc Writer.readWriteNewline()

Explicit call for writing a newline as an alternative to using IO.ioNewline.

proc halt()

Prints an error message to stderr giving the location of the call to halt in the Chapel source, followed by the arguments to the call, if any, then exits the program.

proc halt(s: string)

Prints an error message to stderr giving the location of the call to halt in the Chapel source, followed by the arguments to the call, if any, then exits the program.

proc halt(args ...?numArgs)

Prints an error message to stderr giving the location of the call to halt in the Chapel source, followed by the arguments to the call, if any, then exits the program.

proc warning(s: string)

Prints a warning to stderr giving the location of the call to warning in the Chapel source, followed by the argument(s) to the call.

proc warning(args ...?numArgs)

Prints a warning to stderr giving the location of the call to warning in the Chapel source, followed by the argument(s) to the call.

class StringWriter: Writer

Writer that can save output to a string

proc ref string.write(args ...?n)

Write each argument by appending to the string.