mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Allow omission of the '.' after nullary tag patterns
This commit allows patterns like: alt x { some(_) { ... } none { } } without the '.' after none. The parser suspends judgment about whether a bare ident is a tag or a new bound variable; instead, the resolver disambiguates. This means that any code after resolution that pattern-matches on patterns needs to call pat_util::normalize_pat, which consults an environment to do this disambiguation. In addition, local variables are no longer allowed to shadow tag names, so this required changing some code (e.g. renaming variables named "mut", and renaming ast::sub to subtract). The parser currently accepts patterns with and without the '.'. Once the compiler and libraries are changed, it will no longer accept the '.'.
This commit is contained in:
parent
a7bd817017
commit
c3bc8fada8
@ -9,6 +9,7 @@ import std::list;
|
|||||||
import option::{some, none, is_none};
|
import option::{some, none, is_none};
|
||||||
import list::list;
|
import list::list;
|
||||||
import driver::session::session;
|
import driver::session::session;
|
||||||
|
import pat_util::*;
|
||||||
|
|
||||||
// This is not an alias-analyser (though it would merit from becoming one, or
|
// This is not an alias-analyser (though it would merit from becoming one, or
|
||||||
// getting input from one, to be more precise). It is a pass that checks
|
// getting input from one, to be more precise). It is a pass that checks
|
||||||
@ -323,7 +324,7 @@ fn check_alt(cx: ctx, input: @ast::expr, arms: [ast::arm], sc: scope,
|
|||||||
for a: ast::arm in arms {
|
for a: ast::arm in arms {
|
||||||
let new_bs = sc.bs;
|
let new_bs = sc.bs;
|
||||||
let root_var = path_def_id(cx, root.ex);
|
let root_var = path_def_id(cx, root.ex);
|
||||||
let pat_id_map = ast_util::pat_id_map(a.pats[0]);
|
let pat_id_map = pat_util::pat_id_map(cx.tcx, a.pats[0]);
|
||||||
type info = {
|
type info = {
|
||||||
id: node_id,
|
id: node_id,
|
||||||
mutable unsafe_tys: [unsafe_ty],
|
mutable unsafe_tys: [unsafe_ty],
|
||||||
@ -588,10 +589,11 @@ fn pattern_roots(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat)
|
|||||||
-> [pattern_root] {
|
-> [pattern_root] {
|
||||||
fn walk(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat,
|
fn walk(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat,
|
||||||
&set: [pattern_root]) {
|
&set: [pattern_root]) {
|
||||||
alt pat.node {
|
alt normalize_pat(tcx, pat).node {
|
||||||
ast::pat_wild. | ast::pat_lit(_) | ast::pat_range(_, _) {}
|
ast::pat_wild. | ast::pat_lit(_) | ast::pat_range(_, _) {}
|
||||||
ast::pat_bind(nm, sub) {
|
ast::pat_ident(nm, sub) {
|
||||||
set += [{id: pat.id, name: nm, mut: mut, span: pat.span}];
|
set += [{id: pat.id, name: path_to_ident(nm), mut: mut,
|
||||||
|
span: pat.span}];
|
||||||
alt sub { some(p) { walk(tcx, mut, p, set); } _ {} }
|
alt sub { some(p) { walk(tcx, mut, p, set); } _ {} }
|
||||||
}
|
}
|
||||||
ast::pat_tag(_, ps) | ast::pat_tup(ps) {
|
ast::pat_tag(_, ps) | ast::pat_tup(ps) {
|
||||||
|
@ -44,14 +44,14 @@ fn map_fn(cx: ctx, _fk: visit::fn_kind, decl: fn_decl, _body: blk,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn map_local(cx: ctx, loc: @local) {
|
fn map_local(cx: ctx, loc: @local) {
|
||||||
ast_util::pat_bindings(loc.node.pat) {|p|
|
pat_util::pat_bindings(loc.node.pat) {|p|
|
||||||
cx.map.insert(p.id, node_local(cx.local_id));
|
cx.map.insert(p.id, node_local(cx.local_id));
|
||||||
cx.local_id += 1u;
|
cx.local_id += 1u;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_arm(cx: ctx, arm: arm) {
|
fn map_arm(cx: ctx, arm: arm) {
|
||||||
ast_util::pat_bindings(arm.pats[0]) {|p|
|
pat_util::pat_bindings(arm.pats[0]) {|p|
|
||||||
cx.map.insert(p.id, node_local(cx.local_id));
|
cx.map.insert(p.id, node_local(cx.local_id));
|
||||||
cx.local_id += 1u;
|
cx.local_id += 1u;
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import syntax::ast::*;
|
import syntax::ast::*;
|
||||||
import syntax::ast_util::{variant_def_ids, dummy_sp, compare_lit_exprs,
|
import syntax::ast_util::{variant_def_ids, dummy_sp, compare_lit_exprs,
|
||||||
lit_expr_eq};
|
lit_expr_eq};
|
||||||
|
import pat_util::*;
|
||||||
import syntax::visit;
|
import syntax::visit;
|
||||||
import option::{some, none};
|
import option::{some, none};
|
||||||
import driver::session::session;
|
import driver::session::session;
|
||||||
@ -16,7 +17,12 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) {
|
|||||||
|
|
||||||
fn check_expr(tcx: ty::ctxt, ex: @expr, &&s: (), v: visit::vt<()>) {
|
fn check_expr(tcx: ty::ctxt, ex: @expr, &&s: (), v: visit::vt<()>) {
|
||||||
visit::visit_expr(ex, s, v);
|
visit::visit_expr(ex, s, v);
|
||||||
alt ex.node { expr_alt(_, arms) { check_arms(tcx, arms); } _ { } }
|
alt ex.node {
|
||||||
|
expr_alt(_, arms) {
|
||||||
|
check_arms(tcx, pat_util::normalize_arms(tcx, arms));
|
||||||
|
}
|
||||||
|
_ { }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_arms(tcx: ty::ctxt, arms: [arm]) {
|
fn check_arms(tcx: ty::ctxt, arms: [arm]) {
|
||||||
@ -66,8 +72,8 @@ fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
alt a.node {
|
alt a.node {
|
||||||
pat_bind(_, some(p)) { pattern_supersedes(tcx, p, b) }
|
pat_ident(_, some(p)) { pattern_supersedes(tcx, p, b) }
|
||||||
pat_wild. | pat_bind(_, none.) { true }
|
pat_wild. | pat_ident(_, none.) { true }
|
||||||
pat_lit(la) {
|
pat_lit(la) {
|
||||||
alt b.node {
|
alt b.node {
|
||||||
pat_lit(lb) { lit_expr_eq(la, lb) }
|
pat_lit(lb) { lit_expr_eq(la, lb) }
|
||||||
@ -132,11 +138,11 @@ fn check_local(tcx: ty::ctxt, loc: @local, &&s: (), v: visit::vt<()>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_refutable(tcx: ty::ctxt, pat: @pat) -> bool {
|
fn is_refutable(tcx: ty::ctxt, pat: @pat) -> bool {
|
||||||
alt pat.node {
|
alt normalize_pat(tcx, pat).node {
|
||||||
pat_box(sub) | pat_uniq(sub) | pat_bind(_, some(sub)) {
|
pat_box(sub) | pat_uniq(sub) | pat_ident(_, some(sub)) {
|
||||||
is_refutable(tcx, sub)
|
is_refutable(tcx, sub)
|
||||||
}
|
}
|
||||||
pat_wild. | pat_bind(_, none.) { false }
|
pat_wild. | pat_ident(_, none.) { false }
|
||||||
pat_lit(_) { true }
|
pat_lit(_) { true }
|
||||||
pat_rec(fields, _) {
|
pat_rec(fields, _) {
|
||||||
for field: field_pat in fields {
|
for field: field_pat in fields {
|
||||||
|
@ -8,6 +8,7 @@ import middle::trans_build::B;
|
|||||||
import middle::ty;
|
import middle::ty;
|
||||||
import syntax::{ast, codemap};
|
import syntax::{ast, codemap};
|
||||||
import ast::ty;
|
import ast::ty;
|
||||||
|
import pat_util::*;
|
||||||
import util::ppaux::ty_to_str;
|
import util::ppaux::ty_to_str;
|
||||||
|
|
||||||
export create_local_var;
|
export create_local_var;
|
||||||
@ -629,9 +630,10 @@ fn create_local_var(bcx: @block_ctxt, local: @ast::local)
|
|||||||
option::none. {}
|
option::none. {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = alt local.node.pat.node {
|
let name = path_to_ident(alt pat_util::normalize_pat(bcx_tcx(bcx),
|
||||||
ast::pat_bind(ident, _) { ident /*XXX deal w/ optional node binding*/ }
|
local.node.pat).node {
|
||||||
};
|
ast::pat_ident(ident, _) { ident /*XXX deal w/ optional node binding*/ }
|
||||||
|
});
|
||||||
let loc = codemap::lookup_char_pos(cx.sess.codemap,
|
let loc = codemap::lookup_char_pos(cx.sess.codemap,
|
||||||
local.span.lo);
|
local.span.lo);
|
||||||
let ty = trans::node_id_type(cx, local.node.id);
|
let ty = trans::node_id_type(cx, local.node.id);
|
||||||
|
119
src/comp/middle/pat_util.rs
Normal file
119
src/comp/middle/pat_util.rs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
import syntax::ast::*;
|
||||||
|
import syntax::ast_util;
|
||||||
|
import syntax::ast_util::respan;
|
||||||
|
import syntax::fold;
|
||||||
|
import syntax::fold::*;
|
||||||
|
|
||||||
|
export normalize_arms;
|
||||||
|
export normalize_pat;
|
||||||
|
export normalize_pat_def_map;
|
||||||
|
export pat_binding_ids;
|
||||||
|
export pat_bindings;
|
||||||
|
export pat_id_map;
|
||||||
|
export path_to_ident;
|
||||||
|
|
||||||
|
fn normalize_pat_def_map(dm: resolve::def_map, p: @pat) -> @pat {
|
||||||
|
// have to do it the hard way b/c ast fold doesn't pass around
|
||||||
|
// node IDs. bother.
|
||||||
|
alt p.node {
|
||||||
|
pat_wild. { p }
|
||||||
|
pat_ident(_, none.) { normalize_one(dm, p) }
|
||||||
|
pat_ident(q, some(r)) {
|
||||||
|
@{node: pat_ident(q, some(normalize_pat_def_map(dm, r)))
|
||||||
|
with *p}
|
||||||
|
}
|
||||||
|
pat_tag(a_path, subs) {
|
||||||
|
@{node: pat_tag(a_path,
|
||||||
|
vec::map(subs, {|p| normalize_pat_def_map(dm, p)})) with *p}
|
||||||
|
}
|
||||||
|
pat_rec(field_pats, b) {
|
||||||
|
@{node: pat_rec(vec::map(field_pats,
|
||||||
|
{|fp| {pat: normalize_pat_def_map(dm, fp.pat) with fp}}), b)
|
||||||
|
with *p}
|
||||||
|
}
|
||||||
|
pat_tup(subs) {
|
||||||
|
@{node: pat_tup(vec::map(subs, {|p| normalize_pat_def_map(dm, p)}))
|
||||||
|
with *p}
|
||||||
|
}
|
||||||
|
pat_box(q) {
|
||||||
|
@{node: pat_box(normalize_pat_def_map(dm, q))
|
||||||
|
with *p}
|
||||||
|
}
|
||||||
|
pat_uniq(q) {
|
||||||
|
@{node: pat_uniq(normalize_pat_def_map(dm, q))
|
||||||
|
with *p}
|
||||||
|
}
|
||||||
|
pat_lit(_) { p }
|
||||||
|
pat_range(_,_) { p }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn normalize_one(dm: resolve::def_map, p: @pat) -> @pat {
|
||||||
|
alt dm.find(p.id) {
|
||||||
|
some(d) {
|
||||||
|
alt p.node {
|
||||||
|
pat_ident(tag_path, _) { @{id: p.id,
|
||||||
|
node: pat_tag(tag_path, []),
|
||||||
|
span: p.span} }
|
||||||
|
_ { p }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
none. { p }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn normalize_pat(tcx: ty::ctxt, p: @pat) -> @pat {
|
||||||
|
normalize_pat_def_map(tcx.def_map, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn normalize_arms(tcx: ty::ctxt, arms:[arm]) -> [arm] {
|
||||||
|
vec::map(arms, {|a|
|
||||||
|
{pats:
|
||||||
|
vec::map(a.pats, {|p|
|
||||||
|
pat_util::normalize_pat(tcx, p)})
|
||||||
|
with a}})
|
||||||
|
}
|
||||||
|
|
||||||
|
type pat_id_map = std::map::hashmap<str, node_id>;
|
||||||
|
|
||||||
|
// This is used because same-named variables in alternative patterns need to
|
||||||
|
// use the node_id of their namesake in the first pattern.
|
||||||
|
fn pat_id_map(tcx: ty::ctxt, pat: @pat) -> pat_id_map {
|
||||||
|
let map = std::map::new_str_hash::<node_id>();
|
||||||
|
pat_bindings(normalize_pat(tcx, pat)) {|bound|
|
||||||
|
let name = path_to_ident(alt bound.node
|
||||||
|
{ pat_ident(n, _) { n } });
|
||||||
|
map.insert(name, bound.id);
|
||||||
|
};
|
||||||
|
ret map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This does *not* normalize. The pattern should be already normalized
|
||||||
|
// if you want to get a normalized pattern out of it.
|
||||||
|
// Could return a constrained type in order to express that (future work)
|
||||||
|
fn pat_bindings(pat: @pat, it: block(@pat)) {
|
||||||
|
alt pat.node {
|
||||||
|
pat_ident(_, option::none.) { it(pat); }
|
||||||
|
pat_ident(_, option::some(sub)) { it(pat); pat_bindings(sub, it); }
|
||||||
|
pat_tag(_, sub) { for p in sub { pat_bindings(p, it); } }
|
||||||
|
pat_rec(fields, _) { for f in fields { pat_bindings(f.pat, it); } }
|
||||||
|
pat_tup(elts) { for elt in elts { pat_bindings(elt, it); } }
|
||||||
|
pat_box(sub) { pat_bindings(sub, it); }
|
||||||
|
pat_uniq(sub) { pat_bindings(sub, it); }
|
||||||
|
pat_wild. | pat_lit(_) | pat_range(_, _) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pat_binding_ids(pat: @pat) -> [node_id] {
|
||||||
|
let found = [];
|
||||||
|
pat_bindings(pat) {|b| found += [b.id]; };
|
||||||
|
ret found;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path_to_ident(p: @path) -> ident {
|
||||||
|
alt vec::last(p.node.idents) {
|
||||||
|
none. { // sigh
|
||||||
|
fail "Malformed path"; }
|
||||||
|
some(i) { ret i; }
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ import syntax::{ast, ast_util, codemap};
|
|||||||
import syntax::ast::*;
|
import syntax::ast::*;
|
||||||
import ast::{ident, fn_ident, def, def_id, node_id};
|
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};
|
||||||
|
import pat_util::*;
|
||||||
|
|
||||||
import front::attr;
|
import front::attr;
|
||||||
import metadata::{csearch, cstore};
|
import metadata::{csearch, cstore};
|
||||||
@ -181,10 +182,12 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) ->
|
|||||||
sess: sess};
|
sess: sess};
|
||||||
map_crate(e, crate);
|
map_crate(e, crate);
|
||||||
resolve_imports(*e);
|
resolve_imports(*e);
|
||||||
check_for_collisions(e, *crate);
|
|
||||||
check_exports(e);
|
check_exports(e);
|
||||||
resolve_names(e, crate);
|
resolve_names(e, crate);
|
||||||
resolve_impls(e, crate);
|
resolve_impls(e, crate);
|
||||||
|
// check_for_collisions must happen after resolve_names so we
|
||||||
|
// don't complain if a pattern uses the same nullary tag twice
|
||||||
|
check_for_collisions(e, *crate);
|
||||||
if sess.opts.warn_unused_imports {
|
if sess.opts.warn_unused_imports {
|
||||||
check_unused_imports(e);
|
check_unused_imports(e);
|
||||||
}
|
}
|
||||||
@ -417,6 +420,20 @@ 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 tag. */
|
||||||
|
ast::pat_ident(p, none.) {
|
||||||
|
let fnd = lookup_in_scope(*e, sc, p.span, path_to_ident(p),
|
||||||
|
ns_val(ns_a_tag));
|
||||||
|
alt fnd {
|
||||||
|
some(ast::def_variant(did, vid)) {
|
||||||
|
e.def_map.insert(pat.id, ast::def_variant(did, vid));
|
||||||
|
}
|
||||||
|
_ {
|
||||||
|
// Binds a var -- nothing needs to be done
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ { }
|
_ { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -539,30 +556,32 @@ fn visit_expr_with_scope(x: @ast::expr, sc: scopes, v: vt<scopes>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is only for irrefutable patterns (e.g. ones that appear in a let)
|
||||||
|
// So if x occurs, and x is already known to be a tag, that's always an error.
|
||||||
fn visit_local_with_scope(e: @env, loc: @local, sc:scopes, v:vt<scopes>) {
|
fn visit_local_with_scope(e: @env, loc: @local, sc:scopes, v:vt<scopes>) {
|
||||||
// Checks whether the given local has the same name as a tag that's
|
// Check whether the given local has the same name as a tag that's
|
||||||
// in scope
|
// in scope
|
||||||
// We disallow this, in order to make alt patterns consisting of
|
// We disallow this, in order to make alt patterns consisting of
|
||||||
// a single identifier unambiguous (does the pattern "foo" refer
|
// a single identifier unambiguous (does the pattern "foo" refer
|
||||||
// to tag foo, or is it binding a new name foo?)
|
// to tag foo, or is it binding a new name foo?)
|
||||||
alt loc.node.pat.node {
|
alt loc.node.pat.node {
|
||||||
pat_bind(an_ident,_) {
|
pat_ident(an_ident,_) {
|
||||||
// Be sure to pass ns_a_tag to lookup_in_scope so that
|
// Be sure to pass ns_a_tag to lookup_in_scope so that
|
||||||
// if this is a name that's being shadowed, we don't die
|
// if this is a name that's being shadowed, we don't die
|
||||||
alt lookup_in_scope(*e, sc, loc.span, an_ident, ns_val(ns_a_tag)) {
|
alt lookup_in_scope(*e, sc, loc.span,
|
||||||
|
path_to_ident(an_ident), ns_val(ns_a_tag)) {
|
||||||
some(ast::def_variant(tag_id,variant_id)) {
|
some(ast::def_variant(tag_id,variant_id)) {
|
||||||
// Declaration shadows a tag that's in scope.
|
// Declaration shadows a tag that's in scope.
|
||||||
// That's an error.
|
// That's an error.
|
||||||
e.sess.span_err(loc.span,
|
e.sess.span_err(loc.span,
|
||||||
#fmt("Declaration of %s shadows a tag that's in scope",
|
#fmt("Declaration of %s shadows a tag that's in scope",
|
||||||
an_ident));
|
path_to_ident(an_ident)));
|
||||||
}
|
}
|
||||||
_ {}
|
_ {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ {}
|
_ {}
|
||||||
}
|
}
|
||||||
|
|
||||||
visit::visit_local(loc, sc, v);
|
visit::visit_local(loc, sc, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -907,7 +926,7 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
|
|||||||
}
|
}
|
||||||
scope_loop(local) {
|
scope_loop(local) {
|
||||||
if ns == ns_val(ns_any_value) {
|
if ns == ns_val(ns_any_value) {
|
||||||
alt lookup_in_pat(name, local.node.pat) {
|
alt lookup_in_pat(e, name, local.node.pat) {
|
||||||
some(did) { ret some(ast::def_binding(did)); }
|
some(did) { ret some(ast::def_binding(did)); }
|
||||||
_ { }
|
_ { }
|
||||||
}
|
}
|
||||||
@ -918,7 +937,7 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
|
|||||||
}
|
}
|
||||||
scope_arm(a) {
|
scope_arm(a) {
|
||||||
if ns == ns_val(ns_any_value) {
|
if ns == ns_val(ns_any_value) {
|
||||||
alt lookup_in_pat(name, a.pats[0]) {
|
alt lookup_in_pat(e, name, a.pats[0]) {
|
||||||
some(did) { ret some(ast::def_binding(did)); }
|
some(did) { ret some(ast::def_binding(did)); }
|
||||||
_ { ret none; }
|
_ { ret none; }
|
||||||
}
|
}
|
||||||
@ -997,11 +1016,13 @@ fn lookup_in_ty_params(e: env, name: ident, ty_params: [ast::ty_param])
|
|||||||
ret none::<def>;
|
ret none::<def>;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_in_pat(name: ident, pat: @ast::pat) -> option::t<def_id> {
|
fn lookup_in_pat(e: env, name: ident, pat: @ast::pat) -> option::t<def_id> {
|
||||||
let found = none;
|
let found = none;
|
||||||
ast_util::pat_bindings(pat) {|bound|
|
|
||||||
let p_name = alt bound.node { ast::pat_bind(n, _) { n } };
|
pat_util::pat_bindings(normalize_pat_def_map(e.def_map, pat)) {|bound|
|
||||||
if str::eq(p_name, name) { found = some(local_def(bound.id)); }
|
let p_name = alt bound.node { ast::pat_ident(n, _) { n } };
|
||||||
|
if str::eq(path_to_ident(p_name), name)
|
||||||
|
{ found = some(local_def(bound.id)); }
|
||||||
};
|
};
|
||||||
ret found;
|
ret found;
|
||||||
}
|
}
|
||||||
@ -1041,7 +1062,7 @@ fn lookup_in_block(e: env, name: ident, sp: span, b: ast::blk_, pos: uint,
|
|||||||
let (style, loc) = locs[j];
|
let (style, loc) = locs[j];
|
||||||
if ns == ns_val(ns_any_value)
|
if ns == ns_val(ns_any_value)
|
||||||
&& (i < pos || j < loc_pos) {
|
&& (i < pos || j < loc_pos) {
|
||||||
alt lookup_in_pat(name, loc.node.pat) {
|
alt lookup_in_pat(e, name, loc.node.pat) {
|
||||||
some(did) {
|
some(did) {
|
||||||
ret some(ast::def_local(did, style));
|
ret some(ast::def_local(did, style));
|
||||||
}
|
}
|
||||||
@ -1571,9 +1592,9 @@ fn check_item(e: @env, i: @ast::item, &&x: (), v: vt<()>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_pat(ch: checker, p: @ast::pat) {
|
fn check_pat(e: @env, ch: checker, p: @ast::pat) {
|
||||||
ast_util::pat_bindings(p) {|p|
|
pat_util::pat_bindings(normalize_pat_def_map(e.def_map, p)) {|p|
|
||||||
let ident = alt p.node { pat_bind(n, _) { n } };
|
let ident = path_to_ident(alt p.node { pat_ident(n, _) { n } });
|
||||||
add_name(ch, p.span, ident);
|
add_name(ch, p.span, ident);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1581,13 +1602,13 @@ fn check_pat(ch: checker, p: @ast::pat) {
|
|||||||
fn check_arm(e: @env, a: ast::arm, &&x: (), v: vt<()>) {
|
fn check_arm(e: @env, a: ast::arm, &&x: (), v: vt<()>) {
|
||||||
visit::visit_arm(a, x, v);
|
visit::visit_arm(a, x, v);
|
||||||
let ch0 = checker(*e, "binding");
|
let ch0 = checker(*e, "binding");
|
||||||
check_pat(ch0, a.pats[0]);
|
check_pat(e, ch0, a.pats[0]);
|
||||||
let seen0 = ch0.seen;
|
let seen0 = ch0.seen;
|
||||||
let i = vec::len(a.pats);
|
let i = vec::len(a.pats);
|
||||||
while i > 1u {
|
while i > 1u {
|
||||||
i -= 1u;
|
i -= 1u;
|
||||||
let ch = checker(*e, "binding");
|
let ch = checker(*e, "binding");
|
||||||
check_pat(ch, a.pats[i]);
|
check_pat(e, ch, a.pats[i]);
|
||||||
|
|
||||||
// Ensure the bindings introduced in this pattern are the same as in
|
// Ensure the bindings introduced in this pattern are the same as in
|
||||||
// the first pattern.
|
// the first pattern.
|
||||||
@ -1620,8 +1641,11 @@ fn check_block(e: @env, b: ast::blk, &&x: (), v: vt<()>) {
|
|||||||
ast::decl_local(locs) {
|
ast::decl_local(locs) {
|
||||||
let local_values = checker(*e, "value");
|
let local_values = checker(*e, "value");
|
||||||
for (_, loc) in locs {
|
for (_, loc) in locs {
|
||||||
ast_util::pat_bindings(loc.node.pat) {|p|
|
pat_util::pat_bindings
|
||||||
let ident = alt p.node { pat_bind(n, _) { n } };
|
(normalize_pat_def_map(e.def_map, loc.node.pat))
|
||||||
|
{|p|
|
||||||
|
let ident = path_to_ident(alt p.node
|
||||||
|
{ pat_ident(n, _) { n } });
|
||||||
add_name(local_values, p.span, ident);
|
add_name(local_values, p.span, ident);
|
||||||
check_name(values, p.span, ident);
|
check_name(values, p.span, ident);
|
||||||
};
|
};
|
||||||
|
@ -26,7 +26,8 @@ import back::{link, abi, upcall};
|
|||||||
import syntax::{ast, ast_util, codemap};
|
import syntax::{ast, ast_util, codemap};
|
||||||
import syntax::visit;
|
import syntax::visit;
|
||||||
import syntax::codemap::span;
|
import syntax::codemap::span;
|
||||||
import syntax::print::pprust::{expr_to_str, stmt_to_str};
|
import syntax::print::pprust::{expr_to_str, stmt_to_str, path_to_str};
|
||||||
|
import pat_util::*;
|
||||||
import visit::vt;
|
import visit::vt;
|
||||||
import util::common::*;
|
import util::common::*;
|
||||||
import lib::llvm::{llvm, mk_target_data, mk_type_names};
|
import lib::llvm::{llvm, mk_target_data, mk_type_names};
|
||||||
@ -775,6 +776,8 @@ fn GEP_tag(cx: @block_ctxt, llblobptr: ValueRef, tag_id: ast::def_id,
|
|||||||
|
|
||||||
let true_arg_tys: [ty::t] = [];
|
let true_arg_tys: [ty::t] = [];
|
||||||
for aty: ty::t in arg_tys {
|
for aty: ty::t in arg_tys {
|
||||||
|
// Would be nice to have a way of stating the invariant
|
||||||
|
// that ty_substs is valid for aty
|
||||||
let arg_ty = ty::substitute_type_params(bcx_tcx(cx), ty_substs, aty);
|
let arg_ty = ty::substitute_type_params(bcx_tcx(cx), ty_substs, aty);
|
||||||
true_arg_tys += [arg_ty];
|
true_arg_tys += [arg_ty];
|
||||||
}
|
}
|
||||||
@ -2203,7 +2206,7 @@ fn trans_eager_binop(cx: @block_ctxt, op: ast::binop, lhs: ValueRef,
|
|||||||
if is_float { FAdd(cx, lhs, rhs) }
|
if is_float { FAdd(cx, lhs, rhs) }
|
||||||
else { Add(cx, lhs, rhs) }
|
else { Add(cx, lhs, rhs) }
|
||||||
}
|
}
|
||||||
ast::sub. {
|
ast::subtract. {
|
||||||
if is_float { FSub(cx, lhs, rhs) }
|
if is_float { FSub(cx, lhs, rhs) }
|
||||||
else { Sub(cx, lhs, rhs) }
|
else { Sub(cx, lhs, rhs) }
|
||||||
}
|
}
|
||||||
@ -2641,6 +2644,7 @@ fn trans_local_var(cx: @block_ctxt, def: ast::def) -> local_var_result {
|
|||||||
alt table.find(id) {
|
alt table.find(id) {
|
||||||
some(local_mem(v)) { {val: v, kind: owned} }
|
some(local_mem(v)) { {val: v, kind: owned} }
|
||||||
some(local_imm(v)) { {val: v, kind: owned_imm} }
|
some(local_imm(v)) { {val: v, kind: owned_imm} }
|
||||||
|
r { fail("take_local: internal error"); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
alt def {
|
alt def {
|
||||||
@ -2649,9 +2653,11 @@ fn trans_local_var(cx: @block_ctxt, def: ast::def) -> local_var_result {
|
|||||||
ret { val: cx.fcx.llupvars.get(did.node), kind: owned };
|
ret { val: cx.fcx.llupvars.get(did.node), kind: owned };
|
||||||
}
|
}
|
||||||
ast::def_arg(did, _) {
|
ast::def_arg(did, _) {
|
||||||
|
assert (cx.fcx.llargs.contains_key(did.node));
|
||||||
ret take_local(cx.fcx.llargs, did.node);
|
ret take_local(cx.fcx.llargs, did.node);
|
||||||
}
|
}
|
||||||
ast::def_local(did, _) | ast::def_binding(did) {
|
ast::def_local(did, _) | ast::def_binding(did) {
|
||||||
|
assert (cx.fcx.lllocals.contains_key(did.node));
|
||||||
ret take_local(cx.fcx.lllocals, did.node);
|
ret take_local(cx.fcx.lllocals, did.node);
|
||||||
}
|
}
|
||||||
ast::def_self(did) {
|
ast::def_self(did) {
|
||||||
@ -3502,6 +3508,7 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
|
|||||||
ret trans_expr(bcx, ast_util::ternary_to_if(e), dest);
|
ret trans_expr(bcx, ast_util::ternary_to_if(e), dest);
|
||||||
}
|
}
|
||||||
ast::expr_alt(expr, arms) {
|
ast::expr_alt(expr, arms) {
|
||||||
|
// tcx.sess.span_note(e.span, "about to call trans_alt");
|
||||||
ret trans_alt::trans_alt(bcx, expr, arms, dest);
|
ret trans_alt::trans_alt(bcx, expr, arms, dest);
|
||||||
}
|
}
|
||||||
ast::expr_block(blk) {
|
ast::expr_block(blk) {
|
||||||
@ -4205,8 +4212,9 @@ fn alloc_ty(cx: @block_ctxt, t: ty::t) -> result {
|
|||||||
|
|
||||||
fn alloc_local(cx: @block_ctxt, local: @ast::local) -> @block_ctxt {
|
fn alloc_local(cx: @block_ctxt, local: @ast::local) -> @block_ctxt {
|
||||||
let t = node_id_type(bcx_ccx(cx), local.node.id);
|
let t = node_id_type(bcx_ccx(cx), local.node.id);
|
||||||
let is_simple = alt local.node.pat.node {
|
let p = normalize_pat(bcx_tcx(cx), local.node.pat);
|
||||||
ast::pat_bind(_, none.) { true } _ { false }
|
let is_simple = alt p.node {
|
||||||
|
ast::pat_ident(_, none.) { true } _ { false }
|
||||||
};
|
};
|
||||||
// Do not allocate space for locals that can be kept immediate.
|
// Do not allocate space for locals that can be kept immediate.
|
||||||
let ccx = bcx_ccx(cx);
|
let ccx = bcx_ccx(cx);
|
||||||
@ -4219,10 +4227,10 @@ fn alloc_local(cx: @block_ctxt, local: @ast::local) -> @block_ctxt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let r = alloc_ty(cx, t);
|
let r = alloc_ty(cx, t);
|
||||||
alt local.node.pat.node {
|
alt p.node {
|
||||||
ast::pat_bind(ident, none.) {
|
ast::pat_ident(pth, none.) {
|
||||||
if bcx_ccx(cx).sess.opts.debuginfo {
|
if bcx_ccx(cx).sess.opts.debuginfo {
|
||||||
let _: () = str::as_buf(ident, {|buf|
|
let _: () = str::as_buf(path_to_ident(pth), {|buf|
|
||||||
llvm::LLVMSetValueName(r.val, buf)
|
llvm::LLVMSetValueName(r.val, buf)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -4635,7 +4643,7 @@ fn trans_const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
|
|||||||
if is_float { llvm::LLVMConstFAdd(te1, te2) }
|
if is_float { llvm::LLVMConstFAdd(te1, te2) }
|
||||||
else { llvm::LLVMConstAdd(te1, te2) }
|
else { llvm::LLVMConstAdd(te1, te2) }
|
||||||
}
|
}
|
||||||
ast::sub. {
|
ast::subtract. {
|
||||||
if is_float { llvm::LLVMConstFSub(te1, te2) }
|
if is_float { llvm::LLVMConstFSub(te1, te2) }
|
||||||
else { llvm::LLVMConstSub(te1, te2) }
|
else { llvm::LLVMConstSub(te1, te2) }
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import core::{str, vec, option};
|
import core::{str, vec, option};
|
||||||
import option::{some, none};
|
import option::{some, none};
|
||||||
|
|
||||||
|
import driver::session::session;
|
||||||
import lib::llvm::llvm;
|
import lib::llvm::llvm;
|
||||||
import lib::llvm::llvm::{ValueRef, BasicBlockRef};
|
import lib::llvm::llvm::{ValueRef, BasicBlockRef};
|
||||||
|
import pat_util::*;
|
||||||
import trans_build::*;
|
import trans_build::*;
|
||||||
import trans::{new_sub_block_ctxt, new_scope_block_ctxt, load_if_immediate};
|
import trans::{new_sub_block_ctxt, new_scope_block_ctxt, load_if_immediate};
|
||||||
import syntax::ast;
|
import syntax::ast;
|
||||||
@ -10,6 +12,7 @@ import syntax::ast_util;
|
|||||||
import syntax::ast_util::{dummy_sp};
|
import syntax::ast_util::{dummy_sp};
|
||||||
import syntax::ast::def_id;
|
import syntax::ast::def_id;
|
||||||
import syntax::codemap::span;
|
import syntax::codemap::span;
|
||||||
|
import syntax::print::pprust::pat_to_str;
|
||||||
|
|
||||||
import trans_common::*;
|
import trans_common::*;
|
||||||
|
|
||||||
@ -61,6 +64,7 @@ fn trans_opt(bcx: @block_ctxt, o: opt) -> opt_result {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: invariant -- pat_id is bound in the def_map?
|
||||||
fn variant_opt(ccx: @crate_ctxt, pat_id: ast::node_id) -> opt {
|
fn variant_opt(ccx: @crate_ctxt, pat_id: ast::node_id) -> opt {
|
||||||
let vdef = ast_util::variant_def_ids(ccx.tcx.def_map.get(pat_id));
|
let vdef = ast_util::variant_def_ids(ccx.tcx.def_map.get(pat_id));
|
||||||
let variants = ty::tag_variants(ccx.tcx, vdef.tg);
|
let variants = ty::tag_variants(ccx.tcx, vdef.tg);
|
||||||
@ -83,13 +87,13 @@ type match_branch =
|
|||||||
bound: bind_map,
|
bound: bind_map,
|
||||||
data: @{body: BasicBlockRef,
|
data: @{body: BasicBlockRef,
|
||||||
guard: option::t<@ast::expr>,
|
guard: option::t<@ast::expr>,
|
||||||
id_map: ast_util::pat_id_map}};
|
id_map: pat_id_map}};
|
||||||
type match = [match_branch];
|
type match = [match_branch];
|
||||||
|
|
||||||
fn has_nested_bindings(m: match, col: uint) -> bool {
|
fn has_nested_bindings(m: match, col: uint) -> bool {
|
||||||
for br in m {
|
for br in m {
|
||||||
alt br.pats[col].node {
|
alt br.pats[col].node {
|
||||||
ast::pat_bind(_, some(_)) { ret true; }
|
ast::pat_ident(_, some(_)) { ret true; }
|
||||||
_ {}
|
_ {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,12 +103,13 @@ fn has_nested_bindings(m: match, col: uint) -> bool {
|
|||||||
fn expand_nested_bindings(m: match, col: uint, val: ValueRef) -> match {
|
fn expand_nested_bindings(m: match, col: uint, val: ValueRef) -> match {
|
||||||
let result = [];
|
let result = [];
|
||||||
for br in m {
|
for br in m {
|
||||||
alt br.pats[col].node {
|
alt br.pats[col].node {
|
||||||
ast::pat_bind(name, some(inner)) {
|
ast::pat_ident(name, some(inner)) {
|
||||||
let pats = vec::slice(br.pats, 0u, col) + [inner] +
|
let pats = vec::slice(br.pats, 0u, col) + [inner] +
|
||||||
vec::slice(br.pats, col + 1u, vec::len(br.pats));
|
vec::slice(br.pats, col + 1u, vec::len(br.pats));
|
||||||
result += [@{pats: pats,
|
result += [@{pats: pats,
|
||||||
bound: br.bound + [{ident: name, val: val}]
|
bound: br.bound + [{ident: path_to_ident(name),
|
||||||
|
val: val}]
|
||||||
with *br}];
|
with *br}];
|
||||||
}
|
}
|
||||||
_ { result += [br]; }
|
_ { result += [br]; }
|
||||||
@ -124,8 +129,9 @@ fn enter_match(m: match, col: uint, val: ValueRef, e: enter_pat) -> match {
|
|||||||
vec::slice(br.pats, col + 1u, vec::len(br.pats));
|
vec::slice(br.pats, col + 1u, vec::len(br.pats));
|
||||||
let new_br = @{pats: pats,
|
let new_br = @{pats: pats,
|
||||||
bound: alt br.pats[col].node {
|
bound: alt br.pats[col].node {
|
||||||
ast::pat_bind(name, none.) {
|
ast::pat_ident(name, none.) {
|
||||||
br.bound + [{ident: name, val: val}]
|
br.bound + [{ident: path_to_ident(name),
|
||||||
|
val: val}]
|
||||||
}
|
}
|
||||||
_ { br.bound }
|
_ { br.bound }
|
||||||
} with *br};
|
} with *br};
|
||||||
@ -139,11 +145,11 @@ fn enter_match(m: match, col: uint, val: ValueRef, e: enter_pat) -> match {
|
|||||||
|
|
||||||
fn enter_default(m: match, col: uint, val: ValueRef) -> match {
|
fn enter_default(m: match, col: uint, val: ValueRef) -> match {
|
||||||
fn matches_always(p: @ast::pat) -> bool {
|
fn matches_always(p: @ast::pat) -> bool {
|
||||||
ret alt p.node {
|
alt p.node {
|
||||||
ast::pat_wild. | ast::pat_bind(_, none.) | ast::pat_rec(_, _) |
|
ast::pat_wild. | ast::pat_rec(_, _) |
|
||||||
ast::pat_tup(_) { true }
|
ast::pat_ident(_, none.) | ast::pat_tup(_) { true }
|
||||||
_ { false }
|
_ { false }
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
fn e(p: @ast::pat) -> option::t<[@ast::pat]> {
|
fn e(p: @ast::pat) -> option::t<[@ast::pat]> {
|
||||||
ret if matches_always(p) { some([]) } else { none };
|
ret if matches_always(p) { some([]) } else { none };
|
||||||
@ -257,6 +263,8 @@ fn extract_variant_args(bcx: @block_ctxt, pat_id: ast::node_id,
|
|||||||
vdefs: {tg: def_id, var: def_id}, val: ValueRef) ->
|
vdefs: {tg: def_id, var: def_id}, val: ValueRef) ->
|
||||||
{vals: [ValueRef], bcx: @block_ctxt} {
|
{vals: [ValueRef], bcx: @block_ctxt} {
|
||||||
let ccx = bcx.fcx.lcx.ccx, bcx = bcx;
|
let ccx = bcx.fcx.lcx.ccx, bcx = bcx;
|
||||||
|
// invariant:
|
||||||
|
// pat_id must have the same length ty_param_substs as vdefs?
|
||||||
let ty_param_substs = ty::node_id_to_type_params(ccx.tcx, pat_id);
|
let ty_param_substs = ty::node_id_to_type_params(ccx.tcx, pat_id);
|
||||||
let blobptr = val;
|
let blobptr = val;
|
||||||
let variants = ty::tag_variants(ccx.tcx, vdefs.tg);
|
let variants = ty::tag_variants(ccx.tcx, vdefs.tg);
|
||||||
@ -274,6 +282,9 @@ fn extract_variant_args(bcx: @block_ctxt, pat_id: ast::node_id,
|
|||||||
while i < size {
|
while i < size {
|
||||||
check (valid_variant_index(i, bcx, vdefs_tg, vdefs_var));
|
check (valid_variant_index(i, bcx, vdefs_tg, vdefs_var));
|
||||||
let r =
|
let r =
|
||||||
|
// invariant needed:
|
||||||
|
// how do we know it even makes sense to pass in ty_param_substs
|
||||||
|
// here? What if it's [] and the tag type has variables in it?
|
||||||
trans::GEP_tag(bcx, blobptr, vdefs_tg, vdefs_var, ty_param_substs,
|
trans::GEP_tag(bcx, blobptr, vdefs_tg, vdefs_var, ty_param_substs,
|
||||||
i);
|
i);
|
||||||
bcx = r.bcx;
|
bcx = r.bcx;
|
||||||
@ -328,7 +339,7 @@ fn pick_col(m: match) -> uint {
|
|||||||
fn score(p: @ast::pat) -> uint {
|
fn score(p: @ast::pat) -> uint {
|
||||||
alt p.node {
|
alt p.node {
|
||||||
ast::pat_lit(_) | ast::pat_tag(_, _) | ast::pat_range(_, _) { 1u }
|
ast::pat_lit(_) | ast::pat_tag(_, _) | ast::pat_range(_, _) { 1u }
|
||||||
ast::pat_bind(_, some(p)) { score(p) }
|
ast::pat_ident(_, some(p)) { score(p) }
|
||||||
_ { 0u }
|
_ { 0u }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -582,7 +593,7 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
|
|||||||
|
|
||||||
// Returns false for unreachable blocks
|
// Returns false for unreachable blocks
|
||||||
fn make_phi_bindings(bcx: @block_ctxt, map: [exit_node],
|
fn make_phi_bindings(bcx: @block_ctxt, map: [exit_node],
|
||||||
ids: ast_util::pat_id_map) -> bool {
|
ids: pat_util::pat_id_map) -> bool {
|
||||||
let our_block = bcx.llbb as uint;
|
let our_block = bcx.llbb as uint;
|
||||||
let success = true, bcx = bcx;
|
let success = true, bcx = bcx;
|
||||||
ids.items {|name, node_id|
|
ids.items {|name, node_id|
|
||||||
@ -623,7 +634,7 @@ fn make_phi_bindings(bcx: @block_ctxt, map: [exit_node],
|
|||||||
ret success;
|
ret success;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_alt(cx: @block_ctxt, expr: @ast::expr, arms: [ast::arm],
|
fn trans_alt(cx: @block_ctxt, expr: @ast::expr, arms_: [ast::arm],
|
||||||
dest: trans::dest) -> @block_ctxt {
|
dest: trans::dest) -> @block_ctxt {
|
||||||
let bodies = [];
|
let bodies = [];
|
||||||
let match: match = [];
|
let match: match = [];
|
||||||
@ -633,9 +644,15 @@ fn trans_alt(cx: @block_ctxt, expr: @ast::expr, arms: [ast::arm],
|
|||||||
let er = trans::trans_temp_expr(alt_cx, expr);
|
let er = trans::trans_temp_expr(alt_cx, expr);
|
||||||
if er.bcx.unreachable { ret er.bcx; }
|
if er.bcx.unreachable { ret er.bcx; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
n.b. nothing else in this module should need to normalize,
|
||||||
|
b/c of this call
|
||||||
|
*/
|
||||||
|
let arms = normalize_arms(bcx_tcx(cx), arms_);
|
||||||
|
|
||||||
for a: ast::arm in arms {
|
for a: ast::arm in arms {
|
||||||
let body = new_scope_block_ctxt(er.bcx, "case_body");
|
let body = new_scope_block_ctxt(er.bcx, "case_body");
|
||||||
let id_map = ast_util::pat_id_map(a.pats[0]);
|
let id_map = pat_util::pat_id_map(bcx_tcx(cx), a.pats[0]);
|
||||||
bodies += [body];
|
bodies += [body];
|
||||||
for p: @ast::pat in a.pats {
|
for p: @ast::pat in a.pats {
|
||||||
match +=
|
match +=
|
||||||
@ -666,7 +683,8 @@ fn trans_alt(cx: @block_ctxt, expr: @ast::expr, arms: [ast::arm],
|
|||||||
for a: ast::arm in arms {
|
for a: ast::arm in arms {
|
||||||
let body_cx = bodies[i];
|
let body_cx = bodies[i];
|
||||||
if make_phi_bindings(body_cx, exit_map,
|
if make_phi_bindings(body_cx, exit_map,
|
||||||
ast_util::pat_id_map(a.pats[0])) {
|
pat_util::pat_id_map(bcx_tcx(cx),
|
||||||
|
a.pats[0])) {
|
||||||
let arm_dest = trans::dup_for_join(dest);
|
let arm_dest = trans::dup_for_join(dest);
|
||||||
arm_dests += [arm_dest];
|
arm_dests += [arm_dest];
|
||||||
arm_cxs += [trans::trans_block_dps(body_cx, a.body, arm_dest)];
|
arm_cxs += [trans::trans_block_dps(body_cx, a.body, arm_dest)];
|
||||||
@ -684,8 +702,10 @@ fn trans_alt(cx: @block_ctxt, expr: @ast::expr, arms: [ast::arm],
|
|||||||
fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
|
fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
|
||||||
make_copy: bool) -> @block_ctxt {
|
make_copy: bool) -> @block_ctxt {
|
||||||
let ccx = bcx.fcx.lcx.ccx, bcx = bcx;
|
let ccx = bcx.fcx.lcx.ccx, bcx = bcx;
|
||||||
alt pat.node {
|
|
||||||
ast::pat_bind(_, inner) {
|
// Necessary since bind_irrefutable_pat is called outside trans_alt
|
||||||
|
alt normalize_pat(bcx_tcx(bcx), pat).node {
|
||||||
|
ast::pat_ident(_,inner) {
|
||||||
if make_copy || ccx.copy_map.contains_key(pat.id) {
|
if make_copy || ccx.copy_map.contains_key(pat.id) {
|
||||||
let ty = ty::node_id_to_monotype(ccx.tcx, pat.id);
|
let ty = ty::node_id_to_monotype(ccx.tcx, pat.id);
|
||||||
// FIXME: Could constrain pat_bind to make this
|
// FIXME: Could constrain pat_bind to make this
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
|
|
||||||
import core::{int, uint};
|
import core::{int, uint};
|
||||||
import syntax::ast::*;
|
import syntax::ast::*;
|
||||||
import syntax::ast_util::pat_binding_ids;
|
|
||||||
import syntax::visit;
|
import syntax::visit;
|
||||||
import syntax::codemap::span;
|
import syntax::codemap::span;
|
||||||
import util::common::{log_stmt};
|
import util::common::{log_stmt};
|
||||||
import aux::{num_constraints, get_fn_info, crate_ctxt, add_node};
|
import aux::{num_constraints, get_fn_info, crate_ctxt, add_node};
|
||||||
import middle::tstate::ann::empty_ann;
|
import ann::empty_ann;
|
||||||
|
import pat_util::pat_binding_ids;
|
||||||
|
|
||||||
fn collect_ids_expr(e: @expr, rs: @mutable [node_id]) { *rs += [e.id]; }
|
fn collect_ids_expr(e: @expr, rs: @mutable [node_id]) { *rs += [e.id]; }
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import core::{vec, int, uint, option};
|
import core::{vec, int, uint, option};
|
||||||
import option::*;
|
import option::*;
|
||||||
|
import pat_util::*;
|
||||||
import syntax::ast::*;
|
import syntax::ast::*;
|
||||||
import syntax::ast_util::*;
|
import syntax::ast_util::*;
|
||||||
import syntax::{visit, codemap};
|
import syntax::{visit, codemap};
|
||||||
@ -69,10 +70,10 @@ fn tritv_to_str(fcx: fn_ctxt, v: tritv::t) -> str {
|
|||||||
for p: norm_constraint in constraints(fcx) {
|
for p: norm_constraint in constraints(fcx) {
|
||||||
alt tritv_get(v, p.bit_num) {
|
alt tritv_get(v, p.bit_num) {
|
||||||
dont_care. { }
|
dont_care. { }
|
||||||
t {
|
tt {
|
||||||
s +=
|
s +=
|
||||||
if comma { ", " } else { comma = true; "" } +
|
if comma { ", " } else { comma = true; "" } +
|
||||||
if t == tfalse { "!" } else { "" } +
|
if tt == tfalse { "!" } else { "" } +
|
||||||
constraint_to_str(fcx.ccx.tcx, p.c);
|
constraint_to_str(fcx.ccx.tcx, p.c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,7 +314,7 @@ fn node_id_to_ts_ann(ccx: crate_ctxt, id: node_id) -> ts_ann {
|
|||||||
#error("node_id_to_ts_ann: no ts_ann for node_id %d", id);
|
#error("node_id_to_ts_ann: no ts_ann for node_id %d", id);
|
||||||
fail;
|
fail;
|
||||||
}
|
}
|
||||||
some(t) { ret t; }
|
some(tt) { ret tt; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -779,13 +780,6 @@ fn replace(subst: subst, d: pred_args) -> [constr_arg_general_<inst>] {
|
|||||||
ret rslt;
|
ret rslt;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path_to_ident(cx: ty::ctxt, p: @path) -> ident {
|
|
||||||
alt vec::last(p.node.idents) {
|
|
||||||
none. { cx.sess.span_fatal(p.span, "Malformed path"); }
|
|
||||||
some(i) { ret i; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tag if_ty { if_check; plain_if; }
|
tag if_ty { if_check; plain_if; }
|
||||||
|
|
||||||
fn local_node_id_to_def_id_strict(fcx: fn_ctxt, sp: span, i: node_id) ->
|
fn local_node_id_to_def_id_strict(fcx: fn_ctxt, sp: span, i: node_id) ->
|
||||||
@ -1059,18 +1053,20 @@ fn ast_constr_to_sp_constr(tcx: ty::ctxt, args: [arg], c: @constr) ->
|
|||||||
|
|
||||||
type binding = {lhs: [inst], rhs: option::t<initializer>};
|
type binding = {lhs: [inst], rhs: option::t<initializer>};
|
||||||
|
|
||||||
fn local_to_bindings(loc: @local) -> binding {
|
fn local_to_bindings(tcx: ty::ctxt, loc: @local) -> binding {
|
||||||
let lhs = [];
|
let lhs = [];
|
||||||
pat_bindings(loc.node.pat) {|p|
|
pat_bindings(pat_util::normalize_pat(tcx, loc.node.pat)) {|p|
|
||||||
let ident = alt p.node { pat_bind(name, _) { name } };
|
let ident = alt p.node
|
||||||
|
{ pat_ident(name, _) { path_to_ident(name) } };
|
||||||
lhs += [{ident: ident, node: p.id}];
|
lhs += [{ident: ident, node: p.id}];
|
||||||
};
|
};
|
||||||
{lhs: lhs, rhs: loc.node.init}
|
{lhs: lhs, rhs: loc.node.init}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn locals_to_bindings(locals: [(let_style, @local)]) -> [binding] {
|
fn locals_to_bindings(tcx: ty::ctxt,
|
||||||
|
locals: [(let_style, @local)]) -> [binding] {
|
||||||
let rslt = [];
|
let rslt = [];
|
||||||
for (_, loc) in locals { rslt += [local_to_bindings(loc)]; }
|
for (_, loc) in locals { rslt += [local_to_bindings(tcx, loc)]; }
|
||||||
ret rslt;
|
ret rslt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
|
import option::*;
|
||||||
|
import pat_util::*;
|
||||||
import syntax::ast::*;
|
import syntax::ast::*;
|
||||||
import syntax::ast_util::*;
|
import syntax::ast_util::*;
|
||||||
import option::*;
|
|
||||||
import syntax::visit;
|
import syntax::visit;
|
||||||
import aux::*;
|
|
||||||
import util::common::new_def_hash;
|
import util::common::new_def_hash;
|
||||||
import syntax::codemap::span;
|
import syntax::codemap::span;
|
||||||
import syntax::ast_util::respan;
|
import syntax::ast_util::respan;
|
||||||
import driver::session::session;
|
import driver::session::session;
|
||||||
|
import aux::*;
|
||||||
|
|
||||||
type ctxt = {cs: @mutable [sp_constr], tcx: ty::ctxt};
|
type ctxt = {cs: @mutable [sp_constr], tcx: ty::ctxt};
|
||||||
|
|
||||||
fn collect_local(loc: @local, cx: ctxt, v: visit::vt<ctxt>) {
|
fn collect_local(loc: @local, cx: ctxt, v: visit::vt<ctxt>) {
|
||||||
pat_bindings(loc.node.pat) {|p|
|
pat_bindings(pat_util::normalize_pat(cx.tcx, loc.node.pat)) {|p|
|
||||||
let ident = alt p.node { pat_bind(id, _) { id } };
|
let ident = alt p.node
|
||||||
|
{ pat_ident(id, _) { path_to_ident(id) } };
|
||||||
log(debug, "collect_local: pushing " + ident);;
|
log(debug, "collect_local: pushing " + ident);;
|
||||||
*cx.cs += [respan(loc.span, ninit(p.id, ident))];
|
*cx.cs += [respan(loc.span, ninit(p.id, ident))];
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,8 @@ import bitvectors::{bit_num, seq_preconds, seq_postconds,
|
|||||||
intersect_states,
|
intersect_states,
|
||||||
relax_precond_block, gen};
|
relax_precond_block, gen};
|
||||||
import tritv::*;
|
import tritv::*;
|
||||||
|
|
||||||
|
import pat_util::*;
|
||||||
import syntax::ast::*;
|
import syntax::ast::*;
|
||||||
import syntax::ast_util::*;
|
import syntax::ast_util::*;
|
||||||
import syntax::visit;
|
import syntax::visit;
|
||||||
@ -16,6 +18,7 @@ import util::common::{new_def_hash, log_expr, field_exprs,
|
|||||||
import syntax::codemap::span;
|
import syntax::codemap::span;
|
||||||
import driver::session::session;
|
import driver::session::session;
|
||||||
|
|
||||||
|
|
||||||
fn find_pre_post_mod(_m: _mod) -> _mod {
|
fn find_pre_post_mod(_m: _mod) -> _mod {
|
||||||
#debug("implement find_pre_post_mod!");
|
#debug("implement find_pre_post_mod!");
|
||||||
fail;
|
fail;
|
||||||
@ -103,8 +106,9 @@ fn find_pre_post_loop(fcx: fn_ctxt, l: @local, index: @expr, body: blk,
|
|||||||
id: node_id) {
|
id: node_id) {
|
||||||
find_pre_post_expr(fcx, index);
|
find_pre_post_expr(fcx, index);
|
||||||
find_pre_post_block(fcx, body);
|
find_pre_post_block(fcx, body);
|
||||||
pat_bindings(l.node.pat) {|p|
|
pat_bindings(normalize_pat(fcx.ccx.tcx, l.node.pat)) {|p|
|
||||||
let ident = alt p.node { pat_bind(id, _) { id } };
|
let ident = alt p.node
|
||||||
|
{ pat_ident(id, _) { path_to_ident(id) } };
|
||||||
let v_init = ninit(p.id, ident);
|
let v_init = ninit(p.id, ident);
|
||||||
relax_precond_block(fcx, bit_num(fcx, v_init) as node_id, body);
|
relax_precond_block(fcx, bit_num(fcx, v_init) as node_id, body);
|
||||||
// Hack: for-loop index variables are frequently ignored,
|
// Hack: for-loop index variables are frequently ignored,
|
||||||
@ -197,7 +201,7 @@ fn gen_if_local(fcx: fn_ctxt, lhs: @expr, rhs: @expr, larger_id: node_id,
|
|||||||
set_pre_and_post(fcx.ccx, larger_id, p.precondition,
|
set_pre_and_post(fcx.ccx, larger_id, p.precondition,
|
||||||
p.postcondition);
|
p.postcondition);
|
||||||
gen(fcx, larger_id,
|
gen(fcx, larger_id,
|
||||||
ninit(d_id.node, path_to_ident(fcx.ccx.tcx, pth)));
|
ninit(d_id.node, path_to_ident(pth)));
|
||||||
}
|
}
|
||||||
_ { find_pre_post_exprs(fcx, [lhs, rhs], larger_id); }
|
_ { find_pre_post_exprs(fcx, [lhs, rhs], larger_id); }
|
||||||
}
|
}
|
||||||
@ -232,7 +236,7 @@ fn handle_update(fcx: fn_ctxt, parent: @expr, lhs: @expr, rhs: @expr,
|
|||||||
def_local(d_id, _) {
|
def_local(d_id, _) {
|
||||||
let i =
|
let i =
|
||||||
bit_num(fcx,
|
bit_num(fcx,
|
||||||
ninit(d_id.node, path_to_ident(fcx.ccx.tcx, p)));
|
ninit(d_id.node, path_to_ident(p)));
|
||||||
require_and_preserve(i, expr_pp(fcx.ccx, lhs));
|
require_and_preserve(i, expr_pp(fcx.ccx, lhs));
|
||||||
}
|
}
|
||||||
_ { }
|
_ { }
|
||||||
@ -250,9 +254,9 @@ fn handle_update(fcx: fn_ctxt, parent: @expr, lhs: @expr, rhs: @expr,
|
|||||||
alt d1 {
|
alt d1 {
|
||||||
some(id1) {
|
some(id1) {
|
||||||
let instlhs =
|
let instlhs =
|
||||||
{ident: path_to_ident(fcx.ccx.tcx, p), node: id};
|
{ident: path_to_ident(p), node: id};
|
||||||
let instrhs =
|
let instrhs =
|
||||||
{ident: path_to_ident(fcx.ccx.tcx, p1), node: id1};
|
{ident: path_to_ident(p1), node: id1};
|
||||||
copy_in_poststate_two(fcx, tmp, post, instlhs, instrhs,
|
copy_in_poststate_two(fcx, tmp, post, instlhs, instrhs,
|
||||||
ty);
|
ty);
|
||||||
}
|
}
|
||||||
@ -340,7 +344,7 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
|
|||||||
expr_path(p) {
|
expr_path(p) {
|
||||||
let rslt = expr_pp(fcx.ccx, e);
|
let rslt = expr_pp(fcx.ccx, e);
|
||||||
clear_pp(rslt);
|
clear_pp(rslt);
|
||||||
handle_var(fcx, rslt, e.id, path_to_ident(fcx.ccx.tcx, p));
|
handle_var(fcx, rslt, e.id, path_to_ident(p));
|
||||||
}
|
}
|
||||||
expr_log(_, lvl, arg) {
|
expr_log(_, lvl, arg) {
|
||||||
find_pre_post_exprs(fcx, [lvl, arg], e.id);
|
find_pre_post_exprs(fcx, [lvl, arg], e.id);
|
||||||
@ -581,18 +585,19 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) {
|
|||||||
_ { }
|
_ { }
|
||||||
}
|
}
|
||||||
|
|
||||||
pat_bindings(alocal.node.pat) {|pat|
|
pat_bindings(normalize_pat(fcx.ccx.tcx, alocal.node.pat))
|
||||||
|
{|pat|
|
||||||
/* FIXME: This won't be necessary when typestate
|
/* FIXME: This won't be necessary when typestate
|
||||||
works well enough for pat_bindings to return a
|
works well enough for pat_bindings to return a
|
||||||
refinement-typed thing. */
|
refinement-typed thing. */
|
||||||
let ident = alt pat.node { pat_bind(n, _) { n } };
|
let ident = alt pat.node
|
||||||
|
{ pat_ident(n, _) { path_to_ident(n) } };
|
||||||
alt p {
|
alt p {
|
||||||
some(p) {
|
some(p) {
|
||||||
copy_in_postcond(fcx, id,
|
copy_in_postcond(fcx, id,
|
||||||
{ident: ident, node: pat.id},
|
{ident: ident, node: pat.id},
|
||||||
{ident:
|
{ident:
|
||||||
path_to_ident(fcx.ccx.tcx,
|
path_to_ident(p),
|
||||||
p),
|
|
||||||
node: an_init.expr.id},
|
node: an_init.expr.id},
|
||||||
op_to_oper_ty(an_init.op));
|
op_to_oper_ty(an_init.op));
|
||||||
}
|
}
|
||||||
@ -612,11 +617,14 @@ fn find_pre_post_stmt(fcx: fn_ctxt, s: stmt) {
|
|||||||
seq_preconds(fcx, [prev_pp, e_pp]));
|
seq_preconds(fcx, [prev_pp, e_pp]));
|
||||||
/* Include the LHSs too, since those aren't in the
|
/* Include the LHSs too, since those aren't in the
|
||||||
postconds of the RHSs themselves */
|
postconds of the RHSs themselves */
|
||||||
pat_bindings(alocal.node.pat) {|pat|
|
pat_bindings(normalize_pat(fcx.ccx.tcx, alocal.node.pat))
|
||||||
|
{|pat|
|
||||||
|
// FIXME
|
||||||
|
// Generalize this pattern? map_if_ident...
|
||||||
alt pat.node {
|
alt pat.node {
|
||||||
pat_bind(n, _) {
|
pat_ident(n, _) {
|
||||||
set_in_postcond(bit_num(fcx, ninit(pat.id, n)),
|
set_in_postcond(bit_num(fcx,
|
||||||
prev_pp);
|
ninit(pat.id, path_to_ident(n))), prev_pp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,7 @@ import aux::*;
|
|||||||
import tritv::{tritv_clone, tritv_set, ttrue};
|
import tritv::{tritv_clone, tritv_set, ttrue};
|
||||||
|
|
||||||
import bitvectors::*;
|
import bitvectors::*;
|
||||||
|
import pat_util::*;
|
||||||
import syntax::ast::*;
|
import syntax::ast::*;
|
||||||
import syntax::ast_util::*;
|
import syntax::ast_util::*;
|
||||||
import syntax::codemap::span;
|
import syntax::codemap::span;
|
||||||
@ -37,7 +38,7 @@ fn handle_move_or_copy(fcx: fn_ctxt, post: poststate, rhs_path: @path,
|
|||||||
some(rhsid) {
|
some(rhsid) {
|
||||||
// RHS is a local var
|
// RHS is a local var
|
||||||
let instrhs =
|
let instrhs =
|
||||||
{ident: path_to_ident(fcx.ccx.tcx, rhs_path), node: rhsid.node};
|
{ident: path_to_ident(rhs_path), node: rhsid.node};
|
||||||
copy_in_poststate(fcx, post, instlhs, instrhs,
|
copy_in_poststate(fcx, post, instlhs, instrhs,
|
||||||
op_to_oper_ty(init_op));
|
op_to_oper_ty(init_op));
|
||||||
}
|
}
|
||||||
@ -143,9 +144,9 @@ fn find_pre_post_state_two(fcx: fn_ctxt, pres: prestate, lhs: @expr,
|
|||||||
alt d1 {
|
alt d1 {
|
||||||
some(id1) {
|
some(id1) {
|
||||||
let instlhs =
|
let instlhs =
|
||||||
{ident: path_to_ident(fcx.ccx.tcx, p), node: id};
|
{ident: path_to_ident(p), node: id};
|
||||||
let instrhs =
|
let instrhs =
|
||||||
{ident: path_to_ident(fcx.ccx.tcx, p1), node: id1};
|
{ident: path_to_ident(p1), node: id1};
|
||||||
copy_in_poststate_two(fcx, tmp, post, instlhs, instrhs,
|
copy_in_poststate_two(fcx, tmp, post, instlhs, instrhs,
|
||||||
ty);
|
ty);
|
||||||
}
|
}
|
||||||
@ -206,8 +207,9 @@ fn find_pre_post_state_loop(fcx: fn_ctxt, pres: prestate, l: @local,
|
|||||||
// Make sure the index vars are considered initialized
|
// Make sure the index vars are considered initialized
|
||||||
// in the body
|
// in the body
|
||||||
let index_post = tritv_clone(expr_poststate(fcx.ccx, index));
|
let index_post = tritv_clone(expr_poststate(fcx.ccx, index));
|
||||||
pat_bindings(l.node.pat) {|p|
|
pat_bindings(pat_util::normalize_pat(fcx.ccx.tcx, l.node.pat)) {|p|
|
||||||
let ident = alt p.node { pat_bind(name, _) { name } };
|
let ident = alt p.node
|
||||||
|
{ pat_ident(name, _) { path_to_ident(name) } };
|
||||||
set_in_poststate_ident(fcx, p.id, ident, index_post);
|
set_in_poststate_ident(fcx, p.id, ident, index_post);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -231,7 +233,7 @@ fn gen_if_local(fcx: fn_ctxt, p: poststate, e: @expr) -> bool {
|
|||||||
alt fcx.ccx.tcx.def_map.find(e.id) {
|
alt fcx.ccx.tcx.def_map.find(e.id) {
|
||||||
some(def_local(loc, _)) {
|
some(def_local(loc, _)) {
|
||||||
ret set_in_poststate_ident(fcx, loc.node,
|
ret set_in_poststate_ident(fcx, loc.node,
|
||||||
path_to_ident(fcx.ccx.tcx, pth), p);
|
path_to_ident(pth), p);
|
||||||
}
|
}
|
||||||
_ { ret false; }
|
_ { ret false; }
|
||||||
}
|
}
|
||||||
@ -632,7 +634,8 @@ fn find_pre_post_state_stmt(fcx: fn_ctxt, pres: prestate, s: @stmt) -> bool {
|
|||||||
alt adecl.node {
|
alt adecl.node {
|
||||||
decl_local(alocals) {
|
decl_local(alocals) {
|
||||||
set_prestate(stmt_ann, pres);
|
set_prestate(stmt_ann, pres);
|
||||||
let c_and_p = seq_states(fcx, pres, locals_to_bindings(alocals));
|
let c_and_p = seq_states(fcx, pres,
|
||||||
|
locals_to_bindings(fcx.ccx.tcx, alocals));
|
||||||
/* important to do this in one step to ensure
|
/* important to do this in one step to ensure
|
||||||
termination (don't want to set changed to true
|
termination (don't want to set changed to true
|
||||||
for intermediate changes) */
|
for intermediate changes) */
|
||||||
|
@ -371,6 +371,8 @@ const idx_first_others: uint = 20u;
|
|||||||
|
|
||||||
type type_store = interner::interner<@raw_t>;
|
type type_store = interner::interner<@raw_t>;
|
||||||
|
|
||||||
|
// substs is a list of actuals that correspond to ty's
|
||||||
|
// formal parameters
|
||||||
type ty_param_substs_opt_and_ty = {substs: option::t<[ty::t]>, ty: ty::t};
|
type ty_param_substs_opt_and_ty = {substs: option::t<[ty::t]>, ty: ty::t};
|
||||||
|
|
||||||
type node_type_table =
|
type node_type_table =
|
||||||
@ -2215,7 +2217,7 @@ mod unify {
|
|||||||
ty::ty_box(expected_mt) {
|
ty::ty_box(expected_mt) {
|
||||||
alt struct(cx.tcx, actual) {
|
alt struct(cx.tcx, actual) {
|
||||||
ty::ty_box(actual_mt) {
|
ty::ty_box(actual_mt) {
|
||||||
let (mut, var) = alt unify_mut(
|
let (mutt, var) = alt unify_mut(
|
||||||
expected_mt.mut, actual_mt.mut, variance) {
|
expected_mt.mut, actual_mt.mut, variance) {
|
||||||
none. { ret ures_err(terr_box_mutability); }
|
none. { ret ures_err(terr_box_mutability); }
|
||||||
some(mv) { mv }
|
some(mv) { mv }
|
||||||
@ -2224,7 +2226,7 @@ mod unify {
|
|||||||
cx, expected_mt.ty, actual_mt.ty, var);
|
cx, expected_mt.ty, actual_mt.ty, var);
|
||||||
alt result {
|
alt result {
|
||||||
ures_ok(result_sub) {
|
ures_ok(result_sub) {
|
||||||
let mt = {ty: result_sub, mut: mut};
|
let mt = {ty: result_sub, mut: mutt};
|
||||||
ret ures_ok(mk_box(cx.tcx, mt));
|
ret ures_ok(mk_box(cx.tcx, mt));
|
||||||
}
|
}
|
||||||
_ { ret result; }
|
_ { ret result; }
|
||||||
@ -2236,7 +2238,7 @@ mod unify {
|
|||||||
ty::ty_uniq(expected_mt) {
|
ty::ty_uniq(expected_mt) {
|
||||||
alt struct(cx.tcx, actual) {
|
alt struct(cx.tcx, actual) {
|
||||||
ty::ty_uniq(actual_mt) {
|
ty::ty_uniq(actual_mt) {
|
||||||
let (mut, var) = alt unify_mut(
|
let (mutt, var) = alt unify_mut(
|
||||||
expected_mt.mut, actual_mt.mut, variance) {
|
expected_mt.mut, actual_mt.mut, variance) {
|
||||||
none. { ret ures_err(terr_box_mutability); }
|
none. { ret ures_err(terr_box_mutability); }
|
||||||
some(mv) { mv }
|
some(mv) { mv }
|
||||||
@ -2245,7 +2247,7 @@ mod unify {
|
|||||||
cx, expected_mt.ty, actual_mt.ty, var);
|
cx, expected_mt.ty, actual_mt.ty, var);
|
||||||
alt result {
|
alt result {
|
||||||
ures_ok(result_mt) {
|
ures_ok(result_mt) {
|
||||||
let mt = {ty: result_mt, mut: mut};
|
let mt = {ty: result_mt, mut: mutt};
|
||||||
ret ures_ok(mk_uniq(cx.tcx, mt));
|
ret ures_ok(mk_uniq(cx.tcx, mt));
|
||||||
}
|
}
|
||||||
_ { ret result; }
|
_ { ret result; }
|
||||||
@ -2257,7 +2259,7 @@ mod unify {
|
|||||||
ty::ty_vec(expected_mt) {
|
ty::ty_vec(expected_mt) {
|
||||||
alt struct(cx.tcx, actual) {
|
alt struct(cx.tcx, actual) {
|
||||||
ty::ty_vec(actual_mt) {
|
ty::ty_vec(actual_mt) {
|
||||||
let (mut, var) = alt unify_mut(
|
let (mutt, var) = alt unify_mut(
|
||||||
expected_mt.mut, actual_mt.mut, variance) {
|
expected_mt.mut, actual_mt.mut, variance) {
|
||||||
none. { ret ures_err(terr_vec_mutability); }
|
none. { ret ures_err(terr_vec_mutability); }
|
||||||
some(mv) { mv }
|
some(mv) { mv }
|
||||||
@ -2266,7 +2268,7 @@ mod unify {
|
|||||||
cx, expected_mt.ty, actual_mt.ty, var);
|
cx, expected_mt.ty, actual_mt.ty, var);
|
||||||
alt result {
|
alt result {
|
||||||
ures_ok(result_sub) {
|
ures_ok(result_sub) {
|
||||||
let mt = {ty: result_sub, mut: mut};
|
let mt = {ty: result_sub, mut: mutt};
|
||||||
ret ures_ok(mk_vec(cx.tcx, mt));
|
ret ures_ok(mk_vec(cx.tcx, mt));
|
||||||
}
|
}
|
||||||
_ { ret result; }
|
_ { ret result; }
|
||||||
@ -2278,7 +2280,7 @@ mod unify {
|
|||||||
ty::ty_ptr(expected_mt) {
|
ty::ty_ptr(expected_mt) {
|
||||||
alt struct(cx.tcx, actual) {
|
alt struct(cx.tcx, actual) {
|
||||||
ty::ty_ptr(actual_mt) {
|
ty::ty_ptr(actual_mt) {
|
||||||
let (mut, var) = alt unify_mut(
|
let (mutt, var) = alt unify_mut(
|
||||||
expected_mt.mut, actual_mt.mut, variance) {
|
expected_mt.mut, actual_mt.mut, variance) {
|
||||||
none. { ret ures_err(terr_vec_mutability); }
|
none. { ret ures_err(terr_vec_mutability); }
|
||||||
some(mv) { mv }
|
some(mv) { mv }
|
||||||
@ -2287,7 +2289,7 @@ mod unify {
|
|||||||
cx, expected_mt.ty, actual_mt.ty, var);
|
cx, expected_mt.ty, actual_mt.ty, var);
|
||||||
alt result {
|
alt result {
|
||||||
ures_ok(result_sub) {
|
ures_ok(result_sub) {
|
||||||
let mt = {ty: result_sub, mut: mut};
|
let mt = {ty: result_sub, mut: mutt};
|
||||||
ret ures_ok(mk_ptr(cx.tcx, mt));
|
ret ures_ok(mk_ptr(cx.tcx, mt));
|
||||||
}
|
}
|
||||||
_ { ret result; }
|
_ { ret result; }
|
||||||
@ -2342,7 +2344,7 @@ mod unify {
|
|||||||
while i < expected_len {
|
while i < expected_len {
|
||||||
let expected_field = expected_fields[i];
|
let expected_field = expected_fields[i];
|
||||||
let actual_field = actual_fields[i];
|
let actual_field = actual_fields[i];
|
||||||
let (mut, var) = alt unify_mut(
|
let (mutt, var) = alt unify_mut(
|
||||||
expected_field.mt.mut, actual_field.mt.mut, variance)
|
expected_field.mt.mut, actual_field.mt.mut, variance)
|
||||||
{
|
{
|
||||||
none. { ret ures_err(terr_record_mutability); }
|
none. { ret ures_err(terr_record_mutability); }
|
||||||
@ -2359,7 +2361,7 @@ mod unify {
|
|||||||
actual_field.mt.ty, var);
|
actual_field.mt.ty, var);
|
||||||
alt result {
|
alt result {
|
||||||
ures_ok(rty) {
|
ures_ok(rty) {
|
||||||
let mt = {ty: rty, mut: mut};
|
let mt = {ty: rty, mut: mutt};
|
||||||
result_fields += [{mt: mt with expected_field}];
|
result_fields += [{mt: mt with expected_field}];
|
||||||
}
|
}
|
||||||
_ { ret result; }
|
_ { ret result; }
|
||||||
@ -2579,11 +2581,18 @@ fn type_err_to_str(err: ty::type_err) -> str {
|
|||||||
// Replaces type parameters in the given type using the given list of
|
// Replaces type parameters in the given type using the given list of
|
||||||
// substitions.
|
// substitions.
|
||||||
fn substitute_type_params(cx: ctxt, substs: [ty::t], typ: t) -> t {
|
fn substitute_type_params(cx: ctxt, substs: [ty::t], typ: t) -> t {
|
||||||
if !type_contains_params(cx, typ) { ret typ; }
|
|
||||||
|
if !type_contains_params(cx, typ) { ret typ; }
|
||||||
|
// Precondition? idx < vec::len(substs)
|
||||||
fn substituter(_cx: ctxt, substs: @[ty::t], idx: uint, _did: def_id)
|
fn substituter(_cx: ctxt, substs: @[ty::t], idx: uint, _did: def_id)
|
||||||
-> t {
|
-> t {
|
||||||
// FIXME: bounds check can fail
|
if idx < vec::len(*substs) {
|
||||||
ret substs[idx];
|
ret substs[idx];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fail #fmt("Internal error in substituter (substitute_type_params)\
|
||||||
|
%u %u", vec::len(*substs), idx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ret fold_ty(cx, fm_param(bind substituter(cx, @substs, _, _)), typ);
|
ret fold_ty(cx, fm_param(bind substituter(cx, @substs, _, _)), typ);
|
||||||
}
|
}
|
||||||
@ -2729,7 +2738,7 @@ fn is_binopable(cx: ctxt, ty: t, op: ast::binop) -> bool {
|
|||||||
fn opcat(op: ast::binop) -> int {
|
fn opcat(op: ast::binop) -> int {
|
||||||
alt op {
|
alt op {
|
||||||
ast::add. { opcat_add }
|
ast::add. { opcat_add }
|
||||||
ast::sub. { opcat_sub }
|
ast::subtract. { opcat_sub }
|
||||||
ast::mul. { opcat_mult }
|
ast::mul. { opcat_mult }
|
||||||
ast::div. { opcat_mult }
|
ast::div. { opcat_mult }
|
||||||
ast::rem. { opcat_mult }
|
ast::rem. { opcat_mult }
|
||||||
|
@ -6,6 +6,7 @@ import metadata::csearch;
|
|||||||
import driver::session::session;
|
import driver::session::session;
|
||||||
import util::common::*;
|
import util::common::*;
|
||||||
import syntax::codemap::span;
|
import syntax::codemap::span;
|
||||||
|
import pat_util::*;
|
||||||
import middle::ty;
|
import middle::ty;
|
||||||
import middle::ty::{node_id_to_type, arg, block_ty,
|
import middle::ty::{node_id_to_type, arg, block_ty,
|
||||||
expr_ty, field, node_type_table, mk_nil,
|
expr_ty, field, node_type_table, mk_nil,
|
||||||
@ -1137,8 +1138,8 @@ fn gather_locals(ccx: @crate_ctxt,
|
|||||||
|
|
||||||
// Add pattern bindings.
|
// Add pattern bindings.
|
||||||
let visit_pat = fn@(p: @ast::pat, &&e: (), v: visit::vt<()>) {
|
let visit_pat = fn@(p: @ast::pat, &&e: (), v: visit::vt<()>) {
|
||||||
alt p.node {
|
alt normalize_pat(ccx.tcx, p).node {
|
||||||
ast::pat_bind(_, _) { assign(p.id, none); }
|
ast::pat_ident(_, _) { assign(p.id, none); }
|
||||||
_ {/* no-op */ }
|
_ {/* no-op */ }
|
||||||
}
|
}
|
||||||
visit::visit_pat(p, e, v);
|
visit::visit_pat(p, e, v);
|
||||||
@ -1181,9 +1182,9 @@ fn valid_range_bounds(from: @ast::expr, to: @ast::expr) -> bool {
|
|||||||
|
|
||||||
// Pattern checking is top-down rather than bottom-up so that bindings get
|
// Pattern checking is top-down rather than bottom-up so that bindings get
|
||||||
// their types immediately.
|
// their types immediately.
|
||||||
fn check_pat(fcx: @fn_ctxt, map: ast_util::pat_id_map, pat: @ast::pat,
|
fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
|
||||||
expected: ty::t) {
|
expected: ty::t) {
|
||||||
alt pat.node {
|
alt normalize_pat(fcx.ccx.tcx, pat).node {
|
||||||
ast::pat_wild. {
|
ast::pat_wild. {
|
||||||
alt structure_of(fcx, pat.span, expected) {
|
alt structure_of(fcx, pat.span, expected) {
|
||||||
ty::ty_tag(_, expected_tps) {
|
ty::ty_tag(_, expected_tps) {
|
||||||
@ -1218,11 +1219,11 @@ fn check_pat(fcx: @fn_ctxt, map: ast_util::pat_id_map, pat: @ast::pat,
|
|||||||
}
|
}
|
||||||
write::ty_only_fixup(fcx, pat.id, b_ty);
|
write::ty_only_fixup(fcx, pat.id, b_ty);
|
||||||
}
|
}
|
||||||
ast::pat_bind(name, sub) {
|
ast::pat_ident(name, sub) {
|
||||||
let vid = lookup_local(fcx, pat.span, pat.id);
|
let vid = lookup_local(fcx, pat.span, pat.id);
|
||||||
let typ = ty::mk_var(fcx.ccx.tcx, vid);
|
let typ = ty::mk_var(fcx.ccx.tcx, vid);
|
||||||
typ = demand::simple(fcx, pat.span, expected, typ);
|
typ = demand::simple(fcx, pat.span, expected, typ);
|
||||||
let canon_id = map.get(name);
|
let canon_id = map.get(path_to_ident(name));
|
||||||
if canon_id != pat.id {
|
if canon_id != pat.id {
|
||||||
let ct =
|
let ct =
|
||||||
ty::mk_var(fcx.ccx.tcx,
|
ty::mk_var(fcx.ccx.tcx,
|
||||||
@ -2014,7 +2015,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
|||||||
// bindings.
|
// bindings.
|
||||||
let pattern_ty = ty::expr_ty(tcx, expr);
|
let pattern_ty = ty::expr_ty(tcx, expr);
|
||||||
for arm: ast::arm in arms {
|
for arm: ast::arm in arms {
|
||||||
let id_map = ast_util::pat_id_map(arm.pats[0]);
|
let id_map = pat_util::pat_id_map(tcx, arm.pats[0]);
|
||||||
for p: @ast::pat in arm.pats {
|
for p: @ast::pat in arm.pats {
|
||||||
check_pat(fcx, id_map, p, pattern_ty);
|
check_pat(fcx, id_map, p, pattern_ty);
|
||||||
}
|
}
|
||||||
@ -2360,7 +2361,7 @@ fn check_decl_local(fcx: @fn_ctxt, local: @ast::local) -> bool {
|
|||||||
}
|
}
|
||||||
_ {/* fall through */ }
|
_ {/* fall through */ }
|
||||||
}
|
}
|
||||||
let id_map = ast_util::pat_id_map(local.node.pat);
|
let id_map = pat_util::pat_id_map(fcx.ccx.tcx, local.node.pat);
|
||||||
check_pat(fcx, id_map, local.node.pat, t);
|
check_pat(fcx, id_map, local.node.pat, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ mod middle {
|
|||||||
mod gc;
|
mod gc;
|
||||||
mod debuginfo;
|
mod debuginfo;
|
||||||
mod capture;
|
mod capture;
|
||||||
|
mod pat_util;
|
||||||
|
|
||||||
mod tstate {
|
mod tstate {
|
||||||
mod ck;
|
mod ck;
|
||||||
|
@ -97,7 +97,17 @@ type field_pat = {ident: ident, pat: @pat};
|
|||||||
|
|
||||||
tag pat_ {
|
tag pat_ {
|
||||||
pat_wild;
|
pat_wild;
|
||||||
pat_bind(ident, option::t<@pat>);
|
// A pat_ident may either be a new bound variable,
|
||||||
|
// or a nullary tag (in which case the second field
|
||||||
|
// is none).
|
||||||
|
// In the nullary tag case, the parser can't determine
|
||||||
|
// which it is. The resolver determines this, and
|
||||||
|
// records this pattern's node_id in an auxiliary
|
||||||
|
// set (of "pat_idents that refer to nullary tags")
|
||||||
|
// After the resolution phase, code should never pattern-
|
||||||
|
// match on a pat directly! Always call pat_util::normalize_pat --
|
||||||
|
// it turns any pat_idents that refer to nullary tags into pat_tags.
|
||||||
|
pat_ident(@path, option::t<@pat>);
|
||||||
pat_tag(@path, [@pat]);
|
pat_tag(@path, [@pat]);
|
||||||
pat_rec([field_pat], bool);
|
pat_rec([field_pat], bool);
|
||||||
pat_tup([@pat]);
|
pat_tup([@pat]);
|
||||||
@ -126,7 +136,7 @@ pure fn is_blockish(p: ast::proto) -> bool {
|
|||||||
|
|
||||||
tag binop {
|
tag binop {
|
||||||
add;
|
add;
|
||||||
sub;
|
subtract;
|
||||||
mul;
|
mul;
|
||||||
div;
|
div;
|
||||||
rem;
|
rem;
|
||||||
|
@ -33,43 +33,10 @@ fn def_id_of_def(d: def) -> def_id {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type pat_id_map = std::map::hashmap<str, node_id>;
|
|
||||||
|
|
||||||
// This is used because same-named variables in alternative patterns need to
|
|
||||||
// use the node_id of their namesake in the first pattern.
|
|
||||||
fn pat_id_map(pat: @pat) -> pat_id_map {
|
|
||||||
let map = std::map::new_str_hash::<node_id>();
|
|
||||||
pat_bindings(pat) {|bound|
|
|
||||||
let name = alt bound.node { pat_bind(n, _) { n } };
|
|
||||||
map.insert(name, bound.id);
|
|
||||||
};
|
|
||||||
ret map;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: could return a constrained type
|
|
||||||
fn pat_bindings(pat: @pat, it: block(@pat)) {
|
|
||||||
alt pat.node {
|
|
||||||
pat_bind(_, option::none.) { it(pat); }
|
|
||||||
pat_bind(_, option::some(sub)) { it(pat); pat_bindings(sub, it); }
|
|
||||||
pat_tag(_, sub) { for p in sub { pat_bindings(p, it); } }
|
|
||||||
pat_rec(fields, _) { for f in fields { pat_bindings(f.pat, it); } }
|
|
||||||
pat_tup(elts) { for elt in elts { pat_bindings(elt, it); } }
|
|
||||||
pat_box(sub) { pat_bindings(sub, it); }
|
|
||||||
pat_uniq(sub) { pat_bindings(sub, it); }
|
|
||||||
pat_wild. | pat_lit(_) | pat_range(_, _) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pat_binding_ids(pat: @pat) -> [node_id] {
|
|
||||||
let found = [];
|
|
||||||
pat_bindings(pat) {|b| found += [b.id]; };
|
|
||||||
ret found;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn binop_to_str(op: binop) -> str {
|
fn binop_to_str(op: binop) -> str {
|
||||||
alt op {
|
alt op {
|
||||||
add. { ret "+"; }
|
add. { ret "+"; }
|
||||||
sub. { ret "-"; }
|
subtract. { ret "-"; }
|
||||||
mul. { ret "*"; }
|
mul. { ret "*"; }
|
||||||
div. { ret "/"; }
|
div. { ret "/"; }
|
||||||
rem. { ret "%"; }
|
rem. { ret "%"; }
|
||||||
@ -262,7 +229,7 @@ fn eval_const_expr(e: @expr) -> const_val {
|
|||||||
alt (eval_const_expr(a), eval_const_expr(b)) {
|
alt (eval_const_expr(a), eval_const_expr(b)) {
|
||||||
(const_float(a), const_float(b)) {
|
(const_float(a), const_float(b)) {
|
||||||
alt op {
|
alt op {
|
||||||
add. { const_float(a + b) } sub. { const_float(a - b) }
|
add. { const_float(a + b) } subtract. { const_float(a - b) }
|
||||||
mul. { const_float(a * b) } div. { const_float(a / b) }
|
mul. { const_float(a * b) } div. { const_float(a / b) }
|
||||||
rem. { const_float(a % b) } eq. { fromb(a == b) }
|
rem. { const_float(a % b) } eq. { fromb(a == b) }
|
||||||
lt. { fromb(a < b) } le. { fromb(a <= b) } ne. { fromb(a != b) }
|
lt. { fromb(a < b) } le. { fromb(a <= b) } ne. { fromb(a != b) }
|
||||||
@ -271,7 +238,7 @@ fn eval_const_expr(e: @expr) -> const_val {
|
|||||||
}
|
}
|
||||||
(const_int(a), const_int(b)) {
|
(const_int(a), const_int(b)) {
|
||||||
alt op {
|
alt op {
|
||||||
add. { const_int(a + b) } sub. { const_int(a - b) }
|
add. { const_int(a + b) } subtract. { const_int(a - b) }
|
||||||
mul. { const_int(a * b) } div. { const_int(a / b) }
|
mul. { const_int(a * b) } div. { const_int(a / b) }
|
||||||
rem. { const_int(a % b) } and. | bitand. { const_int(a & b) }
|
rem. { const_int(a % b) } and. | bitand. { const_int(a & b) }
|
||||||
or. | bitor. { const_int(a | b) } bitxor. { const_int(a ^ b) }
|
or. | bitor. { const_int(a | b) } bitxor. { const_int(a ^ b) }
|
||||||
@ -282,7 +249,7 @@ fn eval_const_expr(e: @expr) -> const_val {
|
|||||||
}
|
}
|
||||||
(const_uint(a), const_uint(b)) {
|
(const_uint(a), const_uint(b)) {
|
||||||
alt op {
|
alt op {
|
||||||
add. { const_uint(a + b) } sub. { const_uint(a - b) }
|
add. { const_uint(a + b) } subtract. { const_uint(a - b) }
|
||||||
mul. { const_uint(a * b) } div. { const_uint(a / b) }
|
mul. { const_uint(a * b) } div. { const_uint(a / b) }
|
||||||
rem. { const_uint(a % b) } and. | bitand. { const_uint(a & b) }
|
rem. { const_uint(a % b) } and. | bitand. { const_uint(a & b) }
|
||||||
or. | bitor. { const_uint(a | b) } bitxor. { const_uint(a ^ b) }
|
or. | bitor. { const_uint(a | b) } bitxor. { const_uint(a ^ b) }
|
||||||
@ -327,6 +294,10 @@ fn lit_eq(a: @lit, b: @lit) -> bool {
|
|||||||
compare_const_vals(lit_to_const(a), lit_to_const(b)) == 0
|
compare_const_vals(lit_to_const(a), lit_to_const(b)) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ident_to_path(s: span, i: ident) -> @path {
|
||||||
|
@respan(s, {global: false, idents: [i], types: []})
|
||||||
|
}
|
||||||
|
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
// mode: rust
|
// mode: rust
|
||||||
// fill-column: 78;
|
// fill-column: 78;
|
||||||
|
@ -10,6 +10,7 @@ export make_fold;
|
|||||||
export noop_fold_crate;
|
export noop_fold_crate;
|
||||||
export noop_fold_item;
|
export noop_fold_item;
|
||||||
export noop_fold_expr;
|
export noop_fold_expr;
|
||||||
|
export noop_fold_pat;
|
||||||
export noop_fold_mod;
|
export noop_fold_mod;
|
||||||
export noop_fold_ty;
|
export noop_fold_ty;
|
||||||
|
|
||||||
@ -273,8 +274,8 @@ fn noop_fold_arm(a: arm, fld: ast_fold) -> arm {
|
|||||||
fn noop_fold_pat(p: pat_, fld: ast_fold) -> pat_ {
|
fn noop_fold_pat(p: pat_, fld: ast_fold) -> pat_ {
|
||||||
ret alt p {
|
ret alt p {
|
||||||
pat_wild. { p }
|
pat_wild. { p }
|
||||||
pat_bind(ident, sub) {
|
pat_ident(pth, sub) {
|
||||||
pat_bind(fld.fold_ident(ident), option::map(sub, fld.fold_pat))
|
pat_ident(fld.fold_path(pth), option::map(sub, fld.fold_pat))
|
||||||
}
|
}
|
||||||
pat_lit(_) { p }
|
pat_lit(_) { p }
|
||||||
pat_tag(pth, pats) {
|
pat_tag(pth, pats) {
|
||||||
@ -317,8 +318,8 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
|
|||||||
let fold_mac = bind fold_mac_(_, fld);
|
let fold_mac = bind fold_mac_(_, fld);
|
||||||
|
|
||||||
ret alt e {
|
ret alt e {
|
||||||
expr_vec(exprs, mut) {
|
expr_vec(exprs, mutt) {
|
||||||
expr_vec(fld.map_exprs(fld.fold_expr, exprs), mut)
|
expr_vec(fld.map_exprs(fld.fold_expr, exprs), mutt)
|
||||||
}
|
}
|
||||||
expr_rec(fields, maybe_expr) {
|
expr_rec(fields, maybe_expr) {
|
||||||
expr_rec(vec::map(fields, fold_field),
|
expr_rec(vec::map(fields, fold_field),
|
||||||
@ -390,8 +391,7 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
|
|||||||
}
|
}
|
||||||
expr_path(pth) { expr_path(fld.fold_path(pth)) }
|
expr_path(pth) { expr_path(fld.fold_path(pth)) }
|
||||||
expr_fail(e) { expr_fail(option::map(e, fld.fold_expr)) }
|
expr_fail(e) { expr_fail(option::map(e, fld.fold_expr)) }
|
||||||
expr_break. { e }
|
expr_break. | expr_cont. { e }
|
||||||
expr_cont. { e }
|
|
||||||
expr_ret(e) { expr_ret(option::map(e, fld.fold_expr)) }
|
expr_ret(e) { expr_ret(option::map(e, fld.fold_expr)) }
|
||||||
expr_be(e) { expr_be(fld.fold_expr(e)) }
|
expr_be(e) { expr_be(fld.fold_expr(e)) }
|
||||||
expr_log(i, lv, e) { expr_log(i, fld.fold_expr(lv),
|
expr_log(i, lv, e) { expr_log(i, fld.fold_expr(lv),
|
||||||
|
@ -8,6 +8,7 @@ import token::can_begin_expr;
|
|||||||
import codemap::span;
|
import codemap::span;
|
||||||
import util::interner;
|
import util::interner;
|
||||||
import ast::{node_id, spanned};
|
import ast::{node_id, spanned};
|
||||||
|
import ast_util::{mk_sp, ident_to_path};
|
||||||
import front::attr;
|
import front::attr;
|
||||||
import lexer::reader;
|
import lexer::reader;
|
||||||
import driver::diagnostic;
|
import driver::diagnostic;
|
||||||
@ -1097,7 +1098,7 @@ fn prec_table() -> @[op_spec] {
|
|||||||
{tok: token::BINOP(token::SLASH), op: ast::div, prec: 11},
|
{tok: token::BINOP(token::SLASH), op: ast::div, prec: 11},
|
||||||
{tok: token::BINOP(token::PERCENT), op: ast::rem, prec: 11},
|
{tok: token::BINOP(token::PERCENT), op: ast::rem, prec: 11},
|
||||||
{tok: token::BINOP(token::PLUS), op: ast::add, prec: 10},
|
{tok: token::BINOP(token::PLUS), op: ast::add, prec: 10},
|
||||||
{tok: token::BINOP(token::MINUS), op: ast::sub, prec: 10},
|
{tok: token::BINOP(token::MINUS), op: ast::subtract, prec: 10},
|
||||||
{tok: token::BINOP(token::LSL), op: ast::lsl, prec: 9},
|
{tok: token::BINOP(token::LSL), op: ast::lsl, prec: 9},
|
||||||
{tok: token::BINOP(token::LSR), op: ast::lsr, prec: 9},
|
{tok: token::BINOP(token::LSR), op: ast::lsr, prec: 9},
|
||||||
{tok: token::BINOP(token::ASR), op: ast::asr, prec: 9},
|
{tok: token::BINOP(token::ASR), op: ast::asr, prec: 9},
|
||||||
@ -1165,7 +1166,7 @@ fn parse_assign_expr(p: parser) -> @ast::expr {
|
|||||||
let aop = ast::add;
|
let aop = ast::add;
|
||||||
alt op {
|
alt op {
|
||||||
token::PLUS. { aop = ast::add; }
|
token::PLUS. { aop = ast::add; }
|
||||||
token::MINUS. { aop = ast::sub; }
|
token::MINUS. { aop = ast::subtract; }
|
||||||
token::STAR. { aop = ast::mul; }
|
token::STAR. { aop = ast::mul; }
|
||||||
token::SLASH. { aop = ast::div; }
|
token::SLASH. { aop = ast::div; }
|
||||||
token::PERCENT. { aop = ast::rem; }
|
token::PERCENT. { aop = ast::rem; }
|
||||||
@ -1426,7 +1427,11 @@ fn parse_pat(p: parser) -> @ast::pat {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let lo1 = p.last_span.lo;
|
||||||
let fieldname = parse_ident(p);
|
let fieldname = parse_ident(p);
|
||||||
|
let hi1 = p.last_span.lo;
|
||||||
|
let fieldpath = ast_util::ident_to_path(ast_util::mk_sp(lo1, hi1),
|
||||||
|
fieldname);
|
||||||
let subpat;
|
let subpat;
|
||||||
if p.token == token::COLON {
|
if p.token == token::COLON {
|
||||||
p.bump();
|
p.bump();
|
||||||
@ -1436,7 +1441,7 @@ fn parse_pat(p: parser) -> @ast::pat {
|
|||||||
p.fatal("found " + fieldname + " in binding position");
|
p.fatal("found " + fieldname + " in binding position");
|
||||||
}
|
}
|
||||||
subpat = @{id: p.get_id(),
|
subpat = @{id: p.get_id(),
|
||||||
node: ast::pat_bind(fieldname, none),
|
node: ast::pat_ident(fieldpath, none),
|
||||||
span: ast_util::mk_sp(lo, hi)};
|
span: ast_util::mk_sp(lo, hi)};
|
||||||
}
|
}
|
||||||
fields += [{ident: fieldname, pat: subpat}];
|
fields += [{ident: fieldname, pat: subpat}];
|
||||||
@ -1478,7 +1483,10 @@ fn parse_pat(p: parser) -> @ast::pat {
|
|||||||
}
|
}
|
||||||
} else if is_plain_ident(p) &&
|
} else if is_plain_ident(p) &&
|
||||||
alt p.look_ahead(1u) {
|
alt p.look_ahead(1u) {
|
||||||
token::DOT. | token::LPAREN. | token::LBRACKET. {
|
// Take this out once the libraries change
|
||||||
|
token::DOT. |
|
||||||
|
token::LPAREN. | token::LBRACKET. |
|
||||||
|
token::LT. {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
_ { true }
|
_ { true }
|
||||||
@ -1486,7 +1494,7 @@ fn parse_pat(p: parser) -> @ast::pat {
|
|||||||
hi = p.span.hi;
|
hi = p.span.hi;
|
||||||
let name = parse_value_ident(p);
|
let name = parse_value_ident(p);
|
||||||
let sub = eat(p, token::AT) ? some(parse_pat(p)) : none;
|
let sub = eat(p, token::AT) ? some(parse_pat(p)) : none;
|
||||||
pat = ast::pat_bind(name, sub);
|
pat = ast::pat_ident(ident_to_path(mk_sp(lo, hi), name), sub);
|
||||||
} else {
|
} else {
|
||||||
let tag_path = parse_path_and_ty_param_substs(p, true);
|
let tag_path = parse_path_and_ty_param_substs(p, true);
|
||||||
hi = tag_path.span.hi;
|
hi = tag_path.span.hi;
|
||||||
@ -1499,10 +1507,19 @@ fn parse_pat(p: parser) -> @ast::pat {
|
|||||||
args = a.node;
|
args = a.node;
|
||||||
hi = a.span.hi;
|
hi = a.span.hi;
|
||||||
}
|
}
|
||||||
|
token::LBRACE. { args = []; }
|
||||||
|
// take this out once the libraries change
|
||||||
token::DOT. { args = []; p.bump(); }
|
token::DOT. { args = []; p.bump(); }
|
||||||
_ { expect(p, token::LPAREN); fail; }
|
_ { expect(p, token::LPAREN); fail; }
|
||||||
}
|
}
|
||||||
pat = ast::pat_tag(tag_path, args);
|
// at this point, we're not sure whether it's a tag or a bind
|
||||||
|
if vec::len(args) == 0u &&
|
||||||
|
vec::len(tag_path.node.idents) == 1u {
|
||||||
|
pat = ast::pat_ident(tag_path, none);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pat = ast::pat_tag(tag_path, args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1055,10 +1055,12 @@ fn print_pat(s: ps, &&pat: @ast::pat) {
|
|||||||
maybe_print_comment(s, pat.span.lo);
|
maybe_print_comment(s, pat.span.lo);
|
||||||
let ann_node = node_pat(s, pat);
|
let ann_node = node_pat(s, pat);
|
||||||
s.ann.pre(ann_node);
|
s.ann.pre(ann_node);
|
||||||
|
/* Pat isn't normalized, but the beauty of it
|
||||||
|
is that it doesn't matter */
|
||||||
alt pat.node {
|
alt pat.node {
|
||||||
ast::pat_wild. { word(s.s, "_"); }
|
ast::pat_wild. { word(s.s, "_"); }
|
||||||
ast::pat_bind(id, sub) {
|
ast::pat_ident(path, sub) {
|
||||||
word(s.s, id);
|
print_path(s, path, true);
|
||||||
alt sub {
|
alt sub {
|
||||||
some(p) { word(s.s, "@"); print_pat(s, p); }
|
some(p) { word(s.s, "@"); print_pat(s, p); }
|
||||||
_ {}
|
_ {}
|
||||||
@ -1070,7 +1072,7 @@ fn print_pat(s: ps, &&pat: @ast::pat) {
|
|||||||
popen(s);
|
popen(s);
|
||||||
commasep(s, inconsistent, args, print_pat);
|
commasep(s, inconsistent, args, print_pat);
|
||||||
pclose(s);
|
pclose(s);
|
||||||
} else { word(s.s, "."); }
|
} else { word(s.s, "."); } // FIXME
|
||||||
}
|
}
|
||||||
ast::pat_rec(fields, etc) {
|
ast::pat_rec(fields, etc) {
|
||||||
word(s.s, "{");
|
word(s.s, "{");
|
||||||
|
@ -195,9 +195,13 @@ fn visit_pat<E>(p: @pat, e: E, v: vt<E>) {
|
|||||||
for f: field_pat in fields { v.visit_pat(f.pat, e, v); }
|
for f: field_pat in fields { v.visit_pat(f.pat, e, v); }
|
||||||
}
|
}
|
||||||
pat_tup(elts) { for elt in elts { v.visit_pat(elt, e, v); } }
|
pat_tup(elts) { for elt in elts { v.visit_pat(elt, e, v); } }
|
||||||
pat_box(inner) | pat_uniq(inner) | pat_bind(_, some(inner)) {
|
pat_box(inner) | pat_uniq(inner) {
|
||||||
v.visit_pat(inner, e, v);
|
v.visit_pat(inner, e, v);
|
||||||
}
|
}
|
||||||
|
pat_ident(path, inner) {
|
||||||
|
visit_path(path, e, v);
|
||||||
|
option::may(inner, {|subpat| v.visit_pat(subpat, e, v)});
|
||||||
|
}
|
||||||
_ { }
|
_ { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1278,7 +1278,7 @@ mod node {
|
|||||||
while true {
|
while true {
|
||||||
alt(get_current_or_next_leaf(it)) {
|
alt(get_current_or_next_leaf(it)) {
|
||||||
option::none. { ret option::none; }
|
option::none. { ret option::none; }
|
||||||
option::some(leaf) {
|
option::some(_) {
|
||||||
let next_char = get_next_char_in_leaf(it);
|
let next_char = get_next_char_in_leaf(it);
|
||||||
alt(next_char) {
|
alt(next_char) {
|
||||||
option::none. {
|
option::none. {
|
||||||
@ -1301,7 +1301,7 @@ mod node {
|
|||||||
let next = leaf_iterator::next(it.leaf_iterator);
|
let next = leaf_iterator::next(it.leaf_iterator);
|
||||||
alt(next) {
|
alt(next) {
|
||||||
option::none. { ret option::none }
|
option::none. { ret option::none }
|
||||||
option::some(leaf) {
|
option::some(_) {
|
||||||
it.leaf = next;
|
it.leaf = next;
|
||||||
it.leaf_byte_pos = 0u;
|
it.leaf_byte_pos = 0u;
|
||||||
ret next;
|
ret next;
|
||||||
@ -1314,16 +1314,16 @@ mod node {
|
|||||||
fn get_next_char_in_leaf(it: t) -> option::t<char> {
|
fn get_next_char_in_leaf(it: t) -> option::t<char> {
|
||||||
alt(it.leaf) {
|
alt(it.leaf) {
|
||||||
option::none. { ret option::none }
|
option::none. { ret option::none }
|
||||||
option::some(leaf) {
|
option::some(aleaf) {
|
||||||
if it.leaf_byte_pos >= leaf.byte_len {
|
if it.leaf_byte_pos >= aleaf.byte_len {
|
||||||
//We are actually past the end of the leaf
|
//We are actually past the end of the leaf
|
||||||
it.leaf = option::none;
|
it.leaf = option::none;
|
||||||
ret option::none
|
ret option::none
|
||||||
} else {
|
} else {
|
||||||
let {ch, next} =
|
let {ch, next} =
|
||||||
str::char_range_at(*leaf.content,
|
str::char_range_at(*aleaf.content,
|
||||||
it.leaf_byte_pos + leaf.byte_offset);
|
it.leaf_byte_pos + aleaf.byte_offset);
|
||||||
it.leaf_byte_pos = next - leaf.byte_offset;
|
it.leaf_byte_pos = next - aleaf.byte_offset;
|
||||||
ret option::some(ch)
|
ret option::some(ch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let i: int =
|
let i: int =
|
||||||
alt some::<int>(3) { none::<int>. { fail } some::<int>(_) { 5 } };
|
alt some::<int>(3) { none::<int> { fail } some::<int>(_) { 5 } };
|
||||||
log(debug, i);
|
log(debug, i);
|
||||||
}
|
}
|
||||||
|
10
src/test/run-pass/nullary-or-pattern.rs
Normal file
10
src/test/run-pass/nullary-or-pattern.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
tag blah { a; b; }
|
||||||
|
|
||||||
|
fn or_alt(q: blah) -> int {
|
||||||
|
alt q { a. | b. { 42 } }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert (or_alt(a) == 42);
|
||||||
|
assert (or_alt(b) == 42);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user