fully working implementation
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 6 Feb 2024 02:21:02 +0000 (20:21 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 6 Feb 2024 02:21:02 +0000 (20:21 -0600)
compiler/src/parser.c
core/container/array.onyx
core/container/bucket_array.onyx
core/container/heap.onyx
core/container/set.onyx
core/onyx/cbindgen.onyx
tests/aoc-2020/day17.onyx
tests/aoc-2020/day19.onyx
tests/aoc-2020/day23.onyx
tests/aoc-2021/day18.onyx
tests/where_clauses.onyx

index 9a2d1c68737a6f3b447823cb1005e947434280d7..a60f522a65dee2573789a457a1700811cfb81907 100644 (file)
@@ -1020,6 +1020,21 @@ static AstTyped* parse_factor(OnyxParser* parser) {
                 break;
             }
 
+            case Token_Type_Inserted_Semicolon: {
+                //
+                // This is a special case for -> method calls because they should be able to be split across
+                // multiple lines, unlike all other postfix operators. This is a personal choice, but I think
+                // it reads better than:
+                //      iter.as_iter(1 .. 10)->
+                //      map(x => x * 2)->
+                //      collect()
+                //
+                if (peek_token(1)->type != Token_Type_Right_Arrow) goto factor_parsed;
+
+                consume_token(parser);
+                // fallthrough
+            }
+
             case Token_Type_Right_Arrow: {
                 AstBinaryOp* method_call = make_node(AstBinaryOp, Ast_Kind_Method_Call);
                 method_call->token = expect_token(parser, Token_Type_Right_Arrow);
@@ -1146,6 +1161,19 @@ static BinaryOp binary_op_from_token_type(TokenType t) {
     }
 }
 
+static BinaryOp binary_op_from_current_token(OnyxParser *parser) {
+    BinaryOp op = binary_op_from_token_type(parser->curr->type);
+
+    if (op == Binary_Op_Count && parser->curr->type == Token_Type_Inserted_Semicolon) {
+        if (peek_token(1)->type == Token_Type_Pipe) {
+            consume_token(parser);
+            op = Binary_Op_Pipe;
+        }
+    }
+
+    return op;
+}
+
 static AstTyped* parse_compound_assignment(OnyxParser* parser, AstTyped* lhs) {
     if (parser->curr->type != '=') return lhs;
 
@@ -1224,7 +1252,7 @@ static AstTyped* parse_expression(OnyxParser* parser, b32 assignment_allowed) {
             goto expression_done;
         }
 
-        bin_op_kind = binary_op_from_token_type(parser->curr->type);
+        bin_op_kind = binary_op_from_current_token(parser);
         if (bin_op_kind == Binary_Op_Count) goto expression_done;
         if (binop_is_assignment(bin_op_kind) && !assignment_allowed) goto expression_done;
         if (bin_op_kind == Binary_Op_Subscript) goto expression_done;
@@ -2339,7 +2367,9 @@ static AstStructType* parse_struct(OnyxParser* parser) {
     while (!consume_token_if_next(parser, '}')) {
         if (parser->hit_unexpected_token) return s_node;
 
-        parse_possible_tag(parser);
+        if (parse_possible_tag(parser)) {
+            consume_token_if_next(parser, ';');
+        }
 
         if (parse_possible_directive(parser, "persist")) {
             b32 thread_local = parse_possible_directive(parser, "thread_local");
index 5b9abc7bfb31385122fbb52288af45a0db748269..95c476e79a0461e7cadb65695f3503827f986344 100644 (file)
@@ -153,7 +153,7 @@ push :: (arr: &[..] $T, x: T) -> bool {
 
 // Semi-useful shortcut for adding something to an array.
 #operator << macro (arr: [..] $T, v: T) {
-    #this_package.push(&arr, v)
+    #this_package.push(&arr, v);
 }
 
 
index 47ef1cd302c863d391a2deb2631a8a5a2cb7c550..74876a93c773e2046514282b465a95f54aeacd60 100644 (file)
@@ -87,7 +87,7 @@ push :: (use b: &Bucket_Array($T), elem: T) -> bool {
 }
 
 #operator << macro (b: Bucket_Array($T), elem: T) {
-    #this_package.push(&b, elem)
+    #this_package.push(&b, elem);
 }
 
 pop :: (use b: &Bucket_Array($T)) {
index 5db9bbcd4da40c3a3edd0329b6797b1fa591529f..f4d9adce914347880a76622cba4cbe60f97b43c5 100644 (file)
@@ -24,7 +24,7 @@ insert :: (use heap: &Heap, v: heap.T) {
 }
 
 #operator << macro (heap: Heap($T), v: T) {
-    #this_package.insert(&heap, v)
+    #this_package.insert(&heap, v);
 }
 
 remove_top :: (use heap: &Heap) -> heap.T {
index c7cda96c08f390d8fc482e3c6e9bf8b811e4a2b1..47cbf92873dc29c45de42dcd670bcf7a054b22e3 100644 (file)
@@ -85,7 +85,7 @@ insert :: (use set: &Set, value: set.Elem_Type) {
 }
 
 #operator << macro (set: Set($T), value: T) {
-    #this_package.insert(&set, value)
+    #this_package.insert(&set, value);
 }
 
 has :: (use set: &Set, value: set.Elem_Type) -> bool {
index d2e81a78042915803a08aa00fe3b3f3aace848ab..ba57760fcd6a5ce422f6d56aaa7e343a68b7a7a6 100644 (file)
@@ -237,8 +237,7 @@ compile_c_file :: (
         io.write(writer, ")) {\n");
 
         method_name := slice.find_opt(ff.tags, [it](it.type == customize))
-                       ->transform(x => misc.any_as(x, customize).symbol_name)
-                       ?? ff.name;
+                       ->transform(x => misc.any_as(x, customize).symbol_name) ?? ff.name;
 
         if name_map != null_proc {
             method_name = name_map(method_name);
@@ -348,8 +347,8 @@ compile_c_file :: (
             } elseif it_info.kind == .Struct && it_info->as_struct().constructed_from != cptr {
                 param_type := it;
                 name := slice.find_opt(cast_map, [x](x.type == param_type))
-                    ->expect(tprintf("Structures used as parameter arguments MUST have a definition in the 'cast_map' in '{}'.", method_name))
-                    .name;
+                    ->transform(x => x.name)
+                    ->expect(tprintf("Structures used as parameter arguments MUST have a definition in the 'cast_map' in '{}'.", method_name));
 
                 io.write_format(&callw, "*({} *) ONYX_PTR(P({}, i32))", name, param_num); // This is dependent on the pointer size
 
@@ -382,8 +381,8 @@ compile_c_file :: (
 
             return_type = return_type->info()->as_pointer().to;
             type_name := slice.find_opt(cast_map, [x](x.type == return_type))
-                ->expect(tprintf("Types used as last argument return values MUST have a definition in the 'cast_map' in '{}'.", method_name))
-                .name;
+                ->transform(x => x.name)
+                ->expect(tprintf("Types used as last argument return values MUST have a definition in the 'cast_map' in '{}'.", method_name));
 
             io.write_format(writer, "    *({} *) ONYX_PTR(P({}, i32)) = {}({});\n", type_name, param_num, method_name, call_str);
             
index 575060dc2161acbd275f39f3c94364a0be5c2b57..f30695a0b9700d4673bbd80bdfaa17d4d0200408 100644 (file)
@@ -25,10 +25,10 @@ CubePos :: struct {
     }
 
     equals :: (a, b: CubePos) => {
-        return (a.x == b.x)
-            && (a.y == b.y)
-            && (a.z == b.z)
-            && (a.w == b.w);
+        return (a.x == b.x) &&
+               (a.y == b.y) &&
+               (a.z == b.z) &&
+               (a.w == b.w);
     }
 }
 
index f1a89651c947a48e82f2fe1f54532296db52bb59..8fe2392259294fe8359fa194e5df7bd1eb8b2d7a 100644 (file)
@@ -92,8 +92,8 @@ cyk_algorithm :: (use grammar: &Grammar, input: str) -> bool {
         for s in 0 .. input.count - l {
             for p in 1 .. l + 1 {
                 for &prod in production_rules {
-                    if    T[(p - 1) * dim_0 + s       * dim_1 + prod.nt1 * dim_2]
-                       && T[(l - p) * dim_0 + (s + p) * dim_1 + prod.nt2 * dim_2] {
+                    if T[(p - 1) * dim_0 + s       * dim_1 + prod.nt1 * dim_2] &&
+                       T[(l - p) * dim_0 + (s + p) * dim_1 + prod.nt2 * dim_2] {
                         T[l * dim_0 + s * dim_1 + prod.nt0 * dim_2] = true;
                     }
                 }
index 310fdb71de698528c83c25b8cffde3cf90dae21e..71b3a4e79701cd4111b02a2d3c91d5f44fcd37bf 100644 (file)
@@ -32,9 +32,10 @@ simulate :: (cups: [] i32, moves := 100) {
         next_3 := cw[next_2];
         
         destination_cup := w(current_cup - 1);
-        while  destination_cup == ~~next_1
-            || destination_cup == ~~next_2
-            || destination_cup == ~~next_3 {
+        while  destination_cup == ~~next_1 ||
+               destination_cup == ~~next_2 ||
+               destination_cup == ~~next_3
+        {
             destination_cup = w(destination_cup - 1);
         }
 
index 1f708d1dcf00fa5b83ebd89ac8db6a0d43975be5..643c95394150fca0295f82086108279f23137e3a 100644 (file)
@@ -182,8 +182,8 @@ SnailNum :: struct {
             return 0;
         }
 
-        return 3 * (left_val + left->magnitude())
-            +  2 * (right_val + right->magnitude());
+        return 3 * (left_val + left->magnitude()) +
+               2 * (right_val + right->magnitude());
     }
 
     parse :: (line: &str) -> &SnailNum {
index dd4aa8c8f89562ec281b864f3612802ad493ed82..be3655f75456c41cd4a506bde58d32d74ec65c28 100644 (file)
@@ -18,8 +18,7 @@ Adder :: interface(T: type_expr) {
     { t + t } -> T;
 }
 
-add :: (a, b: [$N]$T) -> [N]T
-   where Adder(T), N > 0, N <= 4
+add :: (a, b: [$N]$T) -> [N] T where Adder(T), N > 0, N <= 4
 {
    return a + b;
 }