about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-03-29 17:01:27 -0700
committerPatrick Walton <pcwalton@mimiga.net>2011-03-29 17:01:27 -0700
commitc67eb1a575dc09850c3b59ed15252db9cb451c11 (patch)
tree7e0b534ff2f22bfe0e089f07d76a6aa906ddebd3
parent6a5feffd6cb8bb04cf61d1c265254233bb093831 (diff)
rustc: Partially resolve external module imports
-rw-r--r--src/comp/front/creader.rs32
-rw-r--r--src/comp/middle/resolve.rs92
2 files changed, 104 insertions, 20 deletions
diff --git a/src/comp/front/creader.rs b/src/comp/front/creader.rs
index 3b95b24fc8f..35d10422a45 100644
--- a/src/comp/front/creader.rs
+++ b/src/comp/front/creader.rs
@@ -540,18 +540,15 @@ fn read_crates(session.session sess,
 
 // Crate metadata queries
 
-fn lookup_def(session.session sess, &span sp, int cnum, vec[ast.ident] path)
-        -> ast.def {
+fn lookup_def(session.session sess, int cnum, vec[ast.ident] path)
+        -> option.t[ast.def] {
     auto data = sess.get_external_crate(cnum);
 
     auto did;
     alt (resolve_path(path, data)) {
         case (rr_ok(?di)) { did = di; }
         case (rr_not_found(?prev, ?name)) {
-            sess.span_err(sp,
-                #fmt("unbound name '%s' (no item named '%s' found in '%s')",
-                     _str.connect(path, "."), name, _str.connect(prev, ".")));
-            fail;
+            ret none[ast.def];
         }
     }
 
@@ -561,21 +558,24 @@ fn lookup_def(session.session sess, &span sp, int cnum, vec[ast.ident] path)
     did = tup(cnum, did._1);
 
     // FIXME: It'd be great if we had u8 char literals.
-    if (kind_ch == ('c' as u8))      { ret ast.def_const(did);      }
-    else if (kind_ch == ('f' as u8)) { ret ast.def_fn(did);         }
-    else if (kind_ch == ('y' as u8)) { ret ast.def_ty(did);         }
-    else if (kind_ch == ('o' as u8)) { ret ast.def_obj(did);        }
-    else if (kind_ch == ('t' as u8)) { ret ast.def_ty(did);         }
-    else if (kind_ch == ('m' as u8)) { ret ast.def_mod(did);        }
-    else if (kind_ch == ('n' as u8)) { ret ast.def_native_mod(did); }
+    auto def;
+    if (kind_ch == ('c' as u8))      { def = ast.def_const(did);        }
+    else if (kind_ch == ('f' as u8)) { def = ast.def_fn(did);           }
+    else if (kind_ch == ('y' as u8)) { def = ast.def_ty(did);           }
+    else if (kind_ch == ('o' as u8)) { def = ast.def_obj(did);          }
+    else if (kind_ch == ('t' as u8)) { def = ast.def_ty(did);           }
+    else if (kind_ch == ('m' as u8)) { def = ast.def_mod(did);          }
+    else if (kind_ch == ('n' as u8)) { def = ast.def_native_mod(did);   }
     else if (kind_ch == ('v' as u8)) {
         auto tid = get_variant_tag_id(ebml_r);
         tid = tup(cnum, tid._1);
-        ret ast.def_variant(tid, did);
+        def = ast.def_variant(tid, did);
+    } else {
+        log #fmt("lookup_def(): unknown kind char: %d", kind_ch as int);
+        fail;
     }
 
-    log #fmt("lookup_def(): unknown kind char: %d", kind_ch as int);
-    fail;
+    ret some[ast.def](def);
 }
 
 fn get_type(session.session sess, ast.def_id def) -> ty.ty_params_and_ty {
diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs
index 820687caea9..e171a6006b5 100644
--- a/src/comp/middle/resolve.rs
+++ b/src/comp/middle/resolve.rs
@@ -20,6 +20,7 @@ tag scope {
     scope_crate(@ast.crate);
     scope_item(@ast.item);
     scope_native_item(@ast.native_item);
+    scope_external_mod(ast.def_id, vec[ast.ident]);
     scope_loop(@ast.decl); // there's only 1 decl per loop.
     scope_block(ast.block);
     scope_arm(ast.arm);
@@ -37,6 +38,8 @@ tag def_wrap {
     def_wrap_import(@ast.view_item);
     def_wrap_mod(@ast.item);
     def_wrap_native_mod(@ast.item);
+    def_wrap_external_mod(ast.def_id);
+    def_wrap_external_native_mod(ast.def_id);
     def_wrap_other(def);
     def_wrap_expr_field(uint, def);
     def_wrap_resolving;
@@ -79,6 +82,12 @@ fn unwrap_def(def_wrap d) -> def {
                 }
             }
         }
+        case (def_wrap_external_mod(?mod_id)) {
+            ret ast.def_mod(mod_id);
+        }
+        case (def_wrap_external_native_mod(?mod_id)) {
+            ret ast.def_native_mod(mod_id);
+        }
         case (def_wrap_other(?d)) {
             ret d;
         }
@@ -100,6 +109,30 @@ fn lookup_name(&env e, ast.ident i) -> option.t[def] {
     }
 }
 
+fn lookup_external_def(session.session sess, int cnum, vec[ident] idents)
+        -> option.t[def_wrap] {
+    alt (creader.lookup_def(sess, cnum, idents)) {
+        case (none[ast.def]) {
+            ret none[def_wrap];
+        }
+        case (some[ast.def](?def)) {
+            auto dw;
+            alt (def) {
+                case (ast.def_mod(?mod_id)) {
+                    dw = def_wrap_external_mod(mod_id);
+                }
+                case (ast.def_native_mod(?mod_id)) {
+                    dw = def_wrap_external_native_mod(mod_id);
+                }
+                case (_) {
+                    dw = def_wrap_other(def);
+                }
+            }
+            ret some[def_wrap](dw);
+        }
+    }
+}
+
 // Follow the path of an import and return what it ultimately points to.
 
 // If used after imports are resolved, import_id is none.
@@ -136,12 +169,43 @@ fn find_final_def(&env e, import_map index,
             }
         }
 
