From 48769b57e0f184ff42f5226641447e41cf3053a7 Mon Sep 17 00:00:00 2001 From: Tim Chevalier <chevalier@alum.wellesley.edu> Date: Tue, 7 Feb 2012 16:40:07 -0800 Subject: [PATCH] A bit more WIP on classes, and some cleanup in resolve --- src/comp/middle/resolve.rs | 214 +++++++++++++++++++------------- src/comp/syntax/ast_util.rs | 11 +- src/comp/syntax/fold.rs | 2 +- src/comp/syntax/parse/parser.rs | 19 ++- 4 files changed, 150 insertions(+), 96 deletions(-) diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 47b0c71e112..8a0234fc0c3 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -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 } }; } diff --git a/src/comp/syntax/ast_util.rs b/src/comp/syntax/ast_util.rs index 3046ba02907..d0cfb5ee848 100644 --- a/src/comp/syntax/ast_util.rs +++ b/src/comp/syntax/ast_util.rs @@ -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; diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs index 723a70741ab..09c9a46e73f 100644 --- a/src/comp/syntax/fold.rs +++ b/src/comp/syntax/fold.rs @@ -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) diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index dab6be43e2f..d15c333c5fe 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -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);