ox

The Ox programming language, compiler and tools (WIP)
Log | Files | Refs | README | LICENSE

oxdesign.ox (6323B)


      1 i64  a = 42; // like a "let" statement or final variable, runtime constant.
      2 #i32 X = 42; // compile time constant
      3 ~i64 z = 42; // make a integer 32bit that is a variable (can be updated) `~` initialised with 2.
      4 
      5 z = 67;
      6 
      7 str b = str("some string somehow");
      8 chr c = 'c';
      9 
     10 arr<i32>[14] = arr[1, 2, 3];
     11 set<str> names = {};
     12 
     13 fx add (x i32, y i32) i32 {
     14     return x + y;
     15 }
     16 
     17 fx flip(a some, b some) (some, some) => b, a
     18 
     19 fx add (i i32, j i32) i32 {
     20     return i + j;
     21 }
     22 
     23 struct Person {
     24     
     25 }
     26 
     27 fx main() {
     28     print("Hello, world!");
     29 }
     30 
     31 fx fetch_url(str url) str?! async {
     32     str res = await fetch(url);
     33     return res;
     34 }
     35 
     36 // default types
     37 // i8, i16, i32, i64,
     38 // u8, u16, u32, u64,
     39 // f8, f16, f32, f64,
     40 // str, chr, bool,
     41 
     42 // arrays (fixed) and lists (dynamic)
     43 arr<i32>[16] ages;  // fixed slice of 16
     44 vec<i32> bobs;      // dynamic list
     45 set<str> names;     // sets
     46 
     47 struct<Person> {
     48     i32 age;
     49     str name;
     50 }
     51 
     52 fn say_hello () void {
     53     print("hello");     // print is part of stdlib.local which is auto imported
     54     warn("hello");      // this print to stderr instead
     55     print_("hello\n");  // all of the above but with `_` won't insert a trailing \n
     56     fatal("hello");     // fatal print, returning non-zero
     57 }
     58 
     59 // strings are really arrays of special u32, aka vec<chr>
     60 typedef chr u32; // (but u32 is not a rune/chr, as the whole UTF-16 range does not cover u32)
     61 
     62 // exported function returns one i32
     63 fx add (i32 a, b) i32 => a + b;
     64 
     65 // fx = function is exported
     66 // fn = function is static
     67 
     68 fx passed (Person  p) {} // ownership passed and cannot be used after
     69 fn borrow (Person& p) {} // borrowed and unmutable
     70 fn mutate (Person~ p) {} // borrowed and mutable
     71 fn unsafe (Person* p) unsafe {} // C style passing of pointer, must tag `unsafe`
     72 
     73 // lambda style function definition
     74 fx add = (i32 a, b) i32 => a + b;
     75 
     76 // void return is implicit, so is void type arg
     77 fx say_hello() {
     78     print("hello");
     79 }
     80 
     81 // multiple return values go into parens
     82 fx flip(i32 a, b) (i32, i32) => b, a;
     83 
     84 struct Person {
     85     str name,
     86     i16 age,
     87     i32 number,
     88     str street,
     89     str suburb,
     90     str postcode,
     91     str country,
     92     // string interpolation `$.` is identifying a type component
     93     fx address () str => "$.number, $.street, $.suburb $.postcode\n$.country"
     94 }
     95 
     96 extend Person {
     97     ...
     98 }
     99 
    100 // lambda style main function
    101 fn main() void => print("hello world");
    102 
    103 fn main(i32 argc, arr<str> argv) int {
    104     if argc != 0 {
    105         print("usage...");
    106         return 0;
    107     }
    108     print("hello world! $argc"); // string interpolation similar to Dart's
    109     return 0;
    110 }
    111 
    112 fn rename({str name}) str {} // enforce the label to be passed: rename(name:"jack")
    113 
    114 // if statement don't have required parens, they're optional
    115 
    116 if a == b {
    117     do_this();
    118 } else if a == c {
    119     do_that();
    120 } else {
    121     do_nothing();
    122 }
    123 
    124 // inline if can be done as is
    125 if cache_miss() { print("cached missed!"); }
    126 
    127 // ternary if
    128 i32 bla = cond ? 42 : 420;
    129 
    130 // for statements
    131 // classic for statement use commas separated init, cond and modifier
    132 for (i32 i = 0, i < 42, i++) {}
    133 
    134 for i32 i in 0..< 42 {} // shorthand for loop with for each
    135 
    136 for chr c in word {} // for each .. in
    137 
    138 for (chr c, i32 i) in word {} // for each in with index, parens optional
    139 
    140 // while loops
    141 while cond == true {
    142     // body
    143 }
    144 
    145 // infinite loop until broken
    146 loop {}
    147 
    148 // switch
    149 switch (action.key) {
    150     KEY_ENTER {
    151         open_door();
    152     }
    153     KEY_UP { move_up(); }
    154     default {
    155         warn("unsupported!")
    156     }
    157 }
    158 
    159 // match expr
    160 chr c = match key {
    161     61 => 'a';
    162     62 => 'b';
    163     default => '_';
    164 }
    165 
    166 
    167 // dealing with nil values. They're not allowed unless unsafe in play.
    168 Person? p = find("jack");
    169 
    170 if Person x = p {
    171     print("found jack of ${x.age} age");  // safe usage
    172 }
    173 
    174 if p {
    175     print("found jack of ${p!.age} age"); // force unwrap
    176 }
    177 
    178 Person* p = NULL; // is allowed. NULL is a constant 0xffffff of some kind.
    179 
    180 // not allowed: Person&? Person~?
    181 
    182 // null coalescing of maybes
    183 print("jack may be of ${p?.age ?? \"some unknown\"}");
    184 
    185 i32 res = some_test() ?? 42;
    186 
    187 // namespacing
    188 
    189 ns main;  // is default and not required, this unit will require a main function
    190 ns tools; // loosely required to be in tools/
    191 
    192 // using namespaces, importing, namespaces are forced lowercase to not impact types
    193 
    194 use math;                       // bring all of math functions in, to be prefixed by math.something
    195 use math { random, sin, cos };  // limit the import to these symbols, directly accessible: sin()
    196 use math as mth;                // alias math to `mth`
    197 
    198 
    199 // async operations using the Aloha assignment operator `~=`
    200 
    201 i32? response = await some_long_action();
    202 
    203 // error handling
    204 
    205 fn fetch_data({str url}) async str! {
    206     // fetch the data of the website, parse the body content
    207     // return the body content
    208     await ...
    209     return content;
    210 }
    211 
    212 struct Error {
    213     u16 code,
    214     str message,
    215     Error? cause
    216 }
    217 
    218 str website_data = await try fetch_data(url: "fleacebook.com") or Error e => print("could not fetch data ${e.message}");
    219 
    220 
    221 fx flip(i32 a, b) (i32, i32)! {
    222 
    223 }
    224 
    225 
    226 // APPENDIX
    227 
    228 // keywords
    229 // return, break, continue, if, else, for, while, loop, goto, defer, heap, free,
    230 // type, ext, union, arr, vec, set, typedef, fx, fn, maybe, mut, ref, ptr, voidptr,
    231 // unsafe, inline
    232 
    233 
    234 // types
    235 // all of the
    236 // stdlib.local auto imported
    237 // equivalent of `use always { print, print_, warn, warn_, fatal }`
    238 // print, print_, warn, warn_, fatal
    239 
    240 // FFI interaction with C and C types
    241 // core FFI aliases
    242 typedef voidptr = void*;
    243 typedef cstr    = char*;
    244 typedef ccstr   = const char*;
    245 
    246 use math;
    247 use c <stdio.h>;
    248 use c <stdlib.h>;
    249 use c <stdint.h>;
    250 use c "include/termbox2.h";
    251 
    252 extern c {
    253     fn printf(ccstr, ...) int;
    254     fn free(voidptr);
    255     fn malloc(size_t) voidptr;
    256     fn tb_print(i32, i32, u16, u16, cstr); // x, y, fg, bg, text
    257 
    258     // NOTES
    259     // don't use `const char*` etc. and warn against it at compile time
    260     // use cstr or ccstr instead to avoid the baggage of weird
    261     //     pointer precedence and const position
    262     //
    263 }
    264 
    265 fn main() {
    266     voidptr ptr = malloc(65128);
    267     // invalid: *ptr = 420 // voidptr should be undereferenceable
    268     // no deref of voidptr without a cast
    269     ptr<u8> bytes = cast(ptr<u8> p);
    270     bytes[0] = 42;
    271     free(ptr);
    272 
    273     // presume init called etc.
    274     tb_print(12, 12, TB_MAGENTA, TB_BLACK, c_const_str("some words of wisdom"));
    275 }