diff options
| author | Patrick Walton <[email protected]> | 2011-02-17 16:23:31 -0800 |
|---|---|---|
| committer | Patrick Walton <[email protected]> | 2011-02-17 16:23:31 -0800 |
| commit | 10befcd9a4d9f68e2dbec84c4a86450a021143fb (patch) | |
| tree | 7485ae8b66f3349e3987b480d4be44b34e01af5b /src | |
| parent | Steps toward implementing iterators. (diff) | |
| download | rust-10befcd9a4d9f68e2dbec84c4a86450a021143fb.tar.xz rust-10befcd9a4d9f68e2dbec84c4a86450a021143fb.zip | |
Add type parameters to tag types
Diffstat (limited to 'src')
| -rw-r--r-- | src/comp/middle/trans.rs | 6 | ||||
| -rw-r--r-- | src/comp/middle/ty.rs | 87 | ||||
| -rw-r--r-- | src/comp/middle/typeck.rs | 38 | ||||
| -rw-r--r-- | src/test/run-pass/generic-tag.rs | 2 |
4 files changed, 99 insertions, 34 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 62b5a415..9d336f22 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -490,7 +490,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { } case (ty.ty_char) { ret T_char(); } case (ty.ty_str) { ret T_ptr(T_str()); } - case (ty.ty_tag(?tag_id)) { + case (ty.ty_tag(?tag_id, _)) { ret llvm.LLVMResolveTypeHandle(cx.tags.get(tag_id).th.llth); } case (ty.ty_box(?t)) { @@ -1445,7 +1445,9 @@ fn iter_structural_ty(@block_ctxt cx, i += 1; } } - case (ty.ty_tag(?tid)) { + case (ty.ty_tag(?tid, _)) { + // TODO: type params! + 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); diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index adda5a8c..e8f5b046 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -32,7 +32,7 @@ tag sty { ty_machine(util.common.ty_mach); ty_char; ty_str; - ty_tag(ast.def_id); + ty_tag(ast.def_id, vec[@t]); ty_box(@t); ty_vec(@t); ty_tup(vec[@t]); @@ -42,7 +42,7 @@ tag sty { 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 + ty_param(ast.def_id); // fn/tag type param ty_type; ty_native; // TODO: ty_fn_arg(@t), for a possibly-aliased function argument @@ -235,9 +235,14 @@ fn ty_to_str(&@t typ) -> str { s = "rec(" + _str.connect(strs, ",") + ")"; } - case (ty_tag(_)) { + case (ty_tag(_, ?tps)) { // The user should never see this if the cname is set properly! s = "<tag>"; + if (_vec.len[@t](tps) > 0u) { + auto f = ty_to_str; + auto strs = _vec.map[@t,str](f, tps); + s += "[" + _str.connect(strs, ",") + "]"; + } } case (ty_fn(?inputs, ?output)) { @@ -291,7 +296,6 @@ fn fold_ty(ty_fold fld, @t ty) -> @t { 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_type) { ret fld.fold_simple_ty(ty); } case (ty_native) { ret fld.fold_simple_ty(ty); } case (ty_box(?subty)) { @@ -300,6 +304,13 @@ fn fold_ty(ty_fold fld, @t ty) -> @t { case (ty_vec(?subty)) { ret rewrap(ty, ty_vec(fold_ty(fld, subty))); } + case (ty_tag(?tid, ?subtys)) { + let vec[@t] new_subtys = vec(); + for (@t subty in subtys) { + new_subtys += vec(fold_ty(fld, subty)); + } + ret rewrap(ty, ty_tag(tid, new_subtys)); + } case (ty_tup(?subtys)) { let vec[@t] new_subtys = vec(); for (@t subty in subtys) { @@ -364,23 +375,23 @@ fn type_is_nil(@t ty) -> bool { 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; } + 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_tup_like(@t ty) -> bool { alt (ty.struct) { - case (ty_box(_)) { ret true; } - case (ty_tup(_)) { ret true; } - case (ty_rec(_)) { ret true; } - case (ty_tag(_)) { ret true; } - case (_) { ret false; } + case (ty_box(_)) { ret true; } + case (ty_tup(_)) { ret true; } + case (ty_rec(_)) { ret true; } + case (ty_tag(_,_)) { ret true; } + case (_) { ret false; } } fail; } @@ -641,8 +652,13 @@ fn item_ty(@ast.item it) -> ty_params_and_ty { result_ty = ann_to_type(ann); } case (ast.item_tag(_, _, ?tps, ?did)) { + // Create a new generic polytype. ty_params = tps; - result_ty = plain_ty(ty_tag(did)); + let vec[@t] subtys = vec(); + for (ast.ty_param tp in tps) { + subtys += vec(plain_ty(ty_param(tp.id))); + } + result_ty = plain_ty(ty_tag(did, subtys)); } case (ast.item_obj(_, _, ?tps, _, ?ann)) { ty_params = tps; @@ -1001,13 +1017,42 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) case (ty.ty_type) { ret struct_cmp(expected, actual); } case (ty.ty_native) { ret struct_cmp(expected, actual); } - case (ty.ty_tag(?expected_id)) { + case (ty.ty_tag(?expected_id, ?expected_tps)) { alt (actual.struct) { - case (ty.ty_tag(?actual_id)) { - if (expected_id._0 == actual_id._0 && - expected_id._1 == actual_id._1) { - ret ures_ok(expected); + case (ty.ty_tag(?actual_id, ?actual_tps)) { + if (expected_id._0 != actual_id._0 || + expected_id._1 != actual_id._1) { + ret ures_err(terr_mismatch, expected, actual); + } + + // TODO: factor this cruft out, see the TODO in the + // ty.ty_tup case + let vec[@ty.t] result_tps = vec(); + auto i = 0u; + auto expected_len = _vec.len[@ty.t](expected_tps); + while (i < expected_len) { + auto expected_tp = expected_tps.(i); + auto actual_tp = actual_tps.(i); + + auto result = unify_step(bindings, + expected_tp, + actual_tp, + handler); + + alt (result) { + case (ures_ok(?rty)) { + append[@ty.t](result_tps, rty); + } + case (_) { + ret result; + } + } + + i += 1u; } + + ret ures_ok(plain_ty(ty.ty_tag(expected_id, + result_tps))); } case (_) { /* fall through */ } } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 3dab25a7..aa5e9fe5 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -430,8 +430,13 @@ fn collect_item_types(session.session sess, @ast.crate crate) ret ty_; } - case (ast.item_tag(_, _, _, ?def_id)) { - auto t = plain_ty(ty.ty_tag(def_id)); + case (ast.item_tag(_, _, ?tps, ?def_id)) { + // Create a new generic polytype. + let vec[@ty.t] subtys = vec(); + for (ast.ty_param tp in tps) { + subtys += vec(plain_ty(ty.ty_param(tp.id))); + } + auto t = plain_ty(ty.ty_tag(def_id, subtys)); item_to_ty.insert(def_id, t); ret t; } @@ -468,15 +473,23 @@ fn collect_item_types(session.session sess, @ast.crate crate) fn get_tag_variant_types(@ty_item_table id_to_ty_item, @ty_table item_to_ty, &ast.def_id tag_id, - &vec[ast.variant] variants) -> vec[ast.variant] { + &vec[ast.variant] variants, + &vec[ast.ty_param] ty_params) + -> vec[ast.variant] { let vec[ast.variant] result = vec(); + // Create a set of parameter types shared among all the variants. + let vec[@ty.t] ty_param_tys = vec(); + for (ast.ty_param tp in ty_params) { + ty_param_tys += vec(plain_ty(ty.ty_param(tp.id))); + } + for (ast.variant variant in variants) { - // Nullary tag constructors get truned into constants; n-ary tag + // Nullary tag constructors get turned into constants; n-ary tag // constructors get turned into functions. auto result_ty; if (_vec.len[ast.variant_arg](variant.args) == 0u) { - result_ty = plain_ty(ty.ty_tag(tag_id)); + result_ty = plain_ty(ty.ty_tag(tag_id, ty_param_tys)); } else { // As above, tell ast_ty_to_ty() that trans_ty_item_to_ty() // should be called to resolve named types. @@ -487,7 +500,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) auto arg_ty = ast_ty_to_ty(f, va.ty); args += vec(rec(mode=ast.alias, ty=arg_ty)); } - auto tag_t = plain_ty(ty.ty_tag(tag_id)); + auto tag_t = plain_ty(ty.ty_tag(tag_id, ty_param_tys)); result_ty = plain_ty(ty.ty_fn(args, tag_t)); } @@ -674,7 +687,9 @@ fn collect_item_types(session.session sess, @ast.crate crate) ast.def_id id) -> @ast.item { auto variants_t = get_tag_variant_types(e.id_to_ty_item, e.item_to_ty, - id, variants); + id, + variants, + ty_params); auto item = ast.item_tag(i, variants_t, ty_params, id); ret @fold.respan[ast.item_](sp, item); } @@ -857,7 +872,7 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { auto subpats_len = _vec.len[@ast.pat](subpats); alt (variant_ty.struct) { - case (ty.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)); @@ -1198,7 +1213,9 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat { } // Nullary variants have tag types. - case (ty.ty_tag(?tid)) { + case (ty.ty_tag(?tid, _)) { + // TODO: ty params + auto subpats_len = _vec.len[@ast.pat](subpats); if (subpats_len > 0u) { // TODO: pluralize properly @@ -1212,7 +1229,8 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat { fail; // TODO: recover } - auto ann = ast.ann_type(plain_ty(ty.ty_tag(tid))); + let vec[@ty.t] tys = vec(); // FIXME + auto ann = ast.ann_type(plain_ty(ty.ty_tag(tid, tys))); new_pat = ast.pat_tag(p, subpats, vdef_opt, ann); } } diff --git a/src/test/run-pass/generic-tag.rs b/src/test/run-pass/generic-tag.rs index 1fd88255..68d7c18f 100644 --- a/src/test/run-pass/generic-tag.rs +++ b/src/test/run-pass/generic-tag.rs @@ -6,4 +6,4 @@ tag option[T] { fn main() { let option[int] a = some[int](@10); a = none[int]; -}
\ No newline at end of file +} |