bugfixes and bindable foreign blocks
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 28 Apr 2022 18:04:59 +0000 (13:04 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 28 Apr 2022 18:04:59 +0000 (13:04 -0500)
include/astnodes.h
src/checker.c
src/parser.c
src/symres.c
src/utils.c
src/wasm_emit.c

index 0974be0116cd62fce4aeb31a897b23cc0b0543cc..9b4d76ddf5242201e5fea3bacc8857e6e32a751a 100644 (file)
@@ -1294,7 +1294,7 @@ struct AstCodeBlock {
 };
 
 struct AstDirectiveInsert {
-    AstNode_base;
+    AstTyped_base;
 
     AstTyped *code_expr;
 };
@@ -1320,8 +1320,9 @@ struct AstDirectiveLibrary {
 };
 
 struct AstForeignBlock {
-    AstNode_base;
+    AstTyped_base;
 
+    Scope* scope;
     OnyxToken *module_name;
     bh_arr(struct Entity *) captured_entities;
 };
index b48439a7833578a5dcdb07eb2d8303b053cc96b1..3279919cc1a9265ae8d27d0f8c4d0938a87266be 100644 (file)
@@ -1904,6 +1904,7 @@ CheckStatus check_expression(AstTyped** pexpr) {
         case Ast_Kind_Unary_Field_Access: break;
         case Ast_Kind_Constraint_Sentinel: break;
         case Ast_Kind_Switch_Case: break;
+        case Ast_Kind_Foreign_Block: break;
 
         default:
             retval = Check_Error;
index 46d387855c71926a54367122e64e18652b1537cd..348415b6e77715836f033318094f838531e3a095 100644 (file)
@@ -2810,6 +2810,25 @@ static AstDirectiveInit* parse_init_directive(OnyxParser *parser, OnyxToken *tok
     return init;
 }
 
+static AstForeignBlock* parse_foreign_block(OnyxParser* parser, OnyxToken *token) {
+    // :LinearTokenDependent
+    AstForeignBlock *fb = make_node(AstForeignBlock, Ast_Kind_Foreign_Block);
+    fb->token = token;
+    fb->module_name = expect_token(parser, Token_Type_Literal_String);
+
+    bh_arr_new(global_heap_allocator, fb->captured_entities, 4);
+    bh_arr_push(parser->alternate_entity_placement_stack, &fb->captured_entities);
+
+    expect_token(parser, '{');
+    parse_top_level_statements_until(parser, '}');
+    expect_token(parser, '}');
+
+    bh_arr_pop(parser->alternate_entity_placement_stack);
+    ENTITY_SUBMIT(fb);
+
+    return fb;
+}
+
 static AstTyped* parse_top_level_expression(OnyxParser* parser) {
     if (parser->curr->type == Token_Type_Keyword_Global)    return parse_global_declaration(parser);
     if (parser->curr->type == Token_Type_Keyword_Struct)    return (AstTyped *) parse_struct(parser);
@@ -2844,6 +2863,11 @@ static AstTyped* parse_top_level_expression(OnyxParser* parser) {
             distinct->base_type = parse_type(parser);
             return (AstTyped *) distinct;
         }
+
+        if (parse_possible_directive(parser, "foreign")) {
+            AstForeignBlock *foreign = parse_foreign_block(parser, parser->curr - 2);
+            return (AstTyped *) foreign;
+        }
     }
 
     return parse_expression(parser, 1);
@@ -3060,20 +3084,7 @@ static void parse_top_level_statement(OnyxParser* parser) {
                 return;
             }
             else if (parse_possible_directive(parser, "foreign")) {
-                // :LinearTokenDependent
-                AstForeignBlock *fb = make_node(AstForeignBlock, Ast_Kind_Foreign_Block);
-                fb->token = parser->curr - 2;
-                fb->module_name = expect_token(parser, Token_Type_Literal_String);
-
-                bh_arr_new(global_heap_allocator, fb->captured_entities, 4);
-                bh_arr_push(parser->alternate_entity_placement_stack, &fb->captured_entities);
-
-                expect_token(parser, '{');
-                parse_top_level_statements_until(parser, '}');
-                expect_token(parser, '}');
-
-                bh_arr_pop(parser->alternate_entity_placement_stack);
-                ENTITY_SUBMIT(fb);
+                parse_foreign_block(parser, parser->curr - 2);
                 return;
             }
             else if (parse_possible_directive(parser, "operator")) {
index 3d4f9f29d7ecc81cbf3e13423b867c8b3557f65a..c2cf26dee92e903f08f2a542fd7eac350459c6de 100644 (file)
@@ -694,9 +694,11 @@ static SymresStatus symres_switch(AstSwitch* switchnode) {
 static SymresStatus symres_use(AstUse* use) {
     SYMRES(expression, &use->expr);
 
+    AstTyped *use_expr = (AstTyped *) strip_aliases((AstNode *) use->expr);
+
     // :EliminatingSymres
-    if (use->expr->kind == Ast_Kind_Package) {
-        AstPackage* package = (AstPackage *) use->expr;
+    if (use_expr->kind == Ast_Kind_Package) {
+        AstPackage* package = (AstPackage *) use_expr;
         SYMRES(package, package);
 
         if (package->package->scope == curr_scope) return Symres_Success;
@@ -731,8 +733,42 @@ static SymresStatus symres_use(AstUse* use) {
         return Symres_Success;
     }
 
-    if (use->expr->kind == Ast_Kind_Enum_Type) {
-        AstEnumType* et = (AstEnumType *) use->expr;
+    if (use_expr->kind == Ast_Kind_Foreign_Block) {
+        AstForeignBlock* fb = (AstForeignBlock *) use_expr;
+        if (fb->entity->state <= Entity_State_Resolve_Symbols) return Symres_Yield_Macro;
+
+        if (fb->scope == curr_scope) return Symres_Success;
+
+        if (use->only == NULL) {
+            OnyxFilePos pos = { 0 };
+            if (use->token != NULL)
+                pos = use->token->pos;
+
+            scope_include(curr_scope, fb->scope, pos);
+
+        } else {
+            bh_arr_each(QualifiedUse, qu, use->only) {
+                AstNode* thing = symbol_resolve(fb->scope, qu->symbol_name);
+                if (thing == NULL) { // :SymresStall
+                    if (report_unresolved_symbols) {
+                        onyx_report_error(qu->symbol_name->pos, Error_Critical, 
+                                "The symbol '%b' was not found in this package.",
+                                qu->symbol_name->text, qu->symbol_name->length);
+                        return Symres_Error;
+                    } else {
+                        return Symres_Yield_Macro;
+                    }
+                }
+
+                symbol_introduce(curr_scope, qu->as_name, thing);
+            }
+        }
+
+        return Symres_Success;
+    }
+
+    if (use_expr->kind == Ast_Kind_Enum_Type) {
+        AstEnumType* et = (AstEnumType *) use_expr;
 
         bh_arr_each(AstEnumValue *, ev, et->values)
             symbol_introduce(curr_scope, (*ev)->token, (AstNode *) *ev);
@@ -740,8 +776,8 @@ static SymresStatus symres_use(AstUse* use) {
         return Symres_Success;
     }
 
-    if (use->expr->kind == Ast_Kind_Struct_Type) {
-        AstStructType* st = (AstStructType *) use->expr;
+    if (use_expr->kind == Ast_Kind_Struct_Type) {
+        AstStructType* st = (AstStructType *) use_expr;
         if (!st->scope) return Symres_Success;
 
         if (use->only == NULL) {
@@ -764,27 +800,27 @@ static SymresStatus symres_use(AstUse* use) {
         return Symres_Success;
     }
 
-    if (use->expr->type_node == NULL && use->expr->type == NULL) goto cannot_use;
+    if (use_expr->type_node == NULL && use_expr->type == NULL) goto cannot_use;
 
     // :EliminatingSymres
-    AstType* effective_type = use->expr->type_node;
+    AstType* effective_type = use_expr->type_node;
     if (effective_type->kind == Ast_Kind_Pointer_Type)
         effective_type = ((AstPointerType *) effective_type)->elem;
 
     if (effective_type->kind == Ast_Kind_Struct_Type ||
             effective_type->kind == Ast_Kind_Poly_Call_Type) {
 
-        if (use->expr->type == NULL)
-            use->expr->type = type_build_from_ast(context.ast_alloc, use->expr->type_node);
-        if (use->expr->type == NULL) goto cannot_use;
+        if (use_expr->type == NULL)
+            use_expr->type = type_build_from_ast(context.ast_alloc, use_expr->type_node);
+        if (use_expr->type == NULL) goto cannot_use;
 
-        Type* st = use->expr->type;
+        Type* st = use_expr->type;
         if (st->kind == Type_Kind_Pointer)
             st = st->Pointer.elem;
 
         fori (i, 0, shlen(st->Struct.members)) {
             StructMember* value = st->Struct.members[i].value;
-            AstFieldAccess* fa = make_field_access(context.ast_alloc, use->expr, value->name);
+            AstFieldAccess* fa = make_field_access(context.ast_alloc, use_expr, value->name);
             symbol_raw_introduce(curr_scope, value->name, use->token->pos, (AstNode *) fa);
         }
 
@@ -1445,6 +1481,9 @@ static SymresStatus symres_polyquery(AstPolyQuery *query) {
 }
 
 static SymresStatus symres_foreign_block(AstForeignBlock *fb) {
+    if (fb->scope == NULL)
+        fb->scope = scope_create(context.ast_alloc, curr_scope, fb->token->pos);
+
     bh_arr_each(Entity *, pent, fb->captured_entities) {
         Entity *ent = *pent;
         if (ent->type == Entity_Type_Function_Header) {
@@ -1464,6 +1503,22 @@ static SymresStatus symres_foreign_block(AstForeignBlock *fb) {
             continue;
         }
 
+        if (ent->type == Entity_Type_Binding) {
+            AstBinding* new_binding = onyx_ast_node_new(context.ast_alloc, sizeof(AstBinding), Ast_Kind_Binding);
+            new_binding->token = ent->binding->token;
+            new_binding->node = ent->binding->node;
+
+            Entity e;
+            memset(&e, 0, sizeof(e));
+            e.type = Entity_Type_Binding;
+            e.state = Entity_State_Introduce_Symbols;
+            e.binding = new_binding;
+            e.scope = fb->scope;
+            e.package = ent->package;
+
+            entity_heap_insert(&context.entities, e);
+        }
+
         if (ent->type != Entity_Type_Function) {
             entity_heap_insert_existing(&context.entities, ent);
         }
index f65c26adb1707e4841013f1debc78e49e474d251..b7d99036de97058d6ac770c81cce1db30f938cc4 100644 (file)
@@ -204,6 +204,15 @@ all_types_peeled_off:
             return symbol_raw_resolve(package->package->scope, symbol);
         } 
 
+        case Ast_Kind_Foreign_Block: {
+            AstForeignBlock* fb = (AstForeignBlock *) node;
+
+            if (fb->scope == NULL)
+                return NULL;
+
+            return symbol_raw_resolve(fb->scope, symbol);
+        }
+
         case Ast_Kind_Enum_Type: {
             AstEnumType* etype = (AstEnumType *) node;
             return symbol_raw_resolve(etype->scope, symbol);
index 07884a2c19ea8804df628c34b85df32e105646d6..bf1408896af248b9f6b61ec7002210c8cbbe423d 100644 (file)
@@ -3565,6 +3565,7 @@ static void emit_raw_data(OnyxWasmModule* mod, ptr data, AstTyped* node) {
 
 static b32 emit_raw_data_(OnyxWasmModule* mod, ptr data, AstTyped* node) {
     b32 retval = 1;
+    node = (AstTyped *) strip_aliases((AstNode *) node);
 
     if (node_is_type((AstNode *) node)) {
         Type* constructed_type = type_build_from_ast(context.ast_alloc, (AstType *) node);