change list so that it must be used in a purely boxed fashion

The old way was inconsistent---the head was unboxed but the
tail was boxed.  This resulted in numerous needless copies and
also made the borrow check unhappy, because the head tended to be
stored in mutable memory.
This commit is contained in:
Niko Matsakis 2012-05-21 09:37:34 -07:00
parent 8e73bb6ea0
commit 34b42eeb65
12 changed files with 127 additions and 128 deletions

View File

@ -3,9 +3,10 @@
export arena, arena_with_size;
import list;
import list::{list, cons, nil};
type chunk = {data: [u8], mut fill: uint};
type arena = {mut chunks: list::list<@chunk>};
type arena = {mut chunks: @list<@chunk>};
fn chunk(size: uint) -> @chunk {
let mut v = [];
@ -14,7 +15,7 @@ fn chunk(size: uint) -> @chunk {
}
fn arena_with_size(initial_size: uint) -> arena {
ret {mut chunks: list::cons(chunk(initial_size), @list::nil)};
ret {mut chunks: @cons(chunk(initial_size), @nil)};
}
fn arena() -> arena {
@ -28,7 +29,7 @@ fn alloc_grow(n_bytes: uint, align: uint) -> *() {
let chunk_size = vec::capacity(head.data);
let new_min_chunk_size = uint::max(n_bytes, chunk_size);
head = chunk(uint::next_power_of_two(new_min_chunk_size + 1u));
self.chunks = list::cons(head, @self.chunks);
self.chunks = @cons(head, self.chunks);
ret self.alloc(n_bytes, align);
}

View File

@ -11,7 +11,7 @@ enum list<T> {
#[doc = "Create a list from a vector"]
fn from_vec<T: copy>(v: [const T]) -> @list<T> {
@vec::foldr(v, @nil::<T>, { |h, t| @cons(h, t) })
vec::foldr(v, @nil::<T>, { |h, t| @cons(h, t) })
}
#[doc = "
@ -43,7 +43,7 @@ fn foldl<T: copy, U>(z: T, ls: @list<U>, f: fn(T, U) -> T) -> T {
fn find<T: copy>(ls: @list<T>, f: fn(T) -> bool) -> option<T> {
let mut ls = ls;
loop {
ls = alt ls {
ls = alt *ls {
cons(hd, tl) {
if f(hd) { ret some(hd); }
tl
@ -82,7 +82,7 @@ fn len<T>(ls: @list<T>) -> uint {
}
#[doc = "Returns all but the first element of a list"]
pure fn tail<T: copy>(ls: @list<T>) -> list<T> {
pure fn tail<T: copy>(ls: @list<T>) -> @list<T> {
alt *ls {
cons(_, tl) { ret tl; }
nil { fail "list empty" }
@ -98,7 +98,7 @@ fn len<T>(ls: @list<T>) -> uint {
pure fn append<T: copy>(l: @list<T>, m: @list<T>) -> @list<T> {
alt *l {
nil { ret m; }
cons(x, xs) { let rest = append(*xs, m); ret @cons(x, @rest); }
cons(x, xs) { let rest = append(xs, m); ret @cons(x, rest); }
}
}
@ -117,12 +117,13 @@ fn iter<T>(l: @list<T>, f: fn(T)) {
}
#[doc = "Iterate over a list"]
fn each<T>(l: list<T>, f: fn(T) -> bool) {
fn each<T>(l: @list<T>, f: fn(T) -> bool) {
let mut cur = l;
loop {
cur = alt *cur {
cons(hd, tl) {
if !f(hd) { ret; }
tl
}
nil { break; }
}
@ -163,7 +164,7 @@ fn test_from_vec() {
#[test]
fn test_from_vec_empty() {
let empty : @list::list<int> = from_vec([]);
assert (empty == list::nil::<int>);
assert (empty == @list::nil::<int>);
}
#[test]
@ -208,7 +209,7 @@ fn test_find_success() {
fn test_find_fail() {
fn match(&&_i: int) -> bool { ret false; }
let l = from_vec([0, 1, 2]);
let empty = list::nil::<int>;
let empty = @list::nil::<int>;
assert (list::find(l, match) == option::none::<int>);
assert (list::find(empty, match) == option::none::<int>);
}

View File

@ -33,7 +33,7 @@ enum unsafe_ty { contains(ty::t), mutbl_contains(ty::t), }
// FIXME it may be worthwhile to use a linked list of bindings instead
type scope = {bs: [binding],
invalid: @mut list<@invalid>};
invalid: @mut @list<@invalid>};
fn mk_binding(cx: ctx, id: node_id, span: span, root_var: option<node_id>,
unsafe_tys: [unsafe_ty]) -> binding {
@ -68,7 +68,7 @@ fn check_crate(tcx: ty::ctxt, crate: @ast::crate) -> (copy_map, ref_map) {
visit_expr: bind visit_expr(cx, _, _, _),
visit_block: bind visit_block(cx, _, _, _)
with *visit::default_visitor::<scope>()};
let sc = {bs: [], invalid: @mut list::nil};
let sc = {bs: [], invalid: @mut @list::nil};
visit::visit_crate(*crate, sc, visit::mk_vt(v));
tcx.sess.abort_if_errors();
ret (cx.copy_map, cx.ref_map);
@ -88,7 +88,7 @@ fn visit_fn(cx: @ctx, _fk: visit::fn_kind, decl: ast::fn_decl,
check_loop(*cx, sc) {|| v.visit_block(body, sc, v);}
}
ast::proto_box | ast::proto_uniq | ast::proto_bare {
let sc = {bs: [], invalid: @mut list::nil};
let sc = {bs: [], invalid: @mut @list::nil};
v.visit_block(body, sc, v);
}
}
@ -400,7 +400,7 @@ fn check_var(cx: ctx, ex: @ast::expr, p: @ast::path, id: ast::node_id,
if ty_can_unsafely_include(cx, unsafe_ty, var_t, assign) {
let inv = @{reason: val_taken, node_id: b.node_id,
sp: ex.span, path: p};
*sc.invalid = list::cons(inv, @*sc.invalid);
*sc.invalid = @list::cons(inv, *sc.invalid);
}
}
} else if b.node_id == my_defnum {
@ -418,7 +418,7 @@ fn check_lval(cx: @ctx, dest: @ast::expr, sc: scope, v: vt<scope>) {
if b.root_var == some(dnum) {
let inv = @{reason: overwritten, node_id: b.node_id,
sp: dest.span, path: p};
*sc.invalid = list::cons(inv, @*sc.invalid);
*sc.invalid = @list::cons(inv, *sc.invalid);
}
}
}
@ -791,46 +791,43 @@ fn unsafe_set(from: option<unsafe_ty>) -> [unsafe_ty] {
alt from { some(t) { [t] } _ { [] } }
}
fn find_invalid(id: node_id, lst: list<@invalid>)
-> option<@invalid> {
fn find_invalid(id: node_id, lst: @list<@invalid>) -> option<@invalid> {
let mut cur = lst;
loop {
alt cur {
alt *cur {
list::nil { ret none; }
list::cons(head, tail) {
if head.node_id == id { ret some(head); }
cur = *tail;
cur = tail;
}
}
};
}
fn join_invalid(a: list<@invalid>, b: list<@invalid>) -> list<@invalid> {
fn join_invalid(a: @list<@invalid>, b: @list<@invalid>) -> @list<@invalid> {
let mut result = a;
list::iter(b) {|elt|
let mut found = false;
list::iter(a) {|e| if e == elt { found = true; } }
if !found { result = list::cons(elt, @result); }
if !found { result = @list::cons(elt, result); }
}
result
}
fn filter_invalid(src: list<@invalid>, bs: [binding]) -> list<@invalid> {
let mut out = list::nil, cur = src;
while cur != list::nil {
alt cur {
fn filter_invalid(src: @list<@invalid>, bs: [binding]) -> @list<@invalid> {
let mut out = @list::nil, cur = src;
loop {
alt *cur {
list::cons(head, tail) {
let p = vec::position(bs, {|b| b.node_id == head.node_id});
if !is_none(p) { out = list::cons(head, @out); }
cur = *tail;
if !is_none(p) { out = @list::cons(head, out); }
cur = tail;
}
list::nil {
// typestate would help...
unreachable();
ret out;
}
}
}
ret out;
}
fn err(cx: ctx, sp: span, err: str) {

View File

@ -37,7 +37,7 @@ enum seen { unset, seen(node_id), }
enum block_type { func, lp, }
enum use { var_use(node_id), close_over(node_id), }
type set = [{def: node_id, uses: list<use>}];
type set = [{def: node_id, uses: @list<use>}];
type bl = @{type: block_type, mut second: bool, mut exits: [set]};
enum use_id { path(node_id), close(node_id, node_id) }
@ -52,7 +52,7 @@ fn hash_use_id(id: use_id) -> uint {
tcx: ty::ctxt,
// The current set of local last uses
mut current: set,
mut blocks: list<bl>};
mut blocks: @list<bl>};
fn find_last_uses(c: @crate, def_map: resolve::def_map,
ref_map: alias::ref_map, tcx: ty::ctxt)
@ -67,7 +67,7 @@ fn find_last_uses(c: @crate, def_map: resolve::def_map,
ref_map: ref_map,
tcx: tcx,
mut current: [],
mut blocks: nil};
mut blocks: @nil};
visit::visit_crate(*c, cx, v);
let mini_table = std::map::int_hash();
for cx.last_uses.each {|key, val|
@ -136,7 +136,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
option::iter(def_is_owned_local(cx, my_def)) {|nid|
clear_in_current(cx, nid, false);
cx.current += [{def: nid,
uses: cons(var_use(ex.id), @nil)}];
uses: @cons(var_use(ex.id), @nil)}];
}
}
}
@ -249,13 +249,13 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
option::iter(def_is_owned_local(cx, v.def)) {|nid|
clear_in_current(cx, nid, false);
cx.current += [{def: nid,
uses: cons(close_over(id), @nil)}];
uses: @cons(close_over(id), @nil)}];
}
}
}
_ {}
}
let mut old_cur = [], old_blocks = nil;
let mut old_cur = [], old_blocks = @nil;
cx.blocks <-> old_blocks;
cx.current <-> old_cur;
visit::visit_fn(fk, decl, body, sp, id, cx, v);
@ -268,7 +268,7 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
fn visit_block(tp: block_type, cx: ctx, visit: fn()) {
let local = @{type: tp, mut second: false, mut exits: []};
cx.blocks = cons(local, @cx.blocks);
cx.blocks = @cons(local, cx.blocks);
visit();
local.second = true;
local.exits = [];
@ -281,23 +281,20 @@ fn visit_block(tp: block_type, cx: ctx, visit: fn()) {
fn add_block_exit(cx: ctx, tp: block_type) -> bool {
let mut cur = cx.blocks;
while cur != nil {
alt cur {
loop {
alt *cur {
cons(b, tail) {
if (b.type == tp) {
if !b.second { b.exits += [cx.current]; }
ret true;
}
cur = *tail;
cur = tail;
}
nil {
// typestate can't use the while loop condition --
// *sigh*
unreachable();
ret false;
}
}
}
ret false;
}
fn join_branches(branches: [set]) -> set {
@ -312,7 +309,7 @@ fn join_branches(branches: [set]) -> set {
for vec::each(branches[j]) {|elt2|
if elt2.def == elt.def {
list::iter(elt2.uses) {|e|
if !list::has(nne, e) { nne = cons(e, @nne); }
if !list::has(nne, e) { nne = @cons(e, nne); }
}
}
}

View File

@ -42,10 +42,10 @@ enum scope {
scope_method(node_id, [ast::ty_param]),
}
type scopes = list<scope>;
type scopes = @list<scope>;
fn top_scope() -> scopes {
cons(scope_crate, @cons(scope_toplevel, @nil))
@cons(scope_crate, @cons(scope_toplevel, @nil))
}
enum import_state {
@ -91,7 +91,7 @@ enum mod_index_entry {
node_id, span),
}
type mod_index = hashmap<ident, list<mod_index_entry>>;
type mod_index = hashmap<ident, @list<mod_index_entry>>;
// A tuple of an imported def and the view_path from its originating import
type glob_imp_def = {def: def, path: @ast::view_path};
@ -229,7 +229,7 @@ fn iter_effective_import_paths(vi: ast::view_item,
// resolve through them.
fn map_crate(e: @env, c: @ast::crate) {
fn index_vi(e: @env, i: @ast::view_item, sc: scopes, _v: vt<scopes>) {
fn index_vi(e: @env, i: @ast::view_item, &&sc: scopes, _v: vt<scopes>) {
iter_effective_import_paths(*i) { |vp|
alt vp.node {
ast::view_path_simple(name, path, id) {
@ -262,7 +262,7 @@ fn path_from_scope(sc: scopes, n: str) -> str {
path
}
fn index_i(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
fn index_i(e: @env, i: @ast::item, &&sc: scopes, v: vt<scopes>) {
visit_item_with_scope(e, i, sc, v);
alt i.node {
ast::item_mod(md) {
@ -291,7 +291,7 @@ fn index_i(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
// re-export of anything that was exported at the glob-target location.
// So we wind up reusing the glob-import machinery when looking at
// glob exports. They just do re-exporting in a later step.
fn link_glob(e: @env, vi: @ast::view_item, sc: scopes, _v: vt<scopes>) {
fn link_glob(e: @env, vi: @ast::view_item, &&sc: scopes, _v: vt<scopes>) {
iter_effective_import_paths(*vi) { |vp|
alt vp.node {
ast::view_path_glob(path, _) {
@ -429,7 +429,7 @@ fn resolve_names(e: @env, c: @ast::crate) {
e.used_imports.track = false;
e.sess.abort_if_errors();
fn walk_item(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
fn walk_item(e: @env, i: @ast::item, &&sc: scopes, v: vt<scopes>) {
visit_item_with_scope(e, i, sc, v);
alt i.node {
/* At this point, the code knows what ifaces the iface refs
@ -447,7 +447,7 @@ fn walk_item(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
}
}
fn walk_expr(e: @env, exp: @ast::expr, sc: scopes, v: vt<scopes>) {
fn walk_expr(e: @env, exp: @ast::expr, &&sc: scopes, v: vt<scopes>) {
visit::visit_expr(exp, sc, v);
alt exp.node {
ast::expr_path(p) {
@ -463,7 +463,7 @@ fn walk_expr(e: @env, exp: @ast::expr, sc: scopes, v: vt<scopes>) {
_ { }
}
}
fn walk_ty(e: @env, t: @ast::ty, sc: scopes, v: vt<scopes>) {
fn walk_ty(e: @env, t: @ast::ty, &&sc: scopes, v: vt<scopes>) {
visit::visit_ty(t, sc, v);
alt t.node {
ast::ty_path(p, id) {
@ -473,7 +473,7 @@ fn walk_ty(e: @env, t: @ast::ty, sc: scopes, v: vt<scopes>) {
_ { }
}
}
fn walk_tps(e: @env, tps: [ast::ty_param], sc: scopes, v: vt<scopes>) {
fn walk_tps(e: @env, tps: [ast::ty_param], &&sc: scopes, v: vt<scopes>) {
let outer_current_tp = e.current_tp;
let mut current = 0u;
for tps.each {|tp|
@ -488,11 +488,11 @@ fn walk_tps(e: @env, tps: [ast::ty_param], sc: scopes, v: vt<scopes>) {
}
e.current_tp = outer_current_tp;
}
fn walk_constr(e: @env, p: @ast::path, sp: span, id: node_id, sc: scopes,
_v: vt<scopes>) {
fn walk_constr(e: @env, p: @ast::path, sp: span, id: node_id,
&&sc: scopes, _v: vt<scopes>) {
maybe_insert(e, id, lookup_path_strict(*e, sc, sp, p, ns_val));
}
fn walk_pat(e: @env, pat: @ast::pat, sc: scopes, v: vt<scopes>) {
fn walk_pat(e: @env, pat: @ast::pat, &&sc: scopes, v: vt<scopes>) {
visit::visit_pat(pat, sc, v);
alt pat.node {
ast::pat_enum(p, _) {
@ -534,7 +534,8 @@ fn walk_pat(e: @env, pat: @ast::pat, sc: scopes, v: vt<scopes>) {
This is used in more than one context, thus should only call generic
visit methods. Called both from map_crate and resolve_names.
*/
fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
fn visit_item_with_scope(e: @env, i: @ast::item,
&&sc: scopes, v: vt<scopes>) {
// Some magic here. Items with the !resolve_unexported attribute
// cause us to consider every name to be exported when resolving their
// contents. This is used to allow the test runner to run unexported
@ -544,7 +545,7 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
attr::contains_name(attr::attr_metas(i.attrs),
"!resolve_unexported");
let sc = cons(scope_item(i), @sc);
let sc = @cons(scope_item(i), sc);
alt i.node {
ast::item_impl(tps, _, ifce, sty, methods) {
visit::visit_ty_params(tps, sc, v);
@ -552,7 +553,7 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
v.visit_ty(sty, sc, v);
for methods.each {|m|
v.visit_ty_params(m.tps, sc, v);
let msc = cons(scope_method(m.self_id, tps + m.tps), @sc);
let msc = @cons(scope_method(m.self_id, tps + m.tps), sc);
v.visit_fn(visit::fk_method(m.ident, [], m),
m.decl, m.body, m.span, m.id, msc, v);
}
@ -560,7 +561,7 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
ast::item_iface(tps, _, methods) {
visit::visit_ty_params(tps, sc, v);
for methods.each {|m|
let msc = cons(scope_method(i.id, tps + m.tps), @sc);
let msc = @cons(scope_method(i.id, tps + m.tps), sc);
for m.decl.inputs.each {|a| v.visit_ty(a.ty, msc, v); }
v.visit_ty(m.decl.output, msc, v);
}
@ -568,10 +569,10 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
ast::item_class(tps, ifaces, members, ctor, m_dtor, _) {
visit::visit_ty_params(tps, sc, v);
// Can maybe skip this now that we require self on class fields
let class_scope = cons(scope_item(i), @sc);
let class_scope = @cons(scope_item(i), sc);
/* visit the constructor... */
let ctor_scope = cons(scope_method(ctor.node.self_id, tps),
@class_scope);
let ctor_scope = @cons(scope_method(ctor.node.self_id, tps),
class_scope);
/* visit the iface refs in the class scope */
for ifaces.each {|p|
visit::visit_path(p.path, class_scope, v);
@ -581,8 +582,8 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
ctor.node.body, ctor.span, ctor.node.id,
ctor_scope, v);
option::iter(m_dtor) {|dtor|
let dtor_scope = cons(scope_method(dtor.node.self_id, tps),
@class_scope);
let dtor_scope = @cons(scope_method(dtor.node.self_id, tps),
class_scope);
visit_fn_with_scope(e, visit::fk_dtor(tps, dtor.node.self_id,
local_def(i.id)),
@ -594,8 +595,8 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
for members.each {|cm|
alt cm.node {
class_method(m) {
let msc = cons(scope_method(m.self_id, tps + m.tps),
@class_scope);
let msc = @cons(scope_method(m.self_id, tps + m.tps),
class_scope);
visit_fn_with_scope(e,
visit::fk_item_fn(m.ident, tps), m.decl, m.body,
m.span, m.id, msc, v); }
@ -609,14 +610,14 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
e.resolve_unexported = old_resolve_unexported;
}
fn visit_native_item_with_scope(ni: @ast::native_item, sc: scopes,
fn visit_native_item_with_scope(ni: @ast::native_item, &&sc: scopes,
v: vt<scopes>) {
visit::visit_native_item(ni, cons(scope_native_item(ni), @sc), v);
visit::visit_native_item(ni, @cons(scope_native_item(ni), sc), v);
}
fn visit_fn_with_scope(e: @env, fk: visit::fn_kind, decl: ast::fn_decl,
body: ast::blk, sp: span,
id: node_id, sc: scopes, v: vt<scopes>) {
id: node_id, &&sc: scopes, v: vt<scopes>) {
// is this a main fn declaration?
alt fk {
visit::fk_item_fn(nm, _) {
@ -644,12 +645,12 @@ fn visit_fn_with_scope(e: @env, fk: visit::fn_kind, decl: ast::fn_decl,
scope_fn_expr(decl, id, []) }
};
visit::visit_fn(fk, decl, body, sp, id, cons(scope, @sc), v);
visit::visit_fn(fk, decl, body, sp, id, @cons(scope, sc), v);
}
fn visit_block_with_scope(b: ast::blk, sc: scopes, v: vt<scopes>) {
fn visit_block_with_scope(b: ast::blk, &&sc: scopes, v: vt<scopes>) {
let pos = @mut 0u, loc = @mut 0u;
let block_sc = cons(scope_block(b, pos, loc), @sc);
let block_sc = @cons(scope_block(b, pos, loc), sc);
for b.node.view_items.each {|vi| v.visit_view_item(vi, block_sc, v); }
for b.node.stmts.each {|stmt|
v.visit_stmt(stmt, block_sc, v);;
@ -659,7 +660,7 @@ fn visit_block_with_scope(b: ast::blk, sc: scopes, v: vt<scopes>) {
visit::visit_expr_opt(b.node.expr, block_sc, v);
}
fn visit_decl_with_scope(d: @decl, sc: scopes, v: vt<scopes>) {
fn visit_decl_with_scope(d: @decl, &&sc: scopes, v: vt<scopes>) {
let loc_pos = alt list::head(sc) {
scope_block(_, _, pos) { pos }
_ { @mut 0u }
@ -672,9 +673,9 @@ fn visit_decl_with_scope(d: @decl, sc: scopes, v: vt<scopes>) {
}
}
fn visit_arm_with_scope(a: ast::arm, sc: scopes, v: vt<scopes>) {
fn visit_arm_with_scope(a: ast::arm, &&sc: scopes, v: vt<scopes>) {
for a.pats.each {|p| v.visit_pat(p, sc, v); }
let sc_inner = cons(scope_arm(a), @sc);
let sc_inner = @cons(scope_arm(a), sc);
visit::visit_expr_opt(a.guard, sc_inner, v);
v.visit_block(a.body, sc_inner, v);
}
@ -709,7 +710,7 @@ enum that's in scope",
}
fn follow_import(e: env, sc: scopes, path: [ident], sp: span) ->
fn follow_import(e: env, &&sc: scopes, path: [ident], sp: span) ->
option<def> {
let path_len = vec::len(path);
let mut dcur = lookup_in_scope_strict(e, sc, sp, path[0], ns_module);
@ -738,7 +739,7 @@ fn follow_import(e: env, sc: scopes, path: [ident], sp: span) ->
} else { ret none; }
}
fn resolve_constr(e: @env, c: @ast::constr, sc: scopes, _v: vt<scopes>) {
fn resolve_constr(e: @env, c: @ast::constr, &&sc: scopes, _v: vt<scopes>) {
alt lookup_path_strict(*e, sc, c.span, c.node.path, ns_val) {
some(d@ast::def_fn(_,ast::pure_fn)) {
e.def_map.insert(c.node.id, d);
@ -753,7 +754,7 @@ fn resolve_constr(e: @env, c: @ast::constr, sc: scopes, _v: vt<scopes>) {
// Import resolution
fn resolve_import(e: env, n_id: node_id, name: ast::ident,
ids: [ast::ident], sp: codemap::span, sc: scopes) {
ids: [ast::ident], sp: codemap::span, &&sc: scopes) {
fn register(e: env, id: node_id, cx: ctxt, sp: codemap::span,
name: ast::ident, lookup: fn(namespace) -> option<def>,
impls: [@_impl]) {
@ -768,7 +769,7 @@ fn register(e: env, id: node_id, cx: ctxt, sp: codemap::span,
}
// Temporarily disable this import and the imports coming after during
// resolution of this import.
fn find_imports_after(e: env, id: node_id, sc: scopes) -> [node_id] {
fn find_imports_after(e: env, id: node_id, &&sc: scopes) -> [node_id] {
fn lst(my_id: node_id, vis: [@view_item]) -> [node_id] {
let mut imports = [], found = false;
for vis.each {|vi|
@ -790,7 +791,7 @@ fn lst(my_id: node_id, vis: [@view_item]) -> [node_id] {
}
imports
}
alt sc {
alt *sc {
cons(scope_item(@{node: item_mod(m), _}), _) {
lst(id, m.view_items)
}
@ -922,7 +923,7 @@ fn mk_unresolved_msg(id: ident, kind: str) -> str {
}
// Lookup helpers
fn lookup_path_strict(e: env, sc: scopes, sp: span, pth: @ast::path,
fn lookup_path_strict(e: env, &&sc: scopes, sp: span, pth: @ast::path,
ns: namespace) -> option<def> {
let n_idents = vec::len(pth.idents);
let headns = if n_idents == 1u { ns } else { ns_module };
@ -951,7 +952,7 @@ fn lookup_path_strict(e: env, sc: scopes, sp: span, pth: @ast::path,
}
}
fn lookup_in_scope_strict(e: env, sc: scopes, sp: span, name: ident,
fn lookup_in_scope_strict(e: env, &&sc: scopes, sp: span, name: ident,
ns: namespace) -> option<def> {
alt lookup_in_scope(e, sc, sp, name, ns, true) {
none {
@ -998,7 +999,7 @@ fn def_is_ty_arg(d: def) -> bool {
ret alt d { ast::def_ty_param(_, _) { true } _ { false } };
}
fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace,
fn lookup_in_scope(e: env, &&sc: scopes, sp: span, name: ident, ns: namespace,
check_capture: bool) -> option<def> {
fn in_scope(e: env, sp: span, name: ident, s: scope, ns: namespace) ->
@ -1113,7 +1114,7 @@ fn in_scope(e: env, sp: span, name: ident, s: scope, ns: namespace) ->
let mut left_fn_level2 = false;
let mut sc = sc;
loop {
alt copy sc {
alt *sc {
nil { ret none; }
cons(hd, tl) {
alt in_scope(e, sp, name, hd, ns) {
@ -1152,7 +1153,7 @@ fn in_scope(e: env, sp: span, name: ident, s: scope, ns: namespace) ->
_ { }
}
}
sc = *tl;
sc = tl;
}
}
};
@ -1450,15 +1451,15 @@ fn is_exported(e: env, i: ident, m: @indexed_mod) -> bool {
// A list search function. Applies `f` to each element of `v`, starting from
// the first. When `f` returns `some(x)`, `list_search` returns `some(x)`. If
// `f` returns `none` for every element, `list_search` returns `none`.
fn list_search<T: copy, U: copy>(ls: list<T>, f: fn(T) -> option<U>)
fn list_search<T: copy, U: copy>(ls: @list<T>, f: fn(T) -> option<U>)
-> option<U> {
let mut ls = ls;
loop {
ls = alt ls {
ls = alt *ls {
cons(hd, tl) {
let result = f(hd);
if !is_none(result) { ret result; }
*tl
tl
}
nil { ret none; }
};
@ -1585,16 +1586,16 @@ fn lookup_in_mie(e: env, mie: mod_index_entry, ns: namespace) ->
// Module indexing
fn add_to_index(index: hashmap<ident, list<mod_index_entry>>, id: ident,
fn add_to_index(index: hashmap<ident, @list<mod_index_entry>>, id: ident,
ent: mod_index_entry) {
alt index.find(id) {
none { index.insert(id, cons(ent, @nil::<mod_index_entry>)); }
some(prev) { index.insert(id, cons(ent, @prev)); }
none { index.insert(id, @cons(ent, @nil)); }
some(prev) { index.insert(id, @cons(ent, prev)); }
}
}
fn index_view_items(view_items: [@ast::view_item],
index: hashmap<ident, list<mod_index_entry>>) {
index: hashmap<ident, @list<mod_index_entry>>) {
for view_items.each {|vi|
alt vi.node {
ast::view_item_use(ident, _, id) {
@ -1624,7 +1625,7 @@ fn index_view_items(view_items: [@ast::view_item],
}
fn index_mod(md: ast::_mod) -> mod_index {
let index = str_hash::<list<mod_index_entry>>();
let index = str_hash::<@list<mod_index_entry>>();
index_view_items(md.view_items, index);
@ -1664,7 +1665,7 @@ fn index_mod(md: ast::_mod) -> mod_index {
fn index_nmod(md: ast::native_mod) -> mod_index {
let index = str_hash::<list<mod_index_entry>>();
let index = str_hash::<@list<mod_index_entry>>();
index_view_items(md.view_items, index);
@ -1718,7 +1719,7 @@ fn check_for_collisions(e: @env, c: ast::crate) {
visit::visit_crate(c, (), visit::mk_vt(v));
}
fn check_mod_name(e: env, name: ident, entries: list<mod_index_entry>) {
fn check_mod_name(e: env, name: ident, entries: @list<mod_index_entry>) {
let mut saw_mod = false;
let mut saw_type = false;
let mut saw_value = false;
@ -1727,7 +1728,7 @@ fn dup(e: env, sp: span, word: str, name: ident) {
e.sess.span_fatal(sp, "duplicate definition of " + word + name);
}
loop {
alt entries {
alt *entries {
cons(entry, rest) {
if !is_none(lookup_in_mie(e, entry, ns_val)) {
if saw_value {
@ -1744,7 +1745,7 @@ fn dup(e: env, sp: span, word: str, name: ident) {
dup(e, mie_span(entry), "module ", name);
} else { saw_mod = true; }
}
entries = *rest;
entries = rest;
}
nil { break; }
}
@ -2149,10 +2150,10 @@ enum %s",
* methods: the item's methods
*/
type _impl = {did: def_id, ident: ast::ident, methods: [@method_info]};
type iscopes = list<@[@_impl]>;
type iscopes = @list<@[@_impl]>;
fn resolve_impls(e: @env, c: @ast::crate) {
visit::visit_crate(*c, nil, visit::mk_vt(@{
visit::visit_crate(*c, @nil, visit::mk_vt(@{
visit_block: bind visit_block_with_impl_scope(e, _, _, _),
visit_mod: bind visit_mod_with_impl_scope(e, _, _, _, _, _),
visit_expr: bind resolve_impl_in_expr(e, _, _, _)
@ -2310,7 +2311,7 @@ fn find_impls_in_mod(e: env, m: def, &impls: [@_impl],
}
}
fn visit_block_with_impl_scope(e: @env, b: ast::blk, sc: iscopes,
fn visit_block_with_impl_scope(e: @env, b: ast::blk, &&sc: iscopes,
v: vt<iscopes>) {
let mut impls = [];
for b.node.view_items.each {|vi|
@ -2324,12 +2325,12 @@ fn visit_block_with_impl_scope(e: @env, b: ast::blk, sc: iscopes,
_ {}
}
}
let sc = if vec::len(impls) > 0u { cons(@impls, @sc) } else { sc };
let sc = if vec::len(impls) > 0u { @cons(@impls, sc) } else { sc };
visit::visit_block(b, sc, v);
}
fn visit_mod_with_impl_scope(e: @env, m: ast::_mod, s: span, id: node_id,
sc: iscopes, v: vt<iscopes>) {
&&sc: iscopes, v: vt<iscopes>) {
let mut impls = [];
for m.view_items.each {|vi|
find_impls_in_view_item(*e, vi, impls, some(sc));
@ -2337,14 +2338,15 @@ fn visit_mod_with_impl_scope(e: @env, m: ast::_mod, s: span, id: node_id,
for m.items.each {|i| find_impls_in_item(*e, i, impls, none, none); }
let impls = @impls;
visit::visit_mod(m, s, id, if vec::len(*impls) > 0u {
cons(impls, @sc)
@cons(impls, sc)
} else {
sc
}, v);
e.impl_map.insert(id, cons(impls, @nil));
e.impl_map.insert(id, @cons(impls, @nil));
}
fn resolve_impl_in_expr(e: @env, x: @ast::expr, sc: iscopes, v: vt<iscopes>) {
fn resolve_impl_in_expr(e: @env, x: @ast::expr,
&&sc: iscopes, v: vt<iscopes>) {
alt x.node {
// Store the visible impls in all exprs that might need them
ast::expr_field(_, _, _) | ast::expr_path(_) | ast::expr_cast(_, _) |

View File

@ -5267,7 +5267,7 @@ fn reexports(cx: @crate_ctxt) -> [(str, ast::def_id)] {
fn impl_map(cx: @crate_ctxt,
id: ast::node_id) -> [(ast::ident, ast::def_id)] {
alt cx.maps.impl_map.get(id) {
alt *cx.maps.impl_map.get(id) {
list::cons(impls, @list::nil) {
(*impls).map {|i|
(i.ident, i.did)

View File

@ -19,6 +19,7 @@
import std::map::hashmap;
import std::list;
import std::list::{list, cons, nil};
import driver::session::session;
import metadata::csearch;
import syntax::ast::*, syntax::ast_util, syntax::visit;
@ -98,11 +99,11 @@ fn type_needs(cx: ctx, use: uint, ty: ty::t) {
let mut done = true;
// Optimization -- don't descend type if all params already have this use
for vec::each(cx.uses) {|u| if u & use != use { done = false } }
if !done { type_needs_inner(cx, use, ty, list::nil); }
if !done { type_needs_inner(cx, use, ty, @nil); }
}
fn type_needs_inner(cx: ctx, use: uint, ty: ty::t,
enums_seen: list::list<def_id>) {
enums_seen: @list<def_id>) {
ty::maybe_walk_ty(ty) {|ty|
if ty::type_has_params(ty) {
alt ty::get(ty).struct {
@ -110,7 +111,7 @@ fn type_needs_inner(cx: ctx, use: uint, ty: ty::t,
ty::ty_box(_) | ty::ty_iface(_, _) { false }
ty::ty_enum(did, substs) {
if option::is_none(list::find(enums_seen, {|id| id == did})) {
let seen = list::cons(did, @enums_seen);
let seen = @cons(did, enums_seen);
for vec::each(*ty::enum_variants(cx.ccx.tcx, did)) {|v|
for vec::each(v.args) {|aty|
let t = ty::subst(cx.ccx.tcx, substs, aty);

View File

@ -105,7 +105,7 @@ fn get(br: ty::bound_region) -> ty::region {
}
fn find(br: ty::bound_region) -> option<ty::region> {
for list::each(*self) { |isr|
for list::each(self) { |isr|
let (isr_br, isr_r) = isr;
if isr_br == br { ret some(isr_r); }
}

View File

@ -271,7 +271,7 @@ fn visit_mod(
mod_id: ast::node_id
) {
let all_impls = all_impls(m);
alt check ctxt.impl_map.get(mod_id) {
alt check *ctxt.impl_map.get(mod_id) {
list::cons(impls, @list::nil) {
for vec::each(*impls) {|i|
// This impl is not an item in the current mod

View File

@ -12,7 +12,7 @@ fn check_log<T>(exp: str, v: T) {
fn main() {
let x = list::from_vec([a(22u), b("hi")]);
let exp = "cons(a(22), @cons(b(\"hi\"), @nil))";
let exp = "@cons(a(22), @cons(b(\"hi\"), @nil))";
assert #fmt["%?", x] == exp;
check_log(exp, x);
}

View File

@ -2,25 +2,25 @@
import std::list::*;
pure fn pure_length_go<T: copy>(ls: list<T>, acc: uint) -> uint {
alt ls { nil { acc } cons(_, tl) { pure_length_go(*tl, acc + 1u) } }
pure fn pure_length_go<T: copy>(ls: @list<T>, acc: uint) -> uint {
alt *ls { nil { acc } cons(_, tl) { pure_length_go(tl, acc + 1u) } }
}
pure fn pure_length<T: copy>(ls: list<T>) -> uint { pure_length_go(ls, 0u) }
pure fn pure_length<T: copy>(ls: @list<T>) -> uint { pure_length_go(ls, 0u) }
pure fn nonempty_list<T: copy>(ls: list<T>) -> bool { pure_length(ls) > 0u }
pure fn nonempty_list<T: copy>(ls: @list<T>) -> bool { pure_length(ls) > 0u }
// Of course, the compiler can't take advantage of the
// knowledge that ls is a cons node. Future work.
// Also, this is pretty contrived since nonempty_list
// could be a "enum refinement", if we implement those.
fn safe_head<T: copy>(ls: list<T>) : nonempty_list(ls) -> T {
fn safe_head<T: copy>(ls: @list<T>) : nonempty_list(ls) -> T {
check is_not_empty(ls);
ret head(ls);
}
fn main() {
let mylist = cons(@1u, @nil);
let mylist = @cons(@1u, @nil);
// Again, a way to eliminate such "obvious" checks seems
// desirable. (Tags could have postconditions.)
check (nonempty_list(mylist));

View File

@ -7,33 +7,33 @@
// Can't easily be written as a "pure fn" because there's
// no syntax for specifying that f is pure.
fn pure_foldl<T: copy, U: copy>(ls: list<T>, u: U, f: fn(T, U) -> U) -> U {
alt ls {
fn pure_foldl<T: copy, U: copy>(ls: @list<T>, u: U, f: fn(T, U) -> U) -> U {
alt *ls {
nil { u }
cons(hd, tl) { f(hd, pure_foldl(*tl, f(hd, u), f)) }
cons(hd, tl) { f(hd, pure_foldl(tl, f(hd, u), f)) }
}
}
// Shows how to use an "unchecked" block to call a general
// fn from a pure fn
pure fn pure_length<T: copy>(ls: list<T>) -> uint {
pure fn pure_length<T: copy>(ls: @list<T>) -> uint {
fn count<T>(_t: T, &&u: uint) -> uint { u + 1u }
unchecked{ pure_foldl(ls, 0u, count(_, _)) }
}
pure fn nonempty_list<T: copy>(ls: list<T>) -> bool { pure_length(ls) > 0u }
pure fn nonempty_list<T: copy>(ls: @list<T>) -> bool { pure_length(ls) > 0u }
// Of course, the compiler can't take advantage of the
// knowledge that ls is a cons node. Future work.
// Also, this is pretty contrived since nonempty_list
// could be a "enum refinement", if we implement those.
fn safe_head<T: copy>(ls: list<T>) : nonempty_list(ls) -> T {
fn safe_head<T: copy>(ls: @list<T>) : nonempty_list(ls) -> T {
check is_not_empty(ls);
ret head(ls)
}
fn main() {
let mylist = cons(@1u, @nil);
let mylist = @cons(@1u, @nil);
// Again, a way to eliminate such "obvious" checks seems
// desirable. (Tags could have postconditions.)
check (nonempty_list(mylist));