First Class Citizens
First class citizens are top level file structures, all support type parameters.
Functions
// format
<exp> <extern> fn snake_case param1: type1, param2: type2 (-> ReturnType) = <expr body>
// examples
fn foo () = { }
fn bar baz: i32 -> bool = { }
exp fn export_process param1: Type1, truth: bool -> ProcessedType2 = { }
extern fn fopen stream: FILE* -> i32
Modifiers
Export
To export a function from a file, the exp
keyword is used somewhere in the function declaration, before the fn
keyword.
External
To bind a function to an externally linked one, you use the extern
keyword. External functions must not have a function body.
Imports
For importing files, the syntax is use "path"
, with either a relative path or absolute path for resolved external dependencies (currently only aatbe's stdlib is supported).
use "relative/path/to/file" // imports ./relative/path/to/file.aat
use "fmt/print" // imports stdlib/fmt/print.aat
use "math/vec3"
use "prelude" // imports stdlib/prelude.aat
Example
project/
├── main.aat
├── top.aat
└── module
├── foo.aat
└── bar.aat
// main.aat
use "module/foo" // imports project/module/foo.aat
use "top" // imports project/top.aat
// foo.aat
use "bar" // imports project/module/bar.aat
use "../top.aat" // imports project/top.aat
Records
Analogue to C like structures.
rec Name(first: str, last: str)
Usage and initialization
// given the previous definition for Name
fn new :Name, first_val: str, last_val: str -> Name
= Name {
first: first_val,
last: last_val,
}
fn example () = {
val name_a = Name {
first: "John",
last: "Jim",
}
val name_b = new :Name, "Jane", "Doe"
}
Typedefs
Newtype pattern
Newtype is a way to isolate values of a certain type, with a new name. Example definition and usage:
type Age = u8
type Name = str
fn example () = {
val age = Age 18u8
val name = Name "Jack"
*age // accesses the value of age (u8)
*name // accesses the value of name (str)
}
Variant types
type Variant
= CaseA str, bool
| CaseB i32, str
| CaseC bool
fn example () = {
val caseA = CaseA "foo", true
val caseC = CaseC false
// Both caseA and caseC have the same parent type of `Variant
// But they have a different variant type which can be matched on
caseA.1 // access the str (first) field
caseA.2 // access the bool (second) field
}
Misc Typedefs
type union = u8 | u16 | i32 // pretty much UB, works in the language, no idea why
type Opaque // used to forward define an opaque type