|
|
| ||||||
10.3 Declarations |
If the declaration occurs in a class expression, the declarations are placed at the outermost level.
Declarations from local expressions are included in-line when they are only variables and constant values. Otherwise they are placed in a separate namespace outside the definition where the local expression occurred: see section 10.8.23.
Type declarations are always placed in the header file.
To accommodate C++'s requirement of declaration before use the
produced declarations are
sorted according to kind in the following order:
type definitions (including those from embedded objects)
embedded objects (in namespaces)
constants and functions
variables
test cases
An object definition in RSLC++ cannot have a formal array parameter.
A sort definition translates to an almost empty C++ struct in order to support hand-translation.
type Sort |
gives a warning message and translates to (input/output operators omitted):
struct Sort/*INCOMPLETE: abstract type*/{ bool operator==(const Sort& RSL_v) const{ return true; } bool operator!=(const Sort& RSL_v) const{ return false; } };
A variant definition translates to a struct containing a tag field identifying the variant-choice and a pointer to the record variant. Allocation and deallocation of record variant structures are handled by the various constructor and member functions by means of reference counts. The following struct is the base class of all record variants
struct RSL_class { int refcnt; RSL_class () {refcnt = 1;} };
The variant
type | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
V == | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Vconst | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Vint(Int) | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Vrec(d1Vrec : Int ↔ r1Vrec, d2Vrec : V ↔ r2Vrec) |
translates to (input/output operators included)
// From the .h file ... // type and constant declarations and inline functions static const int RSL_Vconst_tag = 1; static const int RSL_Vint_tag = 2; static const int RSL_Vrec_tag = 3; struct RSL_Vint_type; struct RSL_Vrec_type; struct V{ int RSL_tag; RSL_class* RSL_ptr; V(const int RSL_p0 = 0){ RSL_tag = RSL_p0; RSL_ptr = 0; } V(const RSL_Vint_type* RSL_v){ RSL_tag = RSL_Vint_tag; RSL_ptr = (RSL_class*)RSL_v; } V(const RSL_Vrec_type* RSL_v){ RSL_tag = RSL_Vrec_tag; RSL_ptr = (RSL_class*)RSL_v; } void RSL_destructor(); ~V(){ RSL_destructor(); } V(const V& RSL_v); const V& operator=(const V& RSL_v); bool operator==(const V& RSL_v) const; bool operator!=(const V& RSL_v) const{ return !operator==(RSL_v); } }; extern string RSL_to_string(const V& RSL_v); #ifdef RSL_io extern ostream& operator<<(ostream& RSL_os, const V& RSL_v); extern istream& operator>>(istream& RSL_is, V& RSL_v); #endif //RSL_io static const V Vconst(RSL_Vconst_tag); struct RSL_Vint_type : RSL_class, RSLProduct1<int, RSL_constructor_fun>{ RSL_Vint_type(){} RSL_Vint_type(const int RSL_p1) : RSL_class(), RSLProduct1<int, RSL_constructor_fun>::RSLProduct1(RSL_p1){} }; extern V Vint(const int RSL_p1); struct RSL_Vrec_type : RSL_class, RSLProduct2<int, V, RSL_constructor_fun>{ RSL_Vrec_type(){} RSL_Vrec_type(const int RSL_p1, const V& RSL_p2) : RSL_class(), RSLProduct2<int, V, RSL_constructor_fun>::RSLProduct2(RSL_p1, RSL_p2){} }; extern V Vrec(const int RSL_p1, const V& RSL_p2); inline int d1Vrec(const V& RSL_v){ #ifdef RSL_pre if (RSL_v.RSL_tag != RSL_Vrec_tag) { RSL_fail("V.rsl:6:10: Destructor d1Vrec applied to wrong variant"); } #endif //RSL_pre return ((RSL_Vrec_type*)RSL_v.RSL_ptr)->RSL_f1; } inline V d2Vrec(const V& RSL_v){ #ifdef RSL_pre if (RSL_v.RSL_tag != RSL_Vrec_tag) { RSL_fail("V.rsl:6:35: Destructor d2Vrec applied to wrong variant"); } #endif //RSL_pre return ((RSL_Vrec_type*)RSL_v.RSL_ptr)->RSL_f2; } extern V r1Vrec(const int RSL_p0, const V& RSL_v); extern V r2Vrec(const V& RSL_p0, const V& RSL_v);
The templates RSLProductn (1≤n≤10) are defined in
RSL_Prod.h. Each takes as arguments the n types
making the product plus a function generating a string for a
constructor. This function is RSL_constructor_fun (which
generates the empty string) for products and variant components, and a
function generating "mk_T"
for a record type T.
// From the .cc file ... // RSL constructor, destructor and reconstructor functions void V::RSL_destructor(){ switch (RSL_tag) { case RSL_Vint_tag: if (--(RSL_ptr->refcnt) == 0) { delete (RSL_Vint_type*)RSL_ptr; } break; case RSL_Vrec_tag: if (--(RSL_ptr->refcnt) == 0) { delete (RSL_Vrec_type*)RSL_ptr; } break; } } V::V(const V& RSL_v){ switch (RSL_v.RSL_tag) { case RSL_Vint_tag: case RSL_Vrec_tag: RSL_v.RSL_ptr->refcnt++; } RSL_tag = RSL_v.RSL_tag; RSL_ptr = RSL_v.RSL_ptr; } const V& V::operator=(const V& RSL_v){ if (this == &RSL_v) { return RSL_v; } switch (RSL_v.RSL_tag) { case RSL_Vint_tag: case RSL_Vrec_tag: RSL_v.RSL_ptr->refcnt++; } RSL_destructor(); RSL_tag = RSL_v.RSL_tag; RSL_ptr = RSL_v.RSL_ptr; return *this; } bool V::operator==(const V& RSL_v) const{ if (RSL_tag != RSL_v.RSL_tag) { return false; } switch (RSL_tag) { case RSL_Vint_tag: return *(RSL_Vint_type*)RSL_ptr == *(RSL_Vint_type*)RSL_v.RSL_ptr; case RSL_Vrec_tag: return *(RSL_Vrec_type*)RSL_ptr == *(RSL_Vrec_type*)RSL_v.RSL_ptr; default: return true; } } string RSL_to_string(const V& RSL_v){ string RSL_Temp_0; switch (RSL_v.RSL_tag) { case RSL_Vconst_tag: RSL_Temp_0 = "Vconst"; break; case RSL_Vint_tag: RSL_Temp_0 = "Vint" + RSL_to_string(*(RSL_Vint_type*)RSL_v.RSL_ptr); break; case RSL_Vrec_tag: RSL_Temp_0 = "Vrec" + RSL_to_string(*(RSL_Vrec_type*)RSL_v.RSL_ptr); break; default: RSL_Temp_0 = "Unknown variant value"; break; } return RSL_Temp_0; } #ifdef RSL_io ostream& operator<<(ostream& RSL_os, const V& RSL_v){ switch (RSL_v.RSL_tag) { case RSL_Vconst_tag: RSL_os << "Vconst"; break; case RSL_Vint_tag: RSL_os << "Vint" << *(RSL_Vint_type*)RSL_v.RSL_ptr; break; case RSL_Vrec_tag: RSL_os << "Vrec" << *(RSL_Vrec_type*)RSL_v.RSL_ptr; break; default: RSL_os << "Unknown variant value"; break; } return RSL_os; } const RSL_input_token_type RSL_Vconst_token = Token_StartIndex + 1; const RSL_input_token_type RSL_Vint_token = Token_StartIndex + 2; const RSL_input_token_type RSL_Vrec_token = Token_StartIndex + 3; static void RSL_input_token_V(istream& RSL_is, RSL_input_token_type& RSL_token){ char RSL_buf[128]; RSL_fetch_token(RSL_is, RSL_token, RSL_buf); if (RSL_token == RSL_constructor_token) { if (RSL_streq(RSL_buf, "Vconst")) { RSL_token = RSL_Vconst_token; return; } if (RSL_streq(RSL_buf, "Vint")) { RSL_token = RSL_Vint_token; return; } if (RSL_streq(RSL_buf, "Vrec")) { RSL_token = RSL_Vrec_token; return; } RSL_token = RSL_error_token; } } istream& operator>>(istream& RSL_is, V& RSL_v){ RSL_input_token_type RSL_token; V RSL_temp; RSL_class* RSL_ptr = 0; RSL_input_token_V(RSL_is, RSL_token); switch (RSL_token) { case RSL_Vconst_token: RSL_temp = V(RSL_Vconst_tag); break; case RSL_Vint_token: RSL_ptr = new RSL_Vint_type; RSL_is >> *(RSL_Vint_type*)RSL_ptr; if (RSL_is) { RSL_temp = V((RSL_Vint_type*)RSL_ptr); } break; case RSL_Vrec_token: RSL_ptr = new RSL_Vrec_type; RSL_is >> *(RSL_Vrec_type*)RSL_ptr; if (RSL_is) { RSL_temp = V((RSL_Vrec_type*)RSL_ptr); } break; default: RSL_is.clear(ios::badbit); break; } if (RSL_is) { RSL_v = RSL_temp; } else { RSL_is.clear(ios::badbit); } return RSL_is; } #endif //RSL_io V Vint(const int RSL_p1){ RSL_Vint_type* RSL_v = new RSL_Vint_type(RSL_p1); if (!RSL_v) { abort(); } return V(RSL_v); } V Vrec(const int RSL_p1, const V& RSL_p2){ RSL_Vrec_type* RSL_v = new RSL_Vrec_type(RSL_p1, RSL_p2); if (!RSL_v) { abort(); } return V(RSL_v); } V r1Vrec(const int RSL_p0, const V& RSL_v){ #ifdef RSL_pre if (RSL_v.RSL_tag != RSL_Vrec_tag) { RSL_fail("V.rsl:6:27: Reconstructor r1Vrec applied to wrong variant"); } #endif //RSL_pre return Vrec(RSL_p0, ((RSL_Vrec_type*)RSL_v.RSL_ptr)->RSL_f2); } V r2Vrec(const V& RSL_p0, const V& RSL_v){ #ifdef RSL_pre if (RSL_v.RSL_tag != RSL_Vrec_tag) { RSL_fail("V.rsl:6:50: Reconstructor r2Vrec applied to wrong variant"); } #endif //RSL_pre return Vrec(((RSL_Vrec_type*)RSL_v.RSL_ptr)->RSL_f1, RSL_p0); }
Constructors, destructors and reconstructors translate as the identifier or operator does. Wildcard constructors are not accepted.
When the translated code is compiled with the RSL_io flag, a handwritten C++ compilation unit can perform input/output of variant values. For example:
void main(){ V aV, anotherV; aV = Vint(42); cout << "First value: " << aV << "\n"; cout << "Give a value of type V:\n"; cin >> anotherV; cout << "Second value: " << anotherV << "\n"; }The following is an example of an execution of this program (user lines are marked with
#
):
First value: Vint(42) Give a value of type V: Vrec(1957, Vint(1969)) # Second value: Vrec(1957,Vint(1969))
type | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Complex :: re: Real ↔ r im: Real ↔ i |
translates to
// from the .h file ... char* RSL_mk_Complex_fun(){ return "mk_Complex"; } typedef RSLProduct2<double, double, RSL_mk_Complex_fun> Complex; inline Complex mk_Complex(const double RSL_p1, const double RSL_p2){ return Complex(RSL_p1, RSL_p2); } inline double re(const Complex& RSL_v){ return RSL_v.RSL_f1; } inline double im(const Complex& RSL_v){ return RSL_v.RSL_f2; } extern Complex r(const double RSL_p0, const Complex& RSL_v); extern Complex i(const double RSL_p0, const Complex& RSL_v);
// from the .cc file ... Complex r(const double RSL_p0, const Complex& RSL_v){ return Complex(RSL_p0, RSL_v.RSL_f2); } Complex i(const double RSL_p0, const Complex& RSL_v){ return Complex(RSL_v.RSL_f1, RSL_p0); }
type | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
B = C × C, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
C = {| n : Int • n ∈ {0..7} |}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
D = Nat × Int, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
E = D → D, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
F = C × D → D |
translates to
typedef int C; typedef RSLProduct2<int, int, RSL_constructor_fun> RSL_IxI; typedef RSL_IxI D; typedef RSL_IxI (* RSL_IxIfIxI)(const RSL_IxI ); typedef RSL_IxIfIxI E; typedef RSL_IxI (* RSL_Ix6IxI9fIxI)(const int , const RSL_IxI ); typedef RSL_Ix6IxI9fIxI F; typedef RSL_IxI B;
value | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
low: Int = 0, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
high: Int = low + 100, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
max : Int = Max(low, high), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
p : Int × Bool = (7, true) |
translates to
// Header file: extern const int low; extern const int high; extern const int max; extern const RSL_IxB p;
// Body file: const int low = 0; const int high = low + 100; const int max = Max(low, high); const RSL_IxB p = RSL_IxB(7, true);
Additional code, included if RSL_pre is defined, is generated if any constant types are subtypes, to check that the values of the constants are in the subtypes.
An explicit value definition which defines a function translates by means of a C++ pointer to function type. E.g.
value | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f : Int × Int → Int = Max |
translates to
// Header file: typedef int (* RSL_IxIfI)(const int , const int ); extern const RSL_IxIfI f;
// Body file: const RSL_IxIfI f = Max;
As an example
value | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sqr : Real → Real | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sqr(x) ≡ x*x, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+ : V × Int → V | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
v + i ≡ Vrec(i, v) |
(in the context of the type V defined earlier) translates to
double sqr(const double x_38B){ return x_38B * x_38B; } V RSL_PLUS_op(const V& v_4B3, const int i_4B7){ return Vrec(i_4B7, v_4B3); }
Note that a user-defined operator translates into a function with a name derived from the operator name rather than into an operator. This eases the translation of such operators. In particular it makes them all translatable. The names are given below.
Operator | Function name |
= | RSL_EQ_op |
≠ | RSL_NOTEQ_op |
== | RSL_EQEQ_op |
> | RSL_GT_op |
< | RSL_LT_op |
≥ | RSL_GEQ_op |
≤ | RSL_LEQ_op |
⊃ | RSL_PSUP_op |
⊂ | RSL_PSUB_op |
⊆ | RSL_SUP_op |
⊆ | RSL_SUB_op |
∈ | RSL_ISIN_op |
∉ | RSL_NOTISIN_op |
\ | RSL_MOD_op |
^ | RSL_CONC_op |
∪ | RSL_UNION_op |
† | RSL_OVER_op |
* | RSL_AST_op |
/ | RSL_DIV_op |
# | RSL_HASH_op |
∩ | RSL_INTER_op |
↑ | RSL_EXP_op |
abs | RSL_ABS_op |
int | RSL_INT_op |
real | RSL_REAL_op |
card | RSL_CARD_op |
len | RSL_LEN_op |
inds | RSL_INDS_op |
elems | RSL_ELEMS_op |
hd | RSL_HD_op |
tl | RSL_TL_op |
dom | RSL_DOM_op |
rng | RSL_RNG_op |
+ | RSL_PLUS_op |
- | RSL_MINUS_op |
Access descriptors are ignored. The kind of function arrow (→ or -~->) does not matter.
Only one formal function parameter is accepted. It is not possible to translate
f : Int → Int → Int | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f(x)(y) ≡ ... |
It is not required that the number of parameters matches the number of components in the domain of the function's type expression. For example, the following are all accepted:
type | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
U = Int × Bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
value | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f1: Int × Bool → Bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f1(x, y) ≡ ..., | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f2: (Int × Bool) → Bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f2(x, y) ≡ ..., | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f3: U → Bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f3(x, y) ≡ ..., | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f4: U × Int → Bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f4(x, y) ≡ ..., | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f5: (Int × Bool) × Int → Bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f5(x, y) ≡ ... | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f6: (Int × Bool) × Int → Bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f6(x) ≡ ... | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f7: Int × Bool → Bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f7(x) ≡ ..., | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f8: (Int × Bool) → Bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f8(x) ≡ ..., | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f9: U → Bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f9(x) ≡ ..., | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f10: U × Int → Bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f10((x, y), z) ≡ ..., | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f11: (Int × Bool) × Bool → Bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
f11((x, y), z) ≡ ... |
10.3 Declarations | ||||||||
|
|
|