From 503dec1d62c0432aff140758ad7bcb34ef6c060a Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 9 Feb 2012 14:16:12 -0800 Subject: [PATCH] Further WIP on classes Changes to resolve and typeck. Still nothning working yet. --- src/comp/metadata/tyencode.rs | 7 +++++++ src/comp/middle/resolve.rs | 14 +++++++++++++- src/comp/middle/shape.rs | 2 ++ src/comp/middle/ty.rs | 19 +++++++++++++++++-- src/comp/middle/typeck.rs | 29 ++++++++++++++++++++++++++--- src/test/run-pass/classes-simple.rs | 10 ++++++++++ 6 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 src/test/run-pass/classes-simple.rs diff --git a/src/comp/metadata/tyencode.rs b/src/comp/metadata/tyencode.rs index fd2f20c4913..4d8042477d0 100644 --- a/src/comp/metadata/tyencode.rs +++ b/src/comp/metadata/tyencode.rs @@ -192,6 +192,13 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) { w.write_char(']'); } ty::ty_opaque_box { w.write_char('B'); } + ty::ty_class(def, tys) { + w.write_str("c["); + w.write_str(cx.ds(def)); + w.write_char('|'); + for t: ty::t in tys { enc_ty(w, cx, t); } + w.write_char(']'); + } } } fn enc_proto(w: io::writer, proto: proto) { diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index aeb22d88c49..1d47fb0857a 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -472,6 +472,16 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt) { v.visit_ty(m.decl.output, msc, v); } } + ast::item_class(tps, members, ctor_id, ctor_decl, ctor_block) { + visit::visit_ty_params(tps, sc, v); + let ctor_scope = cons(scope_fn_expr(ctor_decl, ctor_id, tps), @sc); + for cm in members { + alt cm.node.decl { + class_method(i) { visit_item_with_scope(e, i, ctor_scope, v); } + _ { } // instance var -- nothing to do + } + } + } _ { visit::visit_item(i, sc, v); } } @@ -1209,7 +1219,9 @@ fn found_def_item(i: @ast::item, ns: namespace) -> option { } } ast::item_class(_, _, _, _, _) { - fail "class! don't know what to do"; + if ns == ns_type { + ret some(ast::def_class(local_def(i.id))); + } } ast::item_impl(_,_,_,_) { /* ??? */ } } diff --git a/src/comp/middle/shape.rs b/src/comp/middle/shape.rs index 5da184d1b5a..bdd43b883db 100644 --- a/src/comp/middle/shape.rs +++ b/src/comp/middle/shape.rs @@ -63,6 +63,7 @@ const shape_stack_fn: u8 = 26u8; const shape_bare_fn: u8 = 27u8; const shape_tydesc: u8 = 28u8; const shape_send_tydesc: u8 = 29u8; +const shape_class: u8 = 30u8; // FIXME: This is a bad API in trans_common. fn C_u8(n: u8) -> ValueRef { ret trans::common::C_u8(n as uint); } @@ -404,6 +405,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] { add_substr(s, sub); } ty::ty_iface(_, _) { s += [shape_iface]; } + ty::ty_class(_, _) { s += [shape_class]; } ty::ty_res(did, raw_subt, tps) { let subt = ty::substitute_type_params(ccx.tcx, tps, raw_subt); let ri = {did: did, t: subt}; diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 11f5c2ac3a0..a90e04c0373 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -40,6 +40,7 @@ export is_pred_ty; export lookup_item_type; export method; export method_idx; +export mk_class; export mk_ctxt; export mk_named, type_name; export mt; @@ -225,6 +226,7 @@ enum sty { ty_rec([field]), ty_fn(fn_ty), ty_iface(def_id, [t]), + ty_class(def_id, [t]), ty_res(def_id, t, [t]), ty_tup([t]), @@ -354,7 +356,7 @@ fn mk_t_named(cx: ctxt, st: sty, name: option) -> t { ty_opaque_box {} ty_param(_, _) { has_params = true; } ty_var(_) | ty_self(_) { has_vars = true; } - ty_enum(_, tys) | ty_iface(_, tys) { + ty_enum(_, tys) | ty_iface(_, tys) | ty_class(_, tys) { for tt in tys { derive_flags(has_params, has_vars, tt); } } ty_box(m) | ty_uniq(m) | ty_vec(m) | ty_ptr(m) { @@ -442,6 +444,10 @@ fn mk_iface(cx: ctxt, did: ast::def_id, tys: [t]) -> t { mk_t(cx, ty_iface(did, tys)) } +fn mk_class(cx: ctxt, class_id: ast::def_id, tys: [t]) -> t { + mk_t(cx, ty_class(class_id, tys)) +} + fn mk_res(cx: ctxt, did: ast::def_id, inner: t, tps: [t]) -> t { mk_t(cx, ty_res(did, inner, tps)) } @@ -487,7 +493,8 @@ fn walk_ty(cx: ctxt, ty: t, f: fn(t)) { ty_str | ty_send_type | ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) | ty_var(_) | ty_param(_, _) {} ty_box(tm) | ty_vec(tm) | ty_ptr(tm) { walk_ty(cx, tm.ty, f); } - ty_enum(_, subtys) | ty_iface(_, subtys) | ty_self(subtys) { + ty_enum(_, subtys) | ty_iface(_, subtys) | ty_class(_, subtys) + | ty_self(subtys) { for subty: t in subtys { walk_ty(cx, subty, f); } } ty_rec(fields) { @@ -1155,6 +1162,11 @@ fn hash_type_structure(st: sty) -> uint { ty_opaque_closure_ptr(ck_box) { 42u } ty_opaque_closure_ptr(ck_uniq) { 43u } ty_opaque_box { 44u } + ty_class(did, tys) { + let h = hash_def(45u, did); + for typ: t in tys { h = hash_subty(h, typ); } + h + } } } @@ -2410,6 +2422,9 @@ fn lookup_item_type(cx: ctxt, did: ast::def_id) -> ty_param_bounds_and_ty { alt cx.tcache.find(did) { some(tpt) { ret tpt; } none { + /* where do things get added to the cache? + Have to add class members */ + // The item is in this crate. The caller should have added it to the // type cache already assert did.crate != ast::local_crate; diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index dcc257956c7..3a7f8e2d55e 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -108,7 +108,9 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) -> } } ast::def_fn(id, _) | ast::def_const(id) | - ast::def_variant(_, id) { ret ty::lookup_item_type(fcx.ccx.tcx, id); } + ast::def_variant(_, id) | ast::def_class(id) + | ast::def_class_method(_, id) | ast::def_class_field(_, id) + { ret ty::lookup_item_type(fcx.ccx.tcx, id); } ast::def_binding(id) { assert (fcx.locals.contains_key(id.node)); let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id.node)); @@ -422,8 +424,12 @@ fn ty_of_item(tcx: ty::ctxt, mode: mode, it: @ast::item) tcx.tcache.insert(local_def(it.id), tpt); ret tpt; } - ast::item_class(_,_,_,_,_) { - fail "ty_of_item: implement item_class"; + ast::item_class(tps,_,_,_,_) { + let {bounds,params} = mk_ty_params(tcx, tps); + let t = ty::mk_class(tcx, local_def(it.id), params); + let tpt = {bounds: bounds, ty: t}; + tcx.tcache.insert(local_def(it.id), tpt); + ret tpt; } ast::item_impl(_, _, _, _) | ast::item_mod(_) | ast::item_native_mod(_) { fail; } @@ -755,6 +761,10 @@ mod collect { _ { fail; } } } + fn convert_class_item(cx: @ctxt, parent_ty: ty::t, + ci: ast::class_member) { + /* TODO */ + } fn convert(cx: @ctxt, it: @ast::item) { alt it.node { // These don't define types. @@ -847,6 +857,19 @@ mod collect { write_ty(cx.tcx, it.id, tpt.ty); ensure_iface_methods(cx.tcx, it.id); } + ast::item_class(tps, members, ctor_id, ctor_decl, ctor_block) { + let parent_ty = ty::lookup_item_type(cx.tcx, local_def(it.id)); + // Write the ctor type + let t_ctor = ty::mk_fn(cx.tcx, + ty_of_fn_decl(cx.tcx, m_collect, + ast::proto_any, ctor_decl)); + write_ty(cx.tcx, ctor_id, t_ctor); + /* FIXME: check for proper public/privateness */ + // Write the type of each of the members + for m in members { + convert_class_item(cx, parent_ty.ty, m.node.decl); + } + } _ { // This call populates the type cache with the converted type // of the item in passing. All we have to do here is to write diff --git a/src/test/run-pass/classes-simple.rs b/src/test/run-pass/classes-simple.rs new file mode 100644 index 00000000000..006c6392a6b --- /dev/null +++ b/src/test/run-pass/classes-simple.rs @@ -0,0 +1,10 @@ +// xfail-test +class cat { + priv { + let mutable meows : uint; + } + + let how_hungry : int; + + new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; } +} \ No newline at end of file