Commit f67ca20655

LemonBoy <thatlemon@gmail.com>
2019-05-21 17:07:40
Make use work with arbitrary structs
1 parent 163a8e9
Changed files (2)
src
test
stage1
behavior
src/analyze.cpp
@@ -3754,49 +3754,59 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {
     analyze_fn_ir(g, fn_table_entry, return_type_node);
 }
 
-static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node, ScopeDecls* decls_scope) {
+static void add_symbols_from_struct(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node, ScopeDecls* decls_scope) {
     if (src_use_node->data.use.resolution == TldResolutionUnresolved) {
         preview_use_decl(g, src_use_node, decls_scope);
     }
 
-    ConstExprValue *use_target_value = src_use_node->data.use.using_namespace_value;
-    if (type_is_invalid(use_target_value->type)) {
+    ConstExprValue *use_expr = src_use_node->data.use.using_namespace_value;
+    if (type_is_invalid(use_expr->type)) {
         decls_scope->any_imports_failed = true;
         return;
     }
 
     dst_use_node->data.use.resolution = TldResolutionOk;
 
-    assert(use_target_value->special != ConstValSpecialRuntime);
+    assert(use_expr->special != ConstValSpecialRuntime);
 
-    ZigType *target_import = use_target_value->data.x_type;
-    assert(target_import);
+    // The source struct for the imported symbols
+    ZigType *src_ty = use_expr->data.x_type;
+    assert(src_ty);
 
-    if (target_import->id != ZigTypeIdStruct) {
+    if (src_ty->id != ZigTypeIdStruct) {
         add_node_error(g, dst_use_node,
-            buf_sprintf("expected struct, found '%s'", buf_ptr(&target_import->name)));
+            buf_sprintf("expected struct, found '%s'", buf_ptr(&src_ty->name)));
         decls_scope->any_imports_failed = true;
         return;
     }
 
-    if (get_container_scope(target_import)->any_imports_failed) {
+    // The source scope for the imported symbols
+    ScopeDecls *src_scope = get_container_scope(src_ty);
+    // The top-level container where the symbols are defined, it's used in the
+    // loop below in order to exclude the ones coming from an import statement
+    ZigType *src_import = get_scope_import(reinterpret_cast<Scope*>(src_scope));
+    assert(src_import && src_import->id == ZigTypeIdStruct);
+
+    if (src_scope->any_imports_failed) {
         decls_scope->any_imports_failed = true;
     }
 
-    auto it = get_container_scope(target_import)->decl_table.entry_iterator();
+    auto it = src_scope->decl_table.entry_iterator();
     for (;;) {
         auto *entry = it.next();
         if (!entry)
             break;
 
+        Buf *target_tld_name = entry->key;
         Tld *target_tld = entry->value;
-        if (target_tld->import != target_import ||
-            target_tld->visib_mod == VisibModPrivate)
-        {
+
+        if (target_tld->visib_mod == VisibModPrivate) {
             continue;
         }
 
-        Buf *target_tld_name = entry->key;
+        if (target_tld->import != src_import) {
+            continue;
+        }
 
         auto existing_entry = decls_scope->decl_table.put_unique(target_tld_name, target_tld);
         if (existing_entry) {
@@ -3811,10 +3821,10 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *
         }
     }
 
-    for (size_t i = 0; i < get_container_scope(target_import)->use_decls.length; i += 1) {
-        AstNode *use_decl_node = get_container_scope(target_import)->use_decls.at(i);
+    for (size_t i = 0; i < src_scope->use_decls.length; i += 1) {
+        AstNode *use_decl_node = src_scope->use_decls.at(i);
         if (use_decl_node->data.use.visib_mod != VisibModPrivate)
-            add_symbols_from_import(g, use_decl_node, dst_use_node, decls_scope);
+            add_symbols_from_struct(g, use_decl_node, dst_use_node, decls_scope);
     }
 }
 
@@ -3826,7 +3836,7 @@ void resolve_use_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) {
     {
         return;
     }
-    add_symbols_from_import(g, node, node, decls_scope);
+    add_symbols_from_struct(g, node, node, decls_scope);
 }
 
 void preview_use_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) {
test/stage1/behavior/struct.zig
@@ -549,3 +549,14 @@ test "packed struct with fp fields" {
     expectEqual(f32(11.0), s.data[1]);
     expectEqual(f32(20.0), s.data[2]);
 }
+
+test "use within struct scope" {
+    const S = struct {
+        use struct {
+            pub fn inner() i32 {
+                return 42;
+            }
+        };
+    };
+    expectEqual(i32(42), S.inner());
+}