use statements are now more universal
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 11 Dec 2020 23:34:23 +0000 (17:34 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 11 Dec 2020 23:34:23 +0000 (17:34 -0600)
docs/todo
include/onyxastnodes.h
onyx
progs/foo_test.onyx
progs/odin_example.onyx
src/onyx.c
src/onyxparser.c
src/onyxsymres.c

index def77412db6347dfce219ba9660f14f84688a1f7..5c6c33038413c70221c532098f9ac3d1f8319047 100644 (file)
--- a/docs/todo
+++ b/docs/todo
@@ -51,7 +51,7 @@ Language Cohesion:
 
             var := some.packages.nested.here.StructName.{ value1, value2, ... };
 
-    [ ] 'use' statements have two different variations and should be unified.
+    [X] 'use' statements have two different variations and should be unified.
         They can be used to include a package, 'use package', and they can
         be used to add names from a namespace to the current scope. The problem
         is that 'use package' can only be at the top level, and 'use' can only
index 9018dfd9a7e21b5390a35e200277b0409f85fd1a..70b192944eddc8777c9b7e191d149466f6ade357 100644 (file)
@@ -754,6 +754,7 @@ typedef struct Entity {
         AstEnumType           *enum_type;
         AstMemRes             *mem_res;
         AstPolyProc           *poly_proc;
+        AstUse                *use;
     };
 } Entity;
 
diff --git a/onyx b/onyx
index e06f4f93635afe6515cae6b5fbcbb251f8087f2d..9b9eec7bcad59e6b03d35baa93c37b6d28ccad04 100755 (executable)
Binary files a/onyx and b/onyx differ
index 08e0f2a97646d3a4d36c69b15e5e4b4a2c862a29..f395f2f558c680451c446ef04d93f66afeff9f96 100644 (file)
@@ -5,3 +5,5 @@ use package core
 TestFoo :: struct { a: i32; }
 
 print_foo :: proc () do println("Foo!");
+
+SomeEnum :: enum #flags { Val1; Val2; Val3; }
index 76fb770daed642cf34d407ca5663d912884b57c0..e3dea71433c0b014c66bf53d8024afa71435273f 100644 (file)
@@ -2,8 +2,6 @@
 #include_file "progs/foo_test"
 
 use package core
