|
|
| ||||||
10.13 Input/output handling |
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 ... }
<.
and .>
are two
tokens, not four, so <.7,9,13. >
will not be accepted.
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.
(1, Vint(7), "Margrethe")
can be interpreted as a value of type Int × V × Text where V is the variant type defined above.
{1,4,9} {1 .. 100}
can be interpreted as values of type Int-set.
<.1,1,4,4,9,9.> <.1 .. 100.>
can be interpreted as values of type Int*.
"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.
[ 1 +> "en", 2 +> "to", 3 +> "tre" ]
can be interpreted as a value of type Int -m-> Text.
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.
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.
'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'
.
RSL_boolalpha
when invoking
the compiler.
There is no way to format the output, e.g. to break a long list over several lines.
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.
10.13 Input/output handling | ||||||||
|
|
|