+        // TODO: Refactor with above.
+        fn found_external_mod(&env e, &import_map index, &span sp,
+                              vec[ident] idents, ast.def_id mod_id)
+                -> def_wrap {
+            auto len = _vec.len[ident](idents);
+            auto rest_idents = _vec.slice[ident](idents, 1u, len);
+            auto empty_e = rec(scopes = nil[scope], sess = e.sess);
+            auto tmp_e = update_env_for_external_mod(empty_e, mod_id, idents);
+            auto next_i = rest_idents.(0);
+            auto next_ = lookup_name_wrapped(tmp_e, next_i);
+            alt (next_) {
+                case (none[tup(@env, def_wrap)]) {
+                    e.sess.span_err(sp, "unresolved name: " + next_i);
+                    fail;
+                }
+                case (some[tup(@env, def_wrap)](?next)) {
+                    auto combined_e = update_env_for_external_mod(e,
+                                                                  mod_id,
+                                                                  idents);
+                    ret found_something(combined_e, index, sp,
+                                        rest_idents, next._1);
+                }
+            }
+        }
+
         fn found_crate(&env e, &import_map index, &span sp,
                        vec[ident] idents, int cnum) -> def_wrap {
             auto len = _vec.len[ident](idents);
             auto rest_idents = _vec.slice[ident](idents, 1u, len);
-            auto def = creader.lookup_def(e.sess, sp, cnum, rest_idents);
-            ret def_wrap_other(def);
+            alt (lookup_external_def(e.sess, cnum, rest_idents)) {
+                case (none[def_wrap]) {
+                    e.sess.span_err(sp, #fmt("unbound name '%s'",
+                                             _str.connect(idents, ".")));
+                    fail;
+                }
+                case (some[def_wrap](?dw)) { ret dw; }
+            }
         }
 
         alt (d) {
@@ -168,6 +232,12 @@ fn find_final_def(&env e, import_map index,
             case (def_wrap_native_mod(?i)) {
                 ret found_mod(e, index, sp, idents, i);
             }
+            case (def_wrap_external_mod(?mod_id)) {
+                ret found_external_mod(e, index, sp, idents, mod_id);
+            }
+            case (def_wrap_external_native_mod(?mod_id)) {
+                ret found_external_mod(e, index, sp, idents, mod_id);
+            }
             case (def_wrap_use(?vi)) {
                 alt (vi.node) {
                     case (ast.view_item_use(_, _, _, ?cnum_opt)) {
@@ -390,7 +460,8 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] {
         }
     }
 
-    fn in_scope(ast.ident i, &scope s) -> option.t[def_wrap] {
+    fn in_scope(&session.session sess, ast.ident i, &scope s)
+            -> option.t[def_wrap] {
         alt (s) {
 
             case (scope_crate(?c)) {
@@ -450,6 +521,10 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] {
                 }
             }
 
+            case (scope_external_mod(?mod_id, ?path)) {
+                ret lookup_external_def(sess, mod_id._0, path);
+            }
+
             case (scope_loop(?d)) {
                 alt (d.node) {
                     case (ast.decl_local(?local)) {
@@ -483,7 +558,7 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] {
             ret none[tup(@env, def_wrap)];
         }
         case (cons[scope](?hd, ?tl)) {
-            auto x = in_scope(i, hd);
+            auto x = in_scope(e.sess, i, hd);
             alt (x) {
                 case (some[def_wrap](?x)) {
                     ret some(tup(@e, x));
@@ -613,6 +688,15 @@ fn update_env_for_native_item(&env e, @ast.native_item i) -> env {
     ret rec(scopes = cons[scope](scope_native_item(i), @e.scopes) with e);
 }
 
+// Not actually called by fold, but here since this is analogous to
+// update_env_for_item() above and is called by find_final_def().
+fn update_env_for_external_mod(&env e, ast.def_id mod_id,
+                               vec[ast.ident] idents) -> env {
+    ret rec(scopes = cons[scope](scope_external_mod(mod_id, idents),
+                                 @e.scopes)
+            with e);
+}
+
 fn update_env_for_block(&env e, &ast.block b) -> env {
     ret rec(scopes = cons[scope](scope_block(b), @e.scopes) with e);
 }