10.12 Universal types10.12 Universal types
10 C++ translator 10 C++ translator
10.14 An example 10.14 An example
10.13 Input/output handling

10.13 Input/output handling

The C++ translator optionally generates code for stream input and output of values of RSL data types.

The i/o routines provide a primitive but easy way of communicating values to and from a program based on translator generated C++ code. The routines are adequate for i/o in a prototype or during debugging. However, due to their lack of error handling at input and formatting at output, they are probably not adequate for handling of interactive i/o in production code.

Non-interactive i/o from and to files etc. can easily be handled.

The i/o facility is based on the C++ concept of streams as described in the standard library header iostream.h. When the C++ code is compiled with the the flag RSL_io defined, each translated type T is equipped with operators for output and input:

struct T {
...
ostream& operator <<(ostream&, const T&);
istream& operator >>(istream&, T&);
...
}

Streams can be connected to files. For interactive i/o, the standard streams cin, cout and cerr correspond to standard input, output and error.

Continuing the example, a value tval specified as having type T, can be printed on the standard output with

cout << "The value is: " << tval << "\n";

Note how RSL data type values can be freely mixed with ordinary C++ values, e.g. strings.

The following code inputs a value of type T to the variable tvar:

T tvar;
cout << "Give a value of type V:\n";
cin >> tvar;

The user is prompted for a string that can be parsed and interpreted as a literal of type T. If the string obeys the input syntax described below, the literal value is assigned to tvar. Otherwise, tvar is unchanged and the state of the stream is set to ios::badbit.

The i/o facility works for any translated type, no matter how complex.

To ensure smooth integration of handwritten C++ with translator generated code, any user defined type, UD, should come equipped with operators for input and output:

struct UD {
...
#ifdef RSL_io

ostream& operator <<(ostream&, const UD&);
istream& operator >>(istream&, UD&);
#endif
...
}

10.13.1 Input syntax

The following describes the syntax that input strings must obey in order to be parsed as values of the given type. For all types, only literal values are accepted. Whitespaces, i.e. blanks, tabs and newlines, can be freely added between lexical tokens. Note, for example, that the list delimiters <. and .> are two tokens, not four, so <.7,9,13. > will not be accepted.

Sort types

As a sort is translated into an empty class, the generated i/o functions have no effect.

Variant types

The input syntax is the same as the RSL syntax for variant literals if the constructors are identifiers. As an example the strings
Vconst
Vint(7)
Vrec(8,Vrec(9,Vint(10)))

can be interpreted as values of type

                                     
 type
 V ==
 Vconst |
 Vint(Int) |
 Vrec(d1Vrec : Int ↔ r1Vrec, d2Vrec : V ↔ r2Vrec)

Internal buffer size limits the number of characters in a constructor identifier to 128.

Union types

Not accepted by the translator, hence no i/o.

Product types

The input syntax is the same as the RSL syntax for product literals. As an example the string (1, Vint(7), "Margrethe") can be interpreted as a value of type Int × V × Text where V is the variant type defined above.

Set types

The input syntax is the same as the RSL syntax for set literals. As an example the strings
{1,4,9}
{1 .. 100}

can be interpreted as values of type Int-set.

List types

The input syntax is the same as the ASCII version of the RSL syntax for list literals. As an example the strings
<.1,1,4,4,9,9.>
<.1 .. 100.>

can be interpreted as values of type Int*.

Text type

The input syntax is the same as the RSL syntax for text literals. As an example the string "Margrethe" can be interpreted as a value of type Text. Note that the quotes must be present. The length of the string must not exceed 256 characters.

Map types

The input syntax is the same as the ASCII version of the RSL syntax for map literals. As an example the string
[ 1 +> "en", 2 +> "to", 3 +> "tre" ]

can be interpreted as a value of type Int -m-> Text.

Unit type

The translator only accepts the unit type in certain contexts, hence no i/o.

Int type

As RSL Int is translated to C++ int, integers are read via the standard int input operator. Therefore, the input syntax differs from the RSL syntax. A unary minus as in -4 can be used whereas e.g. 0-4 is not accepted as it is not a C++ integer literal. Be careful not to enter integer literals that are numerically too large to be represented as ints on the target machine. These will be truncated in a machine dependent way.

Nat type

As Nat is translated to int, the rules for Int apply to Nat as well.

Note that it is possible to input a negative value to a variable that originally was specified as Nat. This can be cause for errors.

Bool type

RSL Bool is translated to C++ bool, and the literal values true and false are interpreted as the corresponding RSL literals.

Real type

As RSL Real is translated to C++ double, floating point numbers are read via the standard double input operator. Therefore, the input syntax differs from the RSL syntax.

Integer literals can be used at input. E.g. 4 is equivalent to 4.0. Exponential notation can be used, e.g. 1.234E-56. A unary minus as in -4.0 can be used whereas e.g. 0.0-4.0 is not accepted as it is not a C++ double literal.

Be careful not to enter literals that are numerically too large to be represented as doubles on the target machine, or contain too many digits to be represented exactly. These will be truncated in a machine dependent way.

Char type

The input syntax is the same as the RSL syntax for character literals. As an example the string 'a' can be interpreted as a value of type Char.

Escaped characters are supported. For example, '\t' is interpreted as a tab character, '\'' as a quote, '\141' (octal notation) and '\x61' (hexadecimal notation) both as 'a'.

Output syntax

All values are converted to output strings with a syntax that is acceptable for input, with the following exceptions:

There is no way to format the output, e.g. to break a long list over several lines.

Conversion to strings

A more flexible way of generating outputs has also been added. The translated C++ code includes the definition of an overloaded function RSL_to_string that will convert any RSL value to a string value. This makes it easier to introduce some formatting.

When using RSL_to_string in hand-written code for a non-built-in type, it is necessary to mention the required type in the RSL code so that RSL_to_string is defined for that type. Defining an abbreviation for the type will suffice.


Chris George, April 17, 2008

10.13 Input/output handling
10.12 Universal types10.12 Universal types
10 C++ translator 10 C++ translator
10.14 An example 10.14 An example