diff --git a/src/comp/back/link.rs b/src/comp/back/link.rs index 81c0f5a265a..202b963bd60 100644 --- a/src/comp/back/link.rs +++ b/src/comp/back/link.rs @@ -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]); diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index a33416c8638..326ad81011d 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -11,6 +11,7 @@ import middle::ty; 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(), diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index fce15a556c6..3588c61c824 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -312,8 +312,8 @@ type mt = rec(@ty ty, mutability mut); 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 @@ tag ty_ { 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 @@ type arg = rec(mode mode, @ty ty, ident ident, def_id id); 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" diff --git a/src/comp/front/creader.rs b/src/comp/front/creader.rs index cae53bc74bf..e0be9606384 100644 --- a/src/comp/front/creader.rs +++ b/src/comp/front/creader.rs @@ -14,8 +14,10 @@ import middle::ty; 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]; } diff --git a/src/comp/front/lexer.rs b/src/comp/front/lexer.rs index 08409bea14c..897ec01aa05 100644 --- a/src/comp/front/lexer.rs +++ b/src/comp/front/lexer.rs @@ -9,7 +9,7 @@ import std::option::some; 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 new_reader(session sess, io::reader rdr, 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); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 562bc0cc32e..b8ec6a8a749 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -345,9 +345,7 @@ fn parse_ty_fn(ast::proto proto, &parser p, uint lo) 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_ty_fn(ast::proto proto, &parser p, uint lo) 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_ty_obj(&parser p, &mutable uint hi) -> ast::ty_ { 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); diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index bad328e028c..73dc08c6d37 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -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 ty_can_unsafely_include(&ctx cx, ty::t needle, ty::t haystack, bool mut) 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 diff --git a/src/comp/middle/metadata.rs b/src/comp/middle/metadata.rs index 59f3cf56387..8322de5bc90 100644 --- a/src/comp/middle/metadata.rs +++ b/src/comp/middle/metadata.rs @@ -9,10 +9,13 @@ import std::option::some; 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 @@ mod Encode { } 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 @@ mod Encode { 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 @@ mod Encode { } 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 @@ mod Encode { 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)); + } + } + } } } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index e08eed612cd..72a382c1361 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -71,6 +71,9 @@ import link::mangle_exported_name; 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 simplify_type(&@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 make_cmp_glue(&@block_ctxt 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_structural_ty_full(&@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_structural_ty_full(&@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(@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 create_vtbl(@local_ctxt cx, 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); diff --git a/src/comp/middle/tstate/auxiliary.rs b/src/comp/middle/tstate/auxiliary.rs index b801954b933..06de1befb74 100644 --- a/src/comp/middle/tstate/auxiliary.rs +++ b/src/comp/middle/tstate/auxiliary.rs @@ -8,6 +8,7 @@ import std::option::none; 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::log_expr_err; 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::set_postcondition; 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 @@ type pred_desc_ = rec(vec[@constr_arg] args, 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 @@ the answer is noreturn. */ 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,62 +547,148 @@ 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; - } - } - } - case (carg_ident(?s)) { - alt (b.node) { - case (carg_ident(?t)) { - ret (s == t); - } - case (_) { - ret false; - } - } - } - case (carg_lit(?l)) { - alt (b.node) { - case (carg_lit(?m)) { - ret lit_eq(l, m); - } - case (_) { - ret false; - } - } - } - } -} -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; - } - i += 1u; - } - ret true; -} - -fn match_args(&fn_ctxt fcx, vec[pred_desc] occs, +// 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 { - for (pred_desc pd in occs) { - if (args_eq(pd.node.args, occ)) { + 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"); + } + } +} + + +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 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 (_) { + 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); +} + +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); + } + case (_) { ret a; } + } + +} + +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"); + } + } + } + } + cx.sess.span_err(sp, "Constraint contains an unbound variable " + i); +} + // // Local Variables: // mode: rust diff --git a/src/comp/middle/tstate/collect_locals.rs b/src/comp/middle/tstate/collect_locals.rs index 8be160a865a..ec782e58ffd 100644 --- a/src/comp/middle/tstate/collect_locals.rs +++ b/src/comp/middle/tstate/collect_locals.rs @@ -17,6 +17,8 @@ import aux::fn_info; 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 @@ import util::common::respan; 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))])); } } } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 1c4046756e8..6901d30b509 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -50,7 +50,8 @@ type method = rec(ast::proto proto, 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 @@ type ty_ctxt = ctxt; // Needed for disambiguation from unify::ctxt. // 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 @@ tag sty { 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 mk_raw_ty(&ctxt cx, &sty st, &option::t[str] cname) -> raw_t { } } - 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 path_to_str(&ast::path pth) -> 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 += ""; - 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 += ""; - } - - 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_type_structure(&sty st) -> 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_ty(&t typ) -> uint { ret typ; } // 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_type_structures(&sty a, &sty 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 @@ mod unify { &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 @@ mod unify { } 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 @@ mod unify { 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 @@ mod unify { } 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 @@ mod unify { 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; diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 23caeb2456b..01e66afd8d1 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -22,7 +22,7 @@ import middle::ty::node_type_table; 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 std::option::from_maybe; 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 ast_ty_to_ty(&ty::ctxt tcx, &ty_getter getter, &@ast::ty ast_ty) -> ty::t { 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 ast_ty_to_ty(&ty::ctxt tcx, &ty_getter getter, &@ast::ty ast_ty) -> ty::t { 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 @@ mod collect { &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 @@ mod collect { 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 @@ mod collect { 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 @@ mod collect { 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 @@ mod collect { 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_expr(&@fn_ctxt fcx, &@ast::expr expr) { // 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_expr(&@fn_ctxt fcx, &@ast::expr expr) { 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_expr(&@fn_ctxt fcx, &@ast::expr expr) { 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_expr(&@fn_ctxt fcx, &@ast::expr expr) { 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_expr(&@fn_ctxt fcx, &@ast::expr expr) { } 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 check_expr(&@fn_ctxt fcx, &@ast::expr expr) { 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, diff --git a/src/comp/middle/visit.rs b/src/comp/middle/visit.rs index 79f74c8f3e8..ce1b2a336d7 100644 --- a/src/comp/middle/visit.rs +++ b/src/comp/middle/visit.rs @@ -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); } diff --git a/src/comp/middle/walk.rs b/src/comp/middle/walk.rs index 214846a5ecf..d1101bcfcd8 100644 --- a/src/comp/middle/walk.rs +++ b/src/comp/middle/walk.rs @@ -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); } diff --git a/src/comp/pretty/ppaux.rs b/src/comp/pretty/ppaux.rs new file mode 100644 index 00000000000..694291dcca9 --- /dev/null +++ b/src/comp/pretty/ppaux.rs @@ -0,0 +1,438 @@ +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 += ""; + 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 += ""; + } + + 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: +// diff --git a/src/comp/pretty/pprust.rs b/src/comp/pretty/pprust.rs index db6d62bdbc8..2fd0356365b 100644 --- a/src/comp/pretty/pprust.rs +++ b/src/comp/pretty/pprust.rs @@ -4,13 +4,12 @@ import std::str; 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::breaks; 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 expr_to_str(&@ast::expr e) -> str { be to_str(e, print_expr); } 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 print_type(&ps s, &ast::ty ty) { 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 print_expr(&ps s, &@ast::expr expr) { 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_ty_fn(&ps s, &ast::proto proto, &option::t[str] id, } 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 diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc index 1b323182cf0..ebd62b99fc3 100644 --- a/src/comp/rustc.rc +++ b/src/comp/rustc.rc @@ -38,6 +38,7 @@ mod middle { mod pretty { mod pprust; mod pp; + mod ppaux; } mod front { diff --git a/src/comp/util/common.rs b/src/comp/util/common.rs index 2435c2610e7..443063c6f3f 100644 --- a/src/comp/util/common.rs +++ b/src/comp/util/common.rs @@ -23,8 +23,8 @@ import pretty::pprust::print_path; 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 diff --git a/src/lib/vec.rs b/src/lib/vec.rs index 742562f17a9..037b26a51e3 100644 --- a/src/lib/vec.rs +++ b/src/lib/vec.rs @@ -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);