A bit more WIP on classes, and some cleanup in resolve

This commit is contained in:
Tim Chevalier 2012-02-07 16:40:07 -08:00
parent 6e680e36a7
commit 48769b57e0
4 changed files with 150 additions and 96 deletions

View File

@ -2,7 +2,7 @@
import syntax::{ast, ast_util, codemap};
import syntax::ast::*;
import ast::{ident, fn_ident, def, def_id, node_id};
import syntax::ast_util::{local_def, def_id_of_def};
import syntax::ast_util::{local_def, def_id_of_def, class_item_ident};
import pat_util::*;
import front::attr;
@ -91,6 +91,8 @@ enum mod_index_entry {
mie_view_item(ident, node_id, span),
mie_import_ident(node_id, span),
mie_item(@ast::item),
mie_class_item(node_id, /* parent class name */
@ast::class_item), /* class member */
mie_native_item(@ast::native_item),
mie_enum_variant(/* variant index */uint,
/*parts of enum item*/ [variant],
@ -267,27 +269,30 @@ fn map_crate(e: @env, c: @ast::crate) {
alt vi.node {
//if it really is a glob import, that is
ast::view_item_import_glob(path, _) {
let imp = follow_import(*e, sc, *path, vi.span);
if option::is_some(imp) {
let glob = {def: option::get(imp), item: vi};
check list::is_not_empty(sc);
alt list::head(sc) {
scope_item(i) {
e.mod_map.get(i.id).glob_imports += [glob];
}
scope_block(b, _, _) {
let globs = alt e.block_map.find(b.node.id) {
some(globs) { globs + [glob] } none { [glob] }
};
e.block_map.insert(b.node.id, globs);
}
scope_crate {
e.mod_map.get(ast::crate_node_id).glob_imports += [glob];
}
_ { e.sess.span_bug(vi.span, "Unexpected scope in a glob \
import"); }
alt follow_import(*e, sc, *path, vi.span) {
some(imp) {
let glob = {def: imp, item: vi};
check list::is_not_empty(sc);
alt list::head(sc) {
scope_item(i) {
e.mod_map.get(i.id).glob_imports += [glob];
}
scope_block(b, _, _) {
let globs = alt e.block_map.find(b.node.id) {
some(globs) { globs + [glob] } none { [glob] }
};
e.block_map.insert(b.node.id, globs);
}
scope_crate {
e.mod_map.get(ast::crate_node_id).glob_imports
+= [glob];
}
_ { e.sess.span_bug(vi.span, "Unexpected scope in a \
glob import"); }
}
}
}
_ { }
}
}
_ { }
}
@ -329,7 +334,10 @@ fn resolve_capture_item(e: @env, sc: scopes, &&cap_item: @ast::capture_item) {
}
fn maybe_insert(e: @env, id: node_id, def: option<def>) {
if option::is_some(def) { e.def_map.insert(id, option::get(def)); }
alt def {
some(df) { e.def_map.insert(id, df); }
_ {}
}
}
fn resolve_names(e: @env, c: @ast::crate) {
@ -401,11 +409,10 @@ fn resolve_names(e: @env, c: @ast::crate) {
visit::visit_pat(pat, sc, v);
alt pat.node {
ast::pat_enum(p, _) {
let fnd = lookup_path_strict(*e, sc, p.span, p.node,
ns_val(ns_any_value));
alt option::get(fnd) {
ast::def_variant(did, vid) {
e.def_map.insert(pat.id, option::get(fnd));
alt lookup_path_strict(*e, sc, p.span, p.node,
ns_val(ns_any_value)) {
some(fnd@ast::def_variant(_,_)) {
e.def_map.insert(pat.id, fnd);
}
_ {
e.sess.span_err(p.span,
@ -417,11 +424,10 @@ fn resolve_names(e: @env, c: @ast::crate) {
/* Here we determine whether a given pat_ident binds a new
variable a refers to a nullary enum. */
ast::pat_ident(p, none) {
let fnd = lookup_in_scope(*e, sc, p.span, path_to_ident(p),
ns_val(ns_a_enum));
alt fnd {
some(ast::def_variant(did, vid)) {
e.def_map.insert(pat.id, ast::def_variant(did, vid));
alt lookup_in_scope(*e, sc, p.span, path_to_ident(p),
ns_val(ns_a_enum)) {
some(fnd@ast::def_variant(_,_)) {
e.def_map.insert(pat.id, fnd);
}
_ {
// Binds a var -- nothing needs to be done
@ -587,16 +593,21 @@ fn follow_import(e: env, sc: scopes, path: [ident], sp: span) ->
let path_len = vec::len(path);
let dcur = lookup_in_scope_strict(e, sc, sp, path[0], ns_module);
let i = 1u;
while true && option::is_some(dcur) {
if i == path_len { break; }
dcur =
lookup_in_mod_strict(e, option::get(dcur), sp, path[i],
while true {
alt dcur {
some(dcur_def) {
if i == path_len { break; }
dcur =
lookup_in_mod_strict(e, dcur_def, sp, path[i],
ns_module, outside);
i += 1u;
i += 1u;
}
_ { break; }
}
}
if i == path_len {
alt option::get(dcur) {
ast::def_mod(_) | ast::def_native_mod(_) { ret dcur; }
alt dcur {
some(ast::def_mod(_)) | some(ast::def_native_mod(_)) { ret dcur; }
_ {
e.sess.span_err(sp, str::connect(path, "::") +
" does not name a module.");
@ -607,20 +618,16 @@ fn follow_import(e: env, sc: scopes, path: [ident], sp: span) ->
}
fn resolve_constr(e: @env, c: @ast::constr, sc: scopes, _v: vt<scopes>) {
let new_def =
lookup_path_strict(*e, sc, c.span, c.node.path.node,
ns_val(ns_any_value));
if option::is_some(new_def) {
alt option::get(new_def) {
ast::def_fn(pred_id, ast::pure_fn) {
e.def_map.insert(c.node.id, ast::def_fn(pred_id, ast::pure_fn));
}
_ {
e.sess.span_err(c.span,
"Non-predicate in constraint: " +
path_to_str(c.node.path));
}
}
alt lookup_path_strict(*e, sc, c.span, c.node.path.node,
ns_val(ns_any_value)) {
some(d@ast::def_fn(_,ast::pure_fn)) {
e.def_map.insert(c.node.id, d);
}
_ {
e.sess.span_err(c.span,
"Non-predicate in constraint: " +
path_to_str(c.node.path));
}
}
}
@ -744,7 +751,7 @@ fn ns_name(ns: namespace) -> str {
ns_a_enum { "enum" }
}
}
ns_module { ret "modulename" }
ns_module { "modulename" }
}
}
@ -814,18 +821,26 @@ fn lookup_path_strict(e: env, sc: scopes, sp: span, pth: ast::path_,
let first_scope = if pth.global { top_scope() } else { sc };
let dcur =
let dcur_ =
lookup_in_scope_strict(e, first_scope, sp, pth.idents[0], headns);
let i = 1u;
while i < n_idents && option::is_some(dcur) {
let curns = if n_idents == i + 1u { ns } else { ns_module };
dcur =
lookup_in_mod_strict(e, option::get(dcur), sp, pth.idents[i],
curns, outside);
i += 1u;
alt dcur_ {
none { ret none; }
some(dcur__) {
let i = 1u;
let dcur = dcur__;
while i < n_idents {
let curns = if n_idents == i + 1u { ns } else { ns_module };
alt lookup_in_mod_strict(e, dcur, sp, pth.idents[i],
curns, outside) {
none { break; }
some(thing) { dcur = thing; }
}
i += 1u;
}
ret some(dcur);
}
}
ret dcur;
}
fn lookup_in_scope_strict(e: env, sc: scopes, sp: span, name: ident,
@ -985,11 +1000,11 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
alt copy sc {
nil { ret none; }
cons(hd, tl) {
let fnd = in_scope(e, sp, name, hd, ns);
if !is_none(fnd) {
let df = option::get(fnd);
let local = def_is_local(df), self_scope = def_is_self(df);
if left_fn && local || left_fn_level2 && self_scope
alt in_scope(e, sp, name, hd, ns) {
some(df_) {
let df = df_;
let local = def_is_local(df), self_scope = def_is_self(df);
if left_fn && local || left_fn_level2 && self_scope
|| scope_is_fn(hd) && left_fn && def_is_ty_arg(df) {
let msg = alt ns {
ns_type {
@ -1013,12 +1028,13 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
i -= 1u;
df = ast::def_upvar(def_id_of_def(df), @df,
closing[i]);
fnd = some(df);
}
}
ret fnd;
ret some(df);
}
if left_fn {
_ {}
}
if left_fn {
left_fn_level2 = true;
} else if ns != ns_module {
left_fn = scope_is_fn(hd);
@ -1193,7 +1209,10 @@ fn found_def_item(i: @ast::item, ns: namespace) -> option<def> {
_ { }
}
}
_ { }
ast::item_class(_, _, _, _, _) {
fail "class! don't know what to do";
}
ast::item_impl(_,_,_,_) { /* ??? */ }
}
ret none;
}
@ -1220,12 +1239,13 @@ fn lookup_in_mod(e: env, m: def, sp: span, name: ident, ns: namespace,
if defid.node != ast::crate_node_id {
path = cstore::get_path(e.cstore, defid) + path;
}
let fnd = lookup_external(e, defid.crate, path, ns);
if !is_none(fnd) {
e.ext_cache.insert({did: defid, ident: name, ns: ns},
option::get(fnd));
alt lookup_external(e, defid.crate, path, ns) {
some(df) {
e.ext_cache.insert({did: defid, ident: name, ns: ns}, df);
ret some(df);
}
_ { ret none; }
}
ret fnd;
}
alt m {
ast::def_mod(defid) {
@ -1263,7 +1283,7 @@ fn lookup_import(e: env, defid: def_id, ns: namespace) -> option<def> {
e.used_imports.data += [defid.node];
}
ret alt ns { ns_val(_) { val } ns_type { typ }
ns_module { md } };
ns_module { md } };
}
is_glob(_,_,_) {
e.sess.bug("lookup_import: can't handle is_glob");
@ -1398,6 +1418,18 @@ fn lookup_in_mie(e: env, mie: mod_index_entry, ns: namespace) ->
}
}
}
mie_class_item(parent_id, class_item) {
alt class_item.node.decl {
instance_var(_,_,_,id) {
ret some(ast::def_class_field(local_def(parent_id),
local_def(id)));
}
class_method(it) {
ret some(ast::def_class_method(local_def(parent_id),
local_def(it.id)));
}
}
}
}
ret none;
}
@ -1452,8 +1484,21 @@ fn index_mod(md: ast::_mod) -> mod_index {
variant_idx += 1u;
}
}
ast::item_class(_, items, _, ctor_decl, _) {
fail "resolve::index_mod: item_class";
ast::item_class(tps, items, ctor_id, ctor_decl, ctor_body) {
// add the class name itself
add_to_index(index, it.ident, mie_item(it));
// add the constructor decl
add_to_index(index, it.ident,
mie_item(@{ident: it.ident, attrs: [],
id: ctor_id,
node:
item_fn(ctor_decl, tps, ctor_body),
span: ctor_body.span}));
// add the members
for ci in items {
add_to_index(index, class_item_ident(ci),
mie_class_item(it.id, ci));
}
}
}
}
@ -1494,11 +1539,13 @@ fn ns_for_def(d: def) -> namespace {
ast::def_variant(_, _) { ns_val(ns_a_enum) }
ast::def_fn(_, _) | ast::def_self(_) |
ast::def_const(_) | ast::def_arg(_, _) | ast::def_local(_, _) |
ast::def_upvar(_, _, _) | ast::def_self(_) { ns_val(ns_any_value) }
ast::def_upvar(_, _, _) | ast::def_self(_) |
ast::def_class_field(_,_) | ast::def_class_method(_,_)
{ ns_val(ns_any_value) }
ast::def_mod(_) | ast::def_native_mod(_) { ns_module }
ast::def_ty(_) | ast::def_binding(_) | ast::def_use(_) |
ast::def_ty_param(_, _) | ast::def_prim_ty(_) { ns_type }
_ { fail "Dead"; }
ast::def_ty_param(_, _) | ast::def_prim_ty(_) | ast::def_class(_)
{ ns_type }
}
}
@ -1583,6 +1630,7 @@ fn mie_span(mie: mod_index_entry) -> span {
mie_item(item) { item.span }
mie_enum_variant(_, _, _, span) { span }
mie_native_item(item) { item.span }
mie_class_item(_,item) { item.span }
};
}

View File

@ -30,9 +30,9 @@ fn def_id_of_def(d: def) -> def_id {
def_fn(id, _) | def_self(id) | def_mod(id) |
def_native_mod(id) | def_const(id) | def_arg(id, _) | def_local(id, _) |
def_variant(_, id) | def_ty(id) | def_ty_param(id, _) |
def_binding(id) | def_use(id) | def_upvar(id, _, _) { id }
def_binding(id) | def_use(id) | def_upvar(id, _, _) |
def_class(id) | def_class_field(_, id) | def_class_method(_, id) { id }
def_prim_ty(_) { fail; }
_ { fail "Dead"; }
}
}
@ -374,6 +374,13 @@ pure fn unguarded_pat(a: arm) -> option<[@pat]> {
// for reserving this id.
fn op_expr_callee_id(e: @expr) -> node_id { e.id - 1 }
pure fn class_item_ident(ci: @class_item) -> ident {
alt ci.node.decl {
instance_var(i,_,_,_) { i }
class_method(it) { it.ident }
}
}
// Local Variables:
// mode: rust
// fill-column: 78;

View File

@ -618,7 +618,7 @@ fn make_fold(afp: ast_fold_precursor) -> ast_fold {
@{node:
{privacy:ci.node.privacy,
decl:
alt ci.node.decl {
alt ci.node.decl {
instance_var(nm, t, mt, id) {
instance_var(nm, f_ty(afp, f, t),
mt, id)

View File

@ -1580,7 +1580,7 @@ fn parse_let(p: parser) -> @ast::decl {
ret @spanned(lo, p.last_span.hi, ast::decl_local(locals));
}
fn parse_instance_var(p:parser) -> @ast::class_member {
fn parse_instance_var(p:parser) -> ast::class_member {
let is_mut = ast::class_immutable;
expect_word(p, "let");
if eat_word(p, "mutable") {
@ -1592,7 +1592,7 @@ fn parse_instance_var(p:parser) -> @ast::class_member {
let name = parse_ident(p);
expect(p, token::COLON);
let ty = parse_ty(p, false);
ret @ast::instance_var(name, ty, is_mut, p.get_id());
ret ast::instance_var(name, ty, is_mut, p.get_id());
}
fn parse_stmt(p: parser, first_item_attrs: [ast::attribute]) -> @ast::stmt {
@ -1973,12 +1973,12 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
the_ctor = some((a_fn_decl, blk));
}
plain_decl(a_decl) {
items += [@{node: {privacy: ast::pub, decl: *a_decl},
items += [@{node: {privacy: ast::pub, decl: a_decl},
span: p.last_span}];
}
priv_decls(some_decls) {
items += vec::map(some_decls, {|d|
@{node: {privacy: ast::priv, decl: *d},
@{node: {privacy: ast::priv, decl: d},
span: p.last_span}});
}
}
@ -1986,8 +1986,7 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
p.bump();
alt the_ctor {
some((ct_d, ct_b)) { ret mk_item(p, lo, p.last_span.hi, class_name,
ast::item_class(ty_params, items, ctor_id,
ct_d, ct_b), attrs); }
ast::item_class(ty_params, items, ctor_id, ct_d, ct_b), attrs); }
/*
Is it strange for the parser to check this?
*/
@ -2000,11 +1999,11 @@ fn parse_item_class(p: parser, attrs: [ast::attribute]) -> @ast::item {
// we don't really want just the fn_decl...
enum class_contents { ctor_decl(ast::fn_decl, ast::blk),
// assumed to be public
plain_decl(@ast::class_member),
plain_decl(ast::class_member),
// contents of a priv section --
// parse_class_item ensures that
// none of these are a ctor decl
priv_decls([@ast::class_member])}
priv_decls([ast::class_member])}
fn parse_class_item(p:parser) -> class_contents {
if eat_word(p, "new") {
@ -2020,7 +2019,7 @@ fn parse_class_item(p:parser) -> class_contents {
while p.token != token::RBRACE {
alt parse_item(p, []) {
some(i) {
results += [@ast::class_method(i)];
results += [ast::class_method(i)];
}
_ {
let a_var = parse_instance_var(p);
@ -2036,7 +2035,7 @@ fn parse_class_item(p:parser) -> class_contents {
// Probably need to parse attrs
alt parse_item(p, []) {
some(i) {
ret plain_decl(@ast::class_method(i));
ret plain_decl(ast::class_method(i));
}
_ {
let a_var = parse_instance_var(p);