[X] Procedures as arguments
+ [ ] Deferred statements
+
+ [ ] Pointer math
+
+ [ ] Better checking for casts
+
+ [ ] Hex literals
+
[ ] Start work on evaluating compile time known values.
- An expression marked COMPTIME will be reduced to its value in the parse tree.
&& binop->operation <= Binary_Op_Assign_End);
}
+static inline b32 binop_is_compare(AstBinaryOp* binop) {
+ return (binop->operation >= Binary_Op_Equal
+ && binop->operation <= Binary_Op_Greater_Equal);
+}
+
static inline b32 node_is_type(AstNode* node) {
return (node->kind > Ast_Kind_Type_Start) && (node->kind < Ast_Kind_Type_End);
}
Token_Type_Keyword_Return,
Token_Type_Keyword_Global,
Token_Type_Keyword_Proc,
+ Token_Type_Keyword_As,
Token_Type_Keyword_Cast,
Token_Type_Keyword_While,
Token_Type_Keyword_For,
# strings in YAML. When using single quoted strings, only single quotes
# need to be escaped: this is done by using two single quotes next to each
# other.
- - match: '\b(package|struct|proc|use|global|enum|if|elseif|else|for|while|do|break|continue|return|as|sizeof|alignof)\b'
+ - match: '\b(package|struct|proc|use|global|enum|if|elseif|else|for|while|do|break|continue|return|as|cast|sizeof|alignof)\b'
scope: keyword.control.onyx
- match: '\b(bool|void|i8|u8|i16|u16|i32|u32|i64|u64|f32|f64|rawptr)\b'
scope: constant.type.onyx
- - match: '\b(true|false)\b'
+ - match: '\b(true|false|null)\b'
scope: constant.boolean.onyx
# Numbers
syn keyword onyxKeyword if elseif else
syn keyword onyxKeyword for while do
syn keyword onyxKeyword break continue return
-syn keyword onyxKeyword as sizeof alignof
+syn keyword onyxKeyword as cast sizeof alignof
syn keyword onyxType bool void
syn keyword onyxType i8 u8
syn region onyxComment start="//" end="$" keepend contains=onyxCommentStart
+syn region onyxDirective start="#" end=" " keepend
+
hi def link onyxKeyword Statement
hi def link onyxType Type
hi def link onyxComment Comment
hi def link onyxCommentStart Todo
hi def link onyxConstant Constant
+hi def link onyxDirective Constant
let b:current_syntax = "onyx"
let &cpo = s:cpo_save
--- /dev/null
+package alloc
+
+use "progs/intrinsics"
+
+use package printing { print }
+
+use package intrinsics {
+ memory_size, memory_grow
+}
+
+// Need to define this somewhere
+null :: cast(rawptr) 0;
+
+heap_state : struct {
+ free_list : ^heap_block;
+ next_alloc : rawptr;
+ remaining_space : u32;
+}
+
+heap_block :: struct {
+ size : i32;
+ next : ^heap_block;
+}
+
+heap_init :: proc {
+ heap_state.free_list = null;
+ heap_state.next_alloc = __heap_start;
+ heap_state.remaining_space = (memory_size() << 16) - cast(u32) __heap_start;
+}
+
+heap_align_to :: 16
+
+heap_alloc :: proc (size_: i32) -> rawptr {
+ if size_ == 0 return null;
+
+ size := size_ + sizeof heap_block;
+ if size % heap_align_to != 0 {
+ size += heap_align_to - (size % heap_align_to);
+ }
+
+ prev := ^heap_state.free_list;
+ hb := heap_state.free_list;
+ while hb != null {
+ if hb.size >= size {
+ *prev = hb.next;
+ hb.next = null;
+
+ return cast(rawptr) (cast(u32) hb + sizeof heap_block);
+ }
+
+ prev = ^hb.next;
+ hb = hb.next;
+ }
+
+ if size < heap_state.remaining_space {
+ ret := cast(^heap_block) heap_state.next_alloc;
+ ret.size = size;
+ ret.next = null;
+
+ heap_state.next_alloc = cast(rawptr) (cast(u32) heap_state.next_alloc + size);
+ heap_state.remaining_space -= size;
+
+ return cast(rawptr) (cast(u32) ret + sizeof heap_block);
+ }
+
+ // grow the memory with memory_grow
+ return cast(rawptr) -1;
+}
+
+heap_free :: proc (ptr: rawptr) {
+ hb_ptr := cast(^heap_block) (cast(u32) ptr - sizeof heap_block);
+ hb_ptr.next = heap_state.free_list;
+ heap_state.free_list = hb_ptr;
+}
\ No newline at end of file
--- /dev/null
+use "progs/alloc"
+use "progs/print_funcs"
+
+use package alloc
+use package printing
+
+proc #export "main" {
+ asdf :: "staring asdfkjasd asdflkjasdflkajsdflk";
+ heap_init();
+
+ first := cast([] i32) heap_alloc(sizeof [4] i32);
+ for i: 0, 4 first[i] = i * 2;
+
+ second := cast([] f32) heap_alloc(sizeof [24] f32);
+ for i: 0, 24 second[i] = cast(f32) i;
+
+ print(cast(u32) first);
+ print(cast(u32) second);
+
+ for i: 0, 4 print(first[i]);
+ for i: 0, 24 print(second[i]);
+
+ heap_free(first);
+
+ third := cast(^i32) heap_alloc(sizeof i32);
+
+ print(cast(u32) third);
+ *third = 1234;
+ print(*third);
+
+ heap_free(second);
+
+ fourth := cast([] i32) heap_alloc(sizeof [128]i32);
+ print(cast(u32) fourth);
+
+ fifth := cast(^i32) heap_alloc(sizeof i32);
+ print(cast(u32) fifth);
+
+ sixth := heap_alloc(8 << 16);
+ print(cast(u32) sixth);
+}
\ No newline at end of file
// Address of and dereference cancel each other out
print(^*hello_str);
- print(hello_str as []u8, 5);
+ print(cast([] u8) hello_str, 5);
for i: 0, 10, 2 print(i);
// Don't need to bind this function to a symbol
proc #export "main" {
len :: 10;
- global_arr = alloc(sizeof [10]i32) as []i32;
+ global_arr = cast([] i32) alloc(sizeof [10]i32);
for i: 0, len global_arr[i] = (len - i) * 10;
alloc :: proc (size: u32) -> rawptr {
- heap_u32 :: __heap_start as ^u32;
+ heap_u32 :: cast(^i32) __heap_start;
curr_offset := *heap_u32;
if curr_offset == 0 curr_offset = 8;
*heap_u32 = curr_offset + size;
- return ((__heap_start as u32) + curr_offset) as rawptr;
+ return cast(rawptr) (cast(u32) __heap_start + curr_offset);
}
alloc_2darr :: proc (rows: u32, cols: u32) -> []^i32 {
- arr := alloc(rows * 4) as []^i32;
- for i: 0, cols arr[i] = alloc(cols * 4) as ^i32;
+ arr := cast([] ^i32) alloc(rows * 4);
+ for i: 0, cols arr[i] = cast(^i32) alloc(cols * 4);
return arr;
}
}
cond :: true;
- print(test(cond) as i32);
+ print(cast(i32) test(cond));
}
use "progs/intrinsics"
}
foo_other :: proc (use this: ^Foo) {
- print(st as i32);
+ print(cast(i32) st);
}
asdf :: proc (pa: PrintableArray) {
- for i: 0, pa.len print(pa.data[i] as i32);
+ for i: 0, pa.len print(cast(i32) pa.data[i]);
}
SomeType :: enum {
}
print_st :: proc (st: SomeType, other: i32) {
- print(st as i32);
+ print(cast(i32) st);
}
single_int : u32
proc #export "main" {
print("Hello World! this is slightly longer\n");
- print(__heap_start as i32);
+ print(cast(i32) __heap_start);
single_int = 10;
print(single_int);
st: SomeType = SomeType.Value4;
print_st(st, 10);
- foo := __heap_start as ^Foo;
+ foo := cast(^Foo) __heap_start;
foo.x = 123;
foo.y = 321;
foo.st = st;
print(foo_sum(foo));
print_st(foo.st, 20);
- pa := (__heap_start as i32 + sizeof Foo) as ^PrintableArray;
- pa.data = __heap_start as ^u8;
+ pa := cast(^PrintableArray) (cast(i32) __heap_start + sizeof Foo);
+ pa.data = cast(^u8) __heap_start;
pa.len = 5;
asdf(*pa);
}
minus_one :: proc (n: i32) -> i32 { return n - 1; }
-double :: proc (n: i32) -> i32 { return n << 1; }
+double :: proc (n: i32) -> i32 { return n << 1; }
proc #export "main" {
call_me(echo, 10);
- print(add as my_int);
+ print(cast(my_int) add);
funcs[0] = add;
funcs[1] = sub;
for i: 0, 5 print(funcs[i](10, 3));
- dc := __heap_start as ^DeferredCall;
+ dc := cast(^DeferredCall) __heap_start;
dc.func = add;
dc.left = 40;
dc.right = 19;
print(execute(dc));
len :: 10;
- data := (__heap_start as i32 + sizeof DeferredCall) as ^i32;
+ data := cast(^i32) (cast(i32) __heap_start + sizeof DeferredCall);
for i: 0, len data[i] = i;
- print(data as [] i32, len);
+ print(cast([] i32) data, len);
add_one :: proc (n: i32) -> i32 { return n + 1; };
array_map(len, data, add_one);
- print(data as [] i32, len);
+ print(cast([] i32) data, len);
cheese := Cheeses.Cheddar;
break;
}
}
-
}
Cheeses :: enum {
Cheddar;
Muenster;
Mozerella;
-}
\ No newline at end of file
+}
// NOTE: print null-terminated string
print_str :: proc (str: ^u8) {
c := str;
- while *c != 0 as u8 {
- print((*c) as i32);
- c = (c as i32 + 1) as ^u8;
+ while *c != cast(u8) 0 {
+ print(cast(i32) (*c));
+ c = cast(^u8) (cast(i32) c + 1);
}
}
print_str_len :: proc (str: [] u8, len: i32) {
- for i: 0, len print(str[i] as i32);
+ for i: 0, len print(cast(i32) str[i]);
}
print :: proc #overloaded {
}
alloc :: proc (size: u32) -> rawptr {
- heap_u32 :: __heap_start as ^u32;
+ heap_u32 :: cast(^u32) __heap_start;
curr_offset := *heap_u32;
if curr_offset == 0 curr_offset = 8;
*heap_u32 = curr_offset + size;
- return ((__heap_start as u32) + curr_offset) as rawptr;
+ return cast(rawptr) (cast(u32) __heap_start + curr_offset);
}
foo_make :: proc -> ^Foo {
- return alloc(sizeof Foo) as ^Foo;
+ return cast(^Foo) alloc(sizeof Foo);
}
foo_get :: proc (fooarr: []Foo, i: i32) -> ^Foo {
}
link_create :: proc (data: i32, parent: ^^Link) {
- link := alloc(sizeof Link) as ^Link;
+ link := cast(^Link) alloc(sizeof Link);
link.data = data;
link.next = *parent;
*parent = link;
count := 0;
walker := start;
- while (walker as i32) != 0 {
+ while cast(i32) walker != 0 {
print(walker.data);
walker = walker.next;
count += 1;
}
link_test :: proc #export "main4" {
- node_head := alloc(sizeof ^Link) as ^^Link;
- *node_head = 0 as ^Link;
+ node_head := cast(^^Link) alloc(sizeof ^Link);
+ *node_head = cast(^Link) 0;
link_create(0, node_head);
link_create(1, node_head);
// TODO: Make everything below this comment work
multi_arr :: proc #export "main2" {
- arr1 := alloc(sizeof [5][5] i32) as [5][5] i32; // Sizeof 25 * 4
- arr2 := alloc(sizeof [5]^ i32) as [5]^ i32; // Sizeof 20
+ arr1 := cast([5][5] i32) alloc(sizeof [5][5] i32); // Sizeof 25 * 4
+ arr2 := cast([5] ^i32) alloc(sizeof [5]^ i32); // Sizeof 20
arr2[3][2] = 5; // (arr1 + (3 * 5 * 4) + (2 * 4))
print(arr2[3][2]);
}
v2magnitude :: proc (v: ^Vec2) -> f32 {
- return sqrt_f32((v.x * v.x + v.y * v.y) as f32);
+ return sqrt_f32(cast(f32) (v.x * v.x + v.y * v.y));
}
v3magnitude :: proc (v: ^Vec3) -> f32 {
- return sqrt_f32((v.x * v.x + v.y * v.y + v.z * v.z) as f32);
+ return sqrt_f32(cast(f32) (v.x * v.x + v.y * v.y + v.z * v.z));
}
magnitude :: proc #overloaded { v2magnitude, v3magnitude };
}
proc #export "main" {
- v2 := alloc(sizeof Vec2) as ^Vec2;
+ v2 := cast(^Vec2) alloc(sizeof Vec2);
v2.x = 5;
v2.y = 12;
print(v2.magnitude());
- v3 := alloc(sizeof Vec3) as ^Vec3;
+ v3 := cast(^Vec3) alloc(sizeof Vec3);
v3.x = 1;
v3.y = 1;
v3.z = 1;
print((1).minus(2));
- foo := alloc(sizeof Fool) as ^Fool;
- foo.bar = alloc(sizeof Bar) as ^Bar;
+ foo := cast(^Fool) alloc(sizeof Fool);
+ foo.bar = cast(^Bar) alloc(sizeof Bar);
foo.bar.i = 50;
- foo.bar.j = 70 as i64;
+ foo.bar.j = cast(i64) 70;
(*foo.bar).print_bar();
}
// print(sizeof SOA); // 240
- soa := alloc(sizeof SOA + 20 * sizeof Vec2) as ^SOA;
+ soa := cast(^SOA) alloc(sizeof SOA + 20 * sizeof Vec2);
for i: 0, 10 {
- soa.things[i] = alloc(sizeof Vec2) as ^Vec2;
+ soa.things[i] = cast(^Vec2) alloc(sizeof Vec2);
}
soa.velocities[2].x = 10;
print(soa.positions[6].x);
print(soa.positions[6].y);
- m_arr := alloc(sizeof [5][5]i32) as [5][5]i32;
+ m_arr := cast([5][5] i32) alloc(sizeof [5][5]i32);
for y: 0, 5 {
for x: 0, 5 {
}
}
- for i: 0, 25 print((m_arr as [] i32)[i]);
+ for i: 0, 25 print((cast([] i32) m_arr)[i]);
}
\ No newline at end of file
+// EVERYTHING IN THIS FILE IS VERY BROKEN SINCE UFC HAS BEEN
+// DISABLED.
+
use "progs/intrinsics"
use "progs/print_funcs"
use package printing as printing
alloc :: proc (size: u32) -> rawptr {
- heap_u32 :: __heap_start as ^u32;
+ heap_u32 :: cast(^u32) __heap_start;
curr_offset := *heap_u32;
if curr_offset == 0 curr_offset = 8;
*heap_u32 = curr_offset + size;
- return ((__heap_start as u32) + curr_offset) as rawptr;
+ return cast(rawptr) (cast(u32) __heap_start + curr_offset);
}
}
vec2_magnitude :: proc (use v: ^Vec2) -> i32 {
- return sqrt_f32(x * x + y * y) as i32;
+ return cast(i32) sqrt_f32(x * x + y * y);
}
Vec3 :: struct {
proc #export "main" {
- vec := alloc(sizeof Vec2) as ^Vec2;
+ vec := cast(^Vec2) alloc(sizeof Vec2);
vec.x = 5.0f;
vec.y = 12.0f;
printing.print(dot(2.0f, 4.0f, -6.0f, 3.0f));
- v3 := alloc(sizeof Vec3) as ^Vec3;
+ v3 := cast(^Vec3) alloc(sizeof Vec3);
v3.x = 5.0f;
v3.y = 12.0f;
v3.z = 13.0f;
return compiler_progress != ONYX_COMPILER_PROGRESS_SUCCESS;
}
-
-// NOTE: Old bits of code that may be useful again at some point.
-#if 0
- bh_printf("There are %d tokens (Allocated space for %d tokens)\n", bh_arr_length(token_arr), bh_arr_capacity(token_arr));
-
- bh_arr_each(OnyxToken, it, token_arr) {
- onyx_token_null_toggle(*it);
- bh_printf("%s (%s:%l:%l)\n", onyx_get_token_type_name(it->type), it->pos.filename, it->pos.line, it->pos.column);
- onyx_token_null_toggle(*it);
- }
-#endif
-
-#if 0
- // NOTE: Ensure type table made correctly
-
- bh_printf("Type map:\n");
- bh_hash_each_start(i32, wasm_mod.type_map);
- bh_printf("%s -> %d\n", key, value);
- bh_hash_each_end;
-
- bh_printf("Type list:\n");
- WasmFuncType** func_type = wasm_mod.functypes;
- while (!bh_arr_end(wasm_mod.functypes, func_type)) {
- for (int p = 0; p < (*func_type)->param_count; p++) {
- bh_printf("%c ", (*func_type)->param_types[p]);
- }
- bh_printf("-> ");
- bh_printf("%c\n", (*func_type)->return_type);
-
- func_type++;
- }
-#endif
-
-#if 0
- // NOTE: Ensure the export table was built correctly
-
- bh_printf("Function types:\n");
- bh_arr_each(WasmFunc, func_it, wasm_mod.funcs) {
- bh_printf("%d\n", func_it->type_idx);
- }
-
- bh_printf("Exports:\n");
- bh_hash_each_start(WasmExport, wasm_mod.exports);
- bh_printf("%s: %d %d\n", key, value.kind, value.idx);
- bh_hash_each_end;
-#endif
}
} else {
- if (type_is_pointer(binop->left->type)
- || type_is_pointer(binop->right->type)) {
+ if (!binop_is_compare(binop) &&
+ (type_is_pointer(binop->left->type)
+ || type_is_pointer(binop->right->type))) {
onyx_message_add(Msg_Type_Literal,
binop->token->pos,
"binary operations are not supported for pointers (yet).");
"global",
"proc",
"as",
+ "cast",
"while",
"for",
"break",
LITERAL_TOKEN("global", 1, Token_Type_Keyword_Global);
LITERAL_TOKEN("return", 1, Token_Type_Keyword_Return);
LITERAL_TOKEN("proc", 1, Token_Type_Keyword_Proc);
- LITERAL_TOKEN("as", 1, Token_Type_Keyword_Cast);
+ LITERAL_TOKEN("as", 1, Token_Type_Keyword_As);
+ LITERAL_TOKEN("cast", 1, Token_Type_Keyword_Cast);
LITERAL_TOKEN("while", 1, Token_Type_Keyword_While);
LITERAL_TOKEN("for", 1, Token_Type_Keyword_For);
LITERAL_TOKEN("break", 1, Token_Type_Keyword_Break);
break;
}
+ case Token_Type_Keyword_Cast: {
+ AstUnaryOp* cast_node = make_node(AstUnaryOp, Ast_Kind_Unary_Op);
+ cast_node->token = expect_token(parser, Token_Type_Keyword_Cast);
+ expect_token(parser, '(');
+ cast_node->type_node = parse_type(parser);
+ expect_token(parser, ')');
+ cast_node->operation = Unary_Op_Cast;
+ cast_node->expr = parse_factor(parser);
+
+ retval = (AstTyped *) cast_node;
+ break;
+ }
+
case Token_Type_Keyword_Sizeof: {
AstSizeOf* so_node = make_node(AstSizeOf, Ast_Kind_Size_Of);
so_node->token = expect_token(parser, Token_Type_Keyword_Sizeof);
return NULL;
}
- while (parser->curr->type == '[' || parser->curr->type == Token_Type_Keyword_Cast
- || parser->curr->type == '.' || parser->curr->type == '(') {
+ while (parser->curr->type == '[' || parser->curr->type == '.' || parser->curr->type == '(') {
switch ((u16) parser->curr->type) {
case '[': {
break;
}
- case Token_Type_Keyword_Cast: {
- AstUnaryOp* cast_node = make_node(AstUnaryOp, Ast_Kind_Unary_Op);
- cast_node->token = expect_token(parser, Token_Type_Keyword_Cast);
- cast_node->type_node = parse_type(parser);
- cast_node->operation = Unary_Op_Cast;
- cast_node->expr = retval;
-
- retval = (AstTyped *) cast_node;
- break;
- }
-
case '(': {
AstCall* call_node = make_node(AstCall, Ast_Kind_Call);
call_node->token = expect_token(parser, '(');
pack_symbol->token = expect_token(parser, Token_Type_Symbol);
upack->package = (AstPackage *) pack_symbol;
- // followed by 'as'
- if (parser->curr->type == Token_Type_Keyword_Cast) {
+ if (parser->curr->type == Token_Type_Keyword_As) {
consume_token(parser);
upack->alias = expect_token(parser, Token_Type_Symbol);
}
AstAlias* alias = make_node(AstAlias, Ast_Kind_Alias);
alias->token = expect_token(parser, Token_Type_Symbol);
- if (parser->curr->type == Token_Type_Keyword_Cast) {
+ if (parser->curr->type == Token_Type_Keyword_As) {
consume_token(parser);
alias->alias = expect_token(parser, Token_Type_Symbol);
} else {
if ((t1->Basic.flags & Basic_Flag_Integer) && (t2->Basic.flags & Basic_Flag_Integer)) {
return t1->Basic.size == t2->Basic.size;
}
+
+ if (t1->Basic.kind == Basic_Kind_Rawptr && type_is_pointer(t2)) {
+ return 1;
+ }
}
break;
return t1->Basic.size == t2->Basic.size;
}
}
+
+ if (t1->Basic.kind == Basic_Kind_Rawptr && type_is_pointer(t2)) {
+ return 1;
+ }
break;
case Type_Kind_Pointer: {
if (t2->kind == Type_Kind_Pointer) {
return types_are_compatible(t1->Pointer.elem, t2->Pointer.elem);
}
+
+ if (t2->kind == Type_Kind_Basic && t2->Basic.kind == Basic_Kind_Rawptr)
+ return 1;
+
break;
}