made even quicker procedures
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 10 Jan 2022 02:20:47 +0000 (20:20 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 10 Jan 2022 02:20:47 +0000 (20:20 -0600)
core/container/list.onyx
src/parser.c
src/polymorph.h
src/symres.c
tests/lazy_iterators.onyx

index 9d8ee581797103ed58690a7ea6a2ed32364634f0..56e2f240318211face61953e4eebec718974f25b 100644 (file)
@@ -8,11 +8,11 @@ ListElem :: struct (T: type_expr) {
     data: T;
 }
 
-List :: struct (T: type_expr) {
+List :: struct (Elem_Type: type_expr) {
     allocator: Allocator;
 
-    first: ^ListElem(T) = null;
-    last:  ^ListElem(T) = null;
+    first: ^ListElem(Elem_Type) = null;
+    last:  ^ListElem(Elem_Type) = null;
 
     // "Method" like things
     free         :: free
@@ -32,7 +32,7 @@ make :: ($T: type_expr, allocator := context.allocator) -> List(T) {
     return .{ allocator = allocator };
 }
 
-free :: (list: ^List($T)) {
+free :: (list: ^List) {
     elem := list.first;
     while elem != null {
         to_delete := elem;
@@ -41,7 +41,7 @@ free :: (list: ^List($T)) {
     }
 }
 
-push_end :: (list: ^List($T), x: T) { 
+push_end :: (list: ^List, x: list.Elem_Type) { 
     new_elem := allocate_elem(list);
     new_elem.data = x;
 
@@ -52,7 +52,7 @@ push_end :: (list: ^List($T), x: T) {
     if list.first == null do list.first = new_elem;
 }
 
-push_begin :: (list: ^List($T), x: T) {
+push_begin :: (list: ^List, x: list.Elem_Type) {
     new_elem := allocate_elem(list);
     new_elem.data = x;
 
@@ -85,7 +85,7 @@ pop_begin :: (list: ^List($T), default: T = __zero_value(T)) -> T {
     return begin.data;
 }
 
-count :: (list: ^List($T)) -> i32 {
+count :: (list: ^List) -> i32 {
     c := 0;
     elem := list.first;
     while elem != null {
@@ -96,7 +96,7 @@ count :: (list: ^List($T)) -> i32 {
     return c;
 }
 
-at :: (list: ^List($T), index: i32) -> ^T {
+at :: (list: ^List, index: i32) -> ^T {
     elem := list.first;
     while elem != null {
         if index == 0 do return ^elem.data;
@@ -107,7 +107,7 @@ at :: (list: ^List($T), index: i32) -> ^T {
     return null;
 }
 
-contains :: (list: ^List($T), x: T) -> bool {
+contains :: (list: ^List, x: list.Elem_Type) -> bool {
     elem := list.first;
     while elem != null {
         if elem.data == x do return true;
index 188dcde0ce0a4cbb517dd574a256dbf7f680caae..24944d6b5f83dd28ca9f582e57832e9783564f40 100644 (file)
@@ -294,7 +294,13 @@ static void parse_arguments(OnyxParser* parser, TokenType end_token, Arguments*
     while (!consume_token_if_next(parser, end_token)) {
         if (parser->hit_unexpected_token) return;
 
-        if (next_tokens_are(parser, 2, Token_Type_Symbol, '=')) {
+        //
+        // This has a weird condition to avoid the problem of using a quick function as an argument:
+        //     f(x => x + 1)
+        // This shouldn't be a named argument, but this should:
+        //     f(g = x => x + 1)
+        //
+        if (next_tokens_are(parser, 2, Token_Type_Symbol, '=') && peek_token(2)->type != '>') {
             OnyxToken* name = expect_token(parser, Token_Type_Symbol);
             expect_token(parser, '=');
 
@@ -440,6 +446,11 @@ static AstTyped* parse_factor(OnyxParser* parser) {
         }
 
         case Token_Type_Symbol: {
+            if (parse_possible_quick_function_definition(parser, &retval)) {
+                ENTITY_SUBMIT(retval);
+                break;
+            }
+
             OnyxToken* sym_token = expect_token(parser, Token_Type_Symbol);
             AstTyped* sym_node = make_node(AstTyped, Ast_Kind_Symbol);
             sym_node->token = sym_token;
@@ -2435,6 +2446,12 @@ typedef struct QuickParam {
 } QuickParam;
 
 static b32 parse_possible_quick_function_definition_no_consume(OnyxParser* parser) {
+    //
+    // x => x + 1 case.
+    if (next_tokens_are(parser, 3, Token_Type_Symbol, '=', '>')) {
+        return 1;
+    }
+
     if (parser->curr->type != '(') return 0;
 
     OnyxToken* matching_paren = find_matching_paren(parser->curr);
@@ -2451,26 +2468,35 @@ static b32 parse_possible_quick_function_definition_no_consume(OnyxParser* parse
 static b32 parse_possible_quick_function_definition(OnyxParser* parser, AstTyped** ret) {
     if (!parse_possible_quick_function_definition_no_consume(parser)) return 0;
 
-    OnyxToken* proc_token = expect_token(parser, '(');
-
     bh_arr(QuickParam) params=NULL;
     bh_arr_new(global_heap_allocator, params, 4);
+    OnyxToken* proc_token;
 
-    while (parser->curr->type != ')') {
-        if (parser->hit_unexpected_token) return 0;
-
+    if (parser->curr->type == Token_Type_Symbol) {
         QuickParam param = { 0 };
-        if (consume_token_if_next(parser, '$')) param.is_baked = 1;
         param.token = expect_token(parser, Token_Type_Symbol);
-
+        proc_token = param.token;
         bh_arr_push(params, param);
 
-        if (parser->curr->type != ')') {
-            expect_token(parser, ',');
+    } else {
+        proc_token = expect_token(parser, '(');
+        while (parser->curr->type != ')') {
+            if (parser->hit_unexpected_token) return 0;
+
+            QuickParam param = { 0 };
+            if (consume_token_if_next(parser, '$')) param.is_baked = 1;
+            param.token = expect_token(parser, Token_Type_Symbol);
+
+            bh_arr_push(params, param);
+
+            if (parser->curr->type != ')') {
+                expect_token(parser, ',');
+            }
         }
+
+        expect_token(parser, ')');
     }
 
-    expect_token(parser, ')');
     expect_token(parser, '=');
     expect_token(parser, '>');
 
index 95781d771586bbfaea57d588dabae54f79836540..744cbfa43719056af09dfb96e65af9eb4fd3955b 100644 (file)
@@ -875,7 +875,7 @@ b32 potentially_convert_function_to_polyproc(AstFunction *func) {
                 case Ast_Kind_Array_Type:   to_replace = &((AstArrayType *)   *to_replace)->elem;  param_type = ((AstArrayType *)   param_type)->elem;  break;
                 case Ast_Kind_Slice_Type:   to_replace = &((AstSliceType *)   *to_replace)->elem;  param_type = ((AstSliceType *)   param_type)->elem;  break;
                 case Ast_Kind_DynArr_Type:  to_replace = &((AstDynArrType *)  *to_replace)->elem;  param_type = ((AstDynArrType *)  param_type)->elem;  break;
-                case Ast_Kind_Alias:                                                               param_type = ((AstAlias *)       param_type)->alias; break;
+                case Ast_Kind_Alias:                                                               param_type = (AstType *) ((AstAlias *) param_type)->alias; break;
                 case Ast_Kind_Type_Alias:                                                          param_type = ((AstTypeAlias *)   param_type)->to;    break;
                 case Ast_Kind_Poly_Struct_Type: {
                     AutoPolymorphVariable apv;
index dc00eff98ddc9cf67a56a8cd6aba194f629bae6e..d6e1ae509271131d40434403b23a315ca80600bc 100644 (file)
@@ -4,6 +4,8 @@
 #include "astnodes.h"
 #include "errors.h"
 
+// :EliminatingSymres - notes the places where too much work is being done in symbol resolution
+
 // Variables used during the symbol resolution phase.
 static Scope*       curr_scope    = NULL;
 static b32 report_unresolved_symbols = 1;
@@ -216,7 +218,7 @@ static SymresStatus symres_type(AstType** type) {
 
         case Ast_Kind_Alias: {
             AstAlias* alias = (AstAlias *) *type;
-            SYMRES_INVISIBLE(type, alias, &alias->alias);
+            SYMRES_INVISIBLE(type, alias, (AstType **) &alias->alias);
 
             break;
         }
@@ -356,6 +358,7 @@ static SymresStatus symres_pipe(AstBinaryOp** pipe) {
 
     if ((*pipe)->left == NULL) return Symres_Error;
 
+    // :EliminatingSymres
     bh_arr_insertn(call_node->args.values, 0, 1);
     call_node->args.values[0] = (AstTyped *) make_argument(context.ast_alloc, (*pipe)->left);
     call_node->next = (*pipe)->next;
@@ -386,14 +389,15 @@ static SymresStatus symres_method_call(AstBinaryOp** mcall) {
     SYMRES(expression, &(*mcall)->left);
     if ((*mcall)->left == NULL) return Symres_Error;
 
+    // :EliminatingSymres
     if (((*mcall)->flags & Ast_Flag_Has_Been_Symres) == 0) {
         AstFieldAccess* implicit_field_access = make_field_access(context.ast_alloc, (*mcall)->left, NULL);
         implicit_field_access->token = call_node->callee->token;
         call_node->callee = (AstTyped *) implicit_field_access;
+        (*mcall)->flags |= Ast_Flag_Has_Been_Symres;
     }
 
     SYMRES(expression, (AstTyped **) &call_node);
-    (*mcall)->flags |= Ast_Flag_Has_Been_Symres;
 
     return Symres_Success;
 }
@@ -411,6 +415,7 @@ static SymresStatus symres_unaryop(AstUnaryOp** unaryop) {
 static SymresStatus symres_struct_literal(AstStructLiteral* sl) {
     if (sl->stnode != NULL) SYMRES(expression, &sl->stnode);
 
+    // :EliminatingSymres
     sl->type_node = (AstType *) sl->stnode;
     while (sl->type_node && sl->type_node->kind == Ast_Kind_Type_Alias)
         sl->type_node = ((AstTypeAlias *) sl->type_node)->to;
@@ -423,6 +428,7 @@ static SymresStatus symres_struct_literal(AstStructLiteral* sl) {
 static SymresStatus symres_array_literal(AstArrayLiteral* al) {
     if (al->atnode != NULL) SYMRES(expression, &al->atnode);
 
+    // :EliminatingSymres
     al->type_node = (AstType *) al->atnode;
     while (al->type_node && al->type_node->kind == Ast_Kind_Type_Alias)
         al->type_node = ((AstTypeAlias *) al->type_node)->to;
@@ -468,6 +474,7 @@ static SymresStatus symres_expression(AstTyped** expr) {
             SYMRES(expression, &((AstRangeLiteral *)(*expr))->low);
             SYMRES(expression, &((AstRangeLiteral *)(*expr))->high);
 
+            // :EliminatingSymres
             SYMRES(type, &builtin_range_type);
             (*expr)->type_node = builtin_range_type;
 
@@ -539,7 +546,7 @@ static SymresStatus symres_expression(AstTyped** expr) {
         case Ast_Kind_Param:
             if ((*expr)->flags & Ast_Flag_Param_Symbol_Dirty) {
                 assert((*expr)->token->type == Token_Type_Symbol);
-                *expr = make_symbol(context.ast_alloc, (*expr)->token);
+                *expr = (AstTyped *) make_symbol(context.ast_alloc, (*expr)->token);
                 SYMRES(expression, expr);
             }
             break;
@@ -657,6 +664,7 @@ static SymresStatus symres_switch(AstSwitch* switchnode) {
 static SymresStatus symres_use(AstUse* use) {
     SYMRES(expression, &use->expr);
 
+    // :EliminatingSymres
     if (use->expr->kind == Ast_Kind_Package) {
         AstPackage* package = (AstPackage *) use->expr;
         SYMRES(package, package);
@@ -728,6 +736,7 @@ static SymresStatus symres_use(AstUse* use) {
 
     if (use->expr->type_node == NULL && use->expr->type == NULL) goto cannot_use;
 
+    // :EliminatingSymres
     AstType* effective_type = use->expr->type_node;
     if (effective_type->kind == Ast_Kind_Pointer_Type)
         effective_type = ((AstPointerType *) effective_type)->elem;
@@ -956,6 +965,7 @@ SymresStatus symres_function(AstFunction* func) {
     scope_enter(func->scope);
 
     if ((func->flags & Ast_Flag_Has_Been_Symres) == 0) {
+        // :EliminatingSymres
         bh_arr_each(AstParam, param, func->params) {
             // CLEANUP: Currently, in order to 'use' parameters, the type must be completely
             // resolved and built. This is excessive because all that should need to be known
@@ -1064,6 +1074,7 @@ static SymresStatus symres_enum(AstEnumType* enum_node) {
 
     scope_enter(enum_node->scope);
 
+    // :EliminatingSymres
     u64 next_assign_value = enum_node->is_flags ? 1 : 0;
     bh_arr_each(AstEnumValue *, value, enum_node->values) {
         if ((*value)->flags & Ast_Flag_Has_Been_Checked) continue;
@@ -1187,6 +1198,7 @@ static SymresStatus symres_static_if(AstIf* static_if) {
 }
 
 static SymresStatus symres_process_directive(AstNode* directive) {
+    // :EliminatingSymres
     switch (directive->kind) {
         case Ast_Kind_Directive_Add_Overload: {
             AstDirectiveAddOverload *add_overload = (AstDirectiveAddOverload *) directive;
@@ -1325,6 +1337,7 @@ static SymresStatus symres_constraint(AstConstraint* constraint) {
 }
 
 static SymresStatus symres_polyquery(AstPolyQuery *query) {
+    // :EliminatingSymres
     query->successful_symres = 0;
 
     if (query->function_header->scope == NULL)
index a87ff4cc4d27eb08896ee5efea8bba85f3042a0b..2363483a9aa763b6ad107f2ddad3b71746167af2 100644 (file)
@@ -42,7 +42,7 @@ main :: (args: [] cstr) {
 
         quick_iterator :=
                     count_iterator(1.0f, 20.0f)
-                    |> iter.map((x) => x * 2)
+                    |> iter.map(x => x * 2)
                     |> iter.filter(lower_bound, (x, l) => x > ~~l)
                     |> iter.map(addition, (x, addition) => x + ~~addition)
                     |> iter.take(5);
@@ -70,9 +70,9 @@ main :: (args: [] cstr) {
 
     println("\nStarting the zipped iteration...");
     zipped_iterator := count_iterator(1, 10)
-                |> iter.map((x) => x * 2)
-                |> iter.filter((x) => x > 10)
-                |> iter.map((x) => x + 42)
+                |> iter.map(x => x * 2)
+                |> iter.filter(x => x > 10)
+                |> iter.map(x => x + 42)
                 |> iter.zip(iter.const(42.0f));
 
     for value: zipped_iterator {