From 744b164b7dafbecd84e6f11e139ca054c283e77c Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 21 Dec 2010 12:13:51 -0800 Subject: [PATCH] rustc: Move type logic out of typeck so trans doesn't look like it's calling into typeck --- src/comp/front/ast.rs | 5 +- src/comp/middle/trans.rs | 325 +++++++------ src/comp/middle/ty.rs | 588 ++++++++++++++++++++++++ src/comp/middle/typeck.rs | 927 ++++++++------------------------------ src/comp/rustc.rc | 1 + 5 files changed, 935 insertions(+), 911 deletions(-) create mode 100644 src/comp/middle/ty.rs diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 8f1a9638959..8159962de1c 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -1,7 +1,6 @@ import std.map.hashmap; import std.option; -import middle.typeck; import util.common.span; import util.common.spanned; import util.common.ty_mach; @@ -21,7 +20,7 @@ type ty_param = rec(ident ident, def_id id); // Annotations added during successive passes. tag ann { ann_none; - ann_type(@typeck.ty); + ann_type(@middle.ty.t); } tag def { @@ -168,7 +167,7 @@ tag lit_ { } // NB: If you change this, you'll probably want to change the corresponding -// type structure in middle/typeck.rs as well. +// type structure in middle/ty.rs as well. type ty_field = rec(ident ident, @ty ty); type ty_arg = rec(mode mode, @ty ty); diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2cf035aa406..190b71f0a76 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -11,11 +11,11 @@ import std.option.none; import front.ast; import driver.session; -import middle.typeck; +import middle.ty; import back.x86; import back.abi; -import middle.typeck.pat_ty; +import middle.ty.pat_ty; import util.common; import util.common.istr; @@ -66,7 +66,7 @@ state type crate_ctxt = rec(session.session sess, hashmap[ast.def_id, ValueRef] item_ids, hashmap[ast.def_id, @ast.item] items, hashmap[ast.def_id, @tag_info] tags, - hashmap[@typeck.ty, ValueRef] tydescs, + hashmap[@ty.t, ValueRef] tydescs, @glue_fns glues, namegen names, str path); @@ -275,27 +275,25 @@ fn T_taskptr() -> TypeRef { ret T_ptr(T_task()); } -fn type_of(@crate_ctxt cx, @typeck.ty t) -> TypeRef { +fn type_of(@crate_ctxt cx, @ty.t t) -> TypeRef { let TypeRef llty = type_of_inner(cx, t); check (llty as int != 0); - llvm.LLVMAddTypeName(cx.llmod, _str.buf(typeck.ty_to_str(t)), llty); + llvm.LLVMAddTypeName(cx.llmod, _str.buf(ty.ty_to_str(t)), llty); ret llty; } -fn type_of_fn(@crate_ctxt cx, - vec[typeck.arg] inputs, - @typeck.ty output) -> TypeRef { +fn type_of_fn(@crate_ctxt cx, vec[ty.arg] inputs, @ty.t output) -> TypeRef { let vec[TypeRef] atys = vec(T_taskptr()); - auto fn_ty = typeck.plain_ty(typeck.ty_fn(inputs, output)); - auto ty_param_count = typeck.count_ty_params(fn_ty); + auto fn_ty = ty.plain_ty(ty.ty_fn(inputs, output)); + auto ty_param_count = ty.count_ty_params(fn_ty); auto i = 0u; while (i < ty_param_count) { atys += T_ptr(T_tydesc()); i += 1u; } - for (typeck.arg arg in inputs) { + for (ty.arg arg in inputs) { let TypeRef t = type_of(cx, arg.ty); alt (arg.mode) { case (ast.alias) { @@ -307,7 +305,7 @@ fn type_of_fn(@crate_ctxt cx, } auto ret_ty; - if (typeck.type_is_nil(output)) { + if (ty.type_is_nil(output)) { ret_ty = llvm.LLVMVoidType(); } else { ret_ty = type_of(cx, output); @@ -316,13 +314,13 @@ fn type_of_fn(@crate_ctxt cx, ret T_fn(atys, ret_ty); } -fn type_of_inner(@crate_ctxt cx, @typeck.ty t) -> TypeRef { +fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { alt (t.struct) { - case (typeck.ty_nil) { ret T_nil(); } - case (typeck.ty_bool) { ret T_bool(); } - case (typeck.ty_int) { ret T_int(); } - case (typeck.ty_uint) { ret T_int(); } - case (typeck.ty_machine(?tm)) { + case (ty.ty_nil) { ret T_nil(); } + case (ty.ty_bool) { ret T_bool(); } + case (ty.ty_int) { ret T_int(); } + case (ty.ty_uint) { ret T_int(); } + case (ty.ty_machine(?tm)) { alt (tm) { case (common.ty_i8) { ret T_i8(); } case (common.ty_u8) { ret T_i8(); } @@ -336,37 +334,37 @@ fn type_of_inner(@crate_ctxt cx, @typeck.ty t) -> TypeRef { case (common.ty_f64) { ret T_f64(); } } } - case (typeck.ty_char) { ret T_char(); } - case (typeck.ty_str) { ret T_ptr(T_str()); } - case (typeck.ty_tag(?tag_id)) { + case (ty.ty_char) { ret T_char(); } + case (ty.ty_str) { ret T_ptr(T_str()); } + case (ty.ty_tag(?tag_id)) { ret llvm.LLVMResolveTypeHandle(cx.tags.get(tag_id).th.llth); } - case (typeck.ty_box(?t)) { + case (ty.ty_box(?t)) { ret T_ptr(T_box(type_of(cx, t))); } - case (typeck.ty_vec(?t)) { + case (ty.ty_vec(?t)) { ret T_ptr(T_vec(type_of(cx, t))); } - case (typeck.ty_tup(?elts)) { + case (ty.ty_tup(?elts)) { let vec[TypeRef] tys = vec(); - for (@typeck.ty elt in elts) { + for (@ty.t elt in elts) { tys += type_of(cx, elt); } ret T_struct(tys); } - case (typeck.ty_rec(?fields)) { + case (ty.ty_rec(?fields)) { let vec[TypeRef] tys = vec(); - for (typeck.field f in fields) { + for (ty.field f in fields) { tys += type_of(cx, f.ty); } ret T_struct(tys); } - case (typeck.ty_fn(?args, ?out)) { + case (ty.ty_fn(?args, ?out)) { ret type_of_fn(cx, args, out); } - case (typeck.ty_obj(?meths)) { + case (ty.ty_obj(?meths)) { let vec[TypeRef] mtys = vec(); - for (typeck.method m in meths) { + for (ty.method m in meths) { let TypeRef mty = type_of_fn(cx, m.inputs, m.output); mtys += T_ptr(mty); } @@ -376,18 +374,18 @@ fn type_of_inner(@crate_ctxt cx, @typeck.ty t) -> TypeRef { T_ptr(T_box(T_nil())))); ret pair; } - case (typeck.ty_var(_)) { + case (ty.ty_var(_)) { log "ty_var in trans.type_of"; fail; } - case (typeck.ty_param(_)) { + case (ty.ty_param(_)) { ret T_ptr(T_i8()); } } fail; } -fn type_of_arg(@crate_ctxt cx, &typeck.arg arg) -> TypeRef { +fn type_of_arg(@crate_ctxt cx, &ty.arg arg) -> TypeRef { auto ty = type_of(cx, arg.ty); if (arg.mode == ast.alias) { ty = T_ptr(ty); @@ -568,7 +566,7 @@ fn align_of(TypeRef t) -> ValueRef { ret llvm.LLVMConstIntCast(lib.llvm.llvm.LLVMAlignOf(t), T_int(), False); } -fn trans_malloc(@block_ctxt cx, @typeck.ty t) -> result { +fn trans_malloc(@block_ctxt cx, @ty.t t) -> result { auto scope_cx = find_scope_cx(cx); auto ptr_ty = type_of(cx.fcx.ccx, t); auto body_ty = lib.llvm.llvm.LLVMGetElementType(ptr_ty); @@ -587,38 +585,38 @@ fn trans_malloc(@block_ctxt cx, @typeck.ty t) -> result { // Given a type and a field index into its corresponding type descriptor, // returns an LLVM ValueRef of that field from the tydesc, generating the // tydesc if necessary. -fn field_of_tydesc(@block_ctxt cx, @typeck.ty ty, int field) -> ValueRef { - auto tydesc = get_tydesc(cx, ty); +fn field_of_tydesc(@block_ctxt cx, @ty.t t, int field) -> ValueRef { + auto tydesc = get_tydesc(cx, t); ret cx.build.GEP(tydesc, vec(C_int(0), C_int(field))); } -fn get_tydesc(&@block_ctxt cx, @typeck.ty ty) -> ValueRef { +fn get_tydesc(&@block_ctxt cx, @ty.t t) -> ValueRef { // Is the supplied type a type param? If so, return the passed-in tydesc. - alt (typeck.type_param(ty)) { + alt (ty.type_param(t)) { case (some[ast.def_id](?id)) { ret cx.fcx.lltydescs.get(id); } case (none[ast.def_id]) { /* fall through */ } } // Does it contain a type param? If so, generate a derived tydesc. - if (typeck.count_ty_params(ty) > 0u) { + if (ty.count_ty_params(t) > 0u) { log "TODO: trans.get_tydesc(): generate a derived type descriptor"; fail; } // Otherwise, generate a tydesc if necessary, and return it. - if (!cx.fcx.ccx.tydescs.contains_key(ty)) { - make_tydesc(cx.fcx.ccx, ty); + if (!cx.fcx.ccx.tydescs.contains_key(t)) { + make_tydesc(cx.fcx.ccx, t); } - ret cx.fcx.ccx.tydescs.get(ty); + ret cx.fcx.ccx.tydescs.get(t); } -fn make_tydesc(@crate_ctxt cx, @typeck.ty ty) { +fn make_tydesc(@crate_ctxt cx, @ty.t t) { auto tg = make_take_glue; - auto take_glue = make_generic_glue(cx, ty, "take", tg); + auto take_glue = make_generic_glue(cx, t, "take", tg); auto dg = make_drop_glue; - auto drop_glue = make_generic_glue(cx, ty, "drop", dg); + auto drop_glue = make_generic_glue(cx, t, "drop", dg); - auto llty = type_of(cx, ty); + auto llty = type_of(cx, t); auto pvoid = T_ptr(T_i8()); auto glue_fn_ty = T_ptr(T_fn(vec(T_taskptr(), pvoid), T_void())); auto tydesc = C_struct(vec(C_null(pvoid), @@ -632,18 +630,18 @@ fn make_tydesc(@crate_ctxt cx, @typeck.ty ty) { C_null(glue_fn_ty), // obj_drop_glue_off C_null(glue_fn_ty))); // is_stateful - auto name = sanitize(cx.names.next("tydesc_" + typeck.ty_to_str(ty))); + auto name = sanitize(cx.names.next("tydesc_" + ty.ty_to_str(t))); auto gvar = llvm.LLVMAddGlobal(cx.llmod, val_ty(tydesc), _str.buf(name)); llvm.LLVMSetInitializer(gvar, tydesc); llvm.LLVMSetGlobalConstant(gvar, True); - cx.tydescs.insert(ty, gvar); + cx.tydescs.insert(t, gvar); } -fn make_generic_glue(@crate_ctxt cx, @typeck.ty t, str name, +fn make_generic_glue(@crate_ctxt cx, @ty.t t, str name, val_and_ty_fn helper) -> ValueRef { auto llfnty = T_fn(vec(T_taskptr(), T_ptr(T_i8())), T_void()); - auto fn_name = cx.names.next("_rust_" + name) + "." + typeck.ty_to_str(t); + auto fn_name = cx.names.next("_rust_" + name) + "." + ty.ty_to_str(t); fn_name = sanitize(fn_name); auto llfn = decl_fastcall_fn(cx.llmod, fn_name, llfnty); @@ -651,9 +649,9 @@ fn make_generic_glue(@crate_ctxt cx, @typeck.ty t, str name, auto bcx = new_top_block_ctxt(fcx); auto re; - if (!typeck.type_is_scalar(t)) { + if (!ty.type_is_scalar(t)) { auto llty; - if (typeck.type_is_structural(t)) { + if (ty.type_is_structural(t)) { llty = T_ptr(type_of(cx, t)); } else { llty = type_of(cx, t); @@ -671,11 +669,11 @@ fn make_generic_glue(@crate_ctxt cx, @typeck.ty t, str name, ret llfn; } -fn make_take_glue(@block_ctxt cx, ValueRef v, @typeck.ty t) -> result { - if (typeck.type_is_boxed(t)) { +fn make_take_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result { + if (ty.type_is_boxed(t)) { ret incr_refcnt_of_boxed(cx, v); - } else if (typeck.type_is_structural(t)) { + } else if (ty.type_is_structural(t)) { ret iter_structural_ty(cx, v, t, bind incr_all_refcnts(_, _, _)); } @@ -701,18 +699,17 @@ fn incr_refcnt_of_boxed(@block_ctxt cx, ValueRef box_ptr) -> result { ret res(next_cx, C_nil()); } -fn make_drop_glue(@block_ctxt cx, ValueRef v, @typeck.ty t) -> result { +fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result { alt (t.struct) { - case (typeck.ty_str) { + case (ty.ty_str) { ret decr_refcnt_and_if_zero(cx, v, bind trans_non_gc_free(_, v), "free string", T_int(), C_int(0)); } - case (typeck.ty_vec(_)) { - fn hit_zero(@block_ctxt cx, ValueRef v, - @typeck.ty t) -> result { + case (ty.ty_vec(_)) { + fn hit_zero(@block_ctxt cx, ValueRef v, @ty.t t) -> result { auto res = iter_sequence(cx, v, t, bind drop_ty(_,_,_)); // FIXME: switch gc/non-gc on layer of the type. ret trans_non_gc_free(res.bcx, v); @@ -723,9 +720,8 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @typeck.ty t) -> result { T_int(), C_int(0)); } - case (typeck.ty_box(?body_ty)) { - fn hit_zero(@block_ctxt cx, ValueRef v, - @typeck.ty body_ty) -> result { + case (ty.ty_box(?body_ty)) { + fn hit_zero(@block_ctxt cx, ValueRef v, @ty.t body_ty) -> result { auto body = cx.build.GEP(v, vec(C_int(0), C_int(abi.box_rc_field_body))); @@ -742,18 +738,18 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @typeck.ty t) -> result { } case (_) { - if (typeck.type_is_structural(t)) { + if (ty.type_is_structural(t)) { ret iter_structural_ty(cx, v, t, bind drop_ty(_, _, _)); - } else if (typeck.type_is_scalar(t) || - typeck.type_is_nil(t)) { + } else if (ty.type_is_scalar(t) || + ty.type_is_nil(t)) { ret res(cx, C_nil()); } } } cx.fcx.ccx.sess.bug("bad type in trans.make_drop_glue_inner: " + - typeck.ty_to_str(t)); + ty.ty_to_str(t)); fail; } @@ -802,9 +798,9 @@ fn decr_refcnt_and_if_zero(@block_ctxt cx, fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef { let vec[TypeRef] lltys = vec(); - alt (typeck.ann_to_type(v.ann).struct) { - case (typeck.ty_fn(?args, _)) { - for (typeck.arg arg in args) { + alt (ty.ann_to_type(v.ann).struct) { + case (ty.ty_fn(?args, _)) { + for (ty.arg arg in args) { lltys += vec(type_of(cx, arg.ty)); } } @@ -813,13 +809,12 @@ fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef { ret T_struct(lltys); } -type val_and_ty_fn = - fn(@block_ctxt cx, ValueRef v, @typeck.ty t) -> result; +type val_and_ty_fn = fn(@block_ctxt cx, ValueRef v, @ty.t t) -> result; // Iterates through the elements of a structural type. fn iter_structural_ty(@block_ctxt cx, ValueRef v, - @typeck.ty t, + @ty.t t, val_and_ty_fn f) -> result { let result r = res(cx, C_nil()); @@ -828,8 +823,8 @@ fn iter_structural_ty(@block_ctxt cx, ValueRef box_cell, val_and_ty_fn f) -> result { auto box_ptr = cx.build.Load(box_cell); - auto tnil = typeck.plain_ty(typeck.ty_nil); - auto tbox = typeck.plain_ty(typeck.ty_box(tnil)); + auto tnil = ty.plain_ty(ty.ty_nil); + auto tbox = ty.plain_ty(ty.ty_box(tnil)); auto inner_cx = new_sub_block_ctxt(cx, "iter box"); auto next_cx = new_sub_block_ctxt(cx, "next"); @@ -842,9 +837,9 @@ fn iter_structural_ty(@block_ctxt cx, } alt (t.struct) { - case (typeck.ty_tup(?args)) { + case (ty.ty_tup(?args)) { let int i = 0; - for (@typeck.ty arg in args) { + for (@ty.t arg in args) { auto elt = r.bcx.build.GEP(v, vec(C_int(0), C_int(i))); r = f(r.bcx, load_non_structural(r.bcx, elt, arg), @@ -852,9 +847,9 @@ fn iter_structural_ty(@block_ctxt cx, i += 1; } } - case (typeck.ty_rec(?fields)) { + case (ty.ty_rec(?fields)) { let int i = 0; - for (typeck.field fld in fields) { + for (ty.field fld in fields) { auto llfld = r.bcx.build.GEP(v, vec(C_int(0), C_int(i))); r = f(r.bcx, load_non_structural(r.bcx, llfld, fld.ty), @@ -862,7 +857,7 @@ fn iter_structural_ty(@block_ctxt cx, i += 1; } } - case (typeck.ty_tag(?tid)) { + case (ty.ty_tag(?tid)) { check (cx.fcx.ccx.tags.contains_key(tid)); auto info = cx.fcx.ccx.tags.get(tid); auto n_variants = _vec.len[tup(ast.def_id,arity)](info.variants); @@ -907,15 +902,15 @@ fn iter_structural_ty(@block_ctxt cx, auto llvarty = type_of_variant(cx.fcx.ccx, variants.(i)); - auto fn_ty = typeck.ann_to_type(variants.(i).ann); + auto fn_ty = ty.ann_to_type(variants.(i).ann); alt (fn_ty.struct) { - case (typeck.ty_fn(?args, _)) { + case (ty.ty_fn(?args, _)) { auto llvarp = variant_cx.build. TruncOrBitCast(llunion_ptr, T_ptr(llvarty)); auto j = 0u; - for (typeck.arg a in args) { + for (ty.arg a in args) { auto llfldp = variant_cx.build.GEP(llvarp, vec(C_int(0), C_int(j as int))); auto llfld = @@ -943,14 +938,14 @@ fn iter_structural_ty(@block_ctxt cx, ret res(next_cx, C_nil()); } - case (typeck.ty_fn(_,_)) { + case (ty.ty_fn(_,_)) { auto box_cell = cx.build.GEP(v, vec(C_int(0), C_int(abi.fn_field_box))); ret iter_boxpp(cx, box_cell, f); } - case (typeck.ty_obj(_)) { + case (ty.ty_obj(_)) { auto box_cell = cx.build.GEP(v, vec(C_int(0), @@ -967,12 +962,12 @@ fn iter_structural_ty(@block_ctxt cx, // Iterates through the elements of a vec or str. fn iter_sequence(@block_ctxt cx, ValueRef v, - @typeck.ty ty, + @ty.t t, val_and_ty_fn f) -> result { fn iter_sequence_body(@block_ctxt cx, ValueRef v, - @typeck.ty elt_ty, + @ty.t elt_ty, val_and_ty_fn f, bool trailing_null) -> result { @@ -1022,12 +1017,12 @@ fn iter_sequence(@block_ctxt cx, ret res(next_cx, C_nil()); } - alt (ty.struct) { - case (typeck.ty_vec(?et)) { + alt (t.struct) { + case (ty.ty_vec(?et)) { ret iter_sequence_body(cx, v, et, f, false); } - case (typeck.ty_str) { - auto et = typeck.plain_ty(typeck.ty_machine(common.ty_u8)); + case (ty.ty_str) { + auto et = ty.plain_ty(ty.ty_machine(common.ty_u8)); ret iter_sequence_body(cx, v, et, f, true); } case (_) { fail; } @@ -1038,9 +1033,9 @@ fn iter_sequence(@block_ctxt cx, fn incr_all_refcnts(@block_ctxt cx, ValueRef v, - @typeck.ty t) -> result { + @ty.t t) -> result { - if (!typeck.type_is_scalar(t)) { + if (!ty.type_is_scalar(t)) { auto llrawptr = cx.build.BitCast(v, T_ptr(T_i8())); auto llfnptr = field_of_tydesc(cx, t, abi.tydesc_field_take_glue_off); auto llfn = cx.build.Load(llfnptr); @@ -1051,7 +1046,7 @@ fn incr_all_refcnts(@block_ctxt cx, fn drop_slot(@block_ctxt cx, ValueRef slot, - @typeck.ty t) -> result { + @ty.t t) -> result { auto llptr = load_non_structural(cx, slot, t); auto re = drop_ty(cx, llptr, t); @@ -1063,9 +1058,9 @@ fn drop_slot(@block_ctxt cx, fn drop_ty(@block_ctxt cx, ValueRef v, - @typeck.ty t) -> result { + @ty.t t) -> result { - if (!typeck.type_is_scalar(t)) { + if (!ty.type_is_scalar(t)) { auto llrawptr = cx.build.BitCast(v, T_ptr(T_i8())); auto llfnptr = field_of_tydesc(cx, t, abi.tydesc_field_drop_glue_off); auto llfn = cx.build.Load(llfnptr); @@ -1102,21 +1097,21 @@ fn copy_ty(@block_ctxt cx, bool is_init, ValueRef dst, ValueRef src, - @typeck.ty t) -> result { - if (typeck.type_is_scalar(t)) { + @ty.t t) -> result { + if (ty.type_is_scalar(t)) { ret res(cx, cx.build.Store(src, dst)); - } else if (typeck.type_is_nil(t)) { + } else if (ty.type_is_nil(t)) { ret res(cx, C_nil()); - } else if (typeck.type_is_boxed(t)) { + } else if (ty.type_is_boxed(t)) { auto r = incr_all_refcnts(cx, src, t); if (! is_init) { r = drop_ty(r.bcx, r.bcx.build.Load(dst), t); } ret res(r.bcx, r.bcx.build.Store(src, dst)); - } else if (typeck.type_is_structural(t)) { + } else if (ty.type_is_structural(t)) { auto r = incr_all_refcnts(cx, src, t); if (! is_init) { r = drop_ty(r.bcx, dst, t); @@ -1128,7 +1123,7 @@ fn copy_ty(@block_ctxt cx, } cx.fcx.ccx.sess.bug("unexpected type in trans.copy_ty: " + - typeck.ty_to_str(t)); + ty.ty_to_str(t)); fail; } @@ -1185,14 +1180,14 @@ impure fn trans_lit(@block_ctxt cx, &ast.lit lit, &ast.ann ann) -> result { } } -fn target_type(@crate_ctxt cx, @typeck.ty t) -> @typeck.ty { +fn target_type(@crate_ctxt cx, @ty.t t) -> @ty.t { alt (t.struct) { - case (typeck.ty_int) { - auto tm = typeck.ty_machine(cx.sess.get_targ_cfg().int_type); + case (ty.ty_int) { + auto tm = ty.ty_machine(cx.sess.get_targ_cfg().int_type); ret @rec(struct=tm with *t); } - case (typeck.ty_uint) { - auto tm = typeck.ty_machine(cx.sess.get_targ_cfg().uint_type); + case (ty.ty_uint) { + auto tm = ty.ty_machine(cx.sess.get_targ_cfg().uint_type); ret @rec(struct=tm with *t); } case (_) { /* fall through */ } @@ -1200,7 +1195,7 @@ fn target_type(@crate_ctxt cx, @typeck.ty t) -> @typeck.ty { ret t; } -fn node_ann_type(@crate_ctxt cx, &ast.ann a) -> @typeck.ty { +fn node_ann_type(@crate_ctxt cx, &ast.ann a) -> @ty.t { alt (a) { case (ast.ann_none) { cx.sess.bug("missing type annotation"); @@ -1235,7 +1230,7 @@ impure fn trans_unary(@block_ctxt cx, ast.unop op, ret sub; } case (ast.box) { - auto e_ty = typeck.expr_ty(e); + auto e_ty = ty.expr_ty(e); auto e_val = sub.val; sub = trans_malloc(sub.bcx, node_ann_type(sub.bcx.fcx.ccx, a)); auto box = sub.val; @@ -1254,8 +1249,8 @@ impure fn trans_unary(@block_ctxt cx, ast.unop op, vec(C_int(0), C_int(abi.box_rc_field_body))); auto e_ty = node_ann_type(sub.bcx.fcx.ccx, a); - if (typeck.type_is_scalar(e_ty) || - typeck.type_is_nil(e_ty)) { + if (ty.type_is_scalar(e_ty) || + ty.type_is_nil(e_ty)) { sub.val = sub.bcx.build.Load(sub.val); } ret sub; @@ -1659,22 +1654,20 @@ impure fn trans_field(@block_ctxt cx, &ast.span sp, @ast.expr base, &ast.ident field, &ast.ann ann) -> tup(result, bool) { auto lv = trans_lval(cx, base); auto r = lv._0; - auto ty = typeck.expr_ty(base); - alt (ty.struct) { - case (typeck.ty_tup(?fields)) { - let uint ix = typeck.field_num(cx.fcx.ccx.sess, sp, field); + auto t = ty.expr_ty(base); + alt (t.struct) { + case (ty.ty_tup(?fields)) { + let uint ix = ty.field_num(cx.fcx.ccx.sess, sp, field); auto v = r.bcx.build.GEP(r.val, vec(C_int(0), C_int(ix as int))); ret tup(res(r.bcx, v), true); } - case (typeck.ty_rec(?fields)) { - let uint ix = typeck.field_idx(cx.fcx.ccx.sess, sp, - field, fields); + case (ty.ty_rec(?fields)) { + let uint ix = ty.field_idx(cx.fcx.ccx.sess, sp, field, fields); auto v = r.bcx.build.GEP(r.val, vec(C_int(0), C_int(ix as int))); ret tup(res(r.bcx, v), true); } - case (typeck.ty_obj(?methods)) { - let uint ix = typeck.method_idx(cx.fcx.ccx.sess, sp, - field, methods); + case (ty.ty_obj(?methods)) { + let uint ix = ty.method_idx(cx.fcx.ccx.sess, sp, field, methods); auto vtbl = r.bcx.build.GEP(r.val, vec(C_int(0), C_int(abi.obj_field_vtbl))); @@ -1747,10 +1740,10 @@ impure fn trans_cast(@block_ctxt cx, @ast.expr e, &ast.ann ann) -> result { auto llsrctype = val_ty(e_res.val); auto t = node_ann_type(cx.fcx.ccx, ann); auto lldsttype = type_of(cx.fcx.ccx, t); - if (!typeck.type_is_fp(t)) { + if (!ty.type_is_fp(t)) { if (llvm.LLVMGetIntTypeWidth(lldsttype) > llvm.LLVMGetIntTypeWidth(llsrctype)) { - if (typeck.type_is_signed(t)) { + if (ty.type_is_signed(t)) { // Widening signed cast. e_res.val = e_res.bcx.build.SExtOrBitCast(e_res.val, @@ -1774,14 +1767,14 @@ impure fn trans_cast(@block_ctxt cx, @ast.expr e, &ast.ann ann) -> result { } -impure fn trans_args(@block_ctxt cx, &vec[@ast.expr] es, @typeck.ty fn_ty) +impure fn trans_args(@block_ctxt cx, &vec[@ast.expr] es, @ty.t fn_ty) -> tup(@block_ctxt, vec[ValueRef]) { let vec[ValueRef] vs = vec(cx.fcx.lltaskptr); let @block_ctxt bcx = cx; - let vec[typeck.arg] args = vec(); // FIXME: typestate bug + let vec[ty.arg] args = vec(); // FIXME: typestate bug alt (fn_ty.struct) { - case (typeck.ty_fn(?a, _)) { args = a; } + case (ty.ty_fn(?a, _)) { args = a; } case (_) { fail; } } @@ -1790,7 +1783,7 @@ impure fn trans_args(@block_ctxt cx, &vec[@ast.expr] es, @typeck.ty fn_ty) auto mode = args.(i).mode; auto re; - if (typeck.type_is_structural(typeck.expr_ty(e))) { + if (ty.type_is_structural(ty.expr_ty(e))) { re = trans_expr(bcx, e); if (mode == ast.val) { // Until here we've been treating structures by pointer; @@ -1800,7 +1793,7 @@ impure fn trans_args(@block_ctxt cx, &vec[@ast.expr] es, @typeck.ty fn_ty) } else { if (mode == ast.alias) { let tup(result, bool /* is a pointer? */) pair; - if (typeck.is_lval(e)) { + if (ty.is_lval(e)) { pair = trans_lval(bcx, e); } else { pair = tup(trans_expr(bcx, e), false); @@ -1836,13 +1829,13 @@ impure fn trans_call(@block_ctxt cx, @ast.expr f, if (f_res._1) { faddr = f_res._0.bcx.build.Load(faddr); } - auto fn_ty = typeck.expr_ty(f); - auto ret_ty = typeck.ann_to_type(ann); + auto fn_ty = ty.expr_ty(f); + auto ret_ty = ty.ann_to_type(ann); auto args_res = trans_args(f_res._0.bcx, args, fn_ty); auto real_retval = args_res._0.build.FastCall(faddr, args_res._1); auto retval; - if (typeck.type_is_nil(ret_ty)) { + if (ty.type_is_nil(ret_ty)) { retval = C_nil(); } else { retval = real_retval; @@ -1851,7 +1844,7 @@ impure fn trans_call(@block_ctxt cx, @ast.expr f, // Structured returns come back as first-class values. This is nice for // LLVM but wrong for us; we treat structured values by pointer in // most of our code here. So spill it to an alloca. - if (typeck.type_is_structural(ret_ty)) { + if (ty.type_is_structural(ret_ty)) { auto local = args_res._0.build.Alloca(type_of(cx.fcx.ccx, ret_ty)); args_res._0.build.Store(retval, local); retval = local; @@ -1867,14 +1860,14 @@ impure fn trans_call(@block_ctxt cx, @ast.expr f, impure fn trans_tup(@block_ctxt cx, vec[ast.elt] elts, &ast.ann ann) -> result { - auto ty = node_ann_type(cx.fcx.ccx, ann); - auto llty = type_of(cx.fcx.ccx, ty); + auto t = node_ann_type(cx.fcx.ccx, ann); + auto llty = type_of(cx.fcx.ccx, t); auto tup_val = cx.build.Alloca(llty); - find_scope_cx(cx).cleanups += clean(bind drop_ty(_, tup_val, ty)); + find_scope_cx(cx).cleanups += clean(bind drop_ty(_, tup_val, t)); let int i = 0; auto r = res(cx, C_nil()); for (ast.elt e in elts) { - auto t = typeck.expr_ty(e.expr); + auto t = ty.expr_ty(e.expr); auto src_res = trans_expr(r.bcx, e.expr); auto dst_elt = r.bcx.build.GEP(tup_val, vec(C_int(0), C_int(i))); r = copy_ty(src_res.bcx, true, dst_elt, src_res.val, t); @@ -1885,10 +1878,10 @@ impure fn trans_tup(@block_ctxt cx, vec[ast.elt] elts, impure fn trans_vec(@block_ctxt cx, vec[@ast.expr] args, &ast.ann ann) -> result { - auto ty = node_ann_type(cx.fcx.ccx, ann); - auto unit_ty = ty; - alt (ty.struct) { - case (typeck.ty_vec(?t)) { + auto t = node_ann_type(cx.fcx.ccx, ann); + auto unit_ty = t; + alt (t.struct) { + case (ty.ty_vec(?t)) { unit_ty = t; } case (_) { @@ -1904,9 +1897,9 @@ impure fn trans_vec(@block_ctxt cx, vec[@ast.expr] args, // FIXME: pass tydesc properly. auto sub = trans_upcall(cx, "upcall_new_vec", vec(data_sz, C_int(0))); - auto llty = type_of(cx.fcx.ccx, ty); + auto llty = type_of(cx.fcx.ccx, t); auto vec_val = sub.bcx.build.IntToPtr(sub.val, llty); - find_scope_cx(cx).cleanups += clean(bind drop_ty(_, vec_val, ty)); + find_scope_cx(cx).cleanups += clean(bind drop_ty(_, vec_val, t)); auto body = sub.bcx.build.GEP(vec_val, vec(C_int(0), C_int(abi.vec_elt_data))); @@ -1926,14 +1919,14 @@ impure fn trans_vec(@block_ctxt cx, vec[@ast.expr] args, impure fn trans_rec(@block_ctxt cx, vec[ast.field] fields, &ast.ann ann) -> result { - auto ty = node_ann_type(cx.fcx.ccx, ann); - auto llty = type_of(cx.fcx.ccx, ty); + auto t = node_ann_type(cx.fcx.ccx, ann); + auto llty = type_of(cx.fcx.ccx, t); auto rec_val = cx.build.Alloca(llty); - find_scope_cx(cx).cleanups += clean(bind drop_ty(_, rec_val, ty)); + find_scope_cx(cx).cleanups += clean(bind drop_ty(_, rec_val, t)); let int i = 0; auto r = res(cx, C_nil()); for (ast.field f in fields) { - auto t = typeck.expr_ty(f.expr); + auto t = ty.expr_ty(f.expr); auto src_res = trans_expr(r.bcx, f.expr); auto dst_elt = r.bcx.build.GEP(rec_val, vec(C_int(0), C_int(i))); // FIXME: calculate copy init-ness in typestate. @@ -2031,7 +2024,7 @@ impure fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { // possibly load the result (if it's non-structural). case (_) { - auto t = typeck.expr_ty(e); + auto t = ty.expr_ty(e); auto sub = trans_lval(cx, e); ret res(sub._0.bcx, load_non_structural(sub._0.bcx, sub._0.val, t)); @@ -2047,8 +2040,8 @@ impure fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { fn load_non_structural(@block_ctxt cx, ValueRef v, - @typeck.ty t) -> ValueRef { - if (typeck.type_is_structural(t)) { + @ty.t t) -> ValueRef { + if (ty.type_is_structural(t)) { ret v; } else { ret cx.build.Load(v); @@ -2058,9 +2051,9 @@ fn load_non_structural(@block_ctxt cx, impure fn trans_log(@block_ctxt cx, @ast.expr e) -> result { auto sub = trans_expr(cx, e); - auto e_ty = typeck.expr_ty(e); + auto e_ty = ty.expr_ty(e); alt (e_ty.struct) { - case (typeck.ty_str) { + case (ty.ty_str) { auto v = sub.bcx.build.PtrToInt(sub.val, T_int()); ret trans_upcall(sub.bcx, "upcall_log_str", @@ -2099,14 +2092,14 @@ impure fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result { auto r = res(cx, C_nil()); alt (e) { case (some[@ast.expr](?x)) { - auto t = typeck.expr_ty(x); + auto t = ty.expr_ty(x); r = trans_expr(cx, x); // A return is an implicit copy into a newborn anonymous // 'return value' in the caller frame. r.bcx = incr_all_refcnts(r.bcx, r.val, t).bcx; - if (typeck.type_is_structural(t)) { + if (ty.type_is_structural(t)) { // We usually treat structurals by-pointer; in particular, // trans_expr will have given us a structure pointer. But in // this case we're about to return. LLVM wants a first-class @@ -2134,7 +2127,7 @@ impure fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result { alt (e) { case (some[@ast.expr](?ex)) { - if (typeck.type_is_nil(typeck.expr_ty(ex))) { + if (ty.type_is_nil(ty.expr_ty(ex))) { r.bcx.build.RetVoid(); r.val = C_nil(); } else { @@ -2359,7 +2352,7 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx, &vec[ast.arg] args, // were passed and whatnot. Apparently mem2reg will mop up. fn copy_args_to_allocas(@block_ctxt cx, vec[ast.arg] args, - vec[typeck.arg] arg_tys) { + vec[ty.arg] arg_tys) { let uint arg_n = 0u; @@ -2382,18 +2375,18 @@ fn is_terminated(@block_ctxt cx) -> bool { ret llvm.LLVMIsATerminatorInst(inst) as int != 0; } -fn arg_tys_of_fn(ast.ann ann) -> vec[typeck.arg] { - alt (typeck.ann_to_type(ann).struct) { - case (typeck.ty_fn(?arg_tys, _)) { +fn arg_tys_of_fn(ast.ann ann) -> vec[ty.arg] { + alt (ty.ann_to_type(ann).struct) { + case (ty.ty_fn(?arg_tys, _)) { ret arg_tys; } } fail; } -fn ret_ty_of_fn(ast.ann ann) -> @typeck.ty { - alt (typeck.ann_to_type(ann).struct) { - case (typeck.ty_fn(_, ?ret_ty)) { +fn ret_ty_of_fn(ast.ann ann) -> @ty.t { + alt (ty.ann_to_type(ann).struct) { + case (ty.ty_fn(_, ?ret_ty)) { ret ret_ty; } } @@ -2498,7 +2491,7 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, id=varg.id)); } - auto var_ty = typeck.ann_to_type(variant.ann); + auto var_ty = ty.ann_to_type(variant.ann); auto llfnty = type_of(cx, var_ty); let str s = cx.names.next("_rust_tag") + "." + cx.path; @@ -2531,7 +2524,7 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, // First, generate the union type. let vec[TypeRef] llargtys = vec(); - for (typeck.arg arg in arg_tys) { + for (ty.arg arg in arg_tys) { llargtys += vec(type_of(cx, arg.ty)); } @@ -2941,9 +2934,9 @@ fn trans_crate(session.session sess, @ast.crate crate, str output) { auto intrinsics = declare_intrinsics(llmod); auto glues = make_glues(llmod); - auto hasher = typeck.hash_ty; - auto eqer = typeck.eq_ty; - auto tydescs = map.mk_hashmap[@typeck.ty,ValueRef](hasher, eqer); + auto hasher = ty.hash_ty; + auto eqer = ty.eq_ty; + auto tydescs = map.mk_hashmap[@ty.t,ValueRef](hasher, eqer); auto cx = @rec(sess = sess, llmod = llmod, diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs new file mode 100644 index 00000000000..19fb0285d58 --- /dev/null +++ b/src/comp/middle/ty.rs @@ -0,0 +1,588 @@ +import std._str; +import std._vec; +import std.option; +import std.option.none; +import std.option.some; + +import driver.session; +import front.ast; +import front.ast.mutability; +import util.common; +import util.common.span; + +// Data types + +type arg = rec(ast.mode mode, @t ty); +type field = rec(ast.ident ident, @t ty); +type method = rec(ast.ident ident, vec[arg] inputs, @t output); + +// NB: If you change this, you'll probably want to change the corresponding +// AST structure in front/ast.rs as well. +type t = rec(sty struct, mutability mut, option.t[str] cname); +tag sty { + ty_nil; + ty_bool; + ty_int; + ty_uint; + ty_machine(util.common.ty_mach); + ty_char; + ty_str; + ty_tag(ast.def_id); + ty_box(@t); + ty_vec(@t); + ty_tup(vec[@t]); + ty_rec(vec[field]); + ty_fn(vec[arg], @t); // TODO: effect + ty_obj(vec[method]); + ty_var(int); // ephemeral type var + ty_local(ast.def_id); // type of a local var + ty_param(ast.def_id); // fn type param + // TODO: ty_fn_arg(@t), for a possibly-aliased function argument +} + +// Stringification + +fn ast_ty_to_str(&@ast.ty ty) -> str { + + fn ast_fn_input_to_str(&rec(ast.mode mode, @ast.ty ty) input) -> str { + auto s; + if (mode_is_alias(input.mode)) { + s = "&"; + } else { + s = ""; + } + + ret s + ast_ty_to_str(input.ty); + } + + fn ast_ty_field_to_str(&ast.ty_field f) -> str { + ret ast_ty_to_str(f.ty) + " " + f.ident; + } + + auto s; + alt (ty.node) { + case (ast.ty_nil) { s = "()"; } + case (ast.ty_bool) { s = "bool"; } + case (ast.ty_int) { s = "int"; } + case (ast.ty_uint) { s = "uint"; } + case (ast.ty_machine(?tm)) { s = common.ty_mach_to_str(tm); } + case (ast.ty_char) { s = "char"; } + case (ast.ty_str) { s = "str"; } + case (ast.ty_box(?t)) { s = "@" + ast_ty_to_str(t); } + case (ast.ty_vec(?t)) { s = "vec[" + ast_ty_to_str(t) + "]"; } + + case (ast.ty_tup(?elts)) { + auto f = ast_ty_to_str; + s = "tup("; + s += _str.connect(_vec.map[@ast.ty,str](f, elts), ","); + s += ")"; + } + + case (ast.ty_rec(?fields)) { + auto f = ast_ty_field_to_str; + s = "rec("; + s += _str.connect(_vec.map[ast.ty_field,str](f, fields), ","); + s += ")"; + } + + case (ast.ty_fn(?inputs, ?output)) { + auto f = ast_fn_input_to_str; + s = "fn("; + auto is = _vec.map[rec(ast.mode mode, @ast.ty ty),str](f, inputs); + s += _str.connect(is, ", "); + s += ")"; + + if (output.node != ast.ty_nil) { + s += " -> " + ast_ty_to_str(output); + } + } + + case (ast.ty_path(?path, _)) { + s = path_to_str(path); + } + + case (ast.ty_mutable(?t)) { + s = "mutable " + ast_ty_to_str(t); + } + + case (_) { + fail; // FIXME: typestate bug + } + } + + ret s; +} + +fn name_to_str(&ast.name nm) -> str { + auto result = nm.node.ident; + if (_vec.len[@ast.ty](nm.node.types) > 0u) { + auto f = ast_ty_to_str; + result += "["; + result += _str.connect(_vec.map[@ast.ty,str](f, nm.node.types), ","); + result += "]"; + } + ret result; +} + +fn path_to_str(&ast.path path) -> str { + auto f = name_to_str; + ret _str.connect(_vec.map[ast.name,str](f, path), "."); +} + +fn ty_to_str(&@t typ) -> str { + + fn fn_input_to_str(&rec(ast.mode mode, @t ty) input) -> str { + auto s; + if (mode_is_alias(input.mode)) { + s = "&"; + } else { + s = ""; + } + + ret s + ty_to_str(input.ty); + } + + fn fn_to_str(option.t[ast.ident] ident, + vec[arg] inputs, @t output) -> str { + auto f = fn_input_to_str; + auto s = "fn"; + alt (ident) { + case (some[ast.ident](?i)) { + s += " "; + s += i; + } + case (_) { } + } + + s += "("; + s += _str.connect(_vec.map[arg,str](f, inputs), ", "); + s += ")"; + + if (output.struct != ty_nil) { + s += " -> " + ty_to_str(output); + } + ret s; + } + + fn method_to_str(&method m) -> str { + ret fn_to_str(some[ast.ident](m.ident), m.inputs, m.output) + ";"; + } + + fn field_to_str(&field f) -> str { + ret ty_to_str(f.ty) + " " + f.ident; + } + + auto s = ""; + if (typ.mut == ast.mut) { + s += "mutable "; + } + + alt (typ.struct) { + case (ty_nil) { s = "()"; } + case (ty_bool) { s = "bool"; } + case (ty_int) { s = "int"; } + 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(?t)) { s = "@" + ty_to_str(t); } + case (ty_vec(?t)) { s = "vec[" + ty_to_str(t) + "]"; } + + case (ty_tup(?elems)) { + auto f = ty_to_str; + auto strs = _vec.map[@t,str](f, elems); + s = "tup(" + _str.connect(strs, ",") + ")"; + } + + case (ty_rec(?elems)) { + auto f = field_to_str; + auto strs = _vec.map[field,str](f, elems); + s = "rec(" + _str.connect(strs, ",") + ")"; + } + + case (ty_tag(_)) { + // The user should never see this if the cname is set properly! + s = ""; + } + + case (ty_fn(?inputs, ?output)) { + s = fn_to_str(none[ast.ident], inputs, output); + } + + case (ty_obj(?meths)) { + auto f = method_to_str; + 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 = ""; + } + } + + ret s; +} + +// Type folds + +type ty_fold = state obj { + fn fold_simple_ty(@t ty) -> @t; +}; + +fn fold_ty(ty_fold fld, @t ty) -> @t { + fn rewrap(@t orig, &sty new) -> @t { + ret @rec(struct=new, mut=orig.mut, cname=orig.cname); + } + + alt (ty.struct) { + case (ty_nil) { ret fld.fold_simple_ty(ty); } + case (ty_bool) { ret fld.fold_simple_ty(ty); } + case (ty_int) { ret fld.fold_simple_ty(ty); } + case (ty_uint) { ret fld.fold_simple_ty(ty); } + case (ty_machine(_)) { ret fld.fold_simple_ty(ty); } + case (ty_char) { ret fld.fold_simple_ty(ty); } + case (ty_str) { ret fld.fold_simple_ty(ty); } + case (ty_tag(_)) { ret fld.fold_simple_ty(ty); } + case (ty_box(?subty)) { + ret rewrap(ty, ty_box(fold_ty(fld, subty))); + } + case (ty_vec(?subty)) { + ret rewrap(ty, ty_vec(fold_ty(fld, subty))); + } + case (ty_tup(?subtys)) { + let vec[@t] new_subtys = vec(); + for (@t subty in subtys) { + new_subtys += vec(fold_ty(fld, subty)); + } + ret rewrap(ty, ty_tup(new_subtys)); + } + case (ty_rec(?fields)) { + let vec[field] new_fields = vec(); + for (field fl in fields) { + auto new_ty = fold_ty(fld, fl.ty); + new_fields += vec(rec(ident=fl.ident, ty=new_ty)); + } + ret rewrap(ty, ty_rec(new_fields)); + } + case (ty_fn(?args, ?ret_ty)) { + let vec[arg] new_args = vec(); + for (arg a in args) { + auto new_ty = fold_ty(fld, a.ty); + new_args += vec(rec(mode=a.mode, ty=new_ty)); + } + ret rewrap(ty, ty_fn(new_args, fold_ty(fld, ret_ty))); + } + case (ty_obj(?methods)) { + let vec[method] new_methods = vec(); + for (method m in methods) { + let vec[arg] new_args = vec(); + for (arg a in m.inputs) { + new_args += vec(rec(mode=a.mode, ty=fold_ty(fld, a.ty))); + } + new_methods += vec(rec(ident=m.ident, inputs=new_args, + output=fold_ty(fld, m.output))); + } + ret rewrap(ty, ty_obj(new_methods)); + } + case (ty_var(_)) { ret fld.fold_simple_ty(ty); } + case (ty_local(_)) { ret fld.fold_simple_ty(ty); } + case (ty_param(_)) { ret fld.fold_simple_ty(ty); } + } + + ret ty; +} + +// Type utilities + +// FIXME: remove me when == works on these tags. +fn mode_is_alias(ast.mode m) -> bool { + alt (m) { + case (ast.val) { ret false; } + case (ast.alias) { ret true; } + } + fail; +} + +fn type_is_nil(@t ty) -> bool { + alt (ty.struct) { + case (ty_nil) { ret true; } + case (_) { ret false; } + } + fail; +} + +fn type_is_structural(@t ty) -> bool { + alt (ty.struct) { + case (ty_tup(_)) { ret true; } + case (ty_rec(_)) { ret true; } + case (ty_tag(_)) { ret true; } + case (ty_fn(_,_)) { ret true; } + case (ty_obj(_)) { ret true; } + case (_) { ret false; } + } + fail; +} + +fn type_is_boxed(@t ty) -> bool { + alt (ty.struct) { + case (ty_str) { ret true; } + case (ty_vec(_)) { ret true; } + case (ty_box(_)) { ret true; } + case (_) { ret false; } + } + fail; +} + +fn type_is_scalar(@t ty) -> bool { + alt (ty.struct) { + case (ty_nil) { ret true; } + case (ty_bool) { ret true; } + case (ty_int) { ret true; } + case (ty_uint) { ret true; } + case (ty_machine(_)) { ret true; } + case (ty_char) { ret true; } + case (_) { ret false; } + } + fail; +} + + +fn type_is_integral(@t ty) -> bool { + alt (ty.struct) { + case (ty_int) { ret true; } + case (ty_uint) { ret true; } + case (ty_machine(?m)) { + alt (m) { + case (common.ty_i8) { ret true; } + case (common.ty_i16) { ret true; } + case (common.ty_i32) { ret true; } + case (common.ty_i64) { ret true; } + + case (common.ty_u8) { ret true; } + case (common.ty_u16) { ret true; } + case (common.ty_u32) { ret true; } + case (common.ty_u64) { ret true; } + case (_) { ret false; } + } + } + case (ty_char) { ret true; } + case (_) { ret false; } + } + fail; +} + +fn type_is_fp(@t ty) -> bool { + alt (ty.struct) { + case (ty_machine(?tm)) { + alt (tm) { + case (common.ty_f32) { ret true; } + case (common.ty_f64) { ret true; } + case (_) { ret false; } + } + } + case (_) { ret false; } + } + fail; +} + +fn type_is_signed(@t ty) -> bool { + alt (ty.struct) { + case (ty_int) { ret true; } + case (ty_machine(?tm)) { + alt (tm) { + case (common.ty_i8) { ret true; } + case (common.ty_i16) { ret true; } + case (common.ty_i32) { ret true; } + case (common.ty_i64) { ret true; } + case (_) { ret false; } + } + } + case (_) { ret false; } + } + fail; +} + +fn type_param(@t ty) -> option.t[ast.def_id] { + alt (ty.struct) { + case (ty_param(?id)) { ret some[ast.def_id](id); } + case (_) { /* fall through */ } + } + ret none[ast.def_id]; +} + +fn plain_ty(&sty st) -> @t { + ret @rec(struct=st, mut=ast.imm, cname=none[str]); +} + +fn hash_ty(&@t ty) -> uint { + ret _str.hash(ty_to_str(ty)); +} + +fn eq_ty(&@t a, &@t b) -> bool { + // FIXME: this is gross, but I think it's safe, and I don't think writing + // a giant function to handle all the cases is necessary when structural + // equality will someday save the day. + ret _str.eq(ty_to_str(a), ty_to_str(b)); +} + +fn ann_to_type(&ast.ann ann) -> @t { + alt (ann) { + case (ast.ann_none) { + // shouldn't happen, but can until the typechecker is complete + ret plain_ty(ty_var(-1)); // FIXME: broken, broken, broken + } + case (ast.ann_type(?ty)) { + ret ty; + } + } +} + +fn count_ty_params(@t ty) -> uint { + state obj ty_param_counter(@mutable vec[ast.def_id] param_ids) { + fn fold_simple_ty(@t ty) -> @t { + alt (ty.struct) { + case (ty_param(?param_id)) { + for (ast.def_id other_param_id in *param_ids) { + if (param_id._0 == other_param_id._0 && + param_id._1 == other_param_id._1) { + ret ty; + } + } + *param_ids += vec(param_id); + } + case (_) { /* fall through */ } + } + ret ty; + } + } + + let vec[ast.def_id] param_ids_inner = vec(); + let @mutable vec[ast.def_id] param_ids = @mutable param_ids_inner; + fold_ty(ty_param_counter(param_ids), ty); + ret _vec.len[ast.def_id](*param_ids); +} + +// Type accessors for AST nodes + +fn stmt_ty(@ast.stmt s) -> @t { + alt (s.node) { + case (ast.stmt_expr(?e)) { + ret expr_ty(e); + } + case (_) { + ret plain_ty(ty_nil); + } + } +} + +fn block_ty(&ast.block b) -> @t { + alt (b.node.expr) { + case (some[@ast.expr](?e)) { ret expr_ty(e); } + case (none[@ast.expr]) { ret plain_ty(ty_nil); } + } +} + +fn pat_ty(@ast.pat pat) -> @t { + alt (pat.node) { + case (ast.pat_wild(?ann)) { ret ann_to_type(ann); } + case (ast.pat_bind(_, _, ?ann)) { ret ann_to_type(ann); } + case (ast.pat_tag(_, _, _, ?ann)) { ret ann_to_type(ann); } + } + fail; // not reached +} + +fn expr_ty(@ast.expr expr) -> @t { + alt (expr.node) { + case (ast.expr_vec(_, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_tup(_, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_rec(_, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_call(_, _, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_binary(_, _, _, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_unary(_, _, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_lit(_, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_cast(_, _, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_if(_, _, _, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_while(_, _, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_do_while(_, _, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_alt(_, _, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_block(_, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_assign(_, _, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_assign_op(_, _, _, ?ann)) + { ret ann_to_type(ann); } + case (ast.expr_field(_, _, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_index(_, _, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_name(_, _, ?ann)) { ret ann_to_type(ann); } + } + fail; +} + +// Expression utilities + +fn field_num(session.session sess, &span sp, &ast.ident id) -> uint { + let uint accum = 0u; + let uint i = 0u; + for (u8 c in id) { + if (i == 0u) { + if (c != ('_' as u8)) { + sess.span_err(sp, + "bad numeric field on tuple: " + + "missing leading underscore"); + } + } else { + if (('0' as u8) <= c && c <= ('9' as u8)) { + accum *= 10u; + accum += (c as uint) - ('0' as uint); + } else { + auto s = ""; + s += c; + sess.span_err(sp, + "bad numeric field on tuple: " + + " non-digit character: " + + s); + } + } + i += 1u; + } + ret accum; +} + +fn field_idx(session.session sess, &span sp, + &ast.ident id, vec[field] fields) -> uint { + let uint i = 0u; + for (field f in fields) { + if (_str.eq(f.ident, id)) { + ret i; + } + i += 1u; + } + sess.span_err(sp, "unknown field '" + id + "' of record"); + fail; +} + +fn method_idx(session.session sess, &span sp, + &ast.ident id, vec[method] meths) -> uint { + let uint i = 0u; + for (method m in meths) { + if (_str.eq(m.ident, id)) { + ret i; + } + i += 1u; + } + sess.span_err(sp, "unknown method '" + id + "' of obj"); + fail; +} + +fn is_lval(@ast.expr expr) -> bool { + alt (expr.node) { + case (ast.expr_field(_,_,_)) { ret true; } + case (ast.expr_index(_,_,_)) { ret true; } + case (ast.expr_name(_,_,_)) { ret true; } + case (_) { ret false; } + } +} + diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 3770c0b88cf..8994d72d151 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -7,6 +7,21 @@ import util.common; import util.common.append; import util.common.span; +import middle.ty; +import middle.ty.ann_to_type; +import middle.ty.arg; +import middle.ty.block_ty; +import middle.ty.expr_ty; +import middle.ty.field; +import middle.ty.method; +import middle.ty.mode_is_alias; +import middle.ty.pat_ty; +import middle.ty.path_to_str; +import middle.ty.plain_ty; +import middle.ty.ty_to_str; +import middle.ty.type_is_integral; +import middle.ty.type_is_scalar; + import std._str; import std._uint; import std._vec; @@ -16,42 +31,17 @@ import std.option; import std.option.none; import std.option.some; -type ty_table = hashmap[ast.def_id, @ty]; +type ty_table = hashmap[ast.def_id, @ty.t]; type crate_ctxt = rec(session.session sess, @ty_table item_types, mutable int next_var_id); -type fn_ctxt = rec(@ty ret_ty, +type fn_ctxt = rec(@ty.t ret_ty, @ty_table locals, @crate_ctxt ccx); -type arg = rec(ast.mode mode, @ty ty); -type field = rec(ast.ident ident, @ty ty); -type method = rec(ast.ident ident, vec[arg] inputs, @ty output); - -// NB: If you change this, you'll probably want to change the corresponding -// AST structure in front/ast.rs as well. -type ty = rec(sty struct, mutability mut, option.t[str] cname); -tag sty { - ty_nil; - ty_bool; - ty_int; - ty_uint; - ty_machine(util.common.ty_mach); - ty_char; - ty_str; - ty_tag(ast.def_id); - ty_box(@ty); - ty_vec(@ty); - ty_tup(vec[@ty]); - ty_rec(vec[field]); - ty_fn(vec[arg], @ty); // TODO: effect - ty_obj(vec[method]); - ty_var(int); // ephemeral type var - ty_local(ast.def_id); // type of a local var - ty_param(ast.def_id); // fn type param - // TODO: ty_fn_arg(@ty), for a possibly-aliased function argument -} +// Used for ast_ty_to_ty() below. +type ty_getter = fn(ast.def_id) -> @ty.t; tag type_err { terr_mismatch; @@ -64,208 +54,18 @@ tag type_err { } tag unify_result { - ures_ok(@ty); - ures_err(type_err, @ty, @ty); -} - -// Used for ast_ty_to_ty() below. -type ty_getter = fn(ast.def_id) -> @ty; - -// Error-reporting utility functions - -fn ast_ty_to_str(&@ast.ty ty) -> str { - - fn ast_fn_input_to_str(&rec(ast.mode mode, @ast.ty ty) input) -> str { - auto s; - if (mode_is_alias(input.mode)) { - s = "&"; - } else { - s = ""; - } - - ret s + ast_ty_to_str(input.ty); - } - - fn ast_ty_field_to_str(&ast.ty_field f) -> str { - ret ast_ty_to_str(f.ty) + " " + f.ident; - } - - auto s; - alt (ty.node) { - case (ast.ty_nil) { s = "()"; } - case (ast.ty_bool) { s = "bool"; } - case (ast.ty_int) { s = "int"; } - case (ast.ty_uint) { s = "uint"; } - case (ast.ty_machine(?tm)) { s = common.ty_mach_to_str(tm); } - case (ast.ty_char) { s = "char"; } - case (ast.ty_str) { s = "str"; } - case (ast.ty_box(?t)) { s = "@" + ast_ty_to_str(t); } - case (ast.ty_vec(?t)) { s = "vec[" + ast_ty_to_str(t) + "]"; } - - case (ast.ty_tup(?elts)) { - auto f = ast_ty_to_str; - s = "tup("; - s += _str.connect(_vec.map[@ast.ty,str](f, elts), ","); - s += ")"; - } - - case (ast.ty_rec(?fields)) { - auto f = ast_ty_field_to_str; - s = "rec("; - s += _str.connect(_vec.map[ast.ty_field,str](f, fields), ","); - s += ")"; - } - - case (ast.ty_fn(?inputs, ?output)) { - auto f = ast_fn_input_to_str; - s = "fn("; - auto is = _vec.map[rec(ast.mode mode, @ast.ty ty),str](f, inputs); - s += _str.connect(is, ", "); - s += ")"; - - if (output.node != ast.ty_nil) { - s += " -> " + ast_ty_to_str(output); - } - } - - case (ast.ty_path(?path, _)) { - s = path_to_str(path); - } - - case (ast.ty_mutable(?t)) { - s = "mutable " + ast_ty_to_str(t); - } - - case (_) { - fail; // FIXME: typestate bug - } - } - - ret s; -} - -fn name_to_str(&ast.name nm) -> str { - auto result = nm.node.ident; - if (_vec.len[@ast.ty](nm.node.types) > 0u) { - auto f = ast_ty_to_str; - result += "["; - result += _str.connect(_vec.map[@ast.ty,str](f, nm.node.types), ","); - result += "]"; - } - ret result; -} - -fn path_to_str(&ast.path path) -> str { - auto f = name_to_str; - ret _str.connect(_vec.map[ast.name,str](f, path), "."); -} - -fn ty_to_str(&@ty typ) -> str { - - fn fn_input_to_str(&rec(ast.mode mode, @ty ty) input) -> str { - auto s; - if (mode_is_alias(input.mode)) { - s = "&"; - } else { - s = ""; - } - - ret s + ty_to_str(input.ty); - } - - fn fn_to_str(option.t[ast.ident] ident, - vec[arg] inputs, @ty output) -> str { - auto f = fn_input_to_str; - auto s = "fn"; - alt (ident) { - case (some[ast.ident](?i)) { - s += " "; - s += i; - } - case (_) { } - } - - s += "("; - s += _str.connect(_vec.map[arg,str](f, inputs), ", "); - s += ")"; - - if (output.struct != ty_nil) { - s += " -> " + ty_to_str(output); - } - ret s; - } - - fn method_to_str(&method m) -> str { - ret fn_to_str(some[ast.ident](m.ident), m.inputs, m.output) + ";"; - } - - fn field_to_str(&field f) -> str { - ret ty_to_str(f.ty) + " " + f.ident; - } - - auto s = ""; - if (typ.mut == ast.mut) { - s += "mutable "; - } - - alt (typ.struct) { - case (ty_nil) { s = "()"; } - case (ty_bool) { s = "bool"; } - case (ty_int) { s = "int"; } - 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(?t)) { s = "@" + ty_to_str(t); } - case (ty_vec(?t)) { s = "vec[" + ty_to_str(t) + "]"; } - - case (ty_tup(?elems)) { - auto f = ty_to_str; - auto strs = _vec.map[@ty,str](f, elems); - s = "tup(" + _str.connect(strs, ",") + ")"; - } - - case (ty_rec(?elems)) { - auto f = field_to_str; - auto strs = _vec.map[field,str](f, elems); - s = "rec(" + _str.connect(strs, ",") + ")"; - } - - case (ty_tag(_)) { - // The user should never see this if the cname is set properly! - s = ""; - } - - case (ty_fn(?inputs, ?output)) { - s = fn_to_str(none[ast.ident], inputs, output); - } - - case (ty_obj(?meths)) { - auto f = method_to_str; - 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 = ""; - } - } - - ret s; + ures_ok(@ty.t); + ures_err(type_err, @ty.t, @ty.t); } // Replaces parameter types inside a type with type variables. -fn generalize_ty(@crate_ctxt cx, @ty t) -> @ty { +fn generalize_ty(@crate_ctxt cx, @ty.t t) -> @ty.t { state obj ty_generalizer(@crate_ctxt cx, - @hashmap[ast.def_id,@ty] ty_params_to_ty_vars) { - fn fold_simple_ty(@ty t) -> @ty { + @hashmap[ast.def_id,@ty.t] + ty_params_to_ty_vars) { + fn fold_simple_ty(@ty.t t) -> @ty.t { alt (t.struct) { - case (ty_param(?pid)) { + case (ty.ty_param(?pid)) { if (ty_params_to_ty_vars.contains_key(pid)) { ret ty_params_to_ty_vars.get(pid); } @@ -279,16 +79,16 @@ fn generalize_ty(@crate_ctxt cx, @ty t) -> @ty { } } - auto generalizer = ty_generalizer(cx, @common.new_def_hash[@ty]()); - ret fold_ty(generalizer, t); + auto generalizer = ty_generalizer(cx, @common.new_def_hash[@ty.t]()); + ret ty.fold_ty(generalizer, t); } // Parses the programmer's textual representation of a type into our internal // notion of a type. `getter` is a function that returns the type // corresponding to a definition ID. -fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty { +fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t { fn ast_arg_to_arg(ty_getter getter, &rec(ast.mode mode, @ast.ty ty) arg) - -> rec(ast.mode mode, @ty ty) { + -> rec(ast.mode mode, @ty.t ty) { ret rec(mode=arg.mode, ty=ast_ty_to_ty(getter, arg.ty)); } @@ -296,21 +96,21 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty { auto sty; auto cname = none[str]; alt (ast_ty.node) { - case (ast.ty_nil) { sty = ty_nil; } - case (ast.ty_bool) { sty = ty_bool; } - case (ast.ty_int) { sty = ty_int; } - case (ast.ty_uint) { sty = ty_uint; } - case (ast.ty_machine(?tm)) { sty = ty_machine(tm); } - case (ast.ty_char) { sty = ty_char; } - case (ast.ty_str) { sty = ty_str; } - case (ast.ty_box(?t)) { sty = ty_box(ast_ty_to_ty(getter, t)); } - case (ast.ty_vec(?t)) { sty = ty_vec(ast_ty_to_ty(getter, t)); } + case (ast.ty_nil) { sty = ty.ty_nil; } + case (ast.ty_bool) { sty = ty.ty_bool; } + case (ast.ty_int) { sty = ty.ty_int; } + case (ast.ty_uint) { sty = ty.ty_uint; } + case (ast.ty_machine(?tm)) { sty = ty.ty_machine(tm); } + case (ast.ty_char) { sty = ty.ty_char; } + case (ast.ty_str) { sty = ty.ty_str; } + case (ast.ty_box(?t)) { sty = ty.ty_box(ast_ty_to_ty(getter, t)); } + case (ast.ty_vec(?t)) { sty = ty.ty_vec(ast_ty_to_ty(getter, t)); } case (ast.ty_tup(?fields)) { - let vec[@ty] flds = vec(); + let vec[@ty.t] flds = vec(); for (@ast.ty field in fields) { - append[@ty](flds, ast_ty_to_ty(getter, field)); + append[@ty.t](flds, ast_ty_to_ty(getter, field)); } - sty = ty_tup(flds); + sty = ty.ty_tup(flds); } case (ast.ty_rec(?fields)) { let vec[field] flds = vec(); @@ -318,13 +118,13 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty { append[field](flds, rec(ident=f.ident, ty=ast_ty_to_ty(getter, f.ty))); } - sty = ty_rec(flds); + sty = ty.ty_rec(flds); } case (ast.ty_fn(?inputs, ?output)) { auto f = bind ast_arg_to_arg(getter, _); auto i = _vec.map[rec(ast.mode mode, @ast.ty ty),arg](f, inputs); - sty = ty_fn(i, ast_ty_to_ty(getter, output)); + sty = ty.ty_fn(i, ast_ty_to_ty(getter, output)); } case (ast.ty_path(?path, ?def)) { @@ -335,7 +135,7 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty { // "foo = int" like OCaml? sty = getter(id).struct; } - case (ast.def_ty_arg(?id)) { sty = ty_param(id); } + case (ast.def_ty_arg(?id)) { sty = ty.ty_param(id); } case (_) { fail; } } @@ -359,8 +159,8 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty { // A convenience function to use a crate_ctxt to resolve names for // ast_ty_to_ty. -fn ast_ty_to_ty_crate(@crate_ctxt ccx, &@ast.ty ast_ty) -> @ty { - fn getter(@crate_ctxt ccx, ast.def_id id) -> @ty { +fn ast_ty_to_ty_crate(@crate_ctxt ccx, &@ast.ty ast_ty) -> @ty.t { + fn getter(@crate_ctxt ccx, ast.def_id id) -> @ty.t { check (ccx.item_types.contains_key(id)); ret ccx.item_types.get(id); } @@ -417,7 +217,7 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) { fn getter(@ty_item_table id_to_ty_item, @ty_table item_to_ty, - ast.def_id id) -> @ty { + ast.def_id id) -> @ty.t { check (id_to_ty_item.contains_key(id)); auto item = id_to_ty_item.get(id); ret ty_of_item(id_to_ty_item, item_to_ty, item); @@ -443,31 +243,31 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) { fn ty_of_obj(@ty_item_table id_to_ty_item, @ty_table item_to_ty, - &ast._obj obj_info) -> @ty { + &ast._obj obj_info) -> @ty.t { auto f = bind ty_of_method(id_to_ty_item, item_to_ty, _); auto methods = _vec.map[@ast.method,method](f, obj_info.methods); - auto t_obj = plain_ty(ty_obj(methods)); + auto t_obj = plain_ty(ty.ty_obj(methods)); ret t_obj; } fn ty_of_obj_ctor(@ty_item_table id_to_ty_item, @ty_table item_to_ty, - &ast._obj obj_info) -> @ty { + &ast._obj obj_info) -> @ty.t { auto t_obj = ty_of_obj(id_to_ty_item, item_to_ty, obj_info); let vec[arg] t_inputs = vec(); for (ast.obj_field f in obj_info.fields) { auto t_field = getter(id_to_ty_item, item_to_ty, f.id); append[arg](t_inputs, rec(mode=ast.alias, ty=t_field)); } - auto t_fn = plain_ty(ty_fn(t_inputs, t_obj)); + auto t_fn = plain_ty(ty.ty_fn(t_inputs, t_obj)); ret t_fn; } fn ty_of_item(@ty_item_table id_to_ty_item, @ty_table item_to_ty, - @ast.item it) -> @ty { + @ast.item it) -> @ty.t { auto get = bind getter(id_to_ty_item, item_to_ty, _); auto convert = bind ast_ty_to_ty(get, _); @@ -485,7 +285,7 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) { auto input_tys = _vec.map[ast.arg,arg](f, fn_info.inputs); auto output_ty = convert(fn_info.output); - auto t_fn = plain_ty(ty_fn(input_tys, output_ty)); + auto t_fn = plain_ty(ty.ty_fn(input_tys, output_ty)); item_to_ty.insert(def_id, t_fn); ret t_fn; } @@ -513,9 +313,9 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) { } case (ast.item_tag(_, _, _, ?def_id)) { - auto ty = plain_ty(ty_tag(def_id)); - item_to_ty.insert(def_id, ty); - ret ty; + auto t = plain_ty(ty.ty_tag(def_id)); + item_to_ty.insert(def_id, t); + ret t; } case (ast.item_mod(_, _, _)) { fail; } @@ -533,7 +333,7 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) { // constructors get turned into functions. auto result_ty; if (_vec.len[ast.variant_arg](variant.args) == 0u) { - result_ty = plain_ty(ty_tag(tag_id)); + result_ty = plain_ty(ty.ty_tag(tag_id)); } else { // As above, tell ast_ty_to_ty() that trans_ty_item_to_ty() // should be called to resolve named types. @@ -544,7 +344,8 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) { auto arg_ty = ast_ty_to_ty(f, va.ty); args += vec(rec(mode=ast.alias, ty=arg_ty)); } - result_ty = plain_ty(ty_fn(args, plain_ty(ty_tag(tag_id)))); + auto tag_t = plain_ty(ty.ty_tag(tag_id)); + result_ty = plain_ty(ty.ty_fn(args, tag_t)); } item_to_ty.insert(variant.id, result_ty); @@ -580,7 +381,7 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) { // Second pass: translate the types of all items. - let @ty_table item_to_ty = @common.new_def_hash[@ty](); + let @ty_table item_to_ty = @common.new_def_hash[@ty.t](); type env = rec(@ty_item_table id_to_ty_item, @ty_table item_to_ty); @@ -621,11 +422,11 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) { ret @fold.respan[ast.item_](sp, item); } - fn get_ctor_obj_methods(@ty t) -> vec[method] { + fn get_ctor_obj_methods(@ty.t t) -> vec[method] { alt (t.struct) { - case (ty_fn(_,?tobj)) { + case (ty.ty_fn(_,?tobj)) { alt (tobj.struct) { - case (ty_obj(?tm)) { + case (ty.ty_obj(?tm)) { ret tm; } case (_) { @@ -646,8 +447,8 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) { &ast._obj ob, vec[ast.ty_param] ty_params, ast.def_id id, ast.ann a) -> @ast.item { check (e.item_to_ty.contains_key(id)); - auto ty = e.item_to_ty.get(id); - let vec[method] meth_tys = get_ctor_obj_methods(ty); + auto t = e.item_to_ty.get(id); + let vec[method] meth_tys = get_ctor_obj_methods(t); let vec[@ast.method] methods = vec(); let uint n = 0u; @@ -655,8 +456,8 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) { let @ast.method meth = ob.methods.(n); let ast.method_ m_; let @ast.method m; - auto meth_tfn = plain_ty(ty_fn(meth_ty.inputs, - meth_ty.output)); + auto meth_tfn = plain_ty(ty.ty_fn(meth_ty.inputs, + meth_ty.output)); m_ = rec(ann=ast.ann_type(meth_tfn) with meth.node); m = @rec(node=m_ with *meth); append[@ast.method](methods, m); @@ -665,7 +466,7 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) { auto ob_ = rec(methods = methods with ob); auto item = ast.item_obj(i, ob_, ty_params, id, - ast.ann_type(ty)); + ast.ann_type(t)); ret @fold.respan[ast.item_](sp, item); } @@ -703,367 +504,9 @@ fn collect_item_types(@ast.crate crate) -> tup(@ast.crate, @ty_table) { ret tup(crate_, item_to_ty); } -// Expression utilities - -fn field_num(session.session sess, &span sp, &ast.ident id) -> uint { - let uint accum = 0u; - let uint i = 0u; - for (u8 c in id) { - if (i == 0u) { - if (c != ('_' as u8)) { - sess.span_err(sp, - "bad numeric field on tuple: " - + "missing leading underscore"); - } - } else { - if (('0' as u8) <= c && c <= ('9' as u8)) { - accum *= 10u; - accum += (c as uint) - ('0' as uint); - } else { - auto s = ""; - s += c; - sess.span_err(sp, - "bad numeric field on tuple: " - + " non-digit character: " - + s); - } - } - i += 1u; - } - ret accum; -} - -fn field_idx(session.session sess, &span sp, - &ast.ident id, vec[field] fields) -> uint { - let uint i = 0u; - for (field f in fields) { - if (_str.eq(f.ident, id)) { - ret i; - } - i += 1u; - } - sess.span_err(sp, "unknown field '" + id + "' of record"); - fail; -} - -fn method_idx(session.session sess, &span sp, - &ast.ident id, vec[method] meths) -> uint { - let uint i = 0u; - for (method m in meths) { - if (_str.eq(m.ident, id)) { - ret i; - } - i += 1u; - } - sess.span_err(sp, "unknown method '" + id + "' of obj"); - fail; -} - -fn is_lval(@ast.expr expr) -> bool { - alt (expr.node) { - case (ast.expr_field(_,_,_)) { ret true; } - case (ast.expr_index(_,_,_)) { ret true; } - case (ast.expr_name(_,_,_)) { ret true; } - case (_) { ret false; } - } -} - -// Type folds - -type ty_fold = state obj { - fn fold_simple_ty(@ty ty) -> @ty; -}; - -fn fold_ty(ty_fold fld, @ty t) -> @ty { - fn rewrap(@ty orig, &sty new) -> @ty { - ret @rec(struct=new, mut=orig.mut, cname=orig.cname); - } - - alt (t.struct) { - case (ty_nil) { ret fld.fold_simple_ty(t); } - case (ty_bool) { ret fld.fold_simple_ty(t); } - case (ty_int) { ret fld.fold_simple_ty(t); } - case (ty_uint) { ret fld.fold_simple_ty(t); } - case (ty_machine(_)) { ret fld.fold_simple_ty(t); } - case (ty_char) { ret fld.fold_simple_ty(t); } - case (ty_str) { ret fld.fold_simple_ty(t); } - case (ty_tag(_)) { ret fld.fold_simple_ty(t); } - case (ty_box(?subty)) { - ret rewrap(t, ty_box(fold_ty(fld, subty))); - } - case (ty_vec(?subty)) { - ret rewrap(t, ty_vec(fold_ty(fld, subty))); - } - case (ty_tup(?subtys)) { - let vec[@ty] new_subtys = vec(); - for (@ty subty in subtys) { - new_subtys += vec(fold_ty(fld, subty)); - } - ret rewrap(t, ty_tup(new_subtys)); - } - case (ty_rec(?fields)) { - let vec[field] new_fields = vec(); - for (field fl in fields) { - auto new_ty = fold_ty(fld, fl.ty); - new_fields += vec(rec(ident=fl.ident, ty=new_ty)); - } - ret rewrap(t, ty_rec(new_fields)); - } - case (ty_fn(?args, ?ret_ty)) { - let vec[arg] new_args = vec(); - for (arg a in args) { - auto new_ty = fold_ty(fld, a.ty); - new_args += vec(rec(mode=a.mode, ty=new_ty)); - } - ret rewrap(t, ty_fn(new_args, fold_ty(fld, ret_ty))); - } - case (ty_obj(?methods)) { - let vec[method] new_methods = vec(); - for (method m in methods) { - let vec[arg] new_args = vec(); - for (arg a in m.inputs) { - new_args += vec(rec(mode=a.mode, ty=fold_ty(fld, a.ty))); - } - new_methods += vec(rec(ident=m.ident, inputs=new_args, - output=fold_ty(fld, m.output))); - } - ret rewrap(t, ty_obj(new_methods)); - } - case (ty_var(_)) { ret fld.fold_simple_ty(t); } - case (ty_local(_)) { ret fld.fold_simple_ty(t); } - case (ty_param(_)) { ret fld.fold_simple_ty(t); } - } - - ret t; -} - -// Type utilities - -// FIXME: remove me when == works on these tags. -fn mode_is_alias(ast.mode m) -> bool { - alt (m) { - case (ast.val) { ret false; } - case (ast.alias) { ret true; } - } - fail; -} - -fn type_is_nil(@ty t) -> bool { - alt (t.struct) { - case (ty_nil) { ret true; } - case (_) { ret false; } - } - fail; -} - -fn type_is_structural(@ty t) -> bool { - alt (t.struct) { - case (ty_tup(_)) { ret true; } - case (ty_rec(_)) { ret true; } - case (ty_tag(_)) { ret true; } - case (ty_fn(_,_)) { ret true; } - case (ty_obj(_)) { ret true; } - case (_) { ret false; } - } - fail; -} - -fn type_is_boxed(@ty t) -> bool { - alt (t.struct) { - case (ty_str) { ret true; } - case (ty_vec(_)) { ret true; } - case (ty_box(_)) { ret true; } - case (_) { ret false; } - } - fail; -} - -fn type_is_scalar(@ty t) -> bool { - alt (t.struct) { - case (ty_nil) { ret true; } - case (ty_bool) { ret true; } - case (ty_int) { ret true; } - case (ty_uint) { ret true; } - case (ty_machine(_)) { ret true; } - case (ty_char) { ret true; } - case (_) { ret false; } - } - fail; -} - - -fn type_is_integral(@ty t) -> bool { - alt (t.struct) { - case (ty_int) { ret true; } - case (ty_uint) { ret true; } - case (ty_machine(?m)) { - alt (m) { - case (common.ty_i8) { ret true; } - case (common.ty_i16) { ret true; } - case (common.ty_i32) { ret true; } - case (common.ty_i64) { ret true; } - - case (common.ty_u8) { ret true; } - case (common.ty_u16) { ret true; } - case (common.ty_u32) { ret true; } - case (common.ty_u64) { ret true; } - case (_) { ret false; } - } - } - case (ty_char) { ret true; } - case (_) { ret false; } - } - fail; -} - -fn type_is_fp(@ty t) -> bool { - alt (t.struct) { - case (ty_machine(?tm)) { - alt (tm) { - case (common.ty_f32) { ret true; } - case (common.ty_f64) { ret true; } - case (_) { ret false; } - } - } - case (_) { ret false; } - } - fail; -} - -fn type_is_signed(@ty t) -> bool { - alt (t.struct) { - case (ty_int) { ret true; } - case (ty_machine(?tm)) { - alt (tm) { - case (common.ty_i8) { ret true; } - case (common.ty_i16) { ret true; } - case (common.ty_i32) { ret true; } - case (common.ty_i64) { ret true; } - case (_) { ret false; } - } - } - case (_) { ret false; } - } - fail; -} - -fn type_param(@ty t) -> option.t[ast.def_id] { - alt (t.struct) { - case (ty_param(?id)) { ret some[ast.def_id](id); } - case (_) { /* fall through */ } - } - ret none[ast.def_id]; -} - -fn plain_ty(&sty st) -> @ty { - ret @rec(struct=st, mut=ast.imm, cname=none[str]); -} - -fn hash_ty(&@ty t) -> uint { - ret _str.hash(ty_to_str(t)); -} - -fn eq_ty(&@ty a, &@ty b) -> bool { - // FIXME: this is gross, but I think it's safe, and I don't think writing - // a giant function to handle all the cases is necessary when structural - // equality will someday save the day. - ret _str.eq(ty_to_str(a), ty_to_str(b)); -} - -fn ann_to_type(&ast.ann ann) -> @ty { - alt (ann) { - case (ast.ann_none) { - // shouldn't happen, but can until the typechecker is complete - ret plain_ty(ty_var(-1)); // FIXME: broken, broken, broken - } - case (ast.ann_type(?ty)) { - ret ty; - } - } -} - -fn count_ty_params(@ty t) -> uint { - state obj ty_param_counter(@mutable vec[ast.def_id] param_ids) { - fn fold_simple_ty(@ty t) -> @ty { - alt (t.struct) { - case (ty_param(?param_id)) { - for (ast.def_id other_param_id in *param_ids) { - if (param_id._0 == other_param_id._0 && - param_id._1 == other_param_id._1) { - ret t; - } - } - *param_ids += vec(param_id); - } - case (_) { /* fall through */ } - } - ret t; - } - } - - let vec[ast.def_id] param_ids_inner = vec(); - let @mutable vec[ast.def_id] param_ids = @mutable param_ids_inner; - fold_ty(ty_param_counter(param_ids), t); - ret _vec.len[ast.def_id](*param_ids); -} - -// Type accessors for AST nodes - -fn stmt_ty(@ast.stmt s) -> @ty { - alt (s.node) { - case (ast.stmt_expr(?e)) { - ret expr_ty(e); - } - case (_) { - ret plain_ty(ty_nil); - } - } -} - -fn block_ty(&ast.block b) -> @ty { - alt (b.node.expr) { - case (some[@ast.expr](?e)) { ret expr_ty(e); } - case (none[@ast.expr]) { ret plain_ty(ty_nil); } - } -} - -fn pat_ty(@ast.pat pat) -> @ty { - alt (pat.node) { - case (ast.pat_wild(?ann)) { ret ann_to_type(ann); } - case (ast.pat_bind(_, _, ?ann)) { ret ann_to_type(ann); } - case (ast.pat_tag(_, _, _, ?ann)) { ret ann_to_type(ann); } - } - fail; // not reached -} - -fn expr_ty(@ast.expr expr) -> @ty { - alt (expr.node) { - case (ast.expr_vec(_, ?ann)) { ret ann_to_type(ann); } - case (ast.expr_tup(_, ?ann)) { ret ann_to_type(ann); } - case (ast.expr_rec(_, ?ann)) { ret ann_to_type(ann); } - case (ast.expr_call(_, _, ?ann)) { ret ann_to_type(ann); } - case (ast.expr_binary(_, _, _, ?ann)) { ret ann_to_type(ann); } - case (ast.expr_unary(_, _, ?ann)) { ret ann_to_type(ann); } - case (ast.expr_lit(_, ?ann)) { ret ann_to_type(ann); } - case (ast.expr_cast(_, _, ?ann)) { ret ann_to_type(ann); } - case (ast.expr_if(_, _, _, ?ann)) { ret ann_to_type(ann); } - case (ast.expr_while(_, _, ?ann)) { ret ann_to_type(ann); } - case (ast.expr_do_while(_, _, ?ann)) { ret ann_to_type(ann); } - case (ast.expr_alt(_, _, ?ann)) { ret ann_to_type(ann); } - case (ast.expr_block(_, ?ann)) { ret ann_to_type(ann); } - case (ast.expr_assign(_, _, ?ann)) { ret ann_to_type(ann); } - case (ast.expr_assign_op(_, _, _, ?ann)) - { ret ann_to_type(ann); } - case (ast.expr_field(_, _, ?ann)) { ret ann_to_type(ann); } - case (ast.expr_index(_, _, ?ann)) { ret ann_to_type(ann); } - case (ast.expr_name(_, _, ?ann)) { ret ann_to_type(ann); } - } - fail; -} - // Type unification -fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result { +fn unify(&fn_ctxt fcx, @ty.t expected, @ty.t actual) -> unify_result { // Wraps the given type in an appropriate cname. // // TODO: This doesn't do anything yet. We should carry the cname up from @@ -1072,7 +515,7 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result { // something we'll probably need to develop over time. // Simple structural type comparison. - fn struct_cmp(@ty expected, @ty actual) -> unify_result { + fn struct_cmp(@ty.t expected, @ty.t actual) -> unify_result { if (expected.struct == actual.struct) { ret ures_ok(expected); } @@ -1080,28 +523,28 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result { ret ures_err(terr_mismatch, expected, actual); } - fn unify_step(&fn_ctxt fcx, &hashmap[int,@ty] bindings, @ty expected, - @ty actual) -> unify_result { + fn unify_step(&fn_ctxt fcx, &hashmap[int,@ty.t] bindings, @ty.t expected, + @ty.t actual) -> unify_result { // TODO: rewrite this using tuple pattern matching when available, to // avoid all this rightward drift and spikiness. // If the RHS is a variable type, then just do the appropriate // binding. alt (actual.struct) { - case (ty_var(?actual_id)) { + case (ty.ty_var(?actual_id)) { alt (bindings.find(actual_id)) { - case (some[@ty](?actual_ty)) { + case (some[@ty.t](?actual_ty)) { // FIXME: change the binding here? // FIXME: "be" ret unify_step(fcx, bindings, expected, actual_ty); } - case (none[@ty]) { + case (none[@ty.t]) { bindings.insert(actual_id, expected); ret ures_ok(expected); } } } - case (ty_local(?actual_id)) { + case (ty.ty_local(?actual_id)) { check (fcx.locals.contains_key(actual_id)); auto actual_ty = fcx.locals.get(actual_id); auto result = unify_step(fcx, bindings, expected, actual_ty); @@ -1117,17 +560,17 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result { } alt (expected.struct) { - case (ty_nil) { ret struct_cmp(expected, actual); } - case (ty_bool) { ret struct_cmp(expected, actual); } - case (ty_int) { ret struct_cmp(expected, actual); } - case (ty_uint) { ret struct_cmp(expected, actual); } - case (ty_machine(_)) { ret struct_cmp(expected, actual); } - case (ty_char) { ret struct_cmp(expected, actual); } - case (ty_str) { ret struct_cmp(expected, actual); } + case (ty.ty_nil) { ret struct_cmp(expected, actual); } + case (ty.ty_bool) { ret struct_cmp(expected, actual); } + case (ty.ty_int) { ret struct_cmp(expected, actual); } + case (ty.ty_uint) { ret struct_cmp(expected, actual); } + case (ty.ty_machine(_)) { ret struct_cmp(expected, actual); } + case (ty.ty_char) { ret struct_cmp(expected, actual); } + case (ty.ty_str) { ret struct_cmp(expected, actual); } - case (ty_tag(?expected_id)) { + case (ty.ty_tag(?expected_id)) { alt (actual.struct) { - case (ty_tag(?actual_id)) { + case (ty.ty_tag(?actual_id)) { if (expected_id._0 == actual_id._0 && expected_id._1 == actual_id._1) { ret ures_ok(expected); @@ -1139,16 +582,16 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result { ret ures_err(terr_mismatch, expected, actual); } - case (ty_box(?expected_sub)) { + case (ty.ty_box(?expected_sub)) { alt (actual.struct) { - case (ty_box(?actual_sub)) { + case (ty.ty_box(?actual_sub)) { auto result = unify_step(fcx, bindings, expected_sub, actual_sub); alt (result) { case (ures_ok(?result_sub)) { - ret ures_ok(plain_ty(ty_box(result_sub))); + ret ures_ok(plain_ty(ty.ty_box(result_sub))); } case (_) { ret result; @@ -1164,16 +607,16 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result { } } - case (ty_vec(?expected_sub)) { + case (ty.ty_vec(?expected_sub)) { alt (actual.struct) { - case (ty_vec(?actual_sub)) { + case (ty.ty_vec(?actual_sub)) { auto result = unify_step(fcx, bindings, expected_sub, actual_sub); alt (result) { case (ures_ok(?result_sub)) { - ret ures_ok(plain_ty(ty_vec(result_sub))); + ret ures_ok(plain_ty(ty.ty_vec(result_sub))); } case (_) { ret result; @@ -1189,11 +632,11 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result { } } - case (ty_tup(?expected_elems)) { + case (ty.ty_tup(?expected_elems)) { alt (actual.struct) { - case (ty_tup(?actual_elems)) { - auto expected_len = _vec.len[@ty](expected_elems); - auto actual_len = _vec.len[@ty](actual_elems); + case (ty.ty_tup(?actual_elems)) { + auto expected_len = _vec.len[@ty.t](expected_elems); + auto actual_len = _vec.len[@ty.t](actual_elems); if (expected_len != actual_len) { auto err = terr_tuple_size(expected_len, actual_len); @@ -1202,7 +645,7 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result { // TODO: implement an iterator that can iterate over // two arrays simultaneously. - let vec[@ty] result_elems = vec(); + let vec[@ty.t] result_elems = vec(); auto i = 0u; while (i < expected_len) { auto expected_elem = expected_elems.(i); @@ -1218,7 +661,7 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result { actual_elem); alt (result) { case (ures_ok(?rty)) { - append[@ty](result_elems,rty); + append[@ty.t](result_elems,rty); } case (_) { ret result; @@ -1228,7 +671,7 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result { i += 1u; } - ret ures_ok(plain_ty(ty_tup(result_elems))); + ret ures_ok(plain_ty(ty.ty_tup(result_elems))); } // TODO: ty_var @@ -1239,9 +682,9 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result { } } - case (ty_rec(?expected_fields)) { + case (ty.ty_rec(?expected_fields)) { alt (actual.struct) { - case (ty_rec(?actual_fields)) { + case (ty.ty_rec(?actual_fields)) { auto expected_len = _vec.len[field](expected_fields); auto actual_len = _vec.len[field](actual_fields); if (expected_len != actual_len) { @@ -1289,7 +732,7 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result { i += 1u; } - ret ures_ok(plain_ty(ty_rec(result_fields))); + ret ures_ok(plain_ty(ty.ty_rec(result_fields))); } // TODO: ty_var @@ -1300,9 +743,9 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result { } } - case (ty_fn(?expected_inputs, ?expected_output)) { + case (ty.ty_fn(?expected_inputs, ?expected_output)) { alt (actual.struct) { - case (ty_fn(?actual_inputs, ?actual_output)) { + case (ty.ty_fn(?actual_inputs, ?actual_output)) { auto expected_len = _vec.len[arg](expected_inputs); auto actual_len = _vec.len[arg](actual_inputs); if (expected_len != actual_len) { @@ -1360,7 +803,8 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result { } } - ret ures_ok(plain_ty(ty_fn(result_ins, result_out))); + auto t = plain_ty(ty.ty_fn(result_ins, result_out)); + ret ures_ok(t); } case (_) { @@ -1369,21 +813,21 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result { } } - case (ty_var(?expected_id)) { + case (ty.ty_var(?expected_id)) { alt (bindings.find(expected_id)) { - case (some[@ty](?expected_ty)) { + case (some[@ty.t](?expected_ty)) { // FIXME: change the binding here? // FIXME: "be" ret unify_step(fcx, bindings, expected_ty, actual); } - case (none[@ty]) { + case (none[@ty.t]) { bindings.insert(expected_id, actual); ret ures_ok(actual); } } } - case (ty_local(?expected_id)) { + case (ty.ty_local(?expected_id)) { check (fcx.locals.contains_key(expected_id)); auto expected_ty = fcx.locals.get(expected_id); auto result = unify_step(fcx, bindings, expected_ty, actual); @@ -1396,9 +840,9 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result { ret result; } - case (ty_param(?expected_id)) { + case (ty.ty_param(?expected_id)) { alt (actual.struct) { - case (ty_param(?actual_id)) { + case (ty.ty_param(?actual_id)) { if (expected_id._0 == actual_id._0 && expected_id._1 == actual_id._1) { ret ures_ok(expected); @@ -1419,14 +863,14 @@ fn unify(&fn_ctxt fcx, @ty expected, @ty actual) -> unify_result { fn eq_int(&int a, &int b) -> bool { ret a == b; } auto hasher = hash_int; auto eqer = eq_int; - auto bindings = map.mk_hashmap[int,@ty](hasher, eqer); + auto bindings = map.mk_hashmap[int,@ty.t](hasher, eqer); ret unify_step(fcx, bindings, expected, actual); } // Requires that the two types unify, and prints an error message if they // don't. Returns the unified type. -fn demand(&fn_ctxt fcx, &span sp, @ty expected, @ty actual) -> @ty { +fn demand(&fn_ctxt fcx, &span sp, @ty.t expected, @ty.t actual) -> @ty.t { alt (unify(fcx, expected, actual)) { case (ures_ok(?ty)) { ret ty; @@ -1446,7 +890,7 @@ fn demand(&fn_ctxt fcx, &span sp, @ty expected, @ty actual) -> @ty { } // Returns true if the two types unify and false if they don't. -fn are_compatible(&fn_ctxt fcx, @ty expected, @ty actual) -> bool { +fn are_compatible(&fn_ctxt fcx, @ty.t expected, @ty.t actual) -> bool { alt (unify(fcx, expected, actual)) { case (ures_ok(_)) { ret true; } case (ures_err(_, _, _)) { ret false; } @@ -1458,7 +902,7 @@ fn are_compatible(&fn_ctxt fcx, @ty expected, @ty actual) -> bool { // // TODO: enforce this via a predicate. -fn demand_pat(&fn_ctxt fcx, @ty expected, @ast.pat pat) -> @ast.pat { +fn demand_pat(&fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { auto p_1 = ast.pat_wild(ast.ann_none); // FIXME: typestate botch alt (pat.node) { @@ -1489,12 +933,12 @@ fn demand_pat(&fn_ctxt fcx, @ty expected, @ast.pat pat) -> @ast.pat { auto subpats_len = _vec.len[@ast.pat](subpats); alt (variant_ty.struct) { - case (ty_tag(_)) { + case (ty.ty_tag(_)) { // Nullary tag variant. check (subpats_len == 0u); p_1 = ast.pat_tag(id, subpats, vdef_opt, ast.ann_type(t)); } - case (ty_fn(?args, ?tag_ty)) { + case (ty.ty_fn(?args, ?tag_ty)) { let vec[@ast.pat] new_subpats = vec(); auto i = 0u; for (arg a in args) { @@ -1519,7 +963,7 @@ fn demand_pat(&fn_ctxt fcx, @ty expected, @ast.pat pat) -> @ast.pat { // TODO: propagate the types downward. This makes the typechecker quadratic, // but we can mitigate that if expected == actual == unified. -fn demand_expr(&fn_ctxt fcx, @ty expected, @ast.expr e) -> @ast.expr { +fn demand_expr(&fn_ctxt fcx, @ty.t expected, @ast.expr e) -> @ast.expr { // FIXME: botch to work around typestate bug in rustboot let vec[@ast.expr] v = vec(); auto e_1 = ast.expr_vec(v, ast.ann_none); @@ -1529,7 +973,7 @@ fn demand_expr(&fn_ctxt fcx, @ty expected, @ast.expr e) -> @ast.expr { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); let vec[@ast.expr] es_1 = vec(); alt (t.struct) { - case (ty_vec(?subty)) { + case (ty.ty_vec(?subty)) { for (@ast.expr e_0 in es_0) { es_1 += vec(demand_expr(fcx, subty, e_0)); } @@ -1545,7 +989,7 @@ fn demand_expr(&fn_ctxt fcx, @ty expected, @ast.expr e) -> @ast.expr { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); let vec[ast.elt] elts_1 = vec(); alt (t.struct) { - case (ty_tup(?subtys)) { + case (ty.ty_tup(?subtys)) { auto i = 0u; for (ast.elt elt_0 in es_0) { auto e_1 = demand_expr(fcx, subtys.(i), elt_0.expr); @@ -1564,7 +1008,7 @@ fn demand_expr(&fn_ctxt fcx, @ty expected, @ast.expr e) -> @ast.expr { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); let vec[ast.field] fields_1 = vec(); alt (t.struct) { - case (ty_rec(?field_tys)) { + case (ty.ty_rec(?field_tys)) { auto i = 0u; for (ast.field field_0 in fields_0) { check (_str.eq(field_0.ident, field_tys.(i).ident)); @@ -1661,7 +1105,7 @@ fn demand_expr(&fn_ctxt fcx, @ty expected, @ast.expr e) -> @ast.expr { } // Type unification over typed blocks. -fn demand_block(&fn_ctxt fcx, @ty expected, &ast.block bloc) -> ast.block { +fn demand_block(&fn_ctxt fcx, @ty.t expected, &ast.block bloc) -> ast.block { alt (bloc.node.expr) { case (some[@ast.expr](?e_0)) { auto e_1 = demand_expr(fcx, expected, e_0); @@ -1671,7 +1115,7 @@ fn demand_block(&fn_ctxt fcx, @ty expected, &ast.block bloc) -> ast.block { ret fold.respan[ast.block_](bloc.span, block_); } case (none[@ast.expr]) { - demand(fcx, bloc.span, expected, plain_ty(ty_nil)); + demand(fcx, bloc.span, expected, plain_ty(ty.ty_nil)); ret bloc; } } @@ -1699,18 +1143,16 @@ fn writeback(&fn_ctxt fcx, &ast.block block) -> ast.block { // AST fragment checking -fn check_lit(@ast.lit lit) -> @ty { +fn check_lit(@ast.lit lit) -> @ty.t { auto sty; alt (lit.node) { - case (ast.lit_str(_)) { sty = ty_str; } - case (ast.lit_char(_)) { sty = ty_char; } - case (ast.lit_int(_)) { sty = ty_int; } - case (ast.lit_uint(_)) { sty = ty_uint; } - case (ast.lit_mach_int(?tm, _)) { - sty = ty_machine(tm); - } - case (ast.lit_nil) { sty = ty_nil; } - case (ast.lit_bool(_)) { sty = ty_bool; } + case (ast.lit_str(_)) { sty = ty.ty_str; } + case (ast.lit_char(_)) { sty = ty.ty_char; } + case (ast.lit_int(_)) { sty = ty.ty_int; } + case (ast.lit_uint(_)) { sty = ty.ty_uint; } + case (ast.lit_mach_int(?tm, _)) { sty = ty.ty_machine(tm); } + case (ast.lit_nil) { sty = ty.ty_nil; } + case (ast.lit_bool(_)) { sty = ty.ty_bool; } } ret plain_ty(sty); @@ -1731,7 +1173,7 @@ fn check_pat(&fn_ctxt fcx, @ast.pat pat) -> @ast.pat { auto t = fcx.ccx.item_types.get(vdef._1); alt (t.struct) { // N-ary variants have function types. - case (ty_fn(?args, ?tag_ty)) { + case (ty.ty_fn(?args, ?tag_ty)) { auto arg_len = _vec.len[arg](args); auto subpats_len = _vec.len[@ast.pat](subpats); if (arg_len != subpats_len) { @@ -1755,7 +1197,7 @@ fn check_pat(&fn_ctxt fcx, @ast.pat pat) -> @ast.pat { } // Nullary variants have tag types. - case (ty_tag(?tid)) { + case (ty.ty_tag(?tid)) { auto subpats_len = _vec.len[@ast.pat](subpats); if (subpats_len > 0u) { // TODO: pluralize properly @@ -1768,7 +1210,7 @@ fn check_pat(&fn_ctxt fcx, @ast.pat pat) -> @ast.pat { fail; // TODO: recover } - auto ann = ast.ann_type(plain_ty(ty_tag(tid))); + auto ann = ast.ann_type(plain_ty(ty.ty_tag(tid))); new_pat = ast.pat_tag(id, subpats, vdef_opt, ann); } } @@ -1799,12 +1241,12 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto t = lhs_t0; alt (binop) { - case (ast.eq) { t = plain_ty(ty_bool); } - case (ast.lt) { t = plain_ty(ty_bool); } - case (ast.le) { t = plain_ty(ty_bool); } - case (ast.ne) { t = plain_ty(ty_bool); } - case (ast.ge) { t = plain_ty(ty_bool); } - case (ast.gt) { t = plain_ty(ty_bool); } + case (ast.eq) { t = plain_ty(ty.ty_bool); } + case (ast.lt) { t = plain_ty(ty.ty_bool); } + case (ast.le) { t = plain_ty(ty.ty_bool); } + case (ast.ne) { t = plain_ty(ty.ty_bool); } + case (ast.ge) { t = plain_ty(ty.ty_bool); } + case (ast.gt) { t = plain_ty(ty.ty_bool); } case (_) { /* fall through */ } } ret @fold.respan[ast.expr_](expr.span, @@ -1817,10 +1259,10 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto oper_1 = check_expr(fcx, oper); auto oper_t = expr_ty(oper_1); alt (unop) { - case (ast.box) { oper_t = plain_ty(ty_box(oper_t)); } + case (ast.box) { oper_t = plain_ty(ty.ty_box(oper_t)); } case (ast.deref) { alt (oper_t.struct) { - case (ty_box(?inner_t)) { + case (ty.ty_box(?inner_t)) { oper_t = inner_t; } case (_) { @@ -1839,7 +1281,7 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } case (ast.expr_name(?name, ?defopt, _)) { - auto t = plain_ty(ty_nil); + auto t = plain_ty(ty.ty_nil); check (defopt != none[ast.def]); alt (option.get[ast.def](defopt)) { case (ast.def_arg(?id)) { @@ -1848,8 +1290,8 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } case (ast.def_local(?id)) { alt (fcx.locals.find(id)) { - case (some[@ty](?t1)) { t = t1; } - case (none[@ty]) { t = plain_ty(ty_local(id)); } + case (some[@ty.t](?t1)) { t = t1; } + case (none[@ty.t]) { t = plain_ty(ty.ty_local(id)); } } } case (ast.def_fn(?id)) { @@ -1917,7 +1359,7 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { case (ast.expr_if(?cond, ?thn, ?elsopt, _)) { auto cond_0 = check_expr(fcx, cond); - auto cond_1 = demand_expr(fcx, plain_ty(ty_bool), cond_0); + auto cond_1 = demand_expr(fcx, plain_ty(ty.ty_bool), cond_0); auto thn_0 = check_block(fcx, thn); auto thn_t = block_ty(thn_0); @@ -1933,7 +1375,7 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } case (none[ast.block]) { elsopt_1 = none[ast.block]; - elsopt_t = plain_ty(ty_nil); + elsopt_t = plain_ty(ty.ty_nil); } } @@ -1946,17 +1388,17 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { case (ast.expr_while(?cond, ?body, _)) { auto cond_0 = check_expr(fcx, cond); - auto cond_1 = demand_expr(fcx, plain_ty(ty_bool), cond_0); + auto cond_1 = demand_expr(fcx, plain_ty(ty.ty_bool), cond_0); auto body_1 = check_block(fcx, body); - auto ann = ast.ann_type(plain_ty(ty_nil)); + auto ann = ast.ann_type(plain_ty(ty.ty_nil)); ret @fold.respan[ast.expr_](expr.span, ast.expr_while(cond_1, body_1, ann)); } case (ast.expr_do_while(?body, ?cond, _)) { auto cond_0 = check_expr(fcx, cond); - auto cond_1 = demand_expr(fcx, plain_ty(ty_bool), cond_0); + auto cond_1 = demand_expr(fcx, plain_ty(ty.ty_bool), cond_0); auto body_1 = check_block(fcx, body); auto ann = ast.ann_type(block_ty(body_1)); @@ -2030,17 +1472,17 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { append[arg](arg_tys_0, rec(mode=ast.val, ty=expr_ty(a_0))); } auto rt_0 = next_ty_var(fcx.ccx); - auto t_0 = plain_ty(ty_fn(arg_tys_0, rt_0)); + auto t_0 = plain_ty(ty.ty_fn(arg_tys_0, rt_0)); // Unify and write back to the function. auto f_1 = demand_expr(fcx, t_0, f_0); // Take the argument types out of the resulting function type. auto t_1 = expr_ty(f_1); - let vec[arg] arg_tys_1 = vec(); // TODO: typestate botch - let @ty rt_1 = plain_ty(ty_nil); // TODO: typestate botch + let vec[arg] arg_tys_1 = vec(); // TODO: typestate botch + let @ty.t rt_1 = plain_ty(ty.ty_nil); // TODO: typestate botch alt (t_1.struct) { - case (ty_fn(?arg_tys, ?rt)) { + case (ty.ty_fn(?arg_tys, ?rt)) { arg_tys_1 = arg_tys; rt_1 = rt; } @@ -2091,7 +1533,7 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { // FIXME: implement mutable vectors with leading 'mutable' flag // marking the elements as mutable. - let @ty t; + let @ty.t t; if (_vec.len[@ast.expr](args) == 0u) { t = next_ty_var(fcx.ccx); } else { @@ -2105,14 +1547,14 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { demand(fcx, expr.span, t, expr_t); append[@ast.expr](args_1,expr_1); } - auto ann = ast.ann_type(plain_ty(ty_vec(t))); + auto ann = ast.ann_type(plain_ty(ty.ty_vec(t))); ret @fold.respan[ast.expr_](expr.span, ast.expr_vec(args_1, ann)); } case (ast.expr_tup(?elts, _)) { let vec[ast.elt] elts_1 = vec(); - let vec[@ty] elts_t = vec(); + let vec[@ty.t] elts_t = vec(); for (ast.elt e in elts) { auto expr_1 = check_expr(fcx, e.expr); @@ -2121,10 +1563,10 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { expr_t = @rec(mut=ast.mut with *expr_t); } append[ast.elt](elts_1, rec(expr=expr_1 with e)); - append[@ty](elts_t, expr_t); + append[@ty.t](elts_t, expr_t); } - auto ann = ast.ann_type(plain_ty(ty_tup(elts_t))); + auto ann = ast.ann_type(plain_ty(ty.ty_tup(elts_t))); ret @fold.respan[ast.expr_](expr.span, ast.expr_tup(elts_1, ann)); } @@ -2143,7 +1585,7 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { append[field](fields_t, rec(ident=f.ident, ty=expr_t)); } - auto ann = ast.ann_type(plain_ty(ty_rec(fields_t))); + auto ann = ast.ann_type(plain_ty(ty.ty_rec(fields_t))); ret @fold.respan[ast.expr_](expr.span, ast.expr_rec(fields_1, ann)); } @@ -2152,10 +1594,10 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto base_1 = check_expr(fcx, base); auto base_t = expr_ty(base_1); alt (base_t.struct) { - case (ty_tup(?args)) { - let uint ix = field_num(fcx.ccx.sess, - expr.span, field); - if (ix >= _vec.len[@ty](args)) { + case (ty.ty_tup(?args)) { + let uint ix = ty.field_num(fcx.ccx.sess, + expr.span, field); + if (ix >= _vec.len[@ty.t](args)) { fcx.ccx.sess.span_err(expr.span, "bad index on tuple"); } @@ -2166,9 +1608,9 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { ann)); } - case (ty_rec(?fields)) { - let uint ix = field_idx(fcx.ccx.sess, - expr.span, field, fields); + case (ty.ty_rec(?fields)) { + let uint ix = ty.field_idx(fcx.ccx.sess, + expr.span, field, fields); if (ix >= _vec.len[typeck.field](fields)) { fcx.ccx.sess.span_err(expr.span, "bad index on record"); @@ -2180,16 +1622,16 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { ann)); } - case (ty_obj(?methods)) { - let uint ix = method_idx(fcx.ccx.sess, - expr.span, field, methods); + case (ty.ty_obj(?methods)) { + let uint ix = ty.method_idx(fcx.ccx.sess, + expr.span, field, methods); if (ix >= _vec.len[typeck.method](methods)) { fcx.ccx.sess.span_err(expr.span, "bad index on obj"); } auto meth = methods.(ix); - auto ty = plain_ty(ty_fn(meth.inputs, meth.output)); - auto ann = ast.ann_type(ty); + auto t = plain_ty(ty.ty_fn(meth.inputs, meth.output)); + auto ann = ast.ann_type(t); ret @fold.respan[ast.expr_](expr.span, ast.expr_field(base_1, field, @@ -2212,7 +1654,7 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto idx_t = expr_ty(idx_1); alt (base_t.struct) { - case (ty_vec(?t)) { + case (ty.ty_vec(?t)) { if (! type_is_integral(idx_t)) { fcx.ccx.sess.span_err (idx.span, @@ -2225,14 +1667,14 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { idx_1, ann)); } - case (ty_str) { + case (ty.ty_str) { if (! type_is_integral(idx_t)) { fcx.ccx.sess.span_err (idx.span, "non-integral type of str index: " + ty_to_str(idx_t)); } - auto t = ty_machine(common.ty_u8); + auto t = ty.ty_machine(common.ty_u8); auto ann = ast.ann_type(plain_ty(t)); ret @fold.respan[ast.expr_](expr.span, ast.expr_index(base_1, @@ -2256,8 +1698,8 @@ fn check_expr(&fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } } -fn next_ty_var(@crate_ctxt ccx) -> @ty { - auto t = plain_ty(ty_var(ccx.next_var_id)); +fn next_ty_var(@crate_ctxt ccx) -> @ty.t { + auto t = plain_ty(ty.ty_var(ccx.next_var_id)); ccx.next_var_id += 1; ret t; } @@ -2287,7 +1729,7 @@ fn check_stmt(&fn_ctxt fcx, &@ast.stmt stmt) alt (local.init) { case (some[@ast.expr](?expr)) { auto expr_0 = check_expr(fcx, expr); - auto lty = plain_ty(ty_local(local.id)); + auto lty = plain_ty(ty.ty_local(local.id)); auto expr_1 = demand_expr(fcx, lty, expr_0); init = some[@ast.expr](expr_1); } @@ -2312,7 +1754,8 @@ fn check_stmt(&fn_ctxt fcx, &@ast.stmt stmt) case (ast.stmt_ret(?expr_opt)) { alt (expr_opt) { case (none[@ast.expr]) { - if (!are_compatible(fcx, fcx.ret_ty, plain_ty(ty_nil))) { + auto nil = plain_ty(ty.ty_nil); + if (!are_compatible(fcx, fcx.ret_ty, nil)) { fcx.ccx.sess.err("ret; in function " + "returning non-nil"); } @@ -2336,7 +1779,7 @@ fn check_stmt(&fn_ctxt fcx, &@ast.stmt stmt) case (ast.stmt_check_expr(?expr)) { auto expr_t = check_expr(fcx, expr); - demand(fcx, expr.span, plain_ty(ty_bool), expr_ty(expr_t)); + demand(fcx, expr.span, plain_ty(ty.ty_bool), expr_ty(expr_t)); ret @fold.respan[ast.stmt_](stmt.span, ast.stmt_check_expr(expr_t)); } @@ -2375,7 +1818,7 @@ fn check_const(&@crate_ctxt ccx, &span sp, ast.ident ident, @ast.ty t, // for checking the initializer expression. auto rty = ann_to_type(ann); let fn_ctxt fcx = rec(ret_ty = rty, - locals = @common.new_def_hash[@ty](), + locals = @common.new_def_hash[@ty.t](), ccx = ccx); auto e_ = check_expr(fcx, e); // FIXME: necessary? Correct sequence? @@ -2387,7 +1830,7 @@ fn check_const(&@crate_ctxt ccx, &span sp, ast.ident ident, @ast.ty t, fn check_fn(&@crate_ctxt ccx, ast.effect effect, vec[ast.arg] inputs, @ast.ty output, &ast.block body) -> ast._fn { - auto local_ty_table = @common.new_def_hash[@ty](); + auto local_ty_table = @common.new_def_hash[@ty.t](); // FIXME: duplicate work: the item annotation already has the arg types // and return type translated to typeck.ty values. We don't need do to it @@ -2426,7 +1869,7 @@ fn check_item_fn(&@crate_ctxt ccx, &span sp, ast.ident ident, &ast._fn f, } auto output_ty = ast_ty_to_ty_crate(ccx, f.output); - auto fn_sty = ty_fn(inputs, output_ty); + auto fn_sty = ty.ty_fn(inputs, output_ty); auto fn_ann = ast.ann_type(plain_ty(fn_sty)); auto item = ast.item_fn(ident, f, ty_params, id, fn_ann); diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc index ef9be053585..8f5414158f9 100644 --- a/src/comp/rustc.rc +++ b/src/comp/rustc.rc @@ -14,6 +14,7 @@ mod middle { mod fold; mod resolve; mod trans; + mod ty; mod typeck; }