19. Built-in Functions, Procedures and Methods
Gazprea has some built-in functions and procedures that do not follow the usual rules for functions and procedures.
The names of the built-in functions and procedures are reserved. A user program
may not declare any function or procedure identifier
with the same name as a built-in function or procedure; doing
so would shadow the built-in, and the compiler must emit a SymbolError
(see Errors). These names are reserved semantically rather than being
syntactic keywords.
The vector/string method names (push,
append, len), by contrast, are not reserved. They live in a method
namespace associated with the compiler-defined vector object
and so do not collide with the
global identifier namespace. A user may freely declare, say, a function
len() or a variable named push.
Note that although the examples below all use arrays, the array-shaped
built-ins (length, reverse) also work on
vectors and strings, using
whatever length that value currently holds. The shape-specific built-ins
keep the domains their own sections describe: rows and columns
require a two-dimensional matrix, and format takes only scalars.
Applying a built-in outside its defined domain
is a compile-time error and the compiler must emit a
TypeError (see Errors).
19.1. Signatures
Gazprea has no user-facing type parameters (they may be added in a future
revision), but the built-ins are generic over element and scalar types. Their
signatures are therefore written below with a [T] type-parameter notation
purely for exposition: function id[T](T obj) returns T; reads as “id is
generic over T”. This notation is not part of the language.
function length[T](T[*] arr) returns integer; // also accepts a vector<T> / string
function rows[T](T[*][*] mat) returns integer;
function columns[T](T[*][*] mat) returns integer;
function reverse[T](T[*] arr) returns T[*]; // also accepts a vector<T> / string
function format[T](T value) returns string; // T is a scalar type
procedure stream_state(var input_stream) returns integer; // notional; see below
The per-built-in sections below give each domain and its error conditions in full.
19.2. Vector and String Methods
In addition to these free-standing built-ins, vector and string values
carry methods – push, append, and len – invoked with receiver
syntax (v.len()). These are specified with the type, in
Method Calls, not here. In particular, len (a method, on vectors
and strings only) and length (a built-in, accepting arrays, vectors, and
strings) answer the same question with different spellings and different domains:
Query on |
|
|
|---|---|---|
array |
the fixed length |
|
|
the current length |
the current length |
19.3. Length
length takes an rank-1 array of any element type, and
returns an integer representing the number of elements in the array.
length is not defined for an array of rank greater than 1; use rows
and columns (see Rows and Columns) for a two-dimensional
matrix instead. In future editions of the spec this may be extended to a
generic shape function, but that is left to future revisions of the
course.
integer[*] v = 1..5;
length(v) -> std_output; /* Prints 5 */
Output
5
Because an array is initialization-time sized, length applied to
an array is invariant after initialization: every call returns the
same number. Applied to a vector (or a
string), length returns the value’s current
length instead, so two calls may return different numbers if the vector grew
in between. In this role length is simply the built-in spelling of the
vector’s len method.
var vector<integer> v = [1, 2, 3];
length(v) -> std_output; /* Prints 3 */
call v.push(4); /* 'v' is now [1, 2, 3, 4] */
length(v) -> std_output; /* Prints 4 */
19.4. Rows and Columns
The built-ins rows and columns report the dimensions of a
rank-2 array (a matrix): rows returns the
number of rows and columns the number of columns.
integer[*][*] M = [[1, 2, 3], [4, 5, 6]];
rows(M) -> std_output; /* Prints 2 */
'\n' -> std_output;
columns(M) -> std_output; /* Prints 3 */
Output
2
3
19.5. Reverse
The reverse built-in takes any rank-1 array, vector, or string, and returns a reversed array. Even when the argument is a vector or string, the result is an array value. Vector-ness (string-ness) is not preserved, just as for the element-wise operators (see Operations). The resulting array may of course be implicitly cast back to a vector or string when stored into one.
integer[*] v = 1..5;
integer[*] w = reverse(v);
v -> std_output; /* Prints [1 2 3 4 5] */
'\n' -> std_output;
w -> std_output; /* Prints [5 4 3 2 1] */
Output
[1 2 3 4 5]
[5 4 3 2 1]
19.6. Format
The format built-in takes any scalar as input and
returns a string containing the formatted value of the scalar. The result
uses the same representation the scalar’s type has when sent to an output
stream (see Output Format). This function only takes scalars;
a type with no defined output format
(a tuple or struct) cannot be formatted.
integer i = 24;
real r = 2.4;
"i = " || format(i) || ", r = " || format(r) || "\n" -> std_output;
// Prints: "i = 24, r = 2.4\n"
Output
i = 24, r = 2.4
Note that format allocates space to hold the return string; the
implementation is responsible for reclaiming it.
19.7. Stream State
When reading values of certain types from std_input it is possible that an
error is encountered, or that the end of the stream has been encountered. In
order to handle these situations Gazprea provides a built-in procedure that is
implicitly defined in every file:
procedure stream_state(var input_stream) returns integer;
The signature is notional: input_stream is not a Gazprea type, and
the only valid argument is std_input. The form is general enough that
it could be reused if the language were expanded to include multiple input
streams.
The returned state codes, the initial state, and the per-type behavior of
reads are specified in Error Handling. In brief: 0 means the
last read succeeded, 1 that it encountered an error, and 2 that it
encountered the end of the stream.
var boolean b;
var integer i;
// Input stream: 9
b <- std_input; // b = false (error reading boolean)
i = stream_state(std_input); // i = 1 (last read was error)
i <- std_input; // i = 9 (successfully read integer)
i = stream_state(std_input); // i = 0 (last read was success)
b <- std_input; // b = false (read end of stream)
i = stream_state(std_input); // i = 2 (last read was end of stream)
Input
9
The input stream is described in more detail in the input stream section.