oxdesign.ox (6323B)
i64 a = 42; // like a "let" statement or final variable, runtime constant.
#i32 X = 42; // compile time constant
~i64 z = 42; // make a integer 32bit that is a variable (can be updated) `~` initialised with 2.
z = 67;
str b = str("some string somehow");
chr c = 'c';
arr<i32>[14] = arr[1, 2, 3];
set<str> names = {};
fx add (x i32, y i32) i32 {
return x + y;
}
fx flip(a some, b some) (some, some) => b, a
fx add (i i32, j i32) i32 {
return i + j;
}
struct Person {
}
fx main() {
print("Hello, world!");
}
fx fetch_url(str url) str?! async {
str res = await fetch(url);
return res;
}
// default types
// i8, i16, i32, i64,
// u8, u16, u32, u64,
// f8, f16, f32, f64,
// str, chr, bool,
// arrays (fixed) and lists (dynamic)
arr<i32>[16] ages; // fixed slice of 16
vec<i32> bobs; // dynamic list
set<str> names; // sets
struct<Person> {
i32 age;
str name;
}
fn say_hello () void {
print("hello"); // print is part of stdlib.local which is auto imported
warn("hello"); // this print to stderr instead
print_("hello\n"); // all of the above but with `_` won't insert a trailing \n
fatal("hello"); // fatal print, returning non-zero
}
// strings are really arrays of special u32, aka vec<chr>
typedef chr u32; // (but u32 is not a rune/chr, as the whole UTF-16 range does not cover u32)
// exported function returns one i32
fx add (i32 a, b) i32 => a + b;
// fx = function is exported
// fn = function is static
fx passed (Person p) {} // ownership passed and cannot be used after
fn borrow (Person& p) {} // borrowed and unmutable
fn mutate (Person~ p) {} // borrowed and mutable
fn unsafe (Person* p) unsafe {} // C style passing of pointer, must tag `unsafe`
// lambda style function definition
fx add = (i32 a, b) i32 => a + b;
// void return is implicit, so is void type arg
fx say_hello() {
print("hello");
}
// multiple return values go into parens
fx flip(i32 a, b) (i32, i32) => b, a;
struct Person {
str name,
i16 age,
i32 number,
str street,
str suburb,
str postcode,
str country,
// string interpolation `$.` is identifying a type component
fx address () str => "$.number, $.street, $.suburb $.postcode\n$.country"
}
extend Person {
...
}
// lambda style main function
fn main() void => print("hello world");
fn main(i32 argc, arr<str> argv) int {
if argc != 0 {
print("usage...");
return 0;
}
print("hello world! $argc"); // string interpolation similar to Dart's
return 0;
}
fn rename({str name}) str {} // enforce the label to be passed: rename(name:"jack")
// if statement don't have required parens, they're optional
if a == b {
do_this();
} else if a == c {
do_that();
} else {
do_nothing();
}
// inline if can be done as is
if cache_miss() { print("cached missed!"); }
// ternary if
i32 bla = cond ? 42 : 420;
// for statements
// classic for statement use commas separated init, cond and modifier
for (i32 i = 0, i < 42, i++) {}
for i32 i in 0..< 42 {} // shorthand for loop with for each
for chr c in word {} // for each .. in
for (chr c, i32 i) in word {} // for each in with index, parens optional
// while loops
while cond == true {
// body
}
// infinite loop until broken
loop {}
// switch
switch (action.key) {
KEY_ENTER {
open_door();
}
KEY_UP { move_up(); }
default {
warn("unsupported!")
}
}
// match expr
chr c = match key {
61 => 'a';
62 => 'b';
default => '_';
}
// dealing with nil values. They're not allowed unless unsafe in play.
Person? p = find("jack");
if Person x = p {
print("found jack of ${x.age} age"); // safe usage
}
if p {
print("found jack of ${p!.age} age"); // force unwrap
}
Person* p = NULL; // is allowed. NULL is a constant 0xffffff of some kind.
// not allowed: Person&? Person~?
// null coalescing of maybes
print("jack may be of ${p?.age ?? \"some unknown\"}");
i32 res = some_test() ?? 42;
// namespacing
ns main; // is default and not required, this unit will require a main function
ns tools; // loosely required to be in tools/
// using namespaces, importing, namespaces are forced lowercase to not impact types
use math; // bring all of math functions in, to be prefixed by math.something
use math { random, sin, cos }; // limit the import to these symbols, directly accessible: sin()
use math as mth; // alias math to `mth`
// async operations using the Aloha assignment operator `~=`
i32? response = await some_long_action();
// error handling
fn fetch_data({str url}) async str! {
// fetch the data of the website, parse the body content
// return the body content
await ...
return content;
}
struct Error {
u16 code,
str message,
Error? cause
}
str website_data = await try fetch_data(url: "fleacebook.com") or Error e => print("could not fetch data ${e.message}");
fx flip(i32 a, b) (i32, i32)! {
}
// APPENDIX
// keywords
// return, break, continue, if, else, for, while, loop, goto, defer, heap, free,
// type, ext, union, arr, vec, set, typedef, fx, fn, maybe, mut, ref, ptr, voidptr,
// unsafe, inline
// types
// all of the
// stdlib.local auto imported
// equivalent of `use always { print, print_, warn, warn_, fatal }`
// print, print_, warn, warn_, fatal
// FFI interaction with C and C types
// core FFI aliases
typedef voidptr = void*;
typedef cstr = char*;
typedef ccstr = const char*;
use math;
use c <stdio.h>;
use c <stdlib.h>;
use c <stdint.h>;
use c "include/termbox2.h";
extern c {
fn printf(ccstr, ...) int;
fn free(voidptr);
fn malloc(size_t) voidptr;
fn tb_print(i32, i32, u16, u16, cstr); // x, y, fg, bg, text
// NOTES
// don't use `const char*` etc. and warn against it at compile time
// use cstr or ccstr instead to avoid the baggage of weird
// pointer precedence and const position
//
}
fn main() {
voidptr ptr = malloc(65128);
// invalid: *ptr = 420 // voidptr should be undereferenceable
// no deref of voidptr without a cast
ptr<u8> bytes = cast(ptr<u8> p);
bytes[0] = 42;
free(ptr);
// presume init called etc.
tb_print(12, 12, TB_MAGENTA, TB_BLACK, c_const_str("some words of wisdom"));
}