-use package test { foo as foo_pkg }
-use package test as test
 
 Foo :: struct {
     data1 : i32;
@@ -59,6 +57,13 @@ make_bar :: proc () -> Bar {
 }
 
 main :: proc (args: [] cstr) {
+    use package test { foo as foo_pkg }
+    use package test as test
+    use test.foo.SomeEnum
+
+    printf("Val2: %i\n", cast(i32) Val2);
+    printf("Val3: %i\n", cast(i32) Val3);
+
     foo_pkg.print_foo();
     foo := test.foo.TestFoo.{ a = 1234 };
     printf("foo.a: %i\n", foo.a);
index a649da20f25f0147fd63a539d3712ecc8f54e85f..0229d810265a496e2f3f4469947ea378187aa50b 100644 (file)
@@ -360,6 +360,13 @@ static void merge_parse_results(CompilerState* compiler_state, ParseResults* res
                 break;
             }
 
+            case Ast_Kind_Use: {
+                ent.type = Entity_Type_Use;
+                ent.use = (AstUse *) node;
+                entity_heap_insert(&compiler_state->prog_info.entities, ent);
+                break;
+            }
+
             case Ast_Kind_Memres: {
                 ent.type = Entity_Type_Memory_Reservation;
                 ent.mem_res = (AstMemRes *) node;
index a2028659d9f387c7c03127079011f1da23c66db3..67e4c8a2bd3df48e8b02e15d4fdab93b51998ef1 100644 (file)
@@ -32,7 +32,8 @@ static AstIfWhile*    parse_while_stmt(OnyxParser* parser);
 static AstFor*        parse_for_stmt(OnyxParser* parser);
 static AstSwitch*     parse_switch_stmt(OnyxParser* parser);
 static b32            parse_possible_symbol_declaration(OnyxParser* parser, AstNode** ret);
-static AstReturn*     parse_return_statement(OnyxParser* parser);
+static AstReturn*     parse_return_stmt(OnyxParser* parser);
+static AstNode*       parse_use_stmt(OnyxParser* parser);
 static AstBlock*      parse_block(OnyxParser* parser);
 static AstNode*       parse_statement(OnyxParser* parser);
 static AstType*       parse_type(OnyxParser* parser);
@@ -1013,7 +1014,7 @@ static b32 parse_possible_symbol_declaration(OnyxParser* parser, AstNode** ret)
 }
 
 // 'return' <expr>?
-static AstReturn* parse_return_statement(OnyxParser* parser) {
+static AstReturn* parse_return_stmt(OnyxParser* parser) {
     AstReturn* return_node = make_node(AstReturn, Ast_Kind_Return);
     return_node->token = expect_token(parser, Token_Type_Keyword_Return);
 
@@ -1032,6 +1033,82 @@ static AstReturn* parse_return_statement(OnyxParser* parser) {
     return return_node;
 }
 
+static AstNode* parse_use_stmt(OnyxParser* parser) {
+    OnyxToken* use_token = expect_token(parser, Token_Type_Keyword_Use);
+
+    if (parser->curr->type == Token_Type_Keyword_Package) {
+        expect_token(parser, Token_Type_Keyword_Package);
+
+        AstUsePackage* upack = make_node(AstUsePackage, Ast_Kind_Use_Package);
+        upack->token = use_token;
+
+        AstNode* pack_symbol = make_node(AstNode, Ast_Kind_Symbol);
+        pack_symbol->token = expect_token(parser, Token_Type_Symbol);
+
+        // CLEANUP: This is just gross.
+        if (parser->curr->type == '.') {
+            consume_token(parser);
+            pack_symbol->token->length += 1;
+
+            while (1) {
+                if (parser->hit_unexpected_token) break;
+
+                OnyxToken* symbol = expect_token(parser, Token_Type_Symbol);
+                pack_symbol->token->length += symbol->length;
+
+                if (parser->curr->type == '.') {
+                    pack_symbol->token->length += 1;
+                    consume_token(parser);
+                } else {
+                    break;
+                }
+            }
+        }
+
+        upack->package = (AstPackage *) pack_symbol;
+
+        if (parser->curr->type == Token_Type_Keyword_As) {
+            consume_token(parser);
+            upack->alias = expect_token(parser, Token_Type_Symbol);
+        }
+
+        if (parser->curr->type == '{') {
+            consume_token(parser);
+
+            bh_arr_new(global_heap_allocator, upack->only, 4);
+
+            while (parser->curr->type != '}') {
+                if (parser->hit_unexpected_token) return NULL;
+
+                AstAlias* alias = make_node(AstAlias, Ast_Kind_Alias);
+                alias->token = expect_token(parser, Token_Type_Symbol);
+
+                if (parser->curr->type == Token_Type_Keyword_As) {
+                    consume_token(parser);
+                    alias->alias = expect_token(parser, Token_Type_Symbol);
+                } else {
+                    alias->alias = alias->token;
+                }
+
+                bh_arr_push(upack->only, alias);
+
+                if (parser->curr->type != '}')
+                    expect_token(parser, ',');
+            }
+
+            consume_token(parser);
+        }
+
+        return (AstNode *) upack;
+
+    } else {
+        AstUse* use_node = make_node(AstUse, Ast_Kind_Use);
+        use_node->token = use_token;
+        use_node->expr = parse_expression(parser);
+        return (AstNode *) use_node;
+    }
+}
+
 // <return> ;
 // <block>
 // <symbol_statement> ;
@@ -1046,7 +1123,7 @@ static AstNode* parse_statement(OnyxParser* parser) {
 
     switch ((u16) parser->curr->type) {
         case Token_Type_Keyword_Return:
-            retval = (AstNode *) parse_return_statement(parser);
+            retval = (AstNode *) parse_return_stmt(parser);
             break;
 
         case '{':
@@ -1152,11 +1229,12 @@ static AstNode* parse_statement(OnyxParser* parser) {
         }
 
         case Token_Type_Keyword_Use: {
-            AstUse* use_node = make_node(AstUse, Ast_Kind_Use);
-            use_node->token = expect_token(parser, Token_Type_Keyword_Use);
-            use_node->expr = parse_expression(parser);
+            // AstUse* use_node = make_node(AstUse, Ast_Kind_Use);
+            // use_node->token = expect_token(parser, Token_Type_Keyword_Use);
+            // use_node->expr = parse_expression(parser);
 
-            retval = (AstNode *) use_node;
+            needs_semicolon = 0;
+            retval = (AstNode *) parse_use_stmt(parser);
             break;
         }
 
@@ -1835,71 +1913,8 @@ static AstNode* parse_top_level_statement(OnyxParser* parser) {
 
     switch ((u16) parser->curr->type) {
         case Token_Type_Keyword_Use: {
-            OnyxToken* use_token = expect_token(parser, Token_Type_Keyword_Use);
-
-            expect_token(parser, Token_Type_Keyword_Package);
-
-            AstUsePackage* upack = make_node(AstUsePackage, Ast_Kind_Use_Package);
-            upack->token = use_token;
-
-            AstNode* pack_symbol = make_node(AstNode, Ast_Kind_Symbol);
-            pack_symbol->token = expect_token(parser, Token_Type_Symbol);
-
-            // CLEANUP: This is just gross.
-            if (parser->curr->type == '.') {
-                consume_token(parser);
-                pack_symbol->token->length += 1;
-
-                while (1) {
-                    if (parser->hit_unexpected_token) break;
-
-                    OnyxToken* symbol = expect_token(parser, Token_Type_Symbol);
-                    pack_symbol->token->length += symbol->length;
-
-                    if (parser->curr->type == '.') {
-                        pack_symbol->token->length += 1;
-                        consume_token(parser);
-                    } else {
-                        break;
-                    }
-                }
-            }
-
-            upack->package = (AstPackage *) pack_symbol;
-
-            if (parser->curr->type == Token_Type_Keyword_As) {
-                consume_token(parser);
-                upack->alias = expect_token(parser, Token_Type_Symbol);
-            }
-
-            if (parser->curr->type == '{') {
-                consume_token(parser);
-
-                bh_arr_new(global_heap_allocator, upack->only, 4);
-
-                while (parser->curr->type != '}') {
-                    if (parser->hit_unexpected_token) return NULL;
-
-                    AstAlias* alias = make_node(AstAlias, Ast_Kind_Alias);
-                    alias->token = expect_token(parser, Token_Type_Symbol);
-
-                    if (parser->curr->type == Token_Type_Keyword_As) {
-                        consume_token(parser);
-                        alias->alias = expect_token(parser, Token_Type_Symbol);
-                    } else {
-                        alias->alias = alias->token;
-                    }
-
-                    bh_arr_push(upack->only, alias);
-
-                    if (parser->curr->type != '}')
-                        expect_token(parser, ',');
-                }
-
-                consume_token(parser);
-            }
-
-            add_node_to_process(parser, (AstNode *) upack);
+            AstNode* use_node = parse_use_stmt(parser);
+            add_node_to_process(parser, use_node);
             return NULL;
         }
 
index 7d054a2ee03bc1e66a7a4360693bdd7554735277..f1683e3c88c22745e32af4b35f51eb8a8224604a 100644 (file)
@@ -517,17 +517,18 @@ cannot_use:
 // NOTE: Returns 1 if the statment should be removed
 static b32 symres_statement(AstNode** stmt) {
     switch ((*stmt)->kind) {
-        case Ast_Kind_Local:      symres_local((AstLocal **) stmt);                  return 1;
-        case Ast_Kind_Return:     symres_return((AstReturn *) *stmt);                return 0;
-        case Ast_Kind_If:         symres_if((AstIfWhile *) *stmt);                   return 0;
-        case Ast_Kind_While:      symres_while((AstIfWhile *) *stmt);                return 0;
-        case Ast_Kind_For:        symres_for((AstFor *) *stmt);                      return 0;
-        case Ast_Kind_Switch:     symres_switch((AstSwitch *) *stmt);                return 0;
-        case Ast_Kind_Call:       symres_call((AstCall *) *stmt);                    return 0;
-        case Ast_Kind_Argument:   symres_expression((AstTyped **) &((AstArgument *) *stmt)->value); return 0;
-        case Ast_Kind_Block:      symres_block((AstBlock *) *stmt);                  return 0;
-        case Ast_Kind_Defer:      symres_statement(&((AstDefer *) *stmt)->stmt);     return 0;
-        case Ast_Kind_Use:        symres_use((AstUse *) *stmt);                       return 1;
+        case Ast_Kind_Local:       symres_local((AstLocal **) stmt);                  return 1;
+        case Ast_Kind_Return:      symres_return((AstReturn *) *stmt);                return 0;
+        case Ast_Kind_If:          symres_if((AstIfWhile *) *stmt);                   return 0;
+        case Ast_Kind_While:       symres_while((AstIfWhile *) *stmt);                return 0;
+        case Ast_Kind_For:         symres_for((AstFor *) *stmt);                      return 0;
+        case Ast_Kind_Switch:      symres_switch((AstSwitch *) *stmt);                return 0;
+        case Ast_Kind_Call:        symres_call((AstCall *) *stmt);                    return 0;
+        case Ast_Kind_Argument:    symres_expression((AstTyped **) &((AstArgument *) *stmt)->value); return 0;
+        case Ast_Kind_Block:       symres_block((AstBlock *) *stmt);                  return 0;
+        case Ast_Kind_Defer:       symres_statement(&((AstDefer *) *stmt)->stmt);     return 0;
+        case Ast_Kind_Use:         symres_use((AstUse *) *stmt);                      return 1;
+        case Ast_Kind_Use_Package: symres_use_package((AstUsePackage *) *stmt);       return 1;
 
         case Ast_Kind_Jump:      return 0;
 
@@ -787,6 +788,8 @@ void symres_entity(Entity* ent) {
         semstate.curr_package = ent->package;
     }
 
+    EntityState next_state = Entity_State_Check_Types;
+
     switch (ent->type) {
         case Entity_Type_Foreign_Function_Header:
         case Entity_Type_Function:            symres_function(ent->function); break;
@@ -795,6 +798,10 @@ void symres_entity(Entity* ent) {
         case Entity_Type_Global_Header:       symres_global(ent->global); break;
 
         case Entity_Type_Use_Package:         symres_use_package(ent->use_package); break;
+        case Entity_Type_Use:                 symres_use(ent->use);
+                                              next_state = Entity_State_Finalized;
+                                              break;
+
         case Entity_Type_Overloaded_Function: symres_overloaded_function(ent->overloaded_function); break;
         case Entity_Type_Expression:          symres_expression(&ent->expr); break;
         case Entity_Type_Type_Alias:          ent->type_alias = symres_type(ent->type_alias); break;
@@ -806,7 +813,7 @@ void symres_entity(Entity* ent) {
         default: break;
     }
 
-    ent->state = Entity_State_Check_Types;
+    ent->state = next_state;
 
     if (ent->package) scope_leave();
 }