ox

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

oxdesign.ox (5982B)


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