提交 17ff2a0d 编写于 作者: T Tim Chevalier

Further support for predicate constraints

Changed function types to include a list of constraints. Added
code for parsing and pretty-printing constraints. This necessitated
splitting pprust into two files (pprust and ppaux) to break a
circulate dependency, as ty_to_str now needs to print out constraints,
which may include literals, but pprust depended on ty.
上级 46920e07
......@@ -431,7 +431,7 @@ fn mangle_internal_name_by_type_only(&@crate_ctxt ccx, &ty::t t,
&str name) -> str {
auto f = metadata::def_to_str;
auto cx = @rec(ds=f, tcx=ccx.tcx, abbrevs=metadata::ac_no_abbrevs);
auto s = ty::ty_to_short_str(ccx.tcx, t);
auto s = pretty::ppaux::ty_to_short_str(ccx.tcx, t);
auto hash = get_symbol_hash(ccx, t);
ret mangle([name, s, hash]);
......
......@@ -11,6 +11,7 @@
import middle::typeck;
import middle::tstate::ck;
import pretty::pprust;
import pretty::ppaux;
import back::link;
import lib::llvm;
import util::common;
......@@ -133,10 +134,10 @@ fn pretty_print_input(session::session sess, eval::env env, str input,
auto def_map = resolve::resolve_crate(sess, crate);
auto ty_cx = ty::mk_ctxt(sess, def_map);
typeck::check_crate(ty_cx, crate);
mode = pprust::mo_typed(ty_cx);
mode = ppaux::mo_typed(ty_cx);
}
case (ppm_normal) { mode = pprust::mo_untyped; }
case (ppm_identified) { mode = pprust::mo_identified; }
case (ppm_normal) { mode = ppaux::mo_untyped; }
case (ppm_identified) { mode = ppaux::mo_identified; }
}
pprust::print_file(sess, crate.node.module, input, std::io::stdout(),
......
......@@ -312,8 +312,8 @@ fn unop_to_str(unop op) -> str {
type ty_field_ = rec(ident ident, mt mt);
type ty_arg_ = rec(mode mode, @ty ty);
type ty_method_ = rec(proto proto, ident ident,
vec[ty_arg] inputs, @ty output,
controlflow cf);
vec[ty_arg] inputs, @ty output,
controlflow cf, vec[@constr] constrs);
type ty_field = spanned[ty_field_];
type ty_arg = spanned[ty_arg_];
type ty_method = spanned[ty_method_];
......@@ -342,7 +342,7 @@ fn unop_to_str(unop op) -> str {
ty_chan(@ty);
ty_tup(vec[mt]);
ty_rec(vec[ty_field]);
ty_fn(proto, vec[ty_arg], @ty, controlflow);
ty_fn(proto, vec[ty_arg], @ty, controlflow, vec[@constr]);
ty_obj(vec[ty_method]);
ty_path(path, ann);
ty_type;
......@@ -362,7 +362,8 @@ fn unop_to_str(unop op) -> str {
type fn_decl = rec(vec[arg] inputs,
@ty output,
purity purity,
controlflow cf);
controlflow cf,
vec[@constr] constraints);
tag purity {
pure_fn; // declared with "pred"
impure_fn; // declared with "fn"
......
......@@ -14,8 +14,10 @@
import back::x86;
import util::common;
import util::common::span;
import util::common::respan;
import util::common::a_bang;
import util::common::a_ty;
import util::common::may_begin_ident;
import std::str;
import std::uint;
......@@ -54,6 +56,14 @@ fn next(@pstate st) -> u8 {
ret ch;
}
fn parse_ident(@pstate st, str_def sd, char last) -> ast::ident {
auto res = "";
while (peek(st) as char != last) {
res += str::unsafe_from_byte(next(st));
}
ret res;
}
fn parse_ty_data(vec[u8] data, int crate_num, uint pos, uint len,
str_def sd, ty::ctxt tcx) -> ty::t {
auto st = @rec(data=data, crate=crate_num,
......@@ -69,6 +79,62 @@ 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 = [];
alt (peek(st) as char) {
case (':') {
do {
auto ignore = next(st);
vec::push(res, parse_constr(st, sd));
} while (peek(st) as char == ',')
}
case (_) {}
}
ret res;
}
fn parse_constr(@pstate st, str_def sd) -> @ast::constr {
let vec[@ast::constr_arg] args = [];
auto sp = rec(lo=0u,hi=0u); // FIXME
let vec[ast::ident] ids = [];
let vec[@ast::ty] tys = [];
let ast::path pth = respan(sp,
rec(idents=ids, types=tys)); // FIXME
let ast::ident p1 = parse_ident(st, sd, '(');
log_err("ignore=");
log_err(p1);
let char ignore = next(st) as char;
assert(ignore as char == '(');
do {
alt (peek(st) as char) {
case ('*') {
auto ignore = next(st);
args += [@respan(sp, ast::carg_base)];
}
case (?c) {
log_err("c =");
log_err(str::from_bytes([c as u8]));
if (may_begin_ident(c)) {
auto id = parse_ident(st, sd, ',');
args += [@respan(sp, ast::carg_ident(id))];
}
else {
log_err("Lit args are unimplemented");
fail; // FIXME
}
/*
else {
auto lit = parse_lit(st, sd, ',');
args += [respan(st.span, ast::carg_lit(lit))];
}
*/
}
}
} while (next(st) as char == ',');
ignore = next(st) as char;
ret @respan(sp, rec(path=pth, args=args));
}
fn parse_ty(@pstate st, str_def sd) -> ty::t {
alt (next(st) as char) {
case ('n') { ret ty::mk_nil(st.tcx); }
......@@ -135,11 +201,13 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
}
case ('F') {
auto func = parse_ty_fn(st, sd);
ret ty::mk_fn(st.tcx, ast::proto_fn, func._0, func._1, func._2);
ret ty::mk_fn(st.tcx, ast::proto_fn, func._0,
func._1, func._2, func._3);
}
case ('W') {
auto func = parse_ty_fn(st, sd);
ret ty::mk_fn(st.tcx, ast::proto_iter, func._0, func._1, func._2);
ret ty::mk_fn(st.tcx, ast::proto_iter, func._0,
func._1, func._2, func._3);
}
case ('N') {
auto abi;
......@@ -170,7 +238,8 @@ fn parse_ty(@pstate st, str_def sd) -> ty::t {
ident=name,
inputs=func._0,
output=func._1,
cf=func._2)];
cf=func._2,
constrs=func._3)];
}
st.pos += 1u;
ret ty::mk_obj(st.tcx, methods);
......@@ -250,7 +319,8 @@ fn parse_hex(@pstate st) -> uint {
}
fn parse_ty_fn(@pstate st, str_def sd) -> tup(vec[ty::arg], ty::t,
ast::controlflow) {
ast::controlflow,
vec[@ast::constr]) {
assert (next(st) as char == '[');
let vec[ty::arg] inputs = [];
while (peek(st) as char != ']') {
......@@ -262,15 +332,17 @@ fn parse_ty_fn(@pstate st, str_def sd) -> tup(vec[ty::arg], ty::t,
inputs += [rec(mode=mode, ty=parse_ty(st, sd))];
}
st.pos = st.pos + 1u;
auto cs = parse_constrs(st, sd);
auto res = parse_ty_or_bang(st, sd);
alt (res) {
case (a_bang) {
ret tup(inputs, ty::mk_bot(st.tcx), ast::noreturn);
ret tup(inputs, ty::mk_bot(st.tcx), ast::noreturn, cs);
}
case (a_ty(?t)) {
ret tup(inputs, t, ast::return);
ret tup(inputs, t, ast::return, cs);
}
}
}
......@@ -579,7 +651,7 @@ fn get_tag_variants(ty::ctxt tcx, ast::def_id def)
auto ctor_ty = item_type(item, external_crate_id, tcx);
let vec[ty::t] arg_tys = [];
alt (ty::struct(tcx, ctor_ty)) {
case (ty::ty_fn(_, ?args, _, _)) {
case (ty::ty_fn(_, ?args, _, _, _)) {
for (ty::arg a in args) {
arg_tys += [a.ty];
}
......
......@@ -9,7 +9,7 @@
import std::option::none;
import driver::session::session;
import util::common;
import util::common::new_str_hash;
import util::common::*;
import util::data::interner;
state type reader = state obj {
......@@ -111,32 +111,6 @@ fn err(str m) {
ret rd;
}
fn in_range(char c, char lo, char hi) -> bool {
ret lo <= c && c <= hi;
}
fn is_alpha(char c) -> bool {
ret in_range(c, 'a', 'z') ||
in_range(c, 'A', 'Z');
}
fn is_dec_digit(char c) -> bool {
ret in_range(c, '0', '9');
}
fn is_alnum(char c) -> bool {
ret is_alpha(c) || is_dec_digit(c);
}
fn is_hex_digit(char c) -> bool {
ret in_range(c, '0', '9') ||
in_range(c, 'a', 'f') ||
in_range(c, 'A', 'F');
}
fn is_bin_digit(char c) -> bool {
ret c == '0' || c == '1';
}
fn dec_digit_val(char c) -> int {
ret (c as int) - ('0' as int);
......
......@@ -345,9 +345,7 @@ fn parse_fn_input_ty(&parser p) -> ast::ty_arg {
auto inputs = parse_seq(token::LPAREN, token::RPAREN,
some(token::COMMA), parse_fn_input_ty, p);
// FIXME: dropping constrs on the floor at the moment.
// pick them up when they're used by typestate pass.
parse_constrs(p);
auto constrs = parse_constrs(p);
let @ast::ty output;
auto cf = ast::return;
......@@ -367,7 +365,7 @@ fn parse_fn_input_ty(&parser p) -> ast::ty_arg {
output = @spanned(lo, inputs.span.hi, ast::ty_nil);
}
ret ast::ty_fn(proto, inputs.node, output, cf);
ret ast::ty_fn(proto, inputs.node, output, cf, constrs.node);
}
fn parse_proto(&parser p) -> ast::proto {
......@@ -386,10 +384,11 @@ fn parse_method_sig(&parser p) -> ast::ty_method {
auto f = parse_ty_fn(proto, p, flo);
expect(p, token::SEMI);
alt (f) {
case (ast::ty_fn(?proto, ?inputs, ?output, ?cf)) {
case (ast::ty_fn(?proto, ?inputs, ?output, ?cf, ?constrs)) {
ret spanned(flo, output.span.hi,
rec(proto=proto, ident=ident,
inputs=inputs, output=output, cf=cf));
inputs=inputs, output=output, cf=cf,
constrs=constrs));
}
}
fail;
......@@ -547,7 +546,7 @@ fn parse_ty(&parser p) -> @ast::ty {
auto flo = p.get_last_lo_pos();
t = parse_ty_fn(ast::proto_fn, p, flo);
alt (t) {
case (ast::ty_fn(_, _, ?out, _)) {
case (ast::ty_fn(_, _, ?out, _, _)) {
hi = out.span.hi;
}
}
......@@ -555,7 +554,7 @@ fn parse_ty(&parser p) -> @ast::ty {
auto flo = p.get_last_lo_pos();
t = parse_ty_fn(ast::proto_iter, p, flo);
alt (t) {
case (ast::ty_fn(_, _, ?out, _)) {
case (ast::ty_fn(_, _, ?out, _, _)) {
hi = out.span.hi;
}
}
......@@ -1756,9 +1755,7 @@ fn parse_fn_decl(&parser p, ast::purity purity) -> ast::fn_decl {
let ty_or_bang res;
// FIXME: dropping constrs on the floor at the moment.
// pick them up when they're used by typestate pass.
parse_constrs(p);
auto constrs = parse_constrs(p).node;
if (p.peek() == token::RARROW) {
p.bump();
......@@ -1771,13 +1768,13 @@ fn parse_fn_decl(&parser p, ast::purity purity) -> ast::fn_decl {
alt (res) {
case (a_ty(?t)) {
ret rec(inputs=inputs.node, output=t,
purity=purity, cf=ast::return);
purity=purity, cf=ast::return, constraints=constrs);
}
case (a_bang) {
ret rec(inputs=inputs.node,
output=@spanned(p.get_lo_pos(),
p.get_hi_pos(), ast::ty_bot),
purity=purity, cf=ast::noreturn);
purity=purity, cf=ast::noreturn, constraints=constrs);
}
}
}
......@@ -1833,7 +1830,9 @@ fn parse_dtor(&parser p) -> @ast::method {
let ast::fn_decl d = rec(inputs=inputs,
output=output,
purity=ast::impure_fn,
cf=ast::return);
cf=ast::return,
// I guess dtors can't have constraints?
constraints=[]);
let ast::_fn f = rec(decl = d,
proto = ast::proto_fn,
body = b);
......
......@@ -100,7 +100,7 @@ fn check_call(&ctx cx, &@ast::expr f, &vec[@ast::expr] args, &scope sc)
-> rec(vec[def_num] root_vars, vec[ty::t] unsafe_ts) {
auto fty = ty::expr_ty(*cx.tcx, f);
auto arg_ts = alt (ty::struct(*cx.tcx, fty)) {
case (ty::ty_fn(_, ?args, _, _)) { args }
case (ty::ty_fn(_, ?args, _, _, _)) { args }
case (ty::ty_native_fn(_, ?args, _)) { args }
};
......@@ -490,7 +490,7 @@ fn helper(&ty::ctxt tcx, ty::t needle, ty::t haystack, bool mut) -> bool {
ret false;
}
// These may contain anything.
case (ty::ty_fn(_, _, _, _)) { ret true; }
case (ty::ty_fn(_, _, _, _, _)) { ret true; }
case (ty::ty_obj(_)) { ret true; }
// A type param may include everything, but can only be treated as
// opaque downstream, and is thus safe unless we saw mutable
......
......@@ -9,10 +9,13 @@
import std::option::none;
import front::ast;
import front::ast::*;
import middle::trans;
import middle::ty;
import middle::ty::path_to_str;
import back::x86;
import util::common;
import pretty::ppaux::lit_to_str;
import lib::llvm::llvm;
import lib::llvm::llvm::ValueRef;
......@@ -194,9 +197,9 @@ fn enc_sty(&io::writer w, &@ctxt cx, &ty::sty st) {
}
w.write_char(']');
}
case (ty::ty_fn(?proto,?args,?out,?cf)) {
case (ty::ty_fn(?proto,?args,?out,?cf,?constrs)) {
enc_proto(w, proto);
enc_ty_fn(w, cx, args, out, cf);
enc_ty_fn(w, cx, args, out, cf, constrs);
}
case (ty::ty_native_fn(?abi,?args,?out)) {
w.write_char('N');
......@@ -208,14 +211,15 @@ fn enc_sty(&io::writer w, &@ctxt cx, &ty::sty st) {
case (ast::native_abi_cdecl) { w.write_char('c'); }
case (ast::native_abi_llvm) { w.write_char('l'); }
}
enc_ty_fn(w, cx, args, out, ast::return);
let vec[@constr] res_constrs = [];
enc_ty_fn(w, cx, args, out, ast::return, res_constrs);
}
case (ty::ty_obj(?methods)) {
w.write_str("O[");
for (ty::method m in methods) {
enc_proto(w, m.proto);
w.write_str(m.ident);
enc_ty_fn(w, cx, m.inputs, m.output, m.cf);
enc_ty_fn(w, cx, m.inputs, m.output, m.cf, m.constrs);
}
w.write_char(']');
}
......@@ -241,7 +245,7 @@ fn enc_proto(&io::writer w, ast::proto proto) {
}
fn enc_ty_fn(&io::writer w, &@ctxt cx, &vec[ty::arg] args, &ty::t out,
&ast::controlflow cf) {
&ast::controlflow cf, &vec[@ast::constr] constrs) {
w.write_char('[');
for (ty::arg arg in args) {
if (arg.mode == ty::mo_alias) { w.write_char('&'); }
......@@ -256,6 +260,37 @@ fn enc_ty_fn(&io::writer w, &@ctxt cx, &vec[ty::arg] args, &ty::t out,
enc_ty(w, cx, out);
}
}
auto colon = true;
for (@ast::constr c in constrs) {
if (colon) { w.write_char(':'); colon = false; }
else { w.write_char(','); }
enc_constr(w, cx, c);
}
}
fn enc_constr(&io::writer w, &@ctxt cx, &@ast::constr c) {
w.write_str(path_to_str(c.node.path));
w.write_char('(');
auto comma = false;
for (@constr_arg a in c.node.args) {
if (comma) {
w.write_char(',');
}
else {
comma = true;
}
alt (a.node) {
case (carg_base) {
w.write_char('*');
}
case (carg_ident(?i)) {
w.write_str(i);
}
case (carg_lit(?l)) {
w.write_str(lit_to_str(l));
}
}
}
}
}
......
......@@ -71,6 +71,9 @@
import link::crate_meta_name;
import link::crate_meta_vers;
import link::crate_meta_extras_hash;
import pretty::ppaux::ty_to_str;
import pretty::ppaux::ty_to_short_str;
import pretty::pprust::expr_to_str;
state obj namegen(mutable int i) {
fn next(str prefix) -> str {
......@@ -677,7 +680,7 @@ fn type_of(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
if (ty::type_has_dynamic_size(cx.tcx, t)) {
cx.sess.span_err (sp,
"type_of() called on a type with dynamic size: " +
ty::ty_to_str(cx.tcx, t));
ty_to_str(cx.tcx, t));
}
ret type_of_inner(cx, sp, t);
......@@ -870,7 +873,7 @@ fn type_of_inner(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
}
llty = T_struct(tys);
}
case (ty::ty_fn(?proto, ?args, ?out, _)) {
case (ty::ty_fn(?proto, ?args, ?out, _, _)) {
llty = T_fn_pair(cx.tn, type_of_fn(cx, sp, proto, args, out, 0u));
}
case (ty::ty_native_fn(?abi, ?args, ?out)) {
......@@ -910,7 +913,7 @@ fn type_of_inner(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
assert (llty as int != 0);
if (cx.sess.get_opts().save_temps) {
llvm::LLVMAddTypeName(cx.llmod,
str::buf(ty::ty_to_short_str(cx.tcx, t)),
str::buf(ty_to_short_str(cx.tcx, t)),
llty);
}
cx.lltypes.insert(t, llty);
......@@ -941,7 +944,7 @@ fn type_of_arg(@local_ctxt cx, &span sp, &ty::arg arg) -> TypeRef {
fn type_of_ty_param_count_and_ty(@local_ctxt lcx, &span sp,
&ty::ty_param_count_and_ty tpt) -> TypeRef {
alt (ty::struct(lcx.ccx.tcx, tpt._1)) {
case (ty::ty_fn(?proto, ?inputs, ?output, _)) {
case (ty::ty_fn(?proto, ?inputs, ?output, _, _)) {
auto llfnty = type_of_fn(lcx.ccx, sp, proto,
inputs, output, tpt._0);
ret T_fn_pair(lcx.ccx.tn, llfnty);
......@@ -1243,7 +1246,7 @@ fn simplifier(@crate_ctxt ccx, ty::t typ) -> ty::t {
case (ty::ty_vec(_)) {
ret ty::mk_imm_vec(ccx.tcx, ty::mk_nil(ccx.tcx));
}
case (ty::ty_fn(_,_,_,_)) {
case (ty::ty_fn(_,_,_,_,_)) {
ret ty::mk_imm_tup(ccx.tcx,
[ty::mk_imm_box(ccx.tcx,
ty::mk_nil(ccx.tcx)),
......@@ -1841,7 +1844,7 @@ fn set_glue_inlining(&@local_ctxt cx, ValueRef f, &ty::t t) {
// Generates the declaration for (but doesn't emit) a type descriptor.
fn declare_tydesc(&@local_ctxt cx, &span sp, &ty::t t,
vec[uint] ty_params) -> @tydesc_info {
log "+++ declare_tydesc " + ty::ty_to_str(cx.ccx.tcx, t);
log "+++ declare_tydesc " + ty_to_str(cx.ccx.tcx, t);
auto ccx = cx.ccx;
auto llsize;
......@@ -1878,7 +1881,7 @@ fn declare_tydesc(&@local_ctxt cx, &span sp, &ty::t t,
mutable cmp_glue = none[ValueRef],
ty_params = ty_params);
log "--- declare_tydesc " + ty::ty_to_str(cx.ccx.tcx, t);
log "--- declare_tydesc " + ty_to_str(cx.ccx.tcx, t);
ret info;
}
......@@ -2163,7 +2166,7 @@ fn make_free_glue(&@block_ctxt cx, ValueRef v0, &ty::t t) {
rslt = trans_non_gc_free(cx_, b);
}
case (ty::ty_fn(_,_,_,_)) {
case (ty::ty_fn(_,_,_,_,_)) {
auto box_cell =
cx.build.GEP(v0,
......@@ -2239,7 +2242,7 @@ fn make_drop_glue(&@block_ctxt cx, ValueRef v0, &ty::t t) {
rslt = decr_refcnt_maybe_free(cx, box_cell, v0, t);
}
case (ty::ty_fn(_,_,_,_)) {
case (ty::ty_fn(_,_,_,_,_)) {
auto box_cell =
cx.build.GEP(v0,
......@@ -2465,7 +2468,7 @@ fn inner(@block_ctxt last_cx,
// FIXME: compare obj, fn by pointer?
trans_fail(cx, none[common::span],
"attempt to compare values of type " +
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, t));
ty_to_str(cx.fcx.lcx.ccx.tcx, t));
}
}
......@@ -2726,7 +2729,7 @@ fn iter_boxpp(@block_ctxt cx,
// N-ary variant.
auto fn_ty = variant.ctor_ty;
alt (ty::struct(bcx.fcx.lcx.ccx.tcx, fn_ty)) {
case (ty::ty_fn(_, ?args, _, _)) {
case (ty::ty_fn(_, ?args, _, _, _)) {
auto j = 0;
for (ty::arg a in args) {
auto v = [C_int(0), C_int(j as int)];
......@@ -2773,7 +2776,7 @@ fn iter_boxpp(@block_ctxt cx,
ret res(next_cx, C_nil());
}
case (ty::ty_fn(_,_,_,_)) {
case (ty::ty_fn(_,_,_,_,_)) {
auto box_cell_a =
cx.build.GEP(av,
[C_int(0),
......@@ -2930,7 +2933,7 @@ fn iter_sequence_body(@block_ctxt cx,
cx.fcx.lcx.ccx.sess.bug("unexpected type in " +
"trans::iter_sequence: " +
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, t));
ty_to_str(cx.fcx.lcx.ccx.tcx, t));
}
}
}
......@@ -2961,7 +2964,7 @@ fn lazily_emit_tydesc_glue(&@block_ctxt cx, int field,
case (some(_)) {}
case (none) {
log #fmt("+++ lazily_emit_tydesc_glue TAKE %s",
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
auto lcx = cx.fcx.lcx;
auto glue_fn =
......@@ -2974,7 +2977,7 @@ fn lazily_emit_tydesc_glue(&@block_ctxt cx, int field,
mgghf_single(tg), ti.ty_params);
log #fmt("--- lazily_emit_tydesc_glue TAKE %s",
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
}
}
} else if (field == abi::tydesc_field_drop_glue) {
......@@ -2982,7 +2985,7 @@ fn lazily_emit_tydesc_glue(&@block_ctxt cx, int field,
case (some(_)) { }
case (none) {
log #fmt("+++ lazily_emit_tydesc_glue DROP %s",
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
auto lcx = cx.fcx.lcx;
auto glue_fn =
declare_generic_glue(lcx, ti.ty,
......@@ -2993,7 +2996,7 @@ fn lazily_emit_tydesc_glue(&@block_ctxt cx, int field,
make_generic_glue(lcx, cx.sp, ti.ty, glue_fn,
mgghf_single(dg), ti.ty_params);
log #fmt("--- lazily_emit_tydesc_glue DROP %s",
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
}
}
......@@ -3002,7 +3005,7 @@ fn lazily_emit_tydesc_glue(&@block_ctxt cx, int field,
case (some(_)) { }
case (none) {
log #fmt("+++ lazily_emit_tydesc_glue FREE %s",
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
auto lcx = cx.fcx.lcx;
auto glue_fn =
declare_generic_glue(lcx, ti.ty,
......@@ -3014,7 +3017,7 @@ fn lazily_emit_tydesc_glue(&@block_ctxt cx, int field,
make_generic_glue(lcx, cx.sp, ti.ty, glue_fn,
mgghf_single(dg), ti.ty_params);
log #fmt("--- lazily_emit_tydesc_glue FREE %s",
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
}
}
......@@ -3023,7 +3026,7 @@ fn lazily_emit_tydesc_glue(&@block_ctxt cx, int field,
case (some(_)) { }
case (none) {
log #fmt("+++ lazily_emit_tydesc_glue CMP %s",
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
auto lcx = cx.fcx.lcx;
auto glue_fn =
declare_generic_glue(lcx, ti.ty,
......@@ -3033,7 +3036,7 @@ fn lazily_emit_tydesc_glue(&@block_ctxt cx, int field,
make_generic_glue(lcx, cx.sp, ti.ty, glue_fn,
mgghf_cmp, ti.ty_params);
log #fmt("--- lazily_emit_tydesc_glue CMP %s",
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
}
}
}
......@@ -3274,7 +3277,7 @@ fn copy_val(&@block_ctxt cx,
}
cx.fcx.lcx.ccx.sess.bug("unexpected type in trans::copy_val: " +
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, t));
ty_to_str(cx.fcx.lcx.ccx.tcx, t));
}
// This works like copy_val, except that it deinitializes the source.
......@@ -3311,7 +3314,7 @@ fn move_val(&@block_ctxt cx,
}
cx.fcx.lcx.ccx.sess.bug("unexpected type in trans::move_val: " +
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, t));
ty_to_str(cx.fcx.lcx.ccx.tcx, t));
}
......@@ -4499,7 +4502,7 @@ fn trans_path(&@block_ctxt cx, &ast::path p, &ast::ann ann) -> lval_result {
case (ast::def_variant(?tid, ?vid)) {
auto v_tyt = ty::lookup_item_type(cx.fcx.lcx.ccx.tcx, vid);
alt (ty::struct(cx.fcx.lcx.ccx.tcx, v_tyt._1)) {
case (ty::ty_fn(_, _, _, _)) {
case (ty::ty_fn(_, _, _, _, _)) {
// N-ary variant.
ret lval_generic_fn(cx, v_tyt, vid, ann);
}
......@@ -4691,7 +4694,7 @@ fn trans_lval(&@block_ctxt cx, &@ast::expr e) -> lval_result {
case (_) {
cx.fcx.lcx.ccx.sess.span_unimpl(e.span,
"expr variant in trans_lval: "
+ pretty::pprust::expr_to_str(e));
+ expr_to_str(e));
}
}
}
......@@ -5850,7 +5853,7 @@ fn trans_log(int lvl, &@block_ctxt cx, &@ast::expr e) -> result {
// FIXME: Support these types.
cx.fcx.lcx.ccx.sess.span_err(e.span,
"log called on unsupported type " +
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, e_ty));
ty_to_str(cx.fcx.lcx.ccx.tcx, e_ty));
}
}
}
......@@ -5864,7 +5867,7 @@ fn trans_log(int lvl, &@block_ctxt cx, &@ast::expr e) -> result {
fn trans_check_expr(&@block_ctxt cx, &@ast::expr e) -> result {
auto cond_res = trans_expr(cx, e);
auto expr_str = pretty::pprust::expr_to_str(e);
auto expr_str = expr_to_str(e);
auto fail_cx = new_sub_block_ctxt(cx, "fail");
auto fail_res = trans_fail(fail_cx, some[common::span](e.span), expr_str);
......@@ -6085,9 +6088,9 @@ fn trans_spawn(&@block_ctxt cx,
// Make the task name
auto tname = alt(name) {
case(none) {
auto argss = vec::map(pretty::pprust::expr_to_str, args);
auto argss = vec::map(expr_to_str, args);
#fmt("%s(%s)",
pretty::pprust::expr_to_str(func),
expr_to_str(func),
str::connect(argss, ", "))
}
case(some(?n)) {
......@@ -6865,7 +6868,7 @@ fn is_terminated(&@block_ctxt cx) -> bool {
fn arg_tys_of_fn(&@crate_ctxt ccx, ast::ann ann) -> vec[ty::arg] {
alt (ty::struct(ccx.tcx, ty::ann_to_type(ccx.tcx, ann))) {
case (ty::ty_fn(_, ?arg_tys, _, _)) {
case (ty::ty_fn(_, ?arg_tys, _, _, _)) {
ret arg_tys;
}
}
......@@ -6873,7 +6876,7 @@ fn arg_tys_of_fn(&@crate_ctxt ccx, ast::ann ann) -> vec[ty::arg] {
fn ret_ty_of_fn_ty(&@crate_ctxt ccx, ty::t t) -> ty::t {
alt (ty::struct(ccx.tcx, t)) {
case (ty::ty_fn(_, _, ?ret_ty, _)) {
case (ty::ty_fn(_, _, ?ret_ty, _, _)) {
ret ret_ty;
}
}
......@@ -7043,7 +7046,7 @@ fn meth_lteq(&@ast::method a, &@ast::method b) -> bool {
auto llfnty = T_nil();
alt (ty::struct(cx.ccx.tcx, node_ann_type(cx.ccx, m.node.ann))) {
case (ty::ty_fn(?proto, ?inputs, ?output, _)) {
case (ty::ty_fn(?proto, ?inputs, ?output, _, _)) {
llfnty = type_of_fn_full(cx.ccx, m.span, proto,
some[TypeRef](llself_ty),
inputs, output,
......@@ -7466,7 +7469,7 @@ fn decl_fn_and_pair(&@crate_ctxt ccx, &span sp,
auto llfty;
auto llpairty;
alt (ty::struct(ccx.tcx, node_ann_type(ccx, ann))) {
case (ty::ty_fn(?proto, ?inputs, ?output, _)) {
case (ty::ty_fn(?proto, ?inputs, ?output, _, _)) {
llfty = type_of_fn(ccx, sp, proto, inputs, output,
vec::len[ast::ty_param](ty_params));
llpairty = T_fn_pair(ccx.tn, llfty);
......
......@@ -8,6 +8,7 @@
import std::option::some;
import std::option::maybe;
import front::ast;
import front::ast::*;
import middle::ty::expr_ann;
......@@ -22,7 +23,6 @@
import util::common::uistr;
import util::common::lit_eq;
import pretty::pprust::path_to_str;
import pretty::pprust::lit_to_str;
import tstate::ann::pre_and_post;
import tstate::ann::pre_and_post_state;
......@@ -42,6 +42,8 @@
import tstate::ann::ts_ann;
import util::common::istr;
import pretty::ppaux::constr_args_to_str;
import pretty::ppaux::lit_to_str;
/* logging funs */
......@@ -214,7 +216,7 @@ fn print_idents(vec[ident] idents) -> () {
type pred_desc = spanned[pred_desc_];
tag constraint {
cinit(uint, span, ident);
cpred(path, vec[pred_desc]);
cpred(path, @vec[pred_desc]);
}
tag constr_ {
ninit(ident);
......@@ -484,7 +486,7 @@ fn controlflow_def_id(&crate_ctxt ccx, &def_id d) -> controlflow {
fn controlflow_expr(&crate_ctxt ccx, @expr e) -> controlflow {
alt (ty::struct(ccx.tcx, ty::ann_to_type(ccx.tcx,
expr_ann(e)))) {
case (ty::ty_fn(_,_,_,?cf)) {
case (ty::ty_fn(_,_,_,?cf,_)) {
ret cf;
}
case (_) {
......@@ -493,6 +495,17 @@ fn controlflow_expr(&crate_ctxt ccx, @expr e) -> controlflow {
}
}
fn constraints_expr(&crate_ctxt ccx, @expr e) -> vec[@ast::constr] {
alt (ty::struct(ccx.tcx, ty::ann_to_type(ccx.tcx, expr_ann(e)))) {
case (ty::ty_fn(_,_,_,_,?cs)) {
ret cs;
}
case (_) {
ret [];
}
}
}
fn ann_to_def_strict(&crate_ctxt ccx, &ann a) -> def {
alt (ccx.tcx.def_map.find(a.id)) {
case (none) {
......@@ -514,7 +527,7 @@ fn norm_a_constraint(&constraint c) -> vec[norm_constraint] {
}
case (cpred(?p, ?descs)) {
let vec[norm_constraint] res = [];
for (pred_desc pd in descs) {
for (pred_desc pd in *descs) {
vec::push(res, rec(bit_num=pd.node.bit_num,
c=respan(pd.span, npred(p, pd.node.args))));
}
......@@ -534,60 +547,146 @@ fn constraints(&fn_ctxt fcx) -> vec[norm_constraint] {
ret res;
}
fn arg_eq(@constr_arg a, @constr_arg b) -> bool {
alt (a.node) {
case (carg_base) {
alt (b.node) {
case (carg_base) {
ret true;
}
case (_) {
ret false;
}
}
// 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] occ) -> uint {
log ("match_args: looking at " + constr_args_to_str(occ));
for (pred_desc pd in *occs) {
log ("match_args: candidate " + pred_desc_to_str(pd));
if (ty::args_eq(pd.node.args, occ)) {
ret pd.node.bit_num;
}
}
fcx.ccx.tcx.sess.bug("match_args: no match for occurring args");
}
type constraint_info = rec(def_id id, constr c);
fn constr_to_constr_occ(&ty::ctxt tcx, &constr_ c) -> constr_occ {
alt (c) {
case (ninit(_)) { ret occ_init; }
case (npred(_, ?args)) { ret occ_args(args); }
}
}
fn def_id_for_constr(ty::ctxt tcx, uint t) -> def_id {
alt (tcx.def_map.find(t)) {
case (none) {
tcx.sess.bug("def_id_for_constr: bad node_id " + uistr(t));
}
case (some(def_fn(?i))) {
ret i;
}
case (_) {
tcx.sess.bug("def_id_for_constr: pred is not a function");
}
case (carg_ident(?s)) {
alt (b.node) {
case (carg_ident(?t)) {
ret (s == t);
}
}
fn exprs_to_constr_args(ty::ctxt tcx, vec[@expr] args) -> vec[@constr_arg] {
fn one(ty::ctxt tcx, &@expr e) -> @constr_arg {
alt (e.node) {
case (expr_path(?p, _)) {
if (vec::len(p.node.idents) == 1u) {
ret @respan(p.span, carg_ident(p.node.idents.(0)));
}
case (_) {
ret false;
else {
tcx.sess.bug("exprs_to_constr_args: non-local variable "
+ "as pred arg");
}
}
case (expr_lit(?l, _)) {
ret @respan(e.span, carg_lit(l));
}
case (_) {
tcx.sess.bug("exprs_to_constr_args: ill-formed pred arg");
}
}
case (carg_lit(?l)) {
alt (b.node) {
case (carg_lit(?m)) {
ret lit_eq(l, m);
}
auto f = bind one(tcx, _);
ret vec::map(f, args);
}
fn expr_to_constr(ty::ctxt tcx, &@expr e) -> constraint_info {
alt (e.node) {
// FIXME
// change the first pattern to expr_path to test a typechecker bug
case (expr_call(?operator, ?args, _)) {
alt (operator.node) {
case (expr_path(?p, ?a)) {
ret rec(id=def_id_for_constr(tcx, a.id),
c=respan(e.span,
npred(p, exprs_to_constr_args(tcx, args))));
}
case (_) {
ret false;
tcx.sess.span_err(operator.span, "Internal error: " +
" ill-formed operator in predicate");
}
}
}
case (_) {
tcx.sess.span_err(e.span, "Internal error: " +
" ill-formed predicate");
}
}
}
fn pred_desc_to_str(&pred_desc p) -> str {
ret ("<" + uistr(p.node.bit_num) + ", " +
constr_args_to_str(p.node.args) + ">");
}
fn substitute_constr_args(&ty::ctxt cx,
&vec[@expr] actuals,
&vec[arg] formals, &@ast::constr c) -> constr_occ {
let vec[@constr_arg] res = [];
auto subst = vec::zip(formals, actuals);
for (@constr_arg a in c.node.args) {
res += [substitute_arg(cx, subst, a)];
}
ret occ_args(res);
}
fn args_eq(vec[@constr_arg] a, vec[@constr_arg] b) -> bool {
let uint i = 0u;
for (@constr_arg arg in a) {
if (!arg_eq(arg, b.(i))) {
ret false;
type subst = vec[tup(arg, @expr)];
fn substitute_arg(&ty::ctxt cx, &subst subst, @ast::constr_arg a)
-> @constr_arg {
alt (a.node) {
case (carg_ident(?i)) {
ret find_arg(a.span, cx, i, subst);
}
i += 1u;
case (_) { ret a; }
}
ret true;
}
fn match_args(&fn_ctxt fcx, vec[pred_desc] occs,
vec[@constr_arg] occ) -> uint {
for (pred_desc pd in occs) {
if (args_eq(pd.node.args, occ)) {
ret pd.node.bit_num;
fn find_arg(&span sp, ty::ctxt cx, ident i, subst subst) -> @constr_arg {
for (tup(arg, @expr) p in subst) {
if (p._0.ident == i) {
alt (p._1.node) {
case (expr_path(?pt, _)) {
// ??? maybe should check that pt is a local?
let option::t[ident] thing = vec::last(pt.node.idents);
assert (! option::is_none(thing));
ret @respan(p._1.span, carg_ident(option::get(thing)));
}
case (expr_lit(?l, _)) {
ret @respan(p._1.span, carg_lit(l));
}
case (_) {
cx.sess.span_err(p._1.span,
"Unsupported form of argument " +
"in a call to a constrained function");
}
}
}
}
fcx.ccx.tcx.sess.bug("match_args: no match for occurring args");
cx.sess.span_err(sp, "Constraint contains an unbound variable " + i);
}
//
......
......@@ -17,6 +17,8 @@
import aux::crate_ctxt;
import aux::num_constraints;
import aux::constr_map;
import aux::constraint_info;
import aux::expr_to_constr;
import util::common::new_def_hash;
import util::common::uistr;
......@@ -26,8 +28,6 @@
type ctxt = rec(@vec[constraint_info] cs,
ty::ctxt tcx);
type constraint_info = rec(def_id id, aux::constr c);
fn collect_local(&ctxt cx, &@decl d) -> () {
alt (d.node) {
case (decl_local(?loc)) {
......@@ -41,67 +41,6 @@ fn collect_local(&ctxt cx, &@decl d) -> () {
}
}
fn exprs_to_constr_args(ty::ctxt tcx, vec[@expr] args) -> vec[@constr_arg] {
fn one(ty::ctxt tcx, &@expr e) -> @constr_arg {
alt (e.node) {
case (expr_path(?p, _)) {
if (vec::len(p.node.idents) == 1u) {
ret @respan(p.span, carg_ident(p.node.idents.(0)));
}
else {
tcx.sess.bug("exprs_to_constr_args: non-local variable "
+ "as pred arg");
}
}
case (expr_lit(?l, _)) {
ret @respan(e.span, carg_lit(l));
}
case (_) {
tcx.sess.bug("exprs_to_constr_args: ill-formed pred arg");
}
}
}
auto f = bind one(tcx, _);
ret vec::map(f, args);
}
fn def_id_for_constr(ty::ctxt tcx, uint t) -> def_id {
alt (tcx.def_map.find(t)) {
case (none) {
tcx.sess.bug("def_id_for_constr: bad node_id " + uistr(t));
}
case (some(def_fn(?i))) {
ret i;
}
case (_) {
tcx.sess.bug("def_id_for_constr: pred is not a function");
}
}
}
fn expr_to_constr(ty::ctxt tcx, &@expr e) -> constraint_info {
alt (e.node) {
// change the first pattern to expr_path to test a typechecker bug
case (expr_call(?operator, ?args, _)) {
alt (operator.node) {
case (expr_path(?p, ?a)) {
ret rec(id=def_id_for_constr(tcx, a.id),
c=respan(e.span,
npred(p, exprs_to_constr_args(tcx, args))));
}
case (_) {
tcx.sess.span_err(operator.span, "Internal error: " +
" ill-formed operator in predicate");
}
}
}
case (_) {
tcx.sess.span_err(e.span, "Internal error: " +
" ill-formed predicate");
}
}
}
fn collect_pred(&ctxt cx, &@expr e) -> () {
alt (e.node) {
case (expr_check(?e, _)) {
......@@ -140,14 +79,14 @@ fn add_constraint(&ty::ctxt tcx, constraint_info c, uint next, constr_map tbl)
+ " as a variable and a pred");
}
case (cpred(_, ?pds)) {
vec::push(pds, respan(cn.span,
vec::push(*pds, respan(cn.span,
rec(args=args, bit_num=next)));
}
}
}
case (none[constraint]) {
tbl.insert(c.id, cpred(p,
[respan(cn.span, rec(args=args, bit_num=next))]));
tbl.insert(c.id, cpred(p,
@[respan(cn.span, rec(args=args, bit_num=next))]));
}
}
}
......
......@@ -50,7 +50,8 @@
ast::ident ident,
vec[arg] inputs,
t output,
controlflow cf);
controlflow cf,
vec[@ast::constr] constrs);
tag any_item {
any_item_rust(@ast::item);
......@@ -77,7 +78,7 @@
// Convert from method type to function type. Pretty easy; we just drop
// 'ident'.
fn method_ty_to_fn_ty(&ctxt cx, method m) -> t {
ret mk_fn(cx, m.proto, m.inputs, m.output, m.cf);
ret mk_fn(cx, m.proto, m.inputs, m.output, m.cf, m.constrs);
}
// Never construct these manually. These are interned.
......@@ -113,7 +114,7 @@ fn method_ty_to_fn_ty(&ctxt cx, method m) -> t {
ty_task;
ty_tup(vec[mt]);
ty_rec(vec[field]);
ty_fn(ast::proto, vec[arg], t, controlflow);
ty_fn(ast::proto, vec[arg], t, controlflow, vec[@ast::constr]);
ty_native_fn(ast::native_abi, vec[arg], t);
ty_obj(vec[method]);
ty_var(int); // type variable
......@@ -324,7 +325,7 @@ fn derive_flags_sig(&ctxt cx,
}
}
case (ty_fn(_, ?args, ?tt, _)) {
case (ty_fn(_, ?args, ?tt, _, _)) {
derive_flags_sig(cx, has_params, has_vars, args, tt);
}
......@@ -428,8 +429,8 @@ 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) -> t {
ret gen_ty(cx, ty_fn(proto, args, ty, cf));
&controlflow cf, &vec[@ast::constr] constrs) -> t {
ret gen_ty(cx, ty_fn(proto, args, ty, cf, constrs));
}
fn mk_native_fn(&ctxt cx, &ast::native_abi abi, &vec[arg] args, &t ty) -> t {
......@@ -478,161 +479,6 @@ fn f(&@ast::ty t) -> str {
ret result;
}
fn ty_to_str(&ctxt cx, &t typ) -> str {
fn fn_input_to_str(&ctxt cx, &rec(mode mode, t ty) input) -> str {
auto s;
alt (input.mode) {
case (mo_val) { s = ""; }
case (mo_alias) { s = "&"; }
}
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) -> str {
auto f = bind fn_input_to_str(cx, _);
auto s;
alt (proto) {
case (ast::proto_iter) {
s = "iter";
}
case (ast::proto_fn) {
s = "fn";
}
}
alt (ident) {
case (some(?i)) {
s += " ";
s += i;
}
case (_) { }
}
s += "(";
s += str::connect(vec::map[arg,str](f, inputs), ", ");
s += ")";
if (struct(cx, output) != ty_nil) {
s += " -> " + ty_to_str(cx, output);
}
ret s;
}
fn method_to_str(&ctxt cx, &method m) -> str {
ret fn_to_str(cx, m.proto, some[ast::ident](m.ident),
m.inputs, m.output) + ";";
}
fn field_to_str(&ctxt cx, &field f) -> str {
ret mt_to_str(cx, f.mt) + " " + f.ident;
}
fn mt_to_str(&ctxt cx, &mt m) -> str {
auto mstr;
alt (m.mut) {
case (ast::mut) { mstr = "mutable "; }
case (ast::imm) { mstr = ""; }
case (ast::maybe_mut) { mstr = "mutable? "; }
}
ret mstr + ty_to_str(cx, m.ty);
}
alt (cname(cx, typ)) {
case (some(?cs)) { ret cs; }
case (_) { /* fall through */ }
}
auto s = "";
alt (struct(cx, typ)) {
case (ty_native) { s += "native"; }
case (ty_nil) { s += "()"; }
case (ty_bot) { s += "_|_"; }
case (ty_bool) { s += "bool"; }
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_char) { s += "char"; }
case (ty_str) { s += "str"; }
case (ty_box(?tm)) { s += "@" + mt_to_str(cx, tm); }
case (ty_ptr(?tm)) { s += "*" + mt_to_str(cx, tm); }
case (ty_vec(?tm)) { s += "vec[" + mt_to_str(cx, tm) + "]"; }
case (ty_port(?t)) { s += "port[" + ty_to_str(cx, t) + "]"; }
case (ty_chan(?t)) { s += "chan[" + ty_to_str(cx, t) + "]"; }
case (ty_type) { s += "type"; }
case (ty_task) { s += "task"; }
case (ty_tup(?elems)) {
auto f = bind mt_to_str(cx, _);
auto strs = vec::map[mt,str](f, elems);
s += "tup(" + str::connect(strs, ",") + ")";
}
case (ty_rec(?elems)) {
auto f = bind field_to_str(cx, _);
auto strs = vec::map[field,str](f, elems);
s += "rec(" + str::connect(strs, ",") + ")";
}
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) + ">";
if (vec::len[t](tps) > 0u) {
auto f = bind ty_to_str(cx, _);
auto strs = vec::map[t,str](f, tps);
s += "[" + str::connect(strs, ",") + "]";
}
}
case (ty_fn(?proto, ?inputs, ?output, _)) {
s += fn_to_str(cx, proto, none[ast::ident], inputs, output);
}
case (ty_native_fn(_, ?inputs, ?output)) {
s += fn_to_str(cx, ast::proto_fn, none[ast::ident],
inputs, output);
}
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_param(?id)) {
s += "'" + str::unsafe_from_bytes([('a' as u8) + (id as u8)]);
}
case (_) {
s += ty_to_short_str(cx, typ);
}
}
ret s;
}
fn ty_to_short_str(&ctxt cx, t typ) -> str {
auto f = def_to_str;
auto ecx = @rec(ds=f, tcx=cx, abbrevs=metadata::ac_no_abbrevs);
auto s = metadata::Encode::ty_str(ecx, typ);
if (str::byte_len(s) >= 32u) { s = str::substr(s, 0u, 32u); }
ret s;
}
// Type folds
type ty_walk = fn(t);
......@@ -669,7 +515,7 @@ fn walk_ty(&ctxt cx, ty_walk walker, t ty) {
walk_ty(cx, walker, fl.mt.ty);
}
}
case (ty_fn(?proto, ?args, ?ret_ty, _)) {
case (ty_fn(?proto, ?args, ?ret_ty, _, _)) {
for (arg a in args) {
walk_ty(cx, walker, a.ty);
}
......@@ -768,14 +614,14 @@ fn fold_ty(&ctxt cx, fold_mode fld, t ty_0) -> t {
}
ty = copy_cname(cx, mk_rec(cx, new_fields), ty);
}
case (ty_fn(?proto, ?args, ?ret_ty, ?cf)) {
case (ty_fn(?proto, ?args, ?ret_ty, ?cf, ?constrs)) {
let vec[arg] new_args = [];
for (arg a in args) {
auto new_ty = fold_ty(cx, fld, a.ty);
new_args += [rec(mode=a.mode, ty=new_ty)];
}
ty = copy_cname(cx, mk_fn(cx, proto, new_args,
fold_ty(cx, fld, ret_ty), cf), ty);
fold_ty(cx, fld, ret_ty), cf, constrs), ty);
}
case (ty_native_fn(?abi, ?args, ?ret_ty)) {
let vec[arg] new_args = [];
......@@ -796,7 +642,8 @@ fn fold_ty(&ctxt cx, fold_mode fld, t ty_0) -> t {
}
new_methods += [rec(proto=m.proto, ident=m.ident,
inputs=new_args,
output=fold_ty(cx, fld, m.output), cf=m.cf)];
output=fold_ty(cx, fld, m.output),
cf=m.cf, constrs=m.constrs)];
}
ty = copy_cname(cx, mk_obj(cx, new_methods), ty);
}
......@@ -860,7 +707,7 @@ fn type_is_structural(&ctxt cx, &t ty) -> bool {
case (ty_tup(_)) { ret true; }
case (ty_rec(_)) { ret true; }
case (ty_tag(_,_)) { ret true; }
case (ty_fn(_,_,_,_)) { ret true; }
case (ty_fn(_,_,_,_,_)) { ret true; }
case (ty_obj(_)) { ret true; }
case (_) { ret false; }
}
......@@ -1177,7 +1024,8 @@ fn hash_fn(uint id, &vec[arg] args, &t rty) -> uint {
}
ret h;
}
case (ty_fn(_, ?args, ?rty, _)) { ret hash_fn(25u, args, rty); }
// ???
case (ty_fn(_, ?args, ?rty, _, _)) { ret hash_fn(25u, args, rty); }
case (ty_native_fn(_, ?args, ?rty)) { ret hash_fn(26u, args, rty); }
case (ty_obj(?methods)) {
auto h = 27u;
......@@ -1211,6 +1059,72 @@ fn hash_type_info(&sty st, &option::t[str] cname_opt) -> uint {
// Type equality. This function is private to this module (and slow); external
// users should use `eq_ty()` instead.
fn arg_eq(@ast::constr_arg a, @ast::constr_arg b) -> bool {
alt (a.node) {
case (ast::carg_base) {
alt (b.node) {
case (ast::carg_base) {
ret true;
}
case (_) {
ret false;
}
}
}
case (ast::carg_ident(?s)) {
alt (b.node) {
case (ast::carg_ident(?t)) {
ret (s == t);
}
case (_) {
ret false;
}
}
}
case (ast::carg_lit(?l)) {
alt (b.node) {
case (ast::carg_lit(?m)) {
ret util::common::lit_eq(l, m);
}
case (_) {
ret false;
}
}
}
}
}
fn args_eq(vec[@ast::constr_arg] a, vec[@ast::constr_arg] b) -> bool {
let uint i = 0u;
for (@ast::constr_arg arg in a) {
if (!arg_eq(arg, b.(i))) {
ret false;
}
i += 1u;
}
ret true;
}
fn constr_eq(&@ast::constr c, &@ast::constr d) -> bool {
ret path_to_str(c.node.path) == path_to_str(d.node.path) // FIXME: hack
&& args_eq(c.node.args, d.node.args);
}
fn constrs_eq(&vec[@ast::constr] cs, &vec[@ast::constr] ds) -> bool {
if (vec::len(cs) != vec::len(ds)) {
ret false;
}
auto i = 0;
for (@ast::constr c in cs) {
if (!constr_eq(c, ds.(i))) {
ret false;
}
i += 1;
}
ret true;
}
fn equal_type_structures(&sty a, &sty b) -> bool {
fn equal_mt(&mt a, &mt b) -> bool {
ret a.mut == b.mut && eq_ty(a.ty, b.ty);
......@@ -1381,11 +1295,12 @@ fn equal_def(&ast::def_id did_a, &ast::def_id did_b) -> bool {
case (_) { ret false; }
}
}
case (ty_fn(?p_a, ?args_a, ?rty_a, ?cf_a)) {
case (ty_fn(?p_a, ?args_a, ?rty_a, ?cf_a, ?constrs_a)) {
alt (b) {
case (ty_fn(?p_b, ?args_b, ?rty_b, ?cf_b)) {
case (ty_fn(?p_b, ?args_b, ?rty_b, ?cf_b, ?constrs_b)) {
ret p_a == p_b &&
cf_a == cf_b &&
constrs_eq(constrs_a, constrs_b) &&
equal_fn(args_a, rty_a, args_b, rty_b);
}
case (_) { ret false; }
......@@ -1576,7 +1491,7 @@ fn type_contains_params(&ctxt cx, &t typ) -> bool {
fn ty_fn_args(&ctxt cx, &t fty) -> vec[arg] {
alt (struct(cx, fty)) {
case (ty::ty_fn(_, ?a, _, _)) { ret a; }
case (ty::ty_fn(_, ?a, _, _, _)) { ret a; }
case (ty::ty_native_fn(_, ?a, _)) { ret a; }
}
cx.sess.bug("ty_fn_args() called on non-fn type");
......@@ -1584,7 +1499,7 @@ fn ty_fn_args(&ctxt cx, &t fty) -> vec[arg] {
fn ty_fn_proto(&ctxt cx, &t fty) -> ast::proto {
alt (struct(cx, fty)) {
case (ty::ty_fn(?p, _, _, _)) { ret p; }
case (ty::ty_fn(?p, _, _, _, _)) { ret p; }
}
cx.sess.bug("ty_fn_proto() called on non-fn type");
}
......@@ -1598,7 +1513,7 @@ fn ty_fn_abi(&ctxt cx, &t fty) -> ast::native_abi {
fn ty_fn_ret(&ctxt cx, &t fty) -> t {
alt (struct(cx, fty)) {
case (ty::ty_fn(_, _, ?r, _)) { ret r; }
case (ty::ty_fn(_, _, ?r, _, _)) { ret r; }
case (ty::ty_native_fn(_, _, ?r)) { ret r; }
}
cx.sess.bug("ty_fn_ret() called on non-fn type");
......@@ -1606,7 +1521,7 @@ fn ty_fn_ret(&ctxt cx, &t fty) -> t {
fn is_fn_ty(&ctxt cx, &t fty) -> bool {
alt (struct(cx, fty)) {
case (ty::ty_fn(_, _, _, _)) { ret true; }
case (ty::ty_fn(_, _, _, _, _)) { ret true; }
case (ty::ty_native_fn(_, _, _)) { ret true; }
case (_) { ret false; }
}
......@@ -2012,7 +1927,9 @@ fn unify_fn(&@ctxt cx,
&t actual,
&vec[arg] expected_inputs, &t expected_output,
&vec[arg] actual_inputs, &t actual_output,
&controlflow expected_cf, &controlflow actual_cf)
&controlflow expected_cf, &controlflow actual_cf,
&vec[@ast::constr] expected_constrs,
&vec[@ast::constr] actual_constrs)
-> result {
if (e_proto != a_proto) {
......@@ -2045,7 +1962,7 @@ fn unify_fn(&@ctxt cx,
}
case (fn_common_res_ok(?result_ins, ?result_out)) {
auto t2 = mk_fn(cx.tcx, e_proto, result_ins, result_out,
actual_cf);
actual_cf, actual_constrs);
ret ures_ok(t2);
}
}
......@@ -2099,14 +2016,16 @@ fn unify_obj(&@ctxt cx,
expected, actual,
e_meth.inputs, e_meth.output,
a_meth.inputs, a_meth.output,
e_meth.cf, a_meth.cf);
e_meth.cf, a_meth.cf,
e_meth.constrs, a_meth.constrs);
alt (r) {
case (ures_ok(?tfn)) {
alt (struct(cx.tcx, tfn)) {
case (ty_fn(?proto, ?ins, ?out, ?cf)) {
case (ty_fn(?proto, ?ins, ?out, ?cf, ?constrs)) {
result_meths += [rec(inputs = ins,
output = out,
cf = cf
cf = cf,
constrs = constrs
with e_meth)];
}
}
......@@ -2486,15 +2405,18 @@ fn unify_step(&@ctxt cx, &t expected, &t actual) -> result {
}
case (ty::ty_fn(?ep, ?expected_inputs,
?expected_output, ?expected_cf)) {
?expected_output, ?expected_cf,
?expected_constrs)) {
alt (struct(cx.tcx, actual)) {
case (ty::ty_fn(?ap, ?actual_inputs,
?actual_output, ?actual_cf)) {
?actual_output, ?actual_cf,
?actual_constrs)) {
ret unify_fn(cx, ep, ap,
expected, actual,
expected_inputs, expected_output,
actual_inputs, actual_output,
expected_cf, actual_cf);
expected_cf, actual_cf,
expected_constrs, actual_constrs);
}
case (_) { ret ures_err(terr_mismatch); }
......@@ -2549,7 +2471,7 @@ fn dump_var_bindings(ty_ctxt tcx, @var_bindings vb) {
alt (smallintmap::find[t](vb.types, i)) {
case (none[t]) { typespec = ""; }
case (some[t](?typ)) {
typespec = " =" + ty_to_str(tcx, typ);
typespec = " =" + pretty::ppaux::ty_to_str(tcx, typ);
}
}
......@@ -2784,7 +2706,7 @@ fn lookup_item_type(ctxt cx, ast::def_id did) -> ty_param_count_and_ty {
fn ret_ty_of_fn_ty(ctxt cx, t a_ty) -> t {
alt (ty::struct(cx, a_ty)) {
case (ty::ty_fn(_, _, ?ret_ty, _)) {
case (ty::ty_fn(_, _, ?ret_ty, _, _)) {
ret ret_ty;
}
case (_) {
......@@ -2797,6 +2719,27 @@ fn ret_ty_of_fn(ctxt cx, ast::ann ann) -> t {
ret ret_ty_of_fn_ty(cx, ann_to_type(cx, ann));
}
fn lookup_fn_decl(ty_ctxt tcx, ast::ann ann)
-> option::t[tup(ast::fn_decl, ast::def_id)] {
auto nada = none[tup(ast::fn_decl, ast::def_id)];
alt (tcx.def_map.find(ann.id)) {
case (some(ast::def_fn(?d))) {
alt (tcx.items.find(d)) {
case (some(any_item_rust(?it))) {
alt (it.node) {
case (ast::item_fn(_,?f,_,_,_)) {
ret some(tup(f.decl, d));
}
case (_) { ret nada; }
}
}
case (_) { ret nada; }
}
}
case (_) { ret nada; }
}
}
// Local Variables:
// mode: rust
// fill-column: 78;
......
......@@ -22,7 +22,7 @@
import middle::ty::pat_ty;
import middle::ty::path_to_str;
import middle::ty::ty_param_substs_opt_and_ty;
import middle::ty::ty_to_str;
import pretty::ppaux::ty_to_str;
import middle::ty::ty_param_count_and_ty;
import middle::ty::ty_nil;
import middle::ty::unify::ures_ok;
......@@ -45,6 +45,8 @@
import middle::tstate::ann::ts_ann;
import pretty::ppaux::ty_to_str;
type ty_table = hashmap[ast::def_id, ty::t];
type fn_purity_table = hashmap[ast::def_id, ast::purity];
......@@ -305,11 +307,11 @@ fn instantiate(&ty::ctxt tcx,
typ = ty::mk_rec(tcx, flds);
}
case (ast::ty_fn(?proto, ?inputs, ?output, ?cf)) {
case (ast::ty_fn(?proto, ?inputs, ?output, ?cf, ?constrs)) {
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);
typ = ty::mk_fn(tcx, proto, i, out_ty, cf, constrs);
}
case (ast::ty_path(?path, ?ann)) {
......@@ -342,7 +344,8 @@ fn instantiate(&ty::ctxt tcx,
ident=m.node.ident,
inputs=ins,
output=out,
cf=m.node.cf);
cf=m.node.cf,
constrs=m.node.constrs);
vec::push[ty::method](tmeths, new_m);
}
......@@ -452,7 +455,8 @@ fn ty_of_fn_decl(&@ctxt cx,
&ast::def_id def_id) -> 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);
auto t_fn = ty::mk_fn(cx.tcx, proto, input_tys, output_ty, decl.cf);
auto t_fn = ty::mk_fn(cx.tcx, proto, input_tys, output_ty,
decl.cf, decl.constraints);
auto ty_param_count = vec::len[ast::ty_param](ty_params);
auto tpt = tup(ty_param_count, t_fn);
cx.tcx.tcache.insert(def_id, tpt);
......@@ -507,7 +511,8 @@ fn ty_of_method(@ctxt cx, &@ast::method m) -> ty::method {
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);
inputs=inputs, output=output, cf=m.node.meth.decl.cf,
constrs=m.node.meth.decl.constraints);
}
fn ty_of_obj(@ctxt cx,
......@@ -536,8 +541,9 @@ fn ty_of_obj_ctor(@ctxt cx,
vec::push[arg](t_inputs, rec(mode=ty::mo_alias, 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);
ast::return, constrs);
auto tpt = tup(t_obj._0, t_fn);
cx.tcx.tcache.insert(ctor_id, tpt);
......@@ -668,8 +674,10 @@ fn get_tag_variant_types(&@ctxt cx, &ast::def_id tag_id,
args += [rec(mode=ty::mo_alias, ty=arg_ty)];
}
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);
ast::return, res_constrs);
}
auto tpt = tup(ty_param_count, result_ty);
......@@ -766,10 +774,10 @@ fn convert(@ctxt cx, @mutable option::t[ast::native_abi] abi,
alt (object.dtor) {
case (none) { /* nothing to do */ }
case (some(?m)) {
// TODO: typechecker botch
let vec[arg] no_args = [];
auto t = ty::mk_fn(cx.tcx, ast::proto_fn, no_args,
ty::mk_nil(cx.tcx), ast::return);
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);
write::ty_only(cx.tcx, m.node.ann.id, t);
}
}
......@@ -970,7 +978,7 @@ fn variant_arg_types(&@crate_ctxt ccx, &span sp, &ast::def_id vid,
auto tpt = ty::lookup_item_type(ccx.tcx, vid);
alt (ty::struct(ccx.tcx, tpt._1)) {
case (ty::ty_fn(_, ?ins, _, _)) {
case (ty::ty_fn(_, ?ins, _, _, _)) {
// N-ary variant.
for (ty::arg arg in ins) {
auto arg_ty = ty::substitute_type_params(ccx.tcx,
......@@ -1290,7 +1298,7 @@ fn check_pat(&@fn_ctxt fcx, &@ast::pat pat, ty::t expected) {
// can never tell.
fcx.ccx.tcx.sess.span_err(pat.span,
#fmt("mismatched types: expected tag but found %s",
ty::ty_to_str(fcx.ccx.tcx, expected)));
ty_to_str(fcx.ccx.tcx, expected)));
}
}
......@@ -1422,7 +1430,7 @@ fn check_call_or_bind(&@fn_ctxt fcx, &span sp, &@ast::expr f,
// Grab the argument types and the return type.
auto arg_tys;
alt (structure_of(fcx, sp, fty)) {
case (ty::ty_fn(_, ?arg_tys_0, _, _)) {
case (ty::ty_fn(_, ?arg_tys_0, _, _, _)) {
arg_tys = arg_tys_0;
}
case (ty::ty_native_fn(_, ?arg_tys_0, _)) {
......@@ -1886,10 +1894,14 @@ fn check_for_or_for_each(&@fn_ctxt fcx, &@ast::decl decl,
auto fty = expr_ty(fcx.ccx.tcx, f);
auto t_1;
alt (structure_of(fcx, expr.span, fty)) {
case (ty::ty_fn(?proto, ?arg_tys, ?rt, ?cf)) {
case (ty::ty_fn(?proto, ?arg_tys, ?rt, ?cf, ?constrs)) {
proto_1 = proto;
rt_1 = rt;
// FIXME:
// probably need to munge the constrs to drop constraints
// for any bound args
// For each blank argument, add the type of that argument
// to the resulting function type.
auto i = 0u;
......@@ -1903,7 +1915,7 @@ fn check_for_or_for_each(&@fn_ctxt fcx, &@ast::decl decl,
i += 1u;
}
t_1 = ty::mk_fn(fcx.ccx.tcx, proto_1, arg_tys_1, rt_1,
cf);
cf, constrs);
}
case (_) {
log_err "LHS of bind expr didn't have a function type?!";
......@@ -1923,10 +1935,10 @@ fn check_for_or_for_each(&@fn_ctxt fcx, &@ast::decl decl,
check_call(fcx, expr.span, f, args);
// Pull the return type out of the type of the function.
auto rt_1 = ty::mk_nil(fcx.ccx.tcx); // FIXME: typestate botch
auto rt_1; // = ty::mk_nil(fcx.ccx.tcx); // FIXME: typestate botch
auto fty = ty::expr_ty(fcx.ccx.tcx, f);
alt (structure_of(fcx, expr.span, fty)) {
case (ty::ty_fn(_,_,?rt,_)) { rt_1 = rt; }
case (ty::ty_fn(_,_,?rt,_, _)) { rt_1 = rt; }
case (ty::ty_native_fn(_, _, ?rt)) { rt_1 = rt; }
case (_) {
log_err "LHS of call expr didn't have a function type?!";
......@@ -2134,7 +2146,8 @@ fn check_for_or_for_each(&@fn_ctxt fcx, &@ast::decl decl,
}
auto meth = methods.(ix);
auto t = ty::mk_fn(fcx.ccx.tcx, meth.proto,
meth.inputs, meth.output, meth.cf);
meth.inputs, meth.output, meth.cf,
meth.constrs);
write::ty_only_fixup(fcx, a.id, t);
}
......@@ -2254,7 +2267,8 @@ fn ty_of_method(@crate_ctxt ccx, &@ast::method m) -> ty::method {
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);
inputs=inputs, output=output, cf=m.node.meth.decl.cf,
constrs=m.node.meth.decl.constraints);
}
fn get_anon_obj_method_types(@crate_ctxt ccx,
......
......@@ -115,7 +115,7 @@ fn visit_ty[E](&@ty t, &E e, &vt[E] v) {
vt(v).visit_ty(f.node.mt.ty, e, v);
}
}
case (ty_fn(_, ?args, ?out, _)) {
case (ty_fn(_, ?args, ?out, _, _)) {
for (ty_arg a in args) {
vt(v).visit_ty(a.node.ty, e, v);
}
......
......@@ -170,7 +170,7 @@ fn walk_ty(&ast_visitor v, @ast::ty t) {
walk_ty(v, f.node.mt.ty);
}
}
case (ast::ty_fn(_, ?args, ?out, _)) {
case (ast::ty_fn(_, ?args, ?out, _, _)) {
for (ast::ty_arg a in args) {
walk_ty(v, a.node.ty);
}
......
import std::io;
import middle::ty::*;
import front::ast::constr_arg;
import front::lexer;
import pp::word;
import pp::eof;
import pp::zerobreak;
import pp::hardbreak;
import front::codemap;
import front::codemap::codemap;
fn ty_to_str(&ctxt cx, &t typ) -> str {
fn fn_input_to_str(&ctxt cx,
&rec(middle::ty::mode mode, t ty) input) -> str {
auto s;
alt (input.mode) {
case (mo_val) { s = ""; }
case (mo_alias) { s = "&"; }
}
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 {
auto f = bind fn_input_to_str(cx, _);
auto s;
alt (proto) {
case (ast::proto_iter) {
s = "iter";
}
case (ast::proto_fn) {
s = "fn";
}
}
alt (ident) {
case (some(?i)) {
s += " ";
s += i;
}
case (_) { }
}
s += "(";
s += str::connect(vec::map[arg,str](f, inputs), ", ");
s += ")";
if (struct(cx, output) != ty_nil) {
alt (cf) {
case (ast::noreturn) {
s += " -> !";
}
case (ast::return) {
s += " -> " + ty_to_str(cx, output);
}
}
}
s += constrs_str(constrs);
ret s;
}
fn method_to_str(&ctxt cx, &method m) -> str {
ret fn_to_str(cx, m.proto, some[ast::ident](m.ident),
m.inputs, m.output, m.cf, m.constrs) + ";";
}
fn field_to_str(&ctxt cx, &field f) -> str {
ret mt_to_str(cx, f.mt) + " " + f.ident;
}
fn mt_to_str(&ctxt cx, &mt m) -> str {
auto mstr;
alt (m.mut) {
case (ast::mut) { mstr = "mutable "; }
case (ast::imm) { mstr = ""; }
case (ast::maybe_mut) { mstr = "mutable? "; }
}
ret mstr + ty_to_str(cx, m.ty);
}
alt (cname(cx, typ)) {
case (some(?cs)) {
ret cs;
}
case (_) { }
}
auto s = "";
alt (struct(cx, typ)) {
case (ty_native) { s += "native"; }
case (ty_nil) { s += "()"; }
case (ty_bot) { s += "_|_"; }
case (ty_bool) { s += "bool"; }
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_char) { s += "char"; }
case (ty_str) { s += "str"; }
case (ty_box(?tm)) { s += "@" + mt_to_str(cx, tm); }
case (ty_vec(?tm)) { s += "vec[" + mt_to_str(cx, tm) + "]"; }
case (ty_port(?t)) { s += "port[" + ty_to_str(cx, t) + "]"; }
case (ty_chan(?t)) { s += "chan[" + ty_to_str(cx, t) + "]"; }
case (ty_type) { s += "type"; }
case (ty_task) { s += "task"; }
case (ty_tup(?elems)) {
auto f = bind mt_to_str(cx, _);
auto strs = vec::map[mt,str](f, elems);
s += "tup(" + str::connect(strs, ",") + ")";
}
case (ty_rec(?elems)) {
auto f = bind field_to_str(cx, _);
auto strs = vec::map[field,str](f, elems);
s += "rec(" + str::connect(strs, ",") + ")";
}
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) + ">";
if (vec::len[t](tps) > 0u) {
auto f = bind ty_to_str(cx, _);
auto strs = vec::map[t,str](f, tps);
s += "[" + str::connect(strs, ",") + "]";
}
}
case (ty_fn(?proto, ?inputs, ?output, ?cf, ?constrs)) {
s += fn_to_str(cx, proto, none[ast::ident], 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);
}
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_param(?id)) {
s += "'" + str::unsafe_from_bytes([('a' as u8) + (id as u8)]);
}
case (_) {
s += ty_to_short_str(cx, typ);
}
}
ret s;
}
fn ty_to_short_str(&ctxt cx, t typ) -> str {
auto f = def_to_str;
auto ecx = @rec(ds=f, tcx=cx, abbrevs=metadata::ac_no_abbrevs);
auto s = metadata::Encode::ty_str(ecx, typ);
if (str::byte_len(s) >= 32u) { s = str::substr(s, 0u, 32u); }
ret s;
}
fn constr_arg_to_str(&ast::constr_arg_ c) -> str {
alt (c) {
case (ast::carg_base) {
ret "*";
}
case (ast::carg_ident(?i)) {
ret i;
}
case (ast::carg_lit(?l)) {
ret lit_to_str(l);
}
}
}
fn constr_args_to_str(&vec[@constr_arg] args) -> str {
auto comma = false;
auto s = "(";
for (@constr_arg a in args) {
if (comma) {
s += ", ";
}
else {
comma = true;
}
s += constr_arg_to_str(a.node);
}
s += ")";
ret s;
}
fn print_literal(&ps s, &@ast::lit lit) {
maybe_print_comment(s, lit.span.lo);
alt (next_lit(s)) {
case (some(?lt)) {
if (lt.pos == lit.span.lo) {
word(s.s, lt.lit);
s.cur_lit += 1u;
ret;
}
}
case (_) {}
}
alt (lit.node) {
case (ast::lit_str(?st)) {print_string(s, st);}
case (ast::lit_char(?ch)) {
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_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));
}
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));
}
case (ast::lit_nil) {word(s.s, "()");}
case (ast::lit_bool(?val)) {
if (val) {word(s.s, "true");} else {word(s.s, "false");}
}
}
}
fn lit_to_str(&@ast::lit l) -> str { be to_str(l, print_literal); }
fn next_lit(&ps s) -> option::t[lexer::lit] {
alt (s.literals) {
case (some(?lits)) {
if (s.cur_lit < vec::len(lits)) {
ret some(lits.(s.cur_lit));
} else {ret none[lexer::lit];}
}
case (_) {ret none[lexer::lit];}
}
}
fn maybe_print_comment(&ps s, uint pos) {
while (true) {
alt (next_comment(s)) {
case (some(?cmnt)) {
if (cmnt.pos < pos) {
print_comment(s, cmnt);
s.cur_cmnt += 1u;
} else { break; }
}
case (_) {break;}
}
}
}
fn print_comment(&ps s, lexer::cmnt cmnt) {
alt (cmnt.style) {
case (lexer::mixed) {
assert vec::len(cmnt.lines) == 1u;
zerobreak(s.s);
word(s.s, cmnt.lines.(0));
zerobreak(s.s);
}
case (lexer::isolated) {
hardbreak(s.s);
ibox(s, 0u);
for (str line in cmnt.lines) {
word(s.s, line);
hardbreak(s.s);
}
end(s);
}
case (lexer::trailing) {
word(s.s, " ");
if (vec::len(cmnt.lines) == 1u) {
word(s.s, cmnt.lines.(0));
hardbreak(s.s);
} else {
ibox(s, 0u);
for (str line in cmnt.lines) {
word(s.s, line);
hardbreak(s.s);
}
end(s);
}
}
}
}
fn print_string(&ps s, &str st) {
word(s.s, "\""); word(s.s, escape_str(st, '"')); word(s.s, "\"");
}
fn escape_str(str st, char to_escape) -> str {
let str out = "";
auto len = str::byte_len(st);
auto i = 0u;
while (i < len) {
alt (st.(i) as char) {
case ('\n') {out += "\\n";}
case ('\t') {out += "\\t";}
case ('\r') {out += "\\r";}
case ('\\') {out += "\\\\";}
case (?cur) {
if (cur == to_escape) {out += "\\";}
// FIXME some (or all?) non-ascii things should be escaped
str::push_char(out, cur);
}
}
i += 1u;
}
ret out;
}
fn to_str[T](&T t, fn(&ps s, &T s) f) -> str {
auto writer = io::string_writer();
auto s = rust_printer(writer.get_writer());
f(s, t);
eof(s.s);
ret writer.get_str();
}
fn next_comment(&ps s) -> option::t[lexer::cmnt] {
alt (s.comments) {
case (some(?cmnts)) {
if (s.cur_cmnt < vec::len(cmnts)) {
ret some(cmnts.(s.cur_cmnt));
} else {ret none[lexer::cmnt];}
}
case (_) {ret none[lexer::cmnt];}
}
}
type ps = @rec(pp::printer s,
option::t[codemap] cm,
option::t[vec[lexer::cmnt]] comments,
option::t[vec[lexer::lit]] literals,
mutable uint cur_cmnt,
mutable uint cur_lit,
mutable vec[pp::breaks] boxes,
mode mode);
fn ibox(&ps s, uint u) {
vec::push(s.boxes, pp::inconsistent);
pp::ibox(s.s, u);
}
fn end(&ps s) {
vec::pop(s.boxes);
pp::end(s.s);
}
tag mode {
mo_untyped;
mo_typed(ctxt);
mo_identified;
}
fn rust_printer(io::writer writer) -> ps {
let vec[pp::breaks] boxes = [];
ret @rec(s=pp::mk_printer(writer, default_columns),
cm=none[codemap],
comments=none[vec[lexer::cmnt]],
literals=none[vec[lexer::lit]],
mutable cur_cmnt=0u,
mutable cur_lit=0u,
mutable boxes=boxes,
mode=mo_untyped);
}
const uint indent_unit = 4u;
const uint default_columns = 78u;
fn constr_to_str(&@ast::constr c) -> str {
ret path_to_str(c.node.path)
+ constr_args_to_str(c.node.args);
}
fn 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 += constr_to_str(c);
}
ret s;
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
......@@ -4,13 +4,12 @@
import std::io;
import std::option;
import driver::session::session;
import front::ast;
import front::lexer;
import front::codemap;
import front::codemap::codemap;
import front::ast;
import middle::ty;
import util::common;
import pp;
import option::some;
import option::none;
......@@ -27,44 +26,7 @@
import pp::consistent;
import pp::inconsistent;
import pp::eof;
const uint indent_unit = 4u;
const uint default_columns = 78u;
tag mode {
mo_untyped;
mo_typed(ty::ctxt);
mo_identified;
}
type ps = @rec(pp::printer s,
option::t[codemap] cm,
option::t[vec[lexer::cmnt]] comments,
option::t[vec[lexer::lit]] literals,
mutable uint cur_cmnt,
mutable uint cur_lit,
mutable vec[pp::breaks] boxes,
mode mode);
fn rust_printer(io::writer writer) -> ps {
let vec[pp::breaks] boxes = [];
ret @rec(s=pp::mk_printer(writer, default_columns),
cm=none[codemap],
comments=none[vec[lexer::cmnt]],
literals=none[vec[lexer::lit]],
mutable cur_cmnt=0u,
mutable cur_lit=0u,
mutable boxes=boxes,
mode=mo_untyped);
}
fn to_str[T](&T t, fn(&ps s, &T s) f) -> str {
auto writer = io::string_writer();
auto s = rust_printer(writer.get_writer());
f(s, t);
eof(s.s);
ret writer.get_str();
}
import ppaux::*;
fn print_file(session sess, ast::_mod _mod, str filename, io::writer out,
mode mode) {
......@@ -88,7 +50,6 @@ fn print_file(session sess, ast::_mod _mod, str filename, io::writer out,
fn stmt_to_str(&ast::stmt s) -> str { be to_str(s, print_stmt); }
fn item_to_str(&@ast::item i) -> str { be to_str(i, print_item); }
fn path_to_str(&ast::path p) -> str { be to_str(p, print_path); }
fn lit_to_str(&@ast::lit l) -> str { be to_str(l, print_literal); }
fn fun_to_str(&ast::_fn f, str name, vec[ast::ty_param] params) -> str {
auto writer = io::string_writer();
......@@ -112,11 +73,6 @@ fn block_to_str(&ast::block blk) -> str {
ret writer.get_str();
}
fn ibox(&ps s, uint u) {
vec::push(s.boxes, pp::inconsistent);
pp::ibox(s.s, u);
}
fn cbox(&ps s, uint u) {
vec::push(s.boxes, pp::consistent);
pp::cbox(s.s, u);
......@@ -127,12 +83,6 @@ fn box(&ps s, uint u, pp::breaks b) {
pp::box(s.s, u, b);
}
fn end(&ps s) {
vec::pop(s.boxes);
pp::end(s.s);
}
fn word_nbsp(&ps s, str w) {
word(s.s, w);
word(s.s, " ");
......@@ -290,14 +240,15 @@ fn get_span(&ast::ty_field f) -> common::span {
cbox(s, indent_unit);
maybe_print_comment(s, m.span.lo);
print_ty_fn(s, m.node.proto, some(m.node.ident),
m.node.inputs, m.node.output, m.node.cf);
m.node.inputs, m.node.output, m.node.cf,
m.node.constrs);
word(s.s, ";");
end(s);
}
bclose(s, ty.span);
}
case (ast::ty_fn(?proto,?inputs,?output,?cf)) {
print_ty_fn(s, proto, none[str], inputs, output, cf);
case (ast::ty_fn(?proto,?inputs,?output,?cf,?constrs)) {
print_ty_fn(s, proto, none[str], inputs, output, cf, constrs);
}
case (ast::ty_path(?path,_)) {
print_path(s, path);
......@@ -501,62 +452,6 @@ fn print_block(&ps s, ast::block blk) {
}
}
fn next_lit(&ps s) -> option::t[lexer::lit] {
alt (s.literals) {
case (some(?lits)) {
if (s.cur_lit < vec::len(lits)) {
ret some(lits.(s.cur_lit));
} else {ret none[lexer::lit];}
}
case (_) {ret none[lexer::lit];}
}
}
fn print_literal(&ps s, &@ast::lit lit) {
maybe_print_comment(s, lit.span.lo);
alt (next_lit(s)) {
case (some(?lt)) {
if (lt.pos == lit.span.lo) {
word(s.s, lt.lit);
s.cur_lit += 1u;
ret;
}
}
case (_) {}
}
alt (lit.node) {
case (ast::lit_str(?st)) {print_string(s, st);}
case (ast::lit_char(?ch)) {
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_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));
}
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));
}
case (ast::lit_nil) {word(s.s, "()");}
case (ast::lit_bool(?val)) {
if (val) {word(s.s, "true");} else {word(s.s, "false");}
}
}
}
fn print_expr(&ps s, &@ast::expr expr) {
maybe_print_comment(s, expr.span.lo);
ibox(s, indent_unit);
......@@ -917,7 +812,7 @@ fn do_else(&ps s, option::t[@ast::expr] els) {
space(s.s);
word(s.s, "as");
space(s.s);
word(s.s, ty::ty_to_str(tcx, ty::expr_ty(tcx, expr)));
word(s.s, ppaux::ty_to_str(tcx, ty::expr_ty(tcx, expr)));
pclose(s);
}
case (mo_identified) {
......@@ -951,7 +846,7 @@ fn print_decl(&ps s, &@ast::decl decl) {
case (mo_typed(?tcx)) {
auto lty =
ty::ann_to_type(tcx, loc.ann);
word_space(s, ty::ty_to_str(tcx, lty));
word_space(s, ppaux::ty_to_str(tcx, lty));
}
case (mo_identified) { /* no-op */ }
}
......@@ -1170,27 +1065,6 @@ fn print_maybe_parens(&ps s, &@ast::expr expr, int outer_prec) {
if (add_them) {pclose(s);}
}
fn escape_str(str st, char to_escape) -> str {
let str out = "";
auto len = str::byte_len(st);
auto i = 0u;
while (i < len) {
alt (st.(i) as char) {
case ('\n') {out += "\\n";}
case ('\t') {out += "\\t";}
case ('\r') {out += "\\r";}
case ('\\') {out += "\\\\";}
case (?cur) {
if (cur == to_escape) {out += "\\";}
// FIXME some (or all?) non-ascii things should be escaped
str::push_char(out, cur);
}
}
i += 1u;
}
ret out;
}
fn print_mt(&ps s, &ast::mt mt) {
alt (mt.mut) {
case (ast::mut) { word_nbsp(s, "mutable"); }
......@@ -1200,13 +1074,9 @@ fn print_mt(&ps s, &ast::mt mt) {
print_type(s, *mt.ty);
}
fn print_string(&ps s, &str st) {
word(s.s, "\""); word(s.s, escape_str(st, '"')); word(s.s, "\"");
}
fn print_ty_fn(&ps s, &ast::proto proto, &option::t[str] id,
&vec[ast::ty_arg] inputs, &@ast::ty output,
&ast::controlflow cf) {
&ast::controlflow cf, &vec[@ast::constr] constrs) {
ibox(s, indent_unit);
if (proto == ast::proto_fn) {word(s.s, "fn");}
else {word(s.s, "iter");}
......@@ -1241,34 +1111,10 @@ fn print_arg(&ps s, &ast::ty_arg input) {
}
end(s);
}
word_space(s, constrs_str(constrs));
end(s);
}
fn next_comment(&ps s) -> option::t[lexer::cmnt] {
alt (s.comments) {
case (some(?cmnts)) {
if (s.cur_cmnt < vec::len(cmnts)) {
ret some(cmnts.(s.cur_cmnt));
} else {ret none[lexer::cmnt];}
}
case (_) {ret none[lexer::cmnt];}
}
}
fn maybe_print_comment(&ps s, uint pos) {
while (true) {
alt (next_comment(s)) {
case (some(?cmnt)) {
if (cmnt.pos < pos) {
print_comment(s, cmnt);
s.cur_cmnt += 1u;
} else { break; }
}
case (_) {break;}
}
}
}
fn maybe_print_trailing_comment(&ps s, common::span span,
option::t[uint] next_pos) {
auto cm;
......@@ -1317,42 +1163,6 @@ fn in_cbox(&ps s) -> bool {
if (len == 0u) { ret false; }
ret s.boxes.(len-1u) == pp::consistent;
}
fn print_comment(&ps s, lexer::cmnt cmnt) {
alt (cmnt.style) {
case (lexer::mixed) {
assert vec::len(cmnt.lines) == 1u;
zerobreak(s.s);
word(s.s, cmnt.lines.(0));
zerobreak(s.s);
}
case (lexer::isolated) {
hardbreak(s.s);
ibox(s, 0u);
for (str line in cmnt.lines) {
word(s.s, line);
hardbreak(s.s);
}
end(s);
}
case (lexer::trailing) {
word(s.s, " ");
if (vec::len(cmnt.lines) == 1u) {
word(s.s, cmnt.lines.(0));
hardbreak(s.s);
} else {
ibox(s, 0u);
for (str line in cmnt.lines) {
word(s.s, line);
hardbreak(s.s);
}
end(s);
}
}
}
}
//
// Local Variables:
// mode: rust
......
......@@ -38,6 +38,7 @@ mod middle {
mod pretty {
mod pprust;
mod pp;
mod ppaux;
}
mod front {
......
......@@ -23,8 +23,8 @@
import pretty::pprust::print_decl;
import pretty::pprust::print_fn;
import pretty::pprust::print_type;
import pretty::pprust::print_literal;
import pretty::pprust::mo_untyped;
import pretty::ppaux::print_literal;
import pretty::ppaux::mo_untyped;
import pretty::pp::mk_printer;
type filename = str;
......@@ -294,6 +294,37 @@ fn respan[T](&span sp, &T t) -> spanned[T] {
ret rec(node=t, span=sp);
}
fn may_begin_ident(char c) -> bool {
ret (is_alpha(c) || c == '_');
}
fn in_range(char c, char lo, char hi) -> bool {
ret lo <= c && c <= hi;
}
fn is_alpha(char c) -> bool {
ret in_range(c, 'a', 'z') ||
in_range(c, 'A', 'Z');
}
fn is_dec_digit(char c) -> bool {
ret in_range(c, '0', '9');
}
fn is_alnum(char c) -> bool {
ret is_alpha(c) || is_dec_digit(c);
}
fn is_hex_digit(char c) -> bool {
ret in_range(c, '0', '9') ||
in_range(c, 'a', 'f') ||
in_range(c, 'A', 'F');
}
fn is_bin_digit(char c) -> bool {
ret c == '0' || c == '1';
}
//
// Local Variables:
// mode: rust
......
......@@ -321,6 +321,21 @@ fn unzip[T, U](&vec[tup(T, U)] v) -> tup(vec[T], vec[U]) {
}
}
// FIXME make the lengths being equal a constraint
fn zip[T, U](&vec[T] v, &vec[U] u) -> vec[tup(T, U)] {
auto sz = len[T](v);
assert (sz == len[U](u));
if (sz == 0u) {
ret alloc[tup(T, U)](0u);
}
else {
auto rest = zip[T, U](slice[T](v, 1u, sz), slice[U](u, 1u, sz));
vec::push(rest, tup(v.(0), u.(0)));
ret rest;
}
}
fn or(&vec[bool] v) -> bool {
auto f = orb;
ret vec::foldl[bool, bool](f, false, v);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册