Repository navigation
Records
Record prototypes are declared roughly accordingly to the following syntax:
record myrec {
int property;
float another_prop = 9f;
}
A property expects a type, an identfier, and then a terminating semicolon. If there isn't a terminating semicolon following the property identifier, a set token and a default value is expected. Note that after the record prototype is declared, no terminating semicolon is required, or expected. Note: The default value of a record doesn't necessarily have to be a constant. It can be a global variable, a procedure evaluation from those global variables, or another struct/array declaration.
Records can inherit and assume the properties of another base record via inheritance using the extend keyword.
record person {
int age = 10;
}
record student extends person{
float gpa;
}
Any instance of student will also have the properties defined in person, and all base classes person has inherited (which in this example, is none). Note that superforth doesn't check for circular inheritance, so it's important to be careful. student can also be succesfully typechecked/casted into any value/argument that expects a person value - though note that it doesn't work vice versa - only for inherited records casting into any of it's base records. Heres an example to better demonstrate the above:
global readonly auto print_age = proc(person myPerson) return nothing {
println(itos(myPerson.age));
};
student michael = new student;
print_age(michael); //this is completley valid
Also note that every instance of a derived record would also assume and initialize the same default values declared in any of it's base records.
Record-prototypes may also specify generic type parameters in the same way procedures do. However, do note that inherited records will also request generic type arguments if applicable. See more here about type arguments/parameters.
record list<elemType> {
//...stuff
}
record queue<queueElem> extends list<queueElem> {
//...more stuff
}
Note: You can also pass generic type parameters as type arguments because after all they are types.
In addition, when generic type parameters, for structs only, are defined, one can also specify a type-requirement - something very much like an interface of sorts. Consider the following declaration:
record listmodif<listType extends list<any>> {
listType list;
extraProperty
}
Note that upon any declaration of a then-undeclared identifier will declare a record type. Note that the first declaration will also specify the amount of expected generic type arguments of a record. This may cause further ERROR_UNEXPECTED_ARGUMENT_SIZE down the line when another reference to the same struct, or a record declaration uses a different amount of generic type arguments.
At the very end of parsing (when an EOF is reached on the first input file), SuperForth will invoke an ERROR_UNDECLARED upon any undefined structs. It doesn't accurately reflect the first-reference/definition, but it will fail compilation.
- Getting Started
- The Language and Syntax
- Type Declarations
- Primitive Values
- Collection/Object Values
- Operators
-
The Standard Library
- More docs coming soon after APs.
- FFI and Interoperability
- The Implementation