very WIP...
// single line comment
/* multiline comment */
// signed and unsigned integers
i8 u8 i16 u16
i32 u32 i64 u64
// floating point numbers
f16 f32 f64
// built-in containers and others
bool
str
T[] // array
(T, ...) // tuple
|T, ...| -> T // function pointer
// modifiers that go before the type, i.e. `var foo: const i32 = 20`
const // compile time constant
readonly // unmutable value stored in memory
all integers & number types default init to 0x00000...
booleans default to false
strings & arrays default init with a length of 0 and an invalid data pointer
function pointers default init with a pointer of 0x00000...
tuples default initialize their contents with each type's default initialization
i.e. var foo: (i32, || -> i32) // foo becomes a valid tuple with all zeros.
// simple variables
var foo: i32 = 10
var bar: i32[] = [20, 30, 40]
var gup: (i32, i32) = (30, 40)
var flag: custom_enum = custom_enum.valid
// constructed things:
var big_data: custom_struct = custom_struct()
var big_state: custom_class = custom_class()
// strings:
var name: str = "joshua"
var info: str = "Health: {hp}, 3 + 5 = {3 + 5}" // string formatting
var multi: str = "strings just automagically
// include the line break! no need
// for special tokens or whatever."
struct // collection of many variables
union // holds one variable that can be only be one type within the union at a time
enum // C style enumerators, effectively compile time constants grouped together nicely
class // C++ style classes
// placed before any declaration in a class (including funcs) I.E. `private var foo: i32 = 10`
public // default, access always allowed
private // access only allowed within the current class
protected // access only allowed within self and any overriding classes
// placed before any `fn` keyword in a class I.E. `virtual fn draw() -> void`
virtual // function that must be overridden
override // keyword that says we're overriding a virtual function
// unions
union message {
var text: str
var num: i32
}
// structs
struct hello {
var a: i32 = 10
var b: str = "beans"
var c: *i16
fn bla() -> void {}
}
// enums
enum hello: i32 {
a = 1,
b = 2,
c = 2 << 3, // expressions work too, etc
}
// classes
class shape {
var position: (f32, f32)
var velocity: (f32, f32)
var color: (f32, f32, f32) = (0.8, 0.5, 0.2) // values to init with on construction
// function stored "outside" of class
// all instances of this class reference the same function pointer
fn update(delta: f64) -> void {
position.x += velocity.x
position.y += velocity.y
}
// pure virtual function declaration
// can include expression if you want i guess
virtual fn render(delta: f64) -> void
}
class circle : shape { // inheritance
var radius: f32,
// virtual function override
override fn render(delta: f64) -> void {
}
}
// multi inheritance syntax same as C++
class bread : fooditem, colorable {}
// important:
= // generally represents equality
// sets variables to EQUAL something, and in typedefs defines defaults
: // used to denote type after names in variable declarations
// used to denote inheritance when defining a class
// and also to define an enumerators underlying type
; // denotes the end of a line of code, maybe needed occasionally
// math:
+ - * / // add, subtract, multiply, divide
^ % // raise power, modulus
<< >> // bitshift
// comparison: (returns true / false)
== !=
< <= > >=
if else elif
do while
for
if ( expr1 ) {
// code ran if expr1 is true
} elif ( expr2 ) {
// otherwise we check if expr2 is true
// if it is, this code is ran instead
} else {
// otherwise we run this if no other expr was true
}
/*
- first argument is used specially by the compiler to
manually set up a new variable local to the scope of the loop
- second argument is an expression
for as long as it is true, the third argument is evaluated and the loop is entered
- third argument is an expression
it's usually used to change the state of the variable defined in the first lambda
it is evaluated every loop
*/
for (index: i32 = 20, index < 50, index++) {
// during this loop
// index is created and set to 20
// and for as long as it is less than 50
// we add 1 to index and go back to the top
}
foreach (key: i32, value: i32, example_dict_container) {
// iterates and unpacks the last argument (the container)
// and puts it into the variables defined by all other arguments
}
for (x: i32 in collection)
for collection.next(&x)
collection implements .next()
array example:
fn next(i: *i32) -> bool {
if (?data[i+1]) {
i += 1;
return true
}
return false
}
while (expr) {
// block is entered if expr is true, and loops for as long as expr is still true
}
do {
// block is always entered, and loops to the start if expr is true
} while (expr)