Refactor data structures representing constraints (again...)

I added a "resolved" version of the ast::constr type -- ty::constr_def
-- that has a def_id field instead of an ann_field. This is more
consistent with other types and eliminates some checking.

Incidentally, I removed the def_map argument to the top-level function
in middle::alias, since the ty::ctxt already has a def_map field.
This commit is contained in:
Tim Chevalier 2011-06-15 15:14:30 -07:00
parent 52d4f48144
commit a5bca7df88
14 changed files with 265 additions and 233 deletions

View File

@ -81,10 +81,10 @@ fn compile_input(session::session sess, eval::env env, str input,
auto crate =
time(time_passes, "parsing", bind parse_input(sess, p, input));
if (sess.get_opts().output_type == link::output_type_none) { ret; }
auto def_map =
auto d =
time(time_passes, "resolution",
bind resolve::resolve_crate(sess, crate));
auto ty_cx = ty::mk_ctxt(sess, def_map);
auto ty_cx = ty::mk_ctxt(sess, d._0, d._1);
time[()](time_passes, "typechecking",
bind typeck::check_crate(ty_cx, crate));
if (sess.get_opts().run_typestate) {
@ -92,7 +92,7 @@ fn compile_input(session::session sess, eval::env env, str input,
bind middle::tstate::ck::check_crate(ty_cx, crate));
}
time(time_passes, "alias checking",
bind middle::alias::check_crate(@ty_cx, def_map, crate));
bind middle::alias::check_crate(@ty_cx, crate));
auto llmod =
time[llvm::llvm::ModuleRef](time_passes, "translation",
bind trans::trans_crate(sess, crate,
@ -109,8 +109,8 @@ fn pretty_print_input(session::session sess, eval::env env, str input,
auto mode;
alt (ppm) {
case (ppm_typed) {
auto def_map = resolve::resolve_crate(sess, crate);
auto ty_cx = ty::mk_ctxt(sess, def_map);
auto d = resolve::resolve_crate(sess, crate);
auto ty_cx = ty::mk_ctxt(sess, d._0, d._1);
typeck::check_crate(ty_cx, crate);
mode = ppaux::mo_typed(ty_cx);
}

View File

@ -359,19 +359,17 @@ tag constr_arg_general_[T] { carg_base; carg_ident(T); carg_lit(@lit); }
type constr_arg = constr_arg_general[uint];
type constr_arg_use = constr_arg_general[ident];
type constr_arg_general[T] = spanned[constr_arg_general_[T]];
type constr_ = rec(path path,
vec[@constr_arg_general[uint]] args,
ann ann);
// The ann field is there so that using the def_map in the type
// context, we can get the def_id for the path.
type constr_general[T] =
rec(path path, vec[@constr_arg_general[T]] args, ann ann);
type constr = spanned[constr_];
type constr = spanned[constr_general[uint]];
type constr_use = spanned[constr_general[ident]];
/* The parser generates ast::constrs; resolve generates
a mapping from each function to a list of ty::constr_defs,
corresponding to these. */
type arg = rec(mode mode, @ty ty, ident ident, def_id id);

View File

@ -78,8 +78,8 @@ fn parse_ty_or_bang(@pstate st, str_def sd) -> ty_or_bang {
}
}
fn parse_constrs(@pstate st, str_def sd) -> vec[@ast::constr] {
let vec[@ast::constr] res = [];
fn parse_constrs(@pstate st, str_def sd) -> vec[@ty::constr_def] {
let vec[@ty::constr_def] res = [];
alt (peek(st) as char) {
case (':') {
do {
@ -92,7 +92,7 @@ fn parse_constrs(@pstate st, str_def sd) -> vec[@ast::constr] {
ret res;
}
fn parse_constr(@pstate st, str_def sd) -> @ast::constr {
fn parse_constr(@pstate st, str_def sd) -> @ty::constr_def {
st.tcx.sess.unimpl("Reading constraints " + " isn't implemented");
/*
let vec[@ast::constr_arg] args = [];
@ -318,7 +318,7 @@ fn parse_hex(@pstate st) -> uint {
}
fn parse_ty_fn(@pstate st, str_def sd) ->
tup(vec[ty::arg], ty::t, ast::controlflow, vec[@ast::constr]) {
tup(vec[ty::arg], ty::t, ast::controlflow, vec[@ty::constr_def]) {
assert (next(st) as char == '[');
let vec[ty::arg] inputs = [];
while (peek(st) as char != ']') {

View File

@ -35,14 +35,11 @@ tag local_info { arg(ast::mode); objfield(ast::mutability); }
type ctx =
rec(@ty::ctxt tcx,
resolve::def_map dm,
std::map::hashmap[def_num, local_info] local_map);
fn check_crate(@ty::ctxt tcx, resolve::def_map dm, &@ast::crate crate) {
fn check_crate(@ty::ctxt tcx, &@ast::crate crate) {
auto cx =
@rec(tcx=tcx,
dm=dm,
// Stores information about object fields and function
// arguments that's otherwise not easily available.
local_map=util::common::new_int_hash());
@ -173,7 +170,7 @@ fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc) ->
if (vec::len(unsafe_ts) > 0u) {
alt (f.node) {
case (ast::expr_path(_, ?ann)) {
if (def_is_local(cx.dm.get(ann.id), true)) {
if (def_is_local(cx.tcx.def_map.get(ann.id), true)) {
cx.tcx.sess.span_err
(f.span, #fmt("function may alias with argument \
%u, which is not immutably rooted",
@ -231,7 +228,7 @@ fn check_tail_call(&ctx cx, &@ast::expr call) {
auto ok = true;
alt (args.(i).node) {
case (ast::expr_path(_, ?ann)) {
auto def = cx.dm.get(ann.id);
auto def = cx.tcx.def_map.get(ann.id);
auto dnum = ast::def_id_of_def(def)._1;
alt (cx.local_map.find(dnum)) {
case (some(arg(ast::alias(?mut)))) {
@ -353,7 +350,7 @@ fn check_for(&ctx cx, &@ast::local local, &@ast::expr seq, &ast::block block,
fn check_var(&ctx cx, &@ast::expr ex, &ast::path p, ast::ann ann, bool assign,
&scope sc) {
auto def = cx.dm.get(ann.id);
auto def = cx.tcx.def_map.get(ann.id);
if (!def_is_local(def, true)) { ret; }
auto my_defnum = ast::def_id_of_def(def)._1;
auto var_t = ty::expr_ty(*cx.tcx, ex);
@ -379,7 +376,7 @@ fn check_assign(&@ctx cx, &@ast::expr dest, &@ast::expr src, &scope sc,
visit_expr(cx, src, sc, v);
alt (dest.node) {
case (ast::expr_path(?p, ?ann)) {
auto dnum = ast::def_id_of_def(cx.dm.get(ann.id))._1;
auto dnum = ast::def_id_of_def(cx.tcx.def_map.get(ann.id))._1;
if (is_immutable_alias(cx, sc, dnum)) {
cx.tcx.sess.span_err(dest.span,
"assigning to immutable alias");
@ -566,7 +563,7 @@ fn inner_mut(&vec[deref] ds) -> option::t[ty::t] {
fn path_def_id(&ctx cx, &@ast::expr ex) -> option::t[ast::def_id] {
alt (ex.node) {
case (ast::expr_path(_, ?ann)) {
ret some(ast::def_id_of_def(cx.dm.get(ann.id)));
ret some(ast::def_id_of_def(cx.tcx.def_map.get(ann.id)));
}
case (_) { ret none; }
}

View File

@ -221,8 +221,7 @@ mod Encode {
case (ast::native_abi_cdecl) { w.write_char('c'); }
case (ast::native_abi_llvm) { w.write_char('l'); }
}
let vec[@constr] res_constrs = [];
enc_ty_fn(w, cx, args, out, ast::return, res_constrs);
enc_ty_fn(w, cx, args, out, ast::return, []);
}
case (ty::ty_obj(?methods)) {
w.write_str("O[");
@ -253,7 +252,7 @@ mod Encode {
}
}
fn enc_ty_fn(&io::writer w, &@ctxt cx, &vec[ty::arg] args, &ty::t out,
&ast::controlflow cf, &vec[@ast::constr] constrs) {
&ast::controlflow cf, &vec[@ty::constr_def] constrs) {
w.write_char('[');
for (ty::arg arg in args) {
alt (arg.mode) {
@ -271,7 +270,7 @@ mod Encode {
case (_) { enc_ty(w, cx, out); }
}
auto colon = true;
for (@ast::constr c in constrs) {
for (@ty::constr_def c in constrs) {
if (colon) {
w.write_char(':');
colon = false;
@ -279,7 +278,7 @@ mod Encode {
enc_constr(w, cx, c);
}
}
fn enc_constr(&io::writer w, &@ctxt cx, &@ast::constr c) {
fn enc_constr(&io::writer w, &@ctxt cx, &@ty::constr_def c) {
w.write_str(path_to_str(c.node.path));
w.write_char('(');
// FIXME

View File

@ -11,7 +11,8 @@ import util::common::new_int_hash;
import util::common::new_uint_hash;
import util::common::new_str_hash;
import util::common::span;
import middle::tstate::ann::ts_ann;
import util::common::respan;
import middle::ty::constr_table;
import visit::vt;
import std::map::hashmap;
import std::list;
@ -111,6 +112,7 @@ type def_map = hashmap[uint, def];
type env =
rec(crate_map crate_map,
def_map def_map,
constr_table fn_constrs,
hashmap[def_id, @ast::item] ast_map,
hashmap[ast::def_num, import_state] imports,
hashmap[ast::def_num, @indexed_mod] mod_map,
@ -118,17 +120,18 @@ type env =
ext_hash ext_cache,
session sess);
// Used to distinguish between lookups from outside and from inside modules,
// since export restrictions should only be applied for the former.
tag dir { inside; outside; }
tag namespace { ns_value; ns_type; ns_module; }
fn resolve_crate(session sess, @ast::crate crate) -> def_map {
fn resolve_crate(session sess, @ast::crate crate)
-> tup(def_map, constr_table) {
auto e =
@rec(crate_map=new_uint_hash[ast::crate_num](),
def_map=new_uint_hash[def](),
fn_constrs = new_def_hash[vec[ty::constr_def]](),
ast_map=new_def_hash[@ast::item](),
imports=new_int_hash[import_state](),
mod_map=new_int_hash[@indexed_mod](),
@ -140,7 +143,7 @@ fn resolve_crate(session sess, @ast::crate crate) -> def_map {
resolve_imports(*e);
check_for_collisions(e, *crate);
resolve_names(e, crate);
ret e.def_map;
ret tup(e.def_map, e.fn_constrs);
}
@ -266,8 +269,9 @@ fn resolve_names(&@env e, &@ast::crate c) {
visit_arm=bind walk_arm(e, _, _, _),
visit_expr=bind walk_expr(e, _, _, _),
visit_ty=bind walk_ty(e, _, _, _),
visit_fn=visit_fn_with_scope,
visit_constr=bind walk_constr(e, _, _, _)
visit_constr = bind walk_constr(e, _, _, _),
visit_fn=bind visit_fn_with_scope
(e, _, _, _, _, _, _, _, _)
with *visit::default_visitor());
visit::visit_crate(*c, cons(scope_crate(c), @nil), visit::vtor(v));
fn walk_expr(@env e, &@ast::expr exp, &scopes sc, &vt[scopes] v) {
@ -282,12 +286,7 @@ fn resolve_names(&@env e, &@ast::crate c) {
case (_) { }
}
}
fn walk_constr(@env e, &@ast::constr c, &scopes sc, &vt[scopes] v) {
auto new_def =
lookup_path_strict(*e, sc, c.span, c.node.path.node.idents,
ns_value);
e.def_map.insert(c.node.ann.id, new_def);
}
fn walk_ty(@env e, &@ast::ty t, &scopes sc, &vt[scopes] v) {
visit::visit_ty(t, sc, v);
alt (t.node) {
@ -300,6 +299,13 @@ fn resolve_names(&@env e, &@ast::crate c) {
case (_) { }
}
}
fn walk_constr(@env e, &@ast::constr c, &scopes sc, &vt[scopes] v) {
auto new_def = lookup_path_strict(*e, sc, c.span,
c.node.path.node.idents, ns_value);
e.def_map.insert(c.node.ann.id, new_def);
}
fn walk_arm(@env e, &ast::arm a, &scopes sc, &vt[scopes] v) {
walk_pat(*e, sc, a.pat);
visit_arm_with_scope(a, sc, v);
@ -338,11 +344,16 @@ fn visit_native_item_with_scope(&@ast::native_item ni, &scopes sc,
visit::visit_native_item(ni, cons(scope_native_item(ni), @sc), v);
}
fn visit_fn_with_scope(&ast::_fn f, &vec[ast::ty_param] tp, &span sp,
fn visit_fn_with_scope(&@env e, &ast::_fn f, &vec[ast::ty_param] tp, &span sp,
&ident name, &def_id d_id, &ann a, &scopes sc,
&vt[scopes] v) {
visit::visit_fn(f, tp, sp, name, d_id, a, cons(scope_fn(f.decl, tp), @sc),
v);
// here's where we need to set up the mapping
// for f's constrs in the table.
for (@ast::constr c in f.decl.constraints) {
resolve_constr(e, d_id, c, sc, v);
}
visit::visit_fn(f, tp, sp, name, d_id, a,
cons(scope_fn(f.decl, tp), @sc), v);
}
fn visit_block_with_scope(&ast::block b, &scopes sc, &vt[scopes] v) {
@ -389,6 +400,37 @@ fn follow_import(&env e, &scopes sc, vec[ident] path, &span sp) -> def {
}
}
fn resolve_constr(@env e, &def_id d_id, &@ast::constr c, &scopes sc,
&vt[scopes] v) {
let def new_def = lookup_path_strict(*e, sc, c.span,
c.node.path.node.idents,
ns_value);
alt (new_def) {
case (ast::def_fn(?pred_id)) {
let ty::constr_general[uint] c_ = rec(path=c.node.path,
args=c.node.args,
id=pred_id);
let ty::constr_def new_constr = respan(c.span, c_);
add_constr(e, d_id, new_constr);
}
case (_) {
e.sess.span_err(c.span, "Non-predicate in constraint: "
+ ty::path_to_str(c.node.path));
}
}
}
fn add_constr(&@env e, &def_id d_id, &ty::constr_def c) {
e.fn_constrs.insert(d_id,
alt (e.fn_constrs.find(d_id)) {
case (none) {
[c]
}
case (some(?cs)) {
cs + [c]
}
});
}
// Import resolution
fn resolve_import(&env e, &@ast::view_item it, &scopes sc) {

View File

@ -198,8 +198,9 @@ to represent predicate *arguments* however. This type
Both types store an ident and span, for error-logging purposes.
*/
type pred_desc_ = rec(vec[@constr_arg_use] args, uint bit_num);
type pred_desc = spanned[pred_desc_];
type constr_arg_use = constr_arg_general[ident];
tag constraint {
cinit(uint, span, ident);
@ -456,7 +457,7 @@ fn controlflow_expr(&crate_ctxt ccx, @expr e) -> controlflow {
}
}
fn constraints_expr(&ty::ctxt cx, @expr e) -> vec[@ast::constr] {
fn constraints_expr(&ty::ctxt cx, @expr e) -> vec[@ty::constr_def] {
alt (ty::struct(cx, ty::ann_to_type(cx, expr_ann(e)))) {
case (ty::ty_fn(_, _, _, _, ?cs)) { ret cs; }
case (_) { ret []; }
@ -511,9 +512,11 @@ fn constraints(&fn_ctxt fcx) -> vec[norm_constraint] {
// FIXME:
// this probably doesn't handle name shadowing well (or at all)
// variables should really always be id'd by def_id and not ident
fn match_args(&fn_ctxt fcx, vec[pred_desc] occs, vec[@constr_arg_use] occ) ->
uint {
log "match_args: looking at " + pretty::ppaux::constr_args_to_str_1(occ);
log ("match_args: looking at " +
pretty::ppaux::constr_args_to_str(std::util::id[str], occ));
for (pred_desc pd in occs) {
log "match_args: candidate " + pred_desc_to_str(pd);
if (ty::args_eq(str::eq, pd.node.args, occ)) { ret pd.node.bit_num; }
@ -586,11 +589,13 @@ fn expr_to_constr(ty::ctxt tcx, &@expr e) -> constr {
fn pred_desc_to_str(&pred_desc p) -> str {
ret "<" + uistr(p.node.bit_num) + ", " +
pretty::ppaux::constr_args_to_str_1(p.node.args) + ">";
pretty::ppaux::constr_args_to_str(std::util::id[str], p.node.args)
+ ">";
}
fn substitute_constr_args(&ty::ctxt cx, &vec[@expr] actuals, &@ast::constr c)
-> constr__ {
fn substitute_constr_args(&ty::ctxt cx,
&vec[@expr] actuals, &@ty::constr_def c)
-> constr__ {
let vec[@constr_arg_use] res = [];
for (@constr_arg a in c.node.args) {
res += [substitute_arg(cx, actuals, a)];

View File

@ -37,30 +37,16 @@ fn collect_pred(&ctxt cx, &@expr e) {
case (expr_check(?e, _)) {
vec::push(*cx.cs, expr_to_constr(cx.tcx, e));
}
case (
// If it's a call, generate appropriate instances of the
// call's constraints.
expr_call(?operator, ?operands, ?a)) {
for (@ast::constr c in constraints_expr(cx.tcx, operator)) {
auto d_id = ann_to_def_strict(cx.tcx, c.node.ann);
alt (d_id) {
case (def_fn(?an_id)) {
let aux::constr ct =
respan(c.span,
rec(id=an_id,
c=aux::substitute_constr_args(cx.tcx,
operands,
c)));
vec::push(*cx.cs, ct);
}
case (_) {
cx.tcx.sess.span_err(c.span,
"Non-pred in constraint");
}
}
// If it's a call, generate appropriate instances of the
// call's constraints.
case (expr_call(?operator, ?operands, ?a)) {
for (@ty::constr_def c in constraints_expr(cx.tcx, operator)) {
let aux::constr ct = respan(c.span,
rec(id=c.node.id,
c=aux::substitute_constr_args(cx.tcx,
operands, c)));
vec::push(*cx.cs, ct);
}
// FIXME: constraints on result type
}
case (_) { }
}

View File

@ -208,38 +208,16 @@ fn find_pre_post_expr(&fn_ctxt fcx, @expr e) {
auto args = vec::clone[@expr](operands);
vec::push[@expr](args, operator);
find_pre_post_exprs(fcx, args, a);
/* should test higher-order constrained functions */
/* FIXME */
/* see if the call has any constraints on its in type */
log "a function: ";
/* see if the call has any constraints on its type */
log("a function: " );
log_expr(*operator);
auto pp = expr_pp(fcx.ccx, e);
for (@constr c in constraints_expr(fcx.ccx.tcx, operator)) {
auto id = ann_to_def(fcx.ccx, c.node.ann);
alt (id) {
case (some(def_fn(?d_id))) {
auto i =
bit_num(fcx,
rec(id=d_id,
c=substitute_constr_args(fcx.ccx.tcx,
operands,
c)));
require(i, pp);
}
case (_) {
fcx.ccx.tcx.sess.span_err(c.span,
"Unbound pred " +
" or pred that's not \
bound to a function");
}
}
for (@ty::constr_def c in
constraints_expr(fcx.ccx.tcx, operator)) {
auto i = bit_num(fcx, rec(id=c.node.id,
c=substitute_constr_args(fcx.ccx.tcx, operands, c)));
require(i, pp);
}
// FIXME: constraints on result type
/* if this is a failing call, its postcondition sets everything */
alt (controlflow_expr(fcx.ccx, operator)) {
case (noreturn) { set_postcond_false(fcx.ccx, a); }

View File

@ -13,23 +13,14 @@ import std::option::some;
import std::smallintmap;
import driver::session;
import front::ast;
import front::ast::def_id;
import front::ast::constr_arg_general;
import front::ast::mutability;
import front::ast::controlflow;
import front::creader;
import middle::metadata;
import util::common;
import util::common::ty_u8;
import util::common::ty_u16;
import util::common::ty_u32;
import util::common::ty_u64;
import util::common::ty_i8;
import util::common::ty_i16;
import util::common::ty_i32;
import util::common::ty_i64;
import util::common::ty_f32;
import util::common::ty_f64;
import util::common::new_def_hash;
import util::common::span;
import util::common::*;
import util::data::interner;
@ -46,7 +37,7 @@ type method =
vec[arg] inputs,
t output,
controlflow cf,
vec[@ast::constr] constrs);
vec[@constr_def] constrs);
tag any_item {
any_item_rust(@ast::item);
@ -54,12 +45,14 @@ tag any_item {
}
type item_table = hashmap[ast::def_id, any_item];
type constr_table = hashmap[ast::def_id, vec[constr_def]];
type mt = rec(t ty, ast::mutability mut);
// Contains information needed to resolve types and (in the future) look up
// the types of AST nodes.
type creader_cache = hashmap[tup(int, uint, uint), ty::t];
type ctxt =
@ -68,7 +61,7 @@ type ctxt =
resolve::def_map def_map,
node_type_table node_types,
item_table items, // Only contains type items
constr_table fn_constrs,
type_cache tcache,
creader_cache rcache,
hashmap[t, str] short_names_cache,
@ -83,7 +76,6 @@ type ty_ctxt = ctxt;
ret mk_fn(cx, m.proto, m.inputs, m.output, m.cf, m.constrs);
}
// Never construct these manually. These are interned.
//
// TODO: It'd be really nice to be able to hide this definition from the
@ -107,11 +99,11 @@ tag sty {
ty_int;
ty_float;
ty_uint;
ty_machine(util::common::ty_mach);
ty_machine(ty_mach);
ty_char;
ty_str;
ty_istr;
ty_tag(ast::def_id, vec[t]);
ty_tag(def_id, vec[t]);
ty_box(mt);
ty_vec(mt);
ty_ivec(mt);
@ -121,7 +113,7 @@ tag sty {
ty_task;
ty_tup(vec[mt]);
ty_rec(vec[field]);
ty_fn(ast::proto, vec[arg], t, controlflow, vec[@ast::constr]);
ty_fn(ast::proto, vec[arg], t, controlflow, vec[@constr_def]);
ty_native_fn(ast::native_abi, vec[arg], t);
ty_obj(vec[method]);
ty_var(int); // type variable
@ -134,6 +126,10 @@ tag sty {
}
type constr_def = spanned[constr_general[uint]];
type constr_general[T] = rec(path path,
vec[@constr_arg_general[T]] args,
def_id id);
// Data structures used in type unification
tag type_err {
@ -247,12 +243,13 @@ fn mk_rcache() -> creader_cache {
ret map::mk_hashmap[tup(int, uint, uint), t](h, e);
}
fn mk_ctxt(session::session s, resolve::def_map dm) -> ctxt {
fn mk_ctxt(session::session s, resolve::def_map dm, constr_table cs) -> ctxt {
let vec[mutable option::t[ty::ty_param_substs_opt_and_ty]] ntt_sub =
[mutable ];
let node_type_table ntt = @mutable ntt_sub;
auto tcache = common::new_def_hash[ty::ty_param_count_and_ty]();
auto items = common::new_def_hash[any_item]();
auto tcache = new_def_hash[ty::ty_param_count_and_ty]();
auto items = new_def_hash[any_item]();
auto ts = @interner::mk[raw_t](hash_raw_ty, eq_raw_ty);
auto cx =
rec(ts=ts,
@ -260,6 +257,7 @@ fn mk_ctxt(session::session s, resolve::def_map dm) -> ctxt {
def_map=dm,
node_types=ntt,
items=items,
fn_constrs = cs,
tcache=tcache,
rcache=mk_rcache(),
short_names_cache=map::mk_hashmap[ty::t,
@ -379,7 +377,7 @@ fn mk_float(&ctxt cx) -> t { ret idx_float; }
fn mk_uint(&ctxt cx) -> t { ret idx_uint; }
fn mk_mach(&ctxt cx, &util::common::ty_mach tm) -> t {
fn mk_mach(&ctxt cx, &ty_mach tm) -> t {
alt (tm) {
case (ty_u8) { ret idx_u8; }
case (ty_u16) { ret idx_u16; }
@ -439,7 +437,7 @@ fn mk_imm_tup(&ctxt cx, &vec[t] tys) -> t {
fn mk_rec(&ctxt cx, &vec[field] fs) -> t { ret gen_ty(cx, ty_rec(fs)); }
fn mk_fn(&ctxt cx, &ast::proto proto, &vec[arg] args, &t ty, &controlflow cf,
&vec[@ast::constr] constrs) -> t {
&vec[@constr_def] constrs) -> t {
ret gen_ty(cx, ty_fn(proto, args, ty, cf, constrs));
}
@ -759,8 +757,8 @@ fn sequence_is_interior(&ctxt cx, &t ty) -> bool {
fn sequence_element_type(&ctxt cx, &t ty) -> t {
alt (struct(cx, ty)) {
case (ty_str) { ret mk_mach(cx, common::ty_u8); }
case (ty_istr) { ret mk_mach(cx, common::ty_u8); }
case (ty_str) { ret mk_mach(cx, ty_u8); }
case (ty_istr) { ret mk_mach(cx, ty_u8); }
case (ty_vec(?mt)) { ret mt.ty; }
case (ty_ivec(?mt)) { ret mt.ty; }
case (_) {
@ -915,14 +913,14 @@ fn type_is_integral(&ctxt cx, &t ty) -> bool {
case (ty_uint) { ret true; }
case (ty_machine(?m)) {
alt (m) {
case (common::ty_i8) { ret true; }
case (common::ty_i16) { ret true; }
case (common::ty_i32) { ret true; }
case (common::ty_i64) { ret true; }
case (common::ty_u8) { ret true; }
case (common::ty_u16) { ret true; }
case (common::ty_u32) { ret true; }
case (common::ty_u64) { ret true; }
case (ty_i8) { ret true; }
case (ty_i16) { ret true; }
case (ty_i32) { ret true; }
case (ty_i64) { ret true; }
case (ty_u8) { ret true; }
case (ty_u16) { ret true; }
case (ty_u32) { ret true; }
case (ty_u64) { ret true; }
case (_) { ret false; }
}
}
@ -935,8 +933,8 @@ fn type_is_fp(&ctxt cx, &t ty) -> bool {
alt (struct(cx, ty)) {
case (ty_machine(?tm)) {
alt (tm) {
case (common::ty_f32) { ret true; }
case (common::ty_f64) { ret true; }
case (ty_f32) { ret true; }
case (ty_f64) { ret true; }
case (_) { ret false; }
}
}
@ -950,10 +948,10 @@ fn type_is_signed(&ctxt cx, &t ty) -> bool {
case (ty_int) { ret true; }
case (ty_machine(?tm)) {
alt (tm) {
case (common::ty_i8) { ret true; }
case (common::ty_i16) { ret true; }
case (common::ty_i32) { ret true; }
case (common::ty_i64) { ret true; }
case (ty_i8) { ret true; }
case (ty_i16) { ret true; }
case (ty_i32) { ret true; }
case (ty_i64) { ret true; }
case (_) { ret false; }
}
}
@ -1005,16 +1003,16 @@ fn hash_type_structure(&sty st) -> uint {
case (ty_uint) { ret 4u; }
case (ty_machine(?tm)) {
alt (tm) {
case (common::ty_i8) { ret 5u; }
case (common::ty_i16) { ret 6u; }
case (common::ty_i32) { ret 7u; }
case (common::ty_i64) { ret 8u; }
case (common::ty_u8) { ret 9u; }
case (common::ty_u16) { ret 10u; }
case (common::ty_u32) { ret 11u; }
case (common::ty_u64) { ret 12u; }
case (common::ty_f32) { ret 13u; }
case (common::ty_f64) { ret 14u; }
case (ty_i8) { ret 5u; }
case (ty_i16) { ret 6u; }
case (ty_i32) { ret 7u; }
case (ty_i64) { ret 8u; }
case (ty_u8) { ret 9u; }
case (ty_u16) { ret 10u; }
case (ty_u32) { ret 11u; }
case (ty_u64) { ret 12u; }
case (ty_f32) { ret 13u; }
case (ty_f64) { ret 14u; }
}
}
case (ty_char) { ret 15u; }
@ -1096,7 +1094,7 @@ fn arg_eq[T](&fn(&T, &T) -> bool eq, @ast::constr_arg_general[T] a,
}
case (ast::carg_lit(?l)) {
alt (b.node) {
case (ast::carg_lit(?m)) { ret util::common::lit_eq(l, m); }
case (ast::carg_lit(?m)) { ret lit_eq(l, m); }
case (_) { ret false; }
}
}
@ -1113,18 +1111,18 @@ fn args_eq[T](fn(&T, &T) -> bool eq, vec[@ast::constr_arg_general[T]] a,
ret true;
}
fn constr_eq(&@ast::constr c, &@ast::constr d) -> bool {
fn constr_eq(&@constr_def c, &@constr_def d) -> bool {
ret path_to_str(c.node.path) == path_to_str(d.node.path) &&
// FIXME: hack
args_eq(eq_int, c.node.args, d.node.args);
}
fn constrs_eq(&vec[@ast::constr] cs, &vec[@ast::constr] ds) -> bool {
fn constrs_eq(&vec[@constr_def] cs, &vec[@constr_def] ds) -> bool {
if (vec::len(cs) != vec::len(ds)) { ret false; }
auto i = 0;
for (@ast::constr c in cs) {
auto i = 0u;
for (@constr_def c in cs) {
if (!constr_eq(c, ds.(i))) { ret false; }
i += 1;
i += 1u;
}
ret true;
}
@ -1829,8 +1827,8 @@ mod unify {
&t expected, &t actual, &vec[arg] expected_inputs,
&t expected_output, &vec[arg] actual_inputs, &t actual_output,
&controlflow expected_cf, &controlflow actual_cf,
&vec[@ast::constr] expected_constrs,
&vec[@ast::constr] actual_constrs) -> result {
&vec[@constr_def] expected_constrs,
&vec[@constr_def] actual_constrs) -> result {
if (e_proto != a_proto) { ret ures_err(terr_mismatch); }
alt (expected_cf) {
case (ast::return) { }
@ -2473,7 +2471,7 @@ fn tag_variant_with_id(&ctxt cx, &ast::def_id tag_id, &ast::def_id variant_id)
auto i = 0u;
while (i < vec::len[variant_info](variants)) {
auto variant = variants.(i);
if (common::def_eq(variant.id, variant_id)) { ret variant; }
if (def_eq(variant.id, variant_id)) { ret variant; }
i += 1u;
}
cx.sess.bug("tag_variant_with_id(): no variant exists with that ID");

View File

@ -6,6 +6,7 @@ import front::creader;
import driver::session;
import util::common;
import util::common::span;
import util::common::respan;
import util::common::new_def_hash;
import util::common::log_expr_err;
import middle::ty;
@ -312,7 +313,10 @@ fn ast_ty_to_ty(&ty::ctxt tcx, &ty_getter getter, &@ast::ty ast_ty) -> ty::t {
auto f = bind ast_arg_to_arg(tcx, getter, _);
auto i = vec::map[ast::ty_arg, arg](f, inputs);
auto out_ty = ast_ty_to_ty(tcx, getter, output);
typ = ty::mk_fn(tcx, proto, i, out_ty, cf, constrs);
let fn(&@ast::constr) -> @ty::constr_def g =
bind ast_constr_to_constr(tcx, _);
let vec[@ty::constr_def] out_constrs = vec::map(g, constrs);
typ = ty::mk_fn(tcx, proto, i, out_ty, cf, out_constrs);
}
case (ast::ty_path(?path, ?ann)) {
alt (tcx.def_map.get(ann.id)) {
@ -341,13 +345,17 @@ fn ast_ty_to_ty(&ty::ctxt tcx, &ty_getter getter, &@ast::ty ast_ty) -> ty::t {
for (ast::ty_method m in meths) {
auto ins = vec::map[ast::ty_arg, arg](f, m.node.inputs);
auto out = ast_ty_to_ty(tcx, getter, m.node.output);
let fn(&@ast::constr) -> @ty::constr_def g =
bind ast_constr_to_constr(tcx, _);
let vec[@ty::constr_def] out_constrs =
vec::map(g, m.node.constrs);
let ty::method new_m =
rec(proto=m.node.proto,
ident=m.node.ident,
inputs=ins,
output=out,
cf=m.node.cf,
constrs=m.node.constrs);
constrs=out_constrs);
vec::push[ty::method](tmeths, new_m);
}
typ = ty::mk_obj(tcx, ty::sort_methods(tmeths));
@ -449,9 +457,12 @@ mod collect {
ty::ty_param_count_and_ty {
auto input_tys = vec::map[ast::arg, arg](ty_of_arg, decl.inputs);
auto output_ty = convert(decl.output);
let fn(&@ast::constr) -> @ty::constr_def g =
bind ast_constr_to_constr(cx.tcx, _);
let vec[@ty::constr_def] out_constrs = vec::map(g, decl.constraints);
auto t_fn =
ty::mk_fn(cx.tcx, proto, input_tys, output_ty, decl.cf,
decl.constraints);
out_constrs);
auto ty_param_count = vec::len[ast::ty_param](ty_params);
auto tpt = tup(ty_param_count, t_fn);
alt (def_id) {
@ -512,12 +523,13 @@ mod collect {
auto f = bind ty_of_arg(cx, _);
auto inputs = vec::map[ast::arg, arg](f, m.node.meth.decl.inputs);
auto output = convert(m.node.meth.decl.output);
ret rec(proto=m.node.meth.proto,
ident=m.node.ident,
inputs=inputs,
output=output,
cf=m.node.meth.decl.cf,
constrs=m.node.meth.decl.constraints);
let fn(&@ast::constr) -> @ty::constr_def g =
bind ast_constr_to_constr(cx.tcx, _);
let vec[@ty::constr_def] out_constrs =
vec::map(g, m.node.meth.decl.constraints);
ret rec(proto=m.node.meth.proto, ident=m.node.ident,
inputs=inputs, output=output, cf=m.node.meth.decl.cf,
constrs=out_constrs);
}
fn ty_of_obj(@ctxt cx, &ast::ident id, &ast::_obj obj_info,
&vec[ast::ty_param] ty_params) -> ty::ty_param_count_and_ty {
@ -537,10 +549,8 @@ mod collect {
auto t_field = ast_ty_to_ty(cx.tcx, g, f.ty);
vec::push(t_inputs, rec(mode=ty::mo_alias(false), ty=t_field));
}
let vec[@ast::constr] constrs = [];
auto t_fn =
ty::mk_fn(cx.tcx, ast::proto_fn, t_inputs, t_obj._1, ast::return,
constrs);
auto t_fn = ty::mk_fn(cx.tcx, ast::proto_fn, t_inputs, t_obj._1,
ast::return, []);
auto tpt = tup(t_obj._0, t_fn);
cx.tcx.tcache.insert(ctor_id, tpt);
ret tpt;
@ -652,11 +662,8 @@ mod collect {
}
auto tag_t = ty::mk_tag(cx.tcx, tag_id, ty_param_tys);
// FIXME: this will be different for constrained types
let vec[@ast::constr] res_constrs = [];
result_ty =
ty::mk_fn(cx.tcx, ast::proto_fn, args, tag_t, ast::return,
res_constrs);
result_ty = ty::mk_fn(cx.tcx, ast::proto_fn, args, tag_t,
ast::return, []);
}
auto tpt = tup(ty_param_count, result_ty);
cx.tcx.tcache.insert(variant.node.id, tpt);
@ -752,12 +759,8 @@ mod collect {
alt (object.dtor) {
case (none) {/* nothing to do */ }
case (some(?m)) {
let vec[@ast::constr] constrs = [];
let vec[arg] res_inputs = [];
auto t =
ty::mk_fn(cx.tcx, ast::proto_fn, res_inputs,
ty::mk_nil(cx.tcx), ast::return,
constrs);
auto t = ty::mk_fn(cx.tcx, ast::proto_fn, [],
ty::mk_nil(cx.tcx), ast::return, []);
write::ty_only(cx.tcx, m.node.ann.id, t);
}
}
@ -2123,12 +2126,13 @@ fn check_expr(&@fn_ctxt fcx, &@ast::expr expr) {
auto inputs =
vec::map[ast::arg, arg](f, m.node.meth.decl.inputs);
auto output = convert(m.node.meth.decl.output);
ret rec(proto=m.node.meth.proto,
ident=m.node.ident,
inputs=inputs,
output=output,
cf=m.node.meth.decl.cf,
constrs=m.node.meth.decl.constraints);
let fn(&@ast::constr) -> @ty::constr_def g =
bind ast_constr_to_constr(ccx.tcx, _);
let vec[@ty::constr_def] out_constrs =
vec::map(g, m.node.meth.decl.constraints);
ret rec(proto=m.node.meth.proto, ident=m.node.ident,
inputs=inputs, output=output, cf=m.node.meth.decl.cf,
constrs=out_constrs);
}
fn get_anon_obj_method_types(@crate_ctxt ccx,
&ast::anon_obj anon_obj) ->
@ -2180,6 +2184,21 @@ fn get_obj_info(&@crate_ctxt ccx) -> option::t[obj_info] {
ret vec::last[obj_info](ccx.obj_infos);
}
fn ast_constr_to_constr(ty::ctxt tcx, &@ast::constr c)
-> @ty::constr_def {
alt (tcx.def_map.find(c.node.ann.id)) {
case (some(ast::def_fn(?pred_id))) {
ret @respan(c.span, rec(path=c.node.path, args=c.node.args,
id=pred_id));
}
case (_) {
tcx.sess.span_err(c.span, "Predicate "
+ path_to_str(c.node.path)
+ " is unbound or bound to a non-function");
}
}
}
fn check_decl_initializer(&@fn_ctxt fcx, &ast::def_id lid,
&ast::initializer init) {
check_expr(fcx, init.expr);

View File

@ -1,7 +1,6 @@
import std::io;
import middle::ty::*;
import front::ast::constr_arg;
import front::lexer;
import pp::word;
import pp::eof;
@ -21,9 +20,10 @@ fn ty_to_str(&ctxt cx, &t typ) -> str {
};
ret s + ty_to_str(cx, input.ty);
}
fn fn_to_str(&ctxt cx, ast::proto proto, option::t[ast::ident] ident,
vec[arg] inputs, t output, ast::controlflow cf,
&vec[@ast::constr] constrs) -> str {
&vec[@constr_def] constrs) -> str {
auto f = bind fn_input_to_str(cx, _);
auto s;
alt (proto) {
@ -69,7 +69,7 @@ fn ty_to_str(&ctxt cx, &t typ) -> str {
case (ty_int) { s += "int"; }
case (ty_float) { s += "float"; }
case (ty_uint) { s += "uint"; }
case (ty_machine(?tm)) { s += common::ty_mach_to_str(tm); }
case (ty_machine(?tm)) { s += ty_mach_to_str(tm); }
case (ty_char) { s += "char"; }
case (ty_str) { s += "str"; }
case (ty_istr) { s += "istr"; }
@ -92,10 +92,8 @@ fn ty_to_str(&ctxt cx, &t typ) -> str {
}
case (ty_tag(?id, ?tps)) {
// The user should never see this if the cname is set properly!
s +=
"<tag#" + util::common::istr(id._0) + ":" +
util::common::istr(id._1) + ">";
"<tag#" + istr(id._0) + ":" + istr(id._1) + ">";
if (vec::len[t](tps) > 0u) {
auto f = bind ty_to_str(cx, _);
auto strs = vec::map[t, str](f, tps);
@ -104,21 +102,20 @@ fn ty_to_str(&ctxt cx, &t typ) -> str {
}
case (ty_fn(?proto, ?inputs, ?output, ?cf, ?constrs)) {
s +=
fn_to_str(cx, proto, none[ast::ident], inputs, output, cf,
fn_to_str(cx, proto, none, inputs, output, cf,
constrs);
}
case (ty_native_fn(_, ?inputs, ?output)) {
let vec[@ast::constr] constrs = [];
s +=
fn_to_str(cx, ast::proto_fn, none[ast::ident], inputs, output,
ast::return, constrs);
fn_to_str(cx, ast::proto_fn, none, inputs, output,
ast::return, []);
}
case (ty_obj(?meths)) {
auto f = bind method_to_str(cx, _);
auto m = vec::map[method, str](f, meths);
s += "obj {\n\t" + str::connect(m, "\n\t") + "\n}";
}
case (ty_var(?v)) { s += "<T" + util::common::istr(v) + ">"; }
case (ty_var(?v)) { s += "<T" + istr(v) + ">"; }
case (ty_param(?id)) {
s += "'" + str::unsafe_from_bytes([('a' as u8) + (id as u8)]);
}
@ -144,7 +141,7 @@ fn constr_arg_to_str[T](fn(&T) -> str f, &ast::constr_arg_general_[T] c) ->
}
}
fn constr_arg_to_str_1(&ast::constr_arg_general_[str] c) -> str {
fn constr_arg_to_str_1(&front::ast::constr_arg_general_[str] c) -> str {
alt (c) {
case (ast::carg_base) { ret "*"; }
case (ast::carg_ident(?i)) { ret i; }
@ -164,18 +161,7 @@ fn constr_args_to_str[T](fn(&T) -> str f,
ret s;
}
fn constr_args_to_str_1(&vec[@ast::constr_arg_use] args) -> str {
auto comma = false;
auto s = "(";
for (@ast::constr_arg_use a in args) {
if (comma) { s += ", "; } else { comma = true; }
s += constr_arg_to_str_1(a.node);
}
s += ")";
ret s;
}
fn print_literal(&ps s, &@ast::lit lit) {
fn print_literal(&ps s, &@front::ast::lit lit) {
maybe_print_comment(s, lit.span.lo);
alt (next_lit(s)) {
case (some(?lt)) {
@ -196,18 +182,18 @@ fn print_literal(&ps s, &@ast::lit lit) {
word(s.s,
"'" + escape_str(str::from_bytes([ch as u8]), '\'') + "'");
}
case (ast::lit_int(?val)) { word(s.s, common::istr(val)); }
case (ast::lit_uint(?val)) { word(s.s, common::uistr(val) + "u"); }
case (ast::lit_int(?val)) { word(s.s, istr(val)); }
case (ast::lit_uint(?val)) { word(s.s, uistr(val) + "u"); }
case (ast::lit_float(?fstr)) { word(s.s, fstr); }
case (ast::lit_mach_int(?mach, ?val)) {
word(s.s, common::istr(val as int));
word(s.s, common::ty_mach_to_str(mach));
word(s.s, istr(val as int));
word(s.s, ty_mach_to_str(mach));
}
case (ast::lit_mach_float(?mach, ?val)) {
// val is already a str
word(s.s, val);
word(s.s, common::ty_mach_to_str(mach));
word(s.s, ty_mach_to_str(mach));
}
case (ast::lit_nil) { word(s.s, "()"); }
case (ast::lit_bool(?val)) {
@ -216,7 +202,7 @@ fn print_literal(&ps s, &@ast::lit lit) {
}
}
fn lit_to_str(&@ast::lit l) -> str { be to_str(l, print_literal); }
fn lit_to_str(&@front::ast::lit l) -> str { be to_str(l, print_literal); }
fn next_lit(&ps s) -> option::t[lexer::lit] {
alt (s.literals) {
@ -360,22 +346,46 @@ const uint default_columns = 78u;
// needed b/c constr_args_to_str needs
// something that takes an alias
// (argh)
fn uint_to_str(&uint i) -> str { ret util::common::uistr(i); }
fn constr_to_str(&@ast::constr c) -> str {
ret path_to_str(c.node.path) +
constr_args_to_str(uint_to_str, c.node.args);
fn uint_to_str(&uint i) -> str { ret uistr(i); }
fn constr_to_str(&@constr_def c) -> str {
ret path_to_str(c.node.path)
+ constr_args_to_str(uint_to_str, c.node.args);
}
fn constrs_str(&vec[@ast::constr] constrs) -> str {
fn ast_constr_to_str(&@front::ast::constr c) -> str {
ret path_to_str(c.node.path)
+ constr_args_to_str(uint_to_str, c.node.args);
}
fn constrs_str(&vec[@constr_def] constrs) -> str {
auto s = "";
auto colon = true;
for (@ast::constr c in constrs) {
for (@constr_def c in constrs) {
if (colon) { s += " : "; colon = false; } else { s += ", "; }
s += constr_to_str(c);
}
ret s;
}
fn ast_constrs_str(&vec[@ast::constr] constrs) -> str {
auto s = "";
auto colon = true;
for (@ast::constr c in constrs) {
if (colon) {
s += " : ";
colon = false;
}
else {
s += ", ";
}
s += ast_constr_to_str(c);
}
ret s;
}
//
// Local Variables:
// mode: rust

View File

@ -1094,7 +1094,7 @@ fn print_ty_fn(&ps s, &ast::proto proto, &option::t[str] id,
}
end(s);
}
word_space(s, constrs_str(constrs));
word_space(s, ast_constrs_str(constrs));
end(s);
}

View File

@ -1,6 +1,6 @@
// -*- rust -*-
// error-pattern: mismatched types
// xfail-stage0
// error-pattern: Non-predicate in constraint: lt
fn f(int a, int b) : lt(a,b) {
}