made 'proc' keyword optional in certain cases; bug fixes
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 21 Jan 2021 00:56:15 +0000 (18:56 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 21 Jan 2021 00:56:15 +0000 (18:56 -0600)
bin/onyx
core/alloc/arena.onyx
core/math.onyx
src/onyxparser.c
tests/aoc-2020/day22.onyx

index 707c6d4bdeae3e61431bef9ca75efcb14ab89fb2..82a5f9a086e1a01f43c584572e2172a770118d70 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 93ac331755e546d77482c723c1bbc3cd5a8ec279..e30515f5c018e6eb04af95ef25a356fc8784f907 100644 (file)
@@ -35,6 +35,10 @@ arena_alloc_proc :: proc (data: rawptr, aa: AllocationAction, size: u32, align:
             return null;
         }
 
+        if alloc_arena.size % align != 0 {
+            alloc_arena.size += align - (alloc_arena.size % align);
+        }
+
         if alloc_arena.size + size >= alloc_arena.arena_size {
             new_arena := cast(^Arena) raw_alloc(alloc_arena.backing_allocator, alloc_arena.arena_size);
             if new_arena == null do return null;
index 812c70f6f523bc915aff993c885797836d57ecc4..7ab959c358daee30046042b7c78cce3cf8e488db 100644 (file)
@@ -2,9 +2,11 @@ package core.math
 
 use package core.intrinsics.wasm {
     sqrt_f32, sqrt_f64,
-    abs_f32,  abs_f64
+    abs_f32,  abs_f64,
+    copysign_f32, copysign_f64
 }
 
+E   :: 2.71828182845904523536f;
 PI  :: 3.14159265f;
 TAU :: 6.28318330f;
 
@@ -67,6 +69,8 @@ sqrt_i32 :: proc (x: i32) -> i32 do return ~~sqrt_f32(~~x);
 sqrt_i64 :: proc (x: i64) -> i64 do return ~~sqrt_f64(~~x);
 sqrt :: proc { sqrt_f32, sqrt_f64, sqrt_i32, sqrt_i64 }
 
+copysign :: proc { copysign_f32, copysign_f64 }
+
 abs_i32 :: proc (x: i32) -> i32 {
     if x >= 0 do return x;
     return -x;
@@ -78,26 +82,51 @@ abs_i64 :: proc (x: i64) -> i64 {
 abs :: proc { abs_i32, abs_i64, abs_f32, abs_f64 }
 
 pow_int :: proc (base: $T, p: i32) -> T {
-    if base == 0 && p == 0 do return 1;
-    elseif p == 0 do return 1;
+    if base == 0 do return 0;
+    if p == 0    do return 1;
+
     a := 1;
-    b := p;
-    c := base;
-    while b > 0 {
-        if b % 2 == 1 do a *= c;
-        b = b >> 1;
-        c *= c;
+    while p > 0 {
+        if p % 2 == 1 do a *= base;
+        p = p >> 1;
+        base *= base;
     }
+
     return a;
 }
 
-pow_float :: proc (base: $T, p: f32) -> T {
-    if base == 0 && p == 0 do return 1;
-    elseif p == 0 do return 1;
+pow_float :: proc (base: $T, p: T) -> T {
+    if p >= 1 {
+        tmp := pow_float(p = p / 2, base = base);
+        return tmp * tmp;
+    }
+
+    low  : T = 0;
+    high : T = 1;
+
+    sqr := sqrt(base);
+    acc := sqr;
+    mid := high / 2;
+
+    while abs(mid - p) > 0.00001 {
+        sqr = sqrt(sqr);
+
+        if mid <= p {
+            low = mid;
+            acc *= sqr;
+        } else {
+            high = mid;
+            acc /= sqr;
+        }
+
+        mid = (low + high) / 2;
+    }
 
+    return acc;
 }
 
 pow :: proc { pow_int, pow_float }
+exp :: proc (p: $T) -> T do return pow(base = cast(T) E, p = p);
 
 ln :: proc (a: f32) -> f32 {
 
index 5f6e1016af4ab719bf3160c472deb2e0497c145a..9273549ef3dc8b2f392263a7c29b680b57be6eca 100644 (file)
@@ -45,7 +45,8 @@ static AstType*       parse_type(OnyxParser* parser);
 static AstStructType* parse_struct(OnyxParser* parser);
 static void           parse_function_params(OnyxParser* parser, AstFunction* func);
 static b32            parse_possible_directive(OnyxParser* parser, const char* dir);
-static AstFunction*   parse_function_definition(OnyxParser* parser);
+static b32            parse_possible_function_definition(OnyxParser* parser, AstTyped** ret);
+static AstFunction*   parse_function_definition(OnyxParser* parser, OnyxToken* token);
 static AstTyped*      parse_global_declaration(OnyxParser* parser);
 static AstEnumType*   parse_enum_declaration(OnyxParser* parser);
 static AstTyped*      parse_top_level_expression(OnyxParser* parser);
@@ -85,6 +86,31 @@ static void find_token(OnyxParser* parser, TokenType token_type) {
     }
 }
 
+static OnyxToken* find_matching_paren(OnyxToken* paren) {
+    TokenType match = 0;
+    switch ((u16) paren->type) {
+        case '(': match = ')'; break;
+        case '[': match = ']'; break;
+        case '{': match = '}'; break;
+        case '<': match = '>'; break;
+        default: return NULL;
+    }
+
+    i32 paren_count = 1;
+    i32 i = 1;
+    while (paren_count > 0) {
+        TokenType type = (paren + i)->type;
+        if (type == Token_Type_End_Stream) return NULL;
+
+        if (type == paren->type) paren_count++;
+        else if (type == match)  paren_count--;
+
+        i++;
+    }
+
+    return paren + (i - 1);
+}
+
 // Advances to next token no matter what
 static OnyxToken* expect_token(OnyxParser* parser, TokenType token_type) {
     if (parser->hit_unexpected_token) return NULL;
@@ -269,6 +295,12 @@ static AstTyped* parse_factor(OnyxParser* parser) {
 
     switch ((u16) parser->curr->type) {
         case '(': {
+            if (parse_possible_function_definition(parser, &retval)) {
+                // CLEANUP
+                add_node_to_process(parser, (AstNode *) retval);
+                break;
+            }
+
             consume_token(parser);
             AstTyped* expr = parse_compound_expression(parser, 0);
             expect_token(parser, ')');
@@ -420,7 +452,8 @@ static AstTyped* parse_factor(OnyxParser* parser) {
         }
 
         case Token_Type_Keyword_Proc: {
-            retval = (AstTyped *) parse_function_definition(parser);
+            OnyxToken* proc_token = expect_token(parser, Token_Type_Keyword_Proc);
+            retval = (AstTyped *) parse_function_definition(parser, proc_token);
             retval->flags |= Ast_Flag_Function_Used;
 
             // TODO: Maybe move this somewhere else?
@@ -684,7 +717,7 @@ static inline i32 get_precedence(BinaryOp kind) {
 }
 
 static BinaryOp binary_op_from_token_type(TokenType t) {
-    switch (t) {
+    switch ((u16) t) {
         case Token_Type_Equal_Equal:       return Binary_Op_Equal;
         case Token_Type_Not_Equal:         return Binary_Op_Not_Equal;
         case Token_Type_Less_Equal:        return Binary_Op_Less_Equal;
@@ -1937,12 +1970,10 @@ static void parse_function_params(OnyxParser* parser, AstFunction* func) {
 }
 
 // 'proc' <func_params> ('->' <type>)? <directive>* <block>
-static AstFunction* parse_function_definition(OnyxParser* parser) {
-    OnyxToken* proc_token = expect_token(parser, Token_Type_Keyword_Proc);
-
+static AstFunction* parse_function_definition(OnyxParser* parser, OnyxToken* token) {
     if (parser->curr->type == '{') {
         AstOverloadedFunction* ofunc = make_node(AstOverloadedFunction, Ast_Kind_Overloaded_Function);
-        ofunc->token = proc_token;
+        ofunc->token = token;
 
         bh_arr_new(global_heap_allocator, ofunc->overloads, 4);
 
@@ -1963,7 +1994,7 @@ static AstFunction* parse_function_definition(OnyxParser* parser) {
     }
 
     AstFunction* func_def = make_node(AstFunction, Ast_Kind_Function);
-    func_def->token = proc_token;
+    func_def->token = token;
     func_def->operator_overload = -1;
 
     bh_arr_new(global_heap_allocator, func_def->allocate_exprs, 4);
@@ -2063,6 +2094,47 @@ static AstFunction* parse_function_definition(OnyxParser* parser) {
     }
 }
 
+static b32 parse_possible_function_definition(OnyxParser* parser, AstTyped** ret) {
+    if (parser->curr->type == Token_Type_Keyword_Proc) {
+        OnyxToken* proc_token = expect_token(parser, Token_Type_Keyword_Proc);
+        AstFunction* func_node = parse_function_definition(parser, proc_token);
+        *ret = (AstTyped *) func_node;
+        return 1;
+    }
+
+    if (parser->curr->type == '(') {
+        OnyxToken* matching_paren = find_matching_paren(parser->curr);
+        if (matching_paren == NULL) return 0;
+
+        OnyxToken* token_after_paren = matching_paren + 1;
+        if (token_after_paren->type != Token_Type_Right_Arrow
+            && token_after_paren->type != '{'
+            && token_after_paren->type != Token_Type_Keyword_Do
+            && token_after_paren->type != Token_Type_Empty_Block)
+            return 0;
+
+        b32 hit_colon = 0;
+        OnyxToken* tmp_token = parser->curr;
+        while (tmp_token < matching_paren) {
+            if (tmp_token->type == ':') {
+                hit_colon = 1;
+                break;
+            }
+
+            tmp_token++;
+        }
+
+        if (!hit_colon) return 0;
+
+        OnyxToken* proc_token = parser->curr;
+        AstFunction* func_node = parse_function_definition(parser, proc_token);
+        *ret = (AstTyped *) func_node;
+        return 1;
+    }
+
+    return 0;
+}
+
 // 'global' <type>
 static AstTyped* parse_global_declaration(OnyxParser* parser) {
     AstGlobal* global_node = make_node(AstGlobal, Ast_Kind_Global);
@@ -2161,7 +2233,8 @@ static AstEnumType* parse_enum_declaration(OnyxParser* parser) {
 // <expr>
 static AstTyped* parse_top_level_expression(OnyxParser* parser) {
     if (parser->curr->type == Token_Type_Keyword_Proc) {
-        AstFunction* func_node = parse_function_definition(parser);
+        OnyxToken* proc_token = expect_token(parser, Token_Type_Keyword_Proc);
+        AstFunction* func_node = parse_function_definition(parser, proc_token);
 
         add_node_to_process(parser, (AstNode *) func_node);
 
index 7786c40c67766ffeb94ba646ea330511953a179b..393b0b8a63dbfd897476ae959c3d0069b278e42c 100644 (file)
@@ -45,7 +45,7 @@ combat :: proc (player1: ^[..] u32, player2: ^[..] u32) -> u32 {
 encode_hands :: proc (alloc: Allocator, p1: ^[..] u32, p2: ^[..] u32) -> str {
     use package core.string.builder as b
 
-    builder := b.make(128, alloc);
+    builder := b.make(256, alloc);
     for n: *p1 {
         b.add_i64(^builder, ~~n, 64);
         b.add_str(^builder, ",");