From ef50d0e668635824cc5ed86aaa385dd6f3181b53 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 31 Jan 2011 18:06:35 -0800 Subject: More work on derived tydescs. Can compile simple tests with generic objects. --- src/comp/middle/trans.rs | 78 ++++++++++++++++++++++++++++++------------------ src/comp/middle/ty.rs | 8 ++--- 2 files changed, 53 insertions(+), 33 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 8eb614e5..7755ed93 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -997,7 +997,7 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { vec(p2i(bcx.fcx.ccx.crate_ptr), sz.val, align.val, - C_int(n_params as int), + C_int((1u + n_params) as int), bcx.build.PtrToInt(tydescs, T_int()))); ret res(v.bcx, v.bcx.build.IntToPtr(v.val, T_ptr(T_tydesc()))); @@ -2193,6 +2193,34 @@ fn lval_val(@block_ctxt cx, ValueRef val) -> lval_result { llobj=none[ValueRef]); } +fn lval_generic_fn(@block_ctxt cx, + ty.ty_params_and_ty tpt, + ast.def_id fn_id, + &ast.ann ann) + -> lval_result { + + check (cx.fcx.ccx.fn_pairs.contains_key(fn_id)); + auto lv = lval_val(cx, cx.fcx.ccx.fn_pairs.get(fn_id)); + auto monoty = node_ann_type(cx.fcx.ccx, ann); + auto tys = ty.resolve_ty_params(tpt, monoty); + + if (_vec.len[@ty.t](tys) != 0u) { + auto bcx = cx; + let vec[ValueRef] tydescs = vec(); + for (@ty.t t in tys) { + auto td = get_tydesc(bcx, t); + bcx = td.bcx; + append[ValueRef](tydescs, td.val); + } + auto gen = rec( item_type = tpt._1, + tydescs = tydescs ); + lv = rec(res = res(bcx, lv.res.val), + generic = some[generic_info](gen) + with lv); + } + ret lv; +} + fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, &ast.ann ann) -> lval_result { alt (dopt) { @@ -2215,39 +2243,33 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, ret lval_mem(cx, cx.fcx.llobjfields.get(did)); } case (ast.def_fn(?did)) { - check (cx.fcx.ccx.fn_pairs.contains_key(did)); - check (cx.fcx.ccx.item_ids.contains_key(did)); - + check (cx.fcx.ccx.items.contains_key(did)); auto fn_item = cx.fcx.ccx.items.get(did); - auto lv = lval_val(cx, cx.fcx.ccx.fn_pairs.get(did)); - auto monoty = node_ann_type(cx.fcx.ccx, ann); - auto tys = ty.resolve_ty_params(fn_item, monoty); - - if (_vec.len[@ty.t](tys) != 0u) { - auto bcx = cx; - let vec[ValueRef] tydescs = vec(); - for (@ty.t t in tys) { - auto td = get_tydesc(bcx, t); - bcx = td.bcx; - append[ValueRef](tydescs, td.val); - } - auto gen = rec( item_type = ty.item_ty(fn_item)._1, - tydescs = tydescs ); - lv = rec(res = res(bcx, lv.res.val), - generic = some[generic_info](gen) - with lv); - } - - ret lv; + ret lval_generic_fn(cx, ty.item_ty(fn_item), did, ann); } case (ast.def_obj(?did)) { - check (cx.fcx.ccx.fn_pairs.contains_key(did)); - ret lval_val(cx, cx.fcx.ccx.fn_pairs.get(did)); + check (cx.fcx.ccx.items.contains_key(did)); + auto fn_item = cx.fcx.ccx.items.get(did); + ret lval_generic_fn(cx, ty.item_ty(fn_item), did, ann); } case (ast.def_variant(?tid, ?vid)) { check (cx.fcx.ccx.tags.contains_key(tid)); if (cx.fcx.ccx.fn_pairs.contains_key(vid)) { - ret lval_val(cx, cx.fcx.ccx.fn_pairs.get(vid)); + check (cx.fcx.ccx.items.contains_key(tid)); + auto tag_item = cx.fcx.ccx.items.get(tid); + auto params = ty.item_ty(tag_item)._0; + auto fty = ty.plain_ty(ty.ty_nil); + alt (tag_item.node) { + case (ast.item_tag(_, ?variants, _, _)) { + for (ast.variant v in variants) { + if (v.id == vid) { + fty = node_ann_type(cx.fcx.ccx, + v.ann); + } + } + } + } + ret lval_generic_fn(cx, tup(params, fty), vid, ann); } else { // Nullary variants are just scalar constants. check (cx.fcx.ccx.item_ids.contains_key(vid)); @@ -3798,7 +3820,6 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { alt (i.node) { case (ast.item_fn(?name, ?f, _, ?fid, ?ann)) { - // TODO: type-params cx.items.insert(fid, i); if (! cx.obj_methods.contains_key(fid)) { decl_fn_and_pair(cx, "fn", name, ann, fid); @@ -3806,7 +3827,6 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { } case (ast.item_obj(?name, ?ob, _, ?oid, ?ann)) { - // TODO: type-params cx.items.insert(oid, i); decl_fn_and_pair(cx, "obj_ctor", name, ann, oid); for (@ast.method m in ob.methods) { diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index f27595a1..7a184bc6 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -571,7 +571,8 @@ fn is_fn_ty(@t fty) -> bool { // Given an item, returns the associated type as well as a list of the IDs of // its type parameters. -fn item_ty(@ast.item it) -> tup(vec[ast.def_id], @t) { +type ty_params_and_ty = tup(vec[ast.def_id], @t); +fn item_ty(@ast.item it) -> ty_params_and_ty { let vec[ast.ty_param] ty_params; auto result_ty; alt (it.node) { @@ -1233,7 +1234,8 @@ fn type_err_to_str(&ty.type_err err) -> str { // Type parameter resolution, used in translation -fn resolve_ty_params(@ast.item item, @t monoty) -> vec[@t] { +fn resolve_ty_params(ty_params_and_ty ty_params_and_polyty, + @t monoty) -> vec[@t] { obj resolve_ty_params_handler(@hashmap[ast.def_id,@t] bindings) { fn resolve_local(ast.def_id id) -> @t { log "resolve local"; fail; } fn record_local(ast.def_id id, @t ty) { log "record local"; fail; } @@ -1249,8 +1251,6 @@ fn resolve_ty_params(@ast.item item, @t monoty) -> vec[@t] { } } - auto ty_params_and_polyty = item_ty(item); - auto bindings = @new_def_hash[@t](); auto handler = resolve_ty_params_handler(bindings); -- cgit v1.2.3 From 8ef22972dbe50b2e05c8983769a638fd5b6a23b5 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 1 Feb 2011 14:56:21 -0800 Subject: Add ty_type. --- src/comp/front/ast.rs | 1 + src/comp/middle/trans.rs | 1 + src/comp/middle/ty.rs | 8 ++++++++ 3 files changed, 10 insertions(+) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 10bcd5c4..9fddb66f 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -197,6 +197,7 @@ tag ty_ { ty_obj(vec[ty_method]); ty_path(path, option.t[def]); ty_mutable(@ty); + ty_type; } type arg = rec(mode mode, @ty ty, ident ident, def_id id); diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 7755ed93..2926b78c 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -471,6 +471,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { case (ty.ty_param(_)) { ret T_typaram_ptr(); } + case (ty.ty_type) { ret T_ptr(T_tydesc()); } } fail; } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 7a184bc6..b840be91 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -42,6 +42,7 @@ tag sty { 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_type; // TODO: ty_fn_arg(@t), for a possibly-aliased function argument } @@ -103,6 +104,7 @@ fn ast_ty_to_str(&@ast.ty ty) -> str { 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_type) { s = "type"; } case (ast.ty_tup(?elts)) { auto f = ast_ty_to_str; @@ -138,6 +140,7 @@ fn ast_ty_to_str(&@ast.ty ty) -> str { s = "mutable " + ast_ty_to_str(t); } + case (_) { fail; // FIXME: typestate bug } @@ -215,6 +218,7 @@ fn ty_to_str(&@t typ) -> str { 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_type) { s = "type"; } case (ty_tup(?elems)) { auto f = ty_to_str; @@ -281,6 +285,7 @@ fn fold_ty(ty_fold fld, @t ty) -> @t { 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_box(?subty)) { ret rewrap(ty, ty_box(fold_ty(fld, subty))); } @@ -363,6 +368,7 @@ fn type_is_structural(@t ty) -> bool { 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; } @@ -402,6 +408,7 @@ fn type_is_scalar(@t ty) -> bool { case (ty_uint) { ret true; } case (ty_machine(_)) { ret true; } case (ty_char) { ret true; } + case (ty_type) { ret true; } case (_) { ret false; } } fail; @@ -939,6 +946,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) 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.ty_type) { ret struct_cmp(expected, actual); } case (ty.ty_tag(?expected_id)) { alt (actual.struct) { -- cgit v1.2.3 From eb16942c1de42c2f30f7e0eb0ff69371a167f7bd Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 1 Feb 2011 14:57:03 -0800 Subject: Use dynamic GEP and silly offset-encoding on tydescs. Successful call into a derived tydesc. --- src/comp/middle/trans.rs | 110 ++++++++++++++++++++++++++++++----------------- 1 file changed, 70 insertions(+), 40 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2926b78c..446b4f10 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -16,6 +16,7 @@ import back.x86; import back.abi; import middle.ty.pat_ty; +import middle.ty.plain_ty; import util.common; import util.common.append; @@ -341,7 +342,7 @@ fn type_of_fn_full(@crate_ctxt cx, @ty.t output) -> TypeRef { let vec[TypeRef] atys = vec(T_taskptr()); - auto fn_ty = ty.plain_ty(ty.ty_fn(inputs, output)); + auto fn_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) { @@ -869,7 +870,7 @@ fn GEP_tup_like(@block_ctxt cx, @ty.t t, // flattened the incoming structure. auto s = split_type(t, ixs, 0u); - auto prefix_ty = ty.plain_ty(ty.ty_tup(s.prefix)); + auto prefix_ty = plain_ty(ty.ty_tup(s.prefix)); auto bcx = cx; auto sz = size_of(bcx, prefix_ty); bcx = sz.bcx; @@ -985,7 +986,12 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { auto i = 0; for (ValueRef td in tys._1) { auto tdp = cx.build.GEP(tydescs, vec(C_int(0), C_int(i))); - cx.build.Store(td, tdp); + if (i == 0) { + cx.build.Store(root, tdp); + } else { + cx.build.Store(td, tdp); + } + i += 1; } auto bcx = cx; @@ -1023,19 +1029,30 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { auto glue_fn_ty = T_ptr(T_fn(vec(T_taskptr(), T_ptr(T_ptr(T_tydesc())), pvoid), T_void())); + + // FIXME: this adjustment has to do with the ridiculous encoding of + // glue-pointer-constants in the tydesc records: They are tydesc-relative + // displacements. This is purely for compatibility with rustboot and + // should go when it is discarded. + fn off(ValueRef tydescp, + ValueRef gluefn) -> ValueRef { + ret i2p(llvm.LLVMConstSub(p2i(gluefn), p2i(tydescp)), + val_ty(gluefn)); + } + + auto name = sanitize(cx.names.next("tydesc_" + ty.ty_to_str(t))); + auto gvar = llvm.LLVMAddGlobal(cx.llmod, T_tydesc(), _str.buf(name)); auto tydesc = C_struct(vec(C_null(T_ptr(T_ptr(T_tydesc()))), llsize_of(llty), llalign_of(llty), - take_glue, // take_glue_off - drop_glue, // drop_glue_off + off(gvar, take_glue), // take_glue_off + off(gvar, drop_glue), // drop_glue_off C_null(glue_fn_ty), // free_glue_off C_null(glue_fn_ty), // sever_glue_off C_null(glue_fn_ty), // mark_glue_off C_null(glue_fn_ty), // obj_drop_glue_off C_null(glue_fn_ty))); // is_stateful - 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); llvm.LLVMSetLinkage(gvar, lib.llvm.LLVMPrivateLinkage @@ -1322,8 +1339,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 = ty.plain_ty(ty.ty_nil); - auto tbox = ty.plain_ty(ty.ty_box(tnil)); + auto tnil = plain_ty(ty.ty_nil); + auto tbox = 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"); @@ -1524,7 +1541,7 @@ fn iter_sequence(@block_ctxt cx, ret iter_sequence_body(cx, v, et, f, false); } case (ty.ty_str) { - auto et = ty.plain_ty(ty.ty_machine(common.ty_u8)); + auto et = plain_ty(ty.ty_machine(common.ty_u8)); ret iter_sequence_body(cx, v, et, f, true); } case (_) { fail; } @@ -1542,6 +1559,15 @@ fn call_tydesc_glue_full(@block_ctxt cx, ValueRef v, lltydescs = cx.build.Load(lltydescs); auto llfnptr = cx.build.GEP(tydesc, vec(C_int(0), C_int(field))); auto llfn = cx.build.Load(llfnptr); + + // FIXME: this adjustment has to do with the ridiculous encoding of + // glue-pointer-constants in the tydesc records: They are tydesc-relative + // displacements. This is purely for compatibility with rustboot and + // should go when it is discarded. + llfn = cx.build.IntToPtr(cx.build.Add(cx.build.PtrToInt(llfn, T_int()), + cx.build.PtrToInt(tydesc, T_int())), + val_ty(llfn)); + cx.build.FastCall(llfn, vec(cx.fcx.lltaskptr, lltydescs, llrawptr)); } @@ -2259,7 +2285,7 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, check (cx.fcx.ccx.items.contains_key(tid)); auto tag_item = cx.fcx.ccx.items.get(tid); auto params = ty.item_ty(tag_item)._0; - auto fty = ty.plain_ty(ty.ty_nil); + auto fty = plain_ty(ty.ty_nil); alt (tag_item.node) { case (ast.item_tag(_, ?variants, _, _)) { for (ast.variant v in variants) { @@ -2635,7 +2661,7 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, } // Synthesize a closure type. - let @ty.t bindings_ty = ty.plain_ty(ty.ty_tup(bound_tys)); + let @ty.t bindings_ty = plain_ty(ty.ty_tup(bound_tys)); let TypeRef lltarget_ty = type_of(bcx.fcx.ccx, ty.expr_ty(f)); let TypeRef llbindings_ty = type_of(bcx.fcx.ccx, bindings_ty); let TypeRef llclosure_ty = T_closure_ptr(lltarget_ty, @@ -3593,52 +3619,52 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, } // Synthesize an obj body type. - let @ty.t fields_ty = ty.plain_ty(ty.ty_tup(obj_fields)); - let TypeRef llfields_ty = type_of(bcx.fcx.ccx, fields_ty); - let TypeRef llobj_body_ty = - T_ptr(T_box(T_struct(vec(T_ptr(T_tydesc()), - llfields_ty)))); + let @ty.t fields_ty = plain_ty(ty.ty_tup(obj_fields)); + let @ty.t body_ty = plain_ty(ty.ty_tup(vec(plain_ty(ty.ty_type), + fields_ty))); + let @ty.t boxed_body_ty = plain_ty(ty.ty_box(body_ty)); + + let TypeRef llboxed_body_ty = type_of(cx, boxed_body_ty); // Malloc a box for the body. - auto r = trans_malloc_inner(bcx, llobj_body_ty); - bcx = r.bcx; - auto box = r.val; - auto rc = bcx.build.GEP(box, - vec(C_int(0), - C_int(abi.box_rc_field_refcnt))); - auto body = bcx.build.GEP(box, - vec(C_int(0), - C_int(abi.box_rc_field_body))); - bcx.build.Store(C_int(1), rc); + auto box = trans_malloc_inner(bcx, llboxed_body_ty); + bcx = box.bcx; + auto rc = GEP_tup_like(bcx, boxed_body_ty, box.val, + vec(0, abi.box_rc_field_refcnt)); + bcx = rc.bcx; + auto body = GEP_tup_like(bcx, boxed_body_ty, box.val, + vec(0, abi.box_rc_field_body)); + bcx = body.bcx; + bcx.build.Store(C_int(1), rc.val); // Store body tydesc. auto body_tydesc = - bcx.build.GEP(body, - vec(C_int(0), - C_int(abi.obj_body_elt_tydesc))); + GEP_tup_like(bcx, body_ty, body.val, + vec(0, abi.obj_body_elt_tydesc)); + bcx = body_tydesc.bcx; - auto fields_tydesc = get_tydesc(r.bcx, fields_ty); + auto fields_tydesc = get_tydesc(bcx, fields_ty); bcx = fields_tydesc.bcx; - bcx.build.Store(fields_tydesc.val, body_tydesc); + bcx.build.Store(fields_tydesc.val, body_tydesc.val); // Copy args into body fields. auto body_fields = - bcx.build.GEP(body, - vec(C_int(0), - C_int(abi.obj_body_elt_fields))); + GEP_tup_like(bcx, body_ty, body.val, + vec(0, abi.obj_body_elt_fields)); + bcx = body_fields.bcx; let int i = 0; for (ast.obj_field f in ob.fields) { auto arg = bcx.fcx.llargs.get(f.id); arg = load_scalar_or_boxed(bcx, arg, arg_tys.(i).ty); - auto field = bcx.build.GEP(body_fields, - vec(C_int(0),C_int(i))); - bcx = copy_ty(bcx, INIT, field, arg, arg_tys.(i).ty).bcx; + auto field = GEP_tup_like(bcx, fields_ty, body_fields.val, + vec(0, i)); + bcx = field.bcx; + bcx = copy_ty(bcx, INIT, field.val, arg, arg_tys.(i).ty).bcx; i += 1; } - // Store box ptr in outer pair. - auto p = bcx.build.PointerCast(box, llbox_ty); + auto p = bcx.build.PointerCast(box.val, llbox_ty); bcx.build.Store(p, pair_box); } bcx.build.Ret(bcx.build.Load(pair)); @@ -4030,6 +4056,10 @@ fn p2i(ValueRef v) -> ValueRef { ret llvm.LLVMConstPtrToInt(v, T_int()); } +fn i2p(ValueRef v, TypeRef t) -> ValueRef { + ret llvm.LLVMConstIntToPtr(v, t); +} + fn trans_exit_task_glue(@crate_ctxt cx) { let vec[TypeRef] T_args = vec(); let vec[ValueRef] V_args = vec(); -- cgit v1.2.3 From 70bf54bcac587c0bc8a3a593bda75115e4c23aa8 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 1 Feb 2011 16:23:48 -0800 Subject: Implement 'else if' --- src/Makefile | 1 + src/comp/front/ast.rs | 2 +- src/comp/front/parser.rs | 42 ++++++++++++++++++++++++++++++++---------- src/comp/middle/fold.rs | 21 +++++++++++++++++---- src/comp/middle/trans.rs | 31 +++++++++++++++++++++++-------- src/comp/middle/ty.rs | 2 +- src/comp/middle/typeck.rs | 33 +++++++++++++++++++++++++++++---- 7 files changed, 104 insertions(+), 28 deletions(-) diff --git a/src/Makefile b/src/Makefile index 56a98b98..ac7dfcbb 100644 --- a/src/Makefile +++ b/src/Makefile @@ -447,6 +447,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ div-mod.rs \ drop-bind-thunk-args.rs \ drop-on-ret.rs \ + else-if.rs \ fact.rs \ fn-lval.rs \ fun-call-variants.rs \ diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 9fddb66f..be47615a 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -149,7 +149,7 @@ tag expr_ { expr_unary(unop, @expr, ann); expr_lit(@lit, ann); expr_cast(@expr, @ty, ann); - expr_if(@expr, block, option.t[block], ann); + expr_if(@expr, block, vec[tup(@expr, block)], option.t[block], ann); expr_while(@expr, block, ann); expr_for(@decl, @expr, block, ann); expr_do_while(block, @expr, ann); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index bef37a3c..0c90df5c 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -891,18 +891,40 @@ impure fn parse_if_expr(parser p) -> @ast.expr { auto cond = parse_expr(p); expect(p, token.RPAREN); auto thn = parse_block(p); - let option.t[ast.block] els = none[ast.block]; hi = thn.span; - alt (p.peek()) { - case (token.ELSE) { - p.bump(); - auto eblk = parse_block(p); - els = some(eblk); - hi = eblk.span; + + let vec[tup(@ast.expr, ast.block)] elifs = vec(); + let option.t[ast.block] els = none[ast.block]; + let bool parsing_elses = true; + while (parsing_elses) { + alt (p.peek()) { + case (token.ELSE) { + expect(p, token.ELSE); + alt (p.peek()) { + case (token.IF) { + expect(p, token.IF); + expect(p, token.LPAREN); + auto elifcond = parse_expr(p); + expect(p, token.RPAREN); + auto elifthn = parse_block(p); + elifs += tup(elifcond, elifthn); + hi = elifthn.span; + } + case (_) { + auto eblk = parse_block(p); + els = some(eblk); + hi = eblk.span; + parsing_elses = false; + } + } + } + case (_) { + parsing_elses = false; + } } - case (_) { /* fall through */ } } - ret @spanned(lo, hi, ast.expr_if(cond, thn, els, ast.ann_none)); + + ret @spanned(lo, hi, ast.expr_if(cond, thn, elifs, els, ast.ann_none)); } impure fn parse_head_local(parser p) -> @ast.decl { @@ -1331,7 +1353,7 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool { case (ast.expr_unary(_,_,_)) { ret true; } case (ast.expr_lit(_,_)) { ret true; } case (ast.expr_cast(_,_,_)) { ret true; } - case (ast.expr_if(_,_,_,_)) { ret false; } + case (ast.expr_if(_,_,_,_,_)) { ret false; } case (ast.expr_for(_,_,_,_)) { ret false; } case (ast.expr_while(_,_,_)) { ret false; } case (ast.expr_do_while(_,_,_)) { ret false; } diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 67c26014..7e6839a8 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -28,6 +28,7 @@ import front.ast.def; import front.ast.def_id; import front.ast.ann; +import std._uint; import std._vec; type ast_fold[ENV] = @@ -100,6 +101,7 @@ type ast_fold[ENV] = (fn(&ENV e, &span sp, @expr cond, &block thn, + &vec[tup(@expr, block)] elifs, &option.t[block] els, ann a) -> @expr) fold_expr_if, @@ -501,9 +503,19 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr { ret fld.fold_expr_cast(env_, e.span, ee, tt, at); } - case (ast.expr_if(?cnd, ?thn, ?els, ?t)) { + case (ast.expr_if(?cnd, ?thn, ?elifs, ?els, ?t)) { auto ccnd = fold_expr(env_, fld, cnd); auto tthn = fold_block(env_, fld, thn); + + let vec[tup(@ast.expr, ast.block)] eelifs = vec(); + for (tup(@expr, block) elif in elifs) { + auto elifcnd = elif._0; + auto elifthn = elif._1; + auto elifccnd = fold_expr(env_, fld, elifcnd); + auto eliftthn = fold_block(env_, fld, elifthn); + eelifs += tup(elifccnd, eliftthn); + } + auto eels = none[block]; alt (els) { case (some[block](?b)) { @@ -511,7 +523,7 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr { } case (_) { /* fall through */ } } - ret fld.fold_expr_if(env_, e.span, ccnd, tthn, eels, t); + ret fld.fold_expr_if(env_, e.span, ccnd, tthn, eelifs, eels, t); } case (ast.expr_for(?decl, ?seq, ?body, ?t)) { @@ -961,8 +973,9 @@ fn identity_fold_expr_cast[ENV](&ENV env, &span sp, @ast.expr e, fn identity_fold_expr_if[ENV](&ENV env, &span sp, @expr cond, &block thn, + &vec[tup(@expr, block)] elifs, &option.t[block] els, ann a) -> @expr { - ret @respan(sp, ast.expr_if(cond, thn, els, a)); + ret @respan(sp, ast.expr_if(cond, thn, elifs, els, a)); } fn identity_fold_expr_for[ENV](&ENV env, &span sp, @@ -1237,7 +1250,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_expr_unary = bind identity_fold_expr_unary[ENV](_,_,_,_,_), fold_expr_lit = bind identity_fold_expr_lit[ENV](_,_,_,_), fold_expr_cast = bind identity_fold_expr_cast[ENV](_,_,_,_,_), - fold_expr_if = bind identity_fold_expr_if[ENV](_,_,_,_,_,_), + fold_expr_if = bind identity_fold_expr_if[ENV](_,_,_,_,_,_,_), fold_expr_for = bind identity_fold_expr_for[ENV](_,_,_,_,_,_), fold_expr_while = bind identity_fold_expr_while[ENV](_,_,_,_,_), fold_expr_do_while diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 446b4f10..c08147fe 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1957,8 +1957,9 @@ fn join_results(@block_ctxt parent_cx, ret res(join_cx, phi); } -fn trans_if(@block_ctxt cx, @ast.expr cond, - &ast.block thn, &option.t[ast.block] els) -> result { +fn trans_if(@block_ctxt cx, @ast.expr cond, &ast.block thn, + &vec[tup(@ast.expr, ast.block)] elifs, + &option.t[ast.block] els) -> result { auto cond_res = trans_expr(cx, cond); @@ -1968,11 +1969,25 @@ fn trans_if(@block_ctxt cx, @ast.expr cond, auto else_cx = new_scope_block_ctxt(cx, "else"); auto else_res = res(else_cx, C_nil()); - alt (els) { - case (some[ast.block](?eblk)) { - else_res = trans_block(else_cx, eblk); + auto num_elifs = _vec.len[tup(@ast.expr, ast.block)](elifs); + if (num_elifs > 0u) { + auto next_elif = elifs.(0u); + auto next_elifthn = next_elif._0; + auto next_elifcnd = next_elif._1; + auto rest_elifs = _vec.shift[tup(@ast.expr, ast.block)](elifs); + else_res = trans_if(else_cx, next_elifthn, next_elifcnd, + rest_elifs, els); + } + + /* else: FIXME: rustboot has a problem here + with preconditions inside an else block */ + if (num_elifs == 0u) { + alt (els) { + case (some[ast.block](?eblk)) { + else_res = trans_block(else_cx, eblk); + } + case (_) { /* fall through */ } } - case (_) { /* fall through */ } } cond_res.bcx.build.CondBr(cond_res.val, @@ -2901,8 +2916,8 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { ret trans_binary(cx, op, x, y); } - case (ast.expr_if(?cond, ?thn, ?els, _)) { - ret trans_if(cx, cond, thn, els); + case (ast.expr_if(?cond, ?thn, ?elifs, ?els, _)) { + ret trans_if(cx, cond, thn, elifs, els); } case (ast.expr_for(?decl, ?seq, ?body, _)) { diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index b840be91..2f14aae6 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -653,7 +653,7 @@ fn expr_ty(@ast.expr expr) -> @t { 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_if(_, _, _, _, ?ann)) { ret ann_to_type(ann); } case (ast.expr_for(_, _, _, ?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); } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index ea9002ae..7112e982 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -864,10 +864,19 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, auto t = demand(fcx, e.span, expected, ann_to_type(ann)); e_1 = ast.expr_cast(sube, ast_ty, ast.ann_type(t)); } - case (ast.expr_if(?cond, ?then_0, ?else_0, ?ann)) { + case (ast.expr_if(?cond, ?then_0, ?elifs_0, ?else_0, ?ann)) { auto t = demand_full(fcx, e.span, expected, ann_to_type(ann), adk); auto then_1 = demand_block(fcx, expected, then_0); + + let vec[tup(@ast.expr, ast.block)] elifs_1 = vec(); + for (tup(@ast.expr, ast.block) elif in elifs_0) { + auto elifcond = elif._0; + auto elifthn_0 = elif._1; + auto elifthn_1 = demand_block(fcx, expected, elifthn_0); + elifs_1 += tup(elifcond, elifthn_1); + } + auto else_1; alt (else_0) { case (none[ast.block]) { else_1 = none[ast.block]; } @@ -876,7 +885,7 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, else_1 = some[ast.block](b_1); } } - e_1 = ast.expr_if(cond, then_1, else_1, ast.ann_type(t)); + e_1 = ast.expr_if(cond, then_1, elifs_1, else_1, ast.ann_type(t)); } case (ast.expr_for(?decl, ?seq, ?bloc, ?ann)) { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); @@ -1195,13 +1204,28 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { ann)); } - case (ast.expr_if(?cond, ?thn, ?elsopt, _)) { + case (ast.expr_if(?cond, ?thn, ?elifs, ?elsopt, _)) { auto cond_0 = check_expr(fcx, cond); 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); + auto num_elifs = _vec.len[tup(@ast.expr, ast.block)](elifs); + let vec[tup(@ast.expr, ast.block)] elifs_1 = vec(); + for each (uint i in _uint.range(0u, num_elifs)) { + auto elif = elifs.(i); + auto elifcond = elif._0; + auto elifcond_0 = check_expr(fcx, cond); + auto elifcond_1 = demand_expr(fcx, + plain_ty(ty.ty_bool), + elifcond_0); + auto elifthn = elif._1; + auto elifthn_0 = check_block(fcx, elifthn); + auto elifthn_1 = demand_block(fcx, thn_t, elifthn_0); + elifs_1 += tup(elifcond_1, elifthn_1); + } + auto elsopt_1; auto elsopt_t; alt (elsopt) { @@ -1220,7 +1244,8 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto thn_1 = demand_block(fcx, elsopt_t, thn_0); ret @fold.respan[ast.expr_](expr.span, - ast.expr_if(cond_1, thn_1, elsopt_1, + ast.expr_if(cond_1, thn_1, + elifs_1, elsopt_1, ast.ann_type(elsopt_t))); } -- cgit v1.2.3 From b3689e7c209d6caf6a0a551b9fbfe87942be723d Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 1 Feb 2011 16:26:49 -0800 Subject: Pick up case for expr_block from brson's other branch. --- src/comp/middle/typeck.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 7112e982..725c02fd 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1333,6 +1333,21 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { ast.expr_alt(expr_1, arms_1, ann)); } + case (ast.expr_block(?b, _)) { + auto b_0 = check_block(fcx, b); + auto ann; + alt (b_0.node.expr) { + case (some[@ast.expr](?expr)) { + ann = ast.ann_type(expr_ty(expr)); + } + case (none[@ast.expr]) { + ann = ast.ann_type(plain_ty(ty.ty_nil)); + } + } + ret @fold.respan[ast.expr_](expr.span, + ast.expr_block(b_0, ann)); + } + case (ast.expr_bind(?f, ?args, _)) { auto f_0 = check_expr(fcx, f); auto t_0 = expr_ty(f_0); -- cgit v1.2.3 From 4b06dc574ba7d3ae50795cbe4f10d4be6e9c64a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Tue, 1 Feb 2011 13:40:04 -0500 Subject: Add very minimal support for native modules. For now they must be empty. --- src/Makefile | 1 + src/comp/front/ast.rs | 6 ++++++ src/comp/front/parser.rs | 19 +++++++++++++++++++ src/comp/middle/fold.rs | 31 +++++++++++++++++++++++++++++-- src/comp/middle/typeck.rs | 4 ++++ src/test/run-pass/native2.rs | 5 +++++ 6 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/native2.rs diff --git a/src/Makefile b/src/Makefile index ac7dfcbb..221ec9ff 100644 --- a/src/Makefile +++ b/src/Makefile @@ -476,6 +476,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ linear-for-loop.rs \ multiline-comment.rs \ mutual-recursion-group.rs \ + native2.rs \ obj-drop.rs \ obj-recursion.rs \ obj-with-vec.rs \ diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index be47615a..5f527f2d 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -227,6 +227,8 @@ type _mod = rec(vec[@view_item] view_items, vec[@item] items, mod_index index); +type native_mod = rec(str native_name); + type variant_arg = rec(@ty ty, def_id id); type variant = rec(str name, vec[variant_arg] args, def_id id, ann ann); @@ -241,6 +243,7 @@ tag item_ { item_const(ident, @ty, @expr, def_id, ann); item_fn(ident, _fn, vec[ty_param], def_id, ann); item_mod(ident, _mod, def_id); + item_native_mod(ident, native_mod, def_id); item_ty(ident, @ty, vec[ty_param], def_id, ann); item_tag(ident, vec[variant], vec[ty_param], def_id); item_obj(ident, _obj, vec[ty_param], def_id, ann); @@ -268,6 +271,9 @@ fn index_item(mod_index index, @item it) { case (ast.item_mod(?id, _, _)) { index.insert(id, ast.mie_item(it)); } + case (ast.item_native_mod(?id, _, _)) { + index.insert(id, ast.mie_item(it)); + } case (ast.item_ty(?id, _, _, _, _)) { index.insert(id, ast.mie_item(it)); } diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 0c90df5c..16adfedb 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1577,6 +1577,20 @@ impure fn parse_item_mod(parser p) -> @ast.item { ret @spanned(lo, hi, item); } +impure fn parse_item_native_mod(parser p) -> @ast.item { + auto lo = p.get_span(); + expect(p, token.NATIVE); + auto native_name = parse_str_lit(p); + expect(p, token.MOD); + auto id = parse_ident(p); + expect(p, token.LBRACE); + auto m = rec(native_name = native_name); + auto hi = p.get_span(); + expect(p, token.RBRACE); + auto item = ast.item_native_mod(id, m, p.next_def_id()); + ret @spanned(lo, hi, item); +} + impure fn parse_item_type(parser p) -> @ast.item { auto lo = p.get_span(); expect(p, token.TYPE); @@ -1717,6 +1731,11 @@ impure fn parse_item(parser p) -> @ast.item { check (lyr == ast.layer_value); ret parse_item_mod(p); } + case (token.NATIVE) { + check (eff == ast.eff_pure); + check (lyr == ast.layer_value); + ret parse_item_native_mod(p); + } case (token.TYPE) { check (eff == ast.eff_pure); ret parse_item_type(p); diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 7e6839a8..2426d8ae 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -196,6 +196,9 @@ type ast_fold[ENV] = (fn(&ENV e, &span sp, ident ident, &ast._mod m, def_id id) -> @item) fold_item_mod, + (fn(&ENV e, &span sp, ident ident, + &ast.native_mod m, def_id id) -> @item) fold_item_native_mod, + (fn(&ENV e, &span sp, ident ident, @ty t, vec[ast.ty_param] ty_params, def_id id, ann a) -> @item) fold_item_ty, @@ -229,6 +232,8 @@ type ast_fold[ENV] = (fn(&ENV e, &ast._mod m) -> ast._mod) fold_mod, + (fn(&ENV e, &ast.native_mod m) -> ast.native_mod) fold_native_mod, + (fn(&ENV e, &span sp, &ast._mod m) -> @ast.crate) fold_crate, @@ -780,6 +785,11 @@ fn fold_item[ENV](&ENV env, ast_fold[ENV] fld, @item i) -> @item { ret fld.fold_item_mod(env_, i.span, ident, mm_, id); } + case (ast.item_native_mod(?ident, ?mm, ?id)) { + let ast.native_mod mm_ = fold_native_mod[ENV](env_, fld, mm); + ret fld.fold_item_native_mod(env_, i.span, ident, mm_, id); + } + case (ast.item_ty(?ident, ?ty, ?params, ?id, ?ann)) { let @ast.ty ty_ = fold_ty[ENV](env_, fld, ty); ret fld.fold_item_ty(env_, i.span, ident, ty_, params, id, ann); @@ -810,7 +820,6 @@ fn fold_item[ENV](&ENV env, ast_fold[ENV] fld, @item i) -> @item { fail; } - fn fold_mod[ENV](&ENV e, ast_fold[ENV] fld, &ast._mod m) -> ast._mod { let vec[@view_item] view_items = vec(); @@ -830,7 +839,12 @@ fn fold_mod[ENV](&ENV e, ast_fold[ENV] fld, &ast._mod m) -> ast._mod { } ret fld.fold_mod(e, rec(view_items=view_items, items=items, index=index)); - } +} + +fn fold_native_mod[ENV](&ENV e, ast_fold[ENV] fld, + &ast.native_mod m) -> ast.native_mod { + ret fld.fold_native_mod(e, rec(native_name = m.native_name)); +} fn fold_crate[ENV](&ENV env, ast_fold[ENV] fld, @ast.crate c) -> @ast.crate { let ENV env_ = fld.update_env_for_crate(env, c); @@ -1105,6 +1119,11 @@ fn identity_fold_item_mod[ENV](&ENV e, &span sp, ident i, ret @respan(sp, ast.item_mod(i, m, id)); } +fn identity_fold_item_native_mod[ENV](&ENV e, &span sp, ident i, + &ast.native_mod m, def_id id) -> @item { + ret @respan(sp, ast.item_native_mod(i, m, id)); +} + fn identity_fold_item_ty[ENV](&ENV e, &span sp, ident i, @ty t, vec[ast.ty_param] ty_params, def_id id, ann a) -> @item { @@ -1159,6 +1178,11 @@ fn identity_fold_mod[ENV](&ENV e, &ast._mod m) -> ast._mod { ret m; } +fn identity_fold_native_mod[ENV](&ENV e, + &ast.native_mod m) -> ast.native_mod { + ret m; +} + fn identity_fold_crate[ENV](&ENV e, &span sp, &ast._mod m) -> @ast.crate { ret @respan(sp, rec(module=m)); } @@ -1281,6 +1305,8 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_item_const= bind identity_fold_item_const[ENV](_,_,_,_,_,_,_), fold_item_fn = bind identity_fold_item_fn[ENV](_,_,_,_,_,_,_), fold_item_mod = bind identity_fold_item_mod[ENV](_,_,_,_,_), + fold_item_native_mod = + bind identity_fold_item_native_mod[ENV](_,_,_,_,_), fold_item_ty = bind identity_fold_item_ty[ENV](_,_,_,_,_,_,_), fold_item_tag = bind identity_fold_item_tag[ENV](_,_,_,_,_,_), fold_item_obj = bind identity_fold_item_obj[ENV](_,_,_,_,_,_,_), @@ -1293,6 +1319,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_block = bind identity_fold_block[ENV](_,_,_), fold_fn = bind identity_fold_fn[ENV](_,_,_,_,_,_), fold_mod = bind identity_fold_mod[ENV](_,_), + fold_native_mod = bind identity_fold_native_mod[ENV](_,_), fold_crate = bind identity_fold_crate[ENV](_,_,_), fold_obj = bind identity_fold_obj[ENV](_,_,_), diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 725c02fd..43d35b37 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -376,6 +376,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) } case (ast.item_mod(_, _, _)) { fail; } + case (ast.item_native_mod(_, _, _)) { fail; } } } @@ -455,6 +456,9 @@ fn collect_item_types(session.session sess, @ast.crate crate) case (ast.item_mod(_, _, _)) { // ignore item_mod, it has no type. } + case (ast.item_native_mod(_, _, _)) { + // ignore item_native_mod, it has no type. + } case (_) { // This call populates the ty_table with the converted type of // the item in passing; we don't need to do anything else. diff --git a/src/test/run-pass/native2.rs b/src/test/run-pass/native2.rs new file mode 100644 index 00000000..abb63352 --- /dev/null +++ b/src/test/run-pass/native2.rs @@ -0,0 +1,5 @@ +native "rust" mod rustrt { +} + +fn main(vec[str] args) { +} -- cgit v1.2.3 From f22dc4d581760d365392323a431f4787f31ae130 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 1 Feb 2011 18:02:57 -0800 Subject: Fix buggy argument assembly for upcall_get_type_desc. Can now complete calls to glue of derived tydescs. --- src/comp/middle/trans.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c08147fe..c955340e 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -983,14 +983,14 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { auto root = cx.fcx.ccx.tydescs.get(t); auto tydescs = cx.build.Alloca(T_array(T_ptr(T_tydesc()), n_params)); + auto i = 0; + auto tdp = cx.build.GEP(tydescs, vec(C_int(0), C_int(i))); + cx.build.Store(root, tdp); + i += 1; for (ValueRef td in tys._1) { auto tdp = cx.build.GEP(tydescs, vec(C_int(0), C_int(i))); - if (i == 0) { - cx.build.Store(root, tdp); - } else { - cx.build.Store(td, tdp); - } + cx.build.Store(td, tdp); i += 1; } -- cgit v1.2.3 From dd3ed6139a6fc6fda15403d0b5679535959945e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Wed, 2 Feb 2011 10:43:57 -0500 Subject: Add most of the plumbing for native items and add support for parsing native type declarations. --- src/comp/front/ast.rs | 19 +++++++++++++++++-- src/comp/front/parser.rs | 35 +++++++++++++++++++++++++++++++++- src/comp/middle/fold.rs | 45 +++++++++++++++++++++++++++++++++++++++++++- src/test/run-pass/native2.rs | 1 + 4 files changed, 96 insertions(+), 4 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 5f527f2d..7b22e700 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -215,7 +215,6 @@ type obj_field = rec(@ty ty, ident ident, def_id id, ann ann); type _obj = rec(vec[obj_field] fields, vec[@method] methods); - tag mod_index_entry { mie_view_item(@view_item); mie_item(@item); @@ -227,7 +226,10 @@ type _mod = rec(vec[@view_item] view_items, vec[@item] items, mod_index index); -type native_mod = rec(str native_name); +type native_mod = rec(str native_name, + vec[@native_item] items, + native_mod_index index); +type native_mod_index = hashmap[ident,@native_item]; type variant_arg = rec(@ty ty, def_id id); type variant = rec(str name, vec[variant_arg] args, def_id id, ann ann); @@ -249,6 +251,11 @@ tag item_ { item_obj(ident, _obj, vec[ty_param], def_id, ann); } +type native_item = spanned[native_item_]; +tag native_item_ { + native_item_ty(ident, def_id); +} + fn index_view_item(mod_index index, @view_item it) { alt (it.node) { case(ast.view_item_use(?id, _, _)) { @@ -292,6 +299,14 @@ fn index_item(mod_index index, @item it) { } } +fn index_native_item(native_mod_index index, @native_item it) { + alt (it.node) { + case (ast.native_item_ty(?id, _)) { + index.insert(id, it); + } + } +} + // // Local Variables: // mode: rust diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 16adfedb..c088e68d 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1577,6 +1577,39 @@ impure fn parse_item_mod(parser p) -> @ast.item { ret @spanned(lo, hi, item); } + +impure fn parse_item_native_type(parser p) -> @ast.native_item { + auto lo = p.get_span(); + expect(p, token.TYPE); + auto id = parse_ident(p); + auto hi = p.get_span(); + expect(p, token.SEMI); + auto item = ast.native_item_ty(id, p.next_def_id()); + ret @spanned(lo, hi, item); +} + +impure fn parse_native_item(parser p) -> @ast.native_item { + alt (p.peek()) { + case (token.TYPE) { + ret parse_item_native_type(p); + } + } +} + +impure fn parse_native_mod_items(parser p, + str native_name) -> ast.native_mod { + auto index = new_str_hash[@ast.native_item](); + let vec[@ast.native_item] items = vec(); + while (p.peek() != token.RBRACE) { + auto item = parse_native_item(p); + items += vec(item); + + // Index the item. + ast.index_native_item(index, item); + } + ret rec(native_name=native_name, items=items, index=index); +} + impure fn parse_item_native_mod(parser p) -> @ast.item { auto lo = p.get_span(); expect(p, token.NATIVE); @@ -1584,7 +1617,7 @@ impure fn parse_item_native_mod(parser p) -> @ast.item { expect(p, token.MOD); auto id = parse_ident(p); expect(p, token.LBRACE); - auto m = rec(native_name = native_name); + auto m = parse_native_mod_items(p, native_name); auto hi = p.get_span(); expect(p, token.RBRACE); auto item = ast.item_native_mod(id, m, p.next_def_id()); diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 2426d8ae..b9027836 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -20,6 +20,7 @@ import front.ast.block; import front.ast.item; import front.ast.view_item; import front.ast.meta_item; +import front.ast.native_item; import front.ast.arg; import front.ast.pat; import front.ast.decl; @@ -203,6 +204,9 @@ type ast_fold[ENV] = @ty t, vec[ast.ty_param] ty_params, def_id id, ann a) -> @item) fold_item_ty, + (fn(&ENV e, &span sp, ident ident, + def_id id) -> @native_item) fold_native_item_ty, + (fn(&ENV e, &span sp, ident ident, vec[ast.variant] variants, vec[ast.ty_param] ty_params, @@ -244,6 +248,7 @@ type ast_fold[ENV] = // Env updates. (fn(&ENV e, @ast.crate c) -> ENV) update_env_for_crate, (fn(&ENV e, @item i) -> ENV) update_env_for_item, + (fn(&ENV e, @native_item i) -> ENV) update_env_for_native_item, (fn(&ENV e, @view_item i) -> ENV) update_env_for_view_item, (fn(&ENV e, &block b) -> ENV) update_env_for_block, (fn(&ENV e, @stmt s) -> ENV) update_env_for_stmt, @@ -841,9 +846,34 @@ fn fold_mod[ENV](&ENV e, ast_fold[ENV] fld, &ast._mod m) -> ast._mod { ret fld.fold_mod(e, rec(view_items=view_items, items=items, index=index)); } +fn fold_native_item[ENV](&ENV env, ast_fold[ENV] fld, + @native_item i) -> @native_item { + let ENV env_ = fld.update_env_for_native_item(env, i); + + if (!fld.keep_going(env_)) { + ret i; + } + alt (i.node) { + case (ast.native_item_ty(?ident, ?id)) { + ret fld.fold_native_item_ty(env_, i.span, ident, id); + } + } +} + fn fold_native_mod[ENV](&ENV e, ast_fold[ENV] fld, &ast.native_mod m) -> ast.native_mod { - ret fld.fold_native_mod(e, rec(native_name = m.native_name)); + let vec[@native_item] items = vec(); + auto index = new_str_hash[@ast.native_item](); + + for (@native_item i in m.items) { + auto new_item = fold_native_item[ENV](e, fld, i); + append[@native_item](items, new_item); + ast.index_native_item(index, new_item); + } + + ret fld.fold_native_mod(e, rec(native_name=m.native_name, + items=items, + index=index)); } fn fold_crate[ENV](&ENV env, ast_fold[ENV] fld, @ast.crate c) -> @ast.crate { @@ -1130,6 +1160,11 @@ fn identity_fold_item_ty[ENV](&ENV e, &span sp, ident i, ret @respan(sp, ast.item_ty(i, t, ty_params, id, a)); } +fn identity_fold_native_item_ty[ENV](&ENV e, &span sp, ident i, + def_id id) -> @native_item { + ret @respan(sp, ast.native_item_ty(i, id)); +} + fn identity_fold_item_tag[ENV](&ENV e, &span sp, ident i, vec[ast.variant] variants, vec[ast.ty_param] ty_params, @@ -1204,6 +1239,10 @@ fn identity_update_env_for_item[ENV](&ENV e, @item i) -> ENV { ret e; } +fn identity_update_env_for_native_item[ENV](&ENV e, @native_item i) -> ENV { + ret e; +} + fn identity_update_env_for_view_item[ENV](&ENV e, @view_item i) -> ENV { ret e; } @@ -1308,6 +1347,8 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_item_native_mod = bind identity_fold_item_native_mod[ENV](_,_,_,_,_), fold_item_ty = bind identity_fold_item_ty[ENV](_,_,_,_,_,_,_), + fold_native_item_ty = + bind identity_fold_native_item_ty[ENV](_,_,_,_), fold_item_tag = bind identity_fold_item_tag[ENV](_,_,_,_,_,_), fold_item_obj = bind identity_fold_item_obj[ENV](_,_,_,_,_,_,_), @@ -1325,6 +1366,8 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { update_env_for_crate = bind identity_update_env_for_crate[ENV](_,_), update_env_for_item = bind identity_update_env_for_item[ENV](_,_), + update_env_for_native_item = + bind identity_update_env_for_native_item[ENV](_,_), update_env_for_view_item = bind identity_update_env_for_view_item[ENV](_,_), update_env_for_block = bind identity_update_env_for_block[ENV](_,_), diff --git a/src/test/run-pass/native2.rs b/src/test/run-pass/native2.rs index abb63352..b848ec8c 100644 --- a/src/test/run-pass/native2.rs +++ b/src/test/run-pass/native2.rs @@ -1,4 +1,5 @@ native "rust" mod rustrt { + type vbuf; } fn main(vec[str] args) { -- cgit v1.2.3 From 8e963f63a8d076c8e2f162ba27c49e6cb1dacb96 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Feb 2011 15:23:49 -0800 Subject: Add trace and trap helpers to trans for low level diagnostics. --- src/comp/middle/trans.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c955340e..d091e3ad 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4186,6 +4186,24 @@ fn declare_intrinsics(ModuleRef llmod) -> hashmap[str,ValueRef] { ret intrinsics; } + +fn trace_str(@block_ctxt cx, str s) { + trans_upcall(cx, "upcall_trace_str", vec(p2i(C_cstr(cx.fcx.ccx, s)))); +} + +fn trace_word(@block_ctxt cx, ValueRef v) { + trans_upcall(cx, "upcall_trace_word", vec(v)); +} + +fn trace_ptr(@block_ctxt cx, ValueRef v) { + trace_word(cx, cx.build.PtrToInt(v, T_int())); +} + +fn trap(@block_ctxt bcx) { + let vec[ValueRef] v = vec(); + bcx.build.Call(bcx.fcx.ccx.intrinsics.get("llvm.trap"), v); +} + fn check_module(ModuleRef llmod) { auto pm = mk_pass_manager(); llvm.LLVMAddVerifierPass(pm.llpm); -- cgit v1.2.3 From c42a2d2bfb9cf8b4b44f28942d2d3f2838611c19 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Feb 2011 15:25:53 -0800 Subject: Change decl_upcall to decl_upcall_glue, more correct name. --- src/comp/middle/trans.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index d091e3ad..dff95974 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -612,7 +612,7 @@ fn decl_glue(ModuleRef llmod, str s) -> ValueRef { ret decl_cdecl_fn(llmod, s, T_fn(vec(T_taskptr()), T_void())); } -fn decl_upcall(ModuleRef llmod, uint _n) -> ValueRef { +fn decl_upcall_glue(ModuleRef llmod, uint _n) -> ValueRef { // It doesn't actually matter what type we come up with here, at the // moment, as we cast the upcall function pointers to int before passing // them to the indirect upcall-invocation glue. But eventually we'd like @@ -4324,7 +4324,7 @@ fn make_glues(ModuleRef llmod) -> @glue_fns { T_fn(vec(T_taskptr()), T_void())), upcall_glues = - _vec.init_fn[ValueRef](bind decl_upcall(llmod, _), + _vec.init_fn[ValueRef](bind decl_upcall_glue(llmod, _), abi.n_upcall_glues as uint), no_op_type_glue = make_no_op_type_glue(llmod), memcpy_glue = make_memcpy_glue(llmod), -- cgit v1.2.3 From c61ff989850f2f77fad9fd1f032632d559e8edab Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Feb 2011 15:26:16 -0800 Subject: Handle missing case in linearize_ty_params. --- src/comp/middle/trans.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index dff95974..66ce8186 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -943,6 +943,7 @@ fn linearize_ty_params(@block_ctxt cx, @ty.t t) r.defs += pid; } } + case (_) { } } ret t; } -- cgit v1.2.3 From b37995664b0149ee92269a3e11f7f6228fe48cc7 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Feb 2011 15:28:11 -0800 Subject: Store tydesc for whole body, not just fields, in objs and closures. Handles unusual field alignment. --- src/comp/middle/trans.rs | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 66ce8186..36f54ea8 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1185,16 +1185,12 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result { vec(C_int(0), C_int(abi.box_rc_field_body))); - auto fields = - cx.build.GEP(body, - vec(C_int(0), - C_int(abi.obj_body_elt_fields))); auto tydescptr = cx.build.GEP(body, vec(C_int(0), C_int(abi.obj_body_elt_tydesc))); - call_tydesc_glue_full(cx, fields, cx.build.Load(tydescptr), + call_tydesc_glue_full(cx, body, cx.build.Load(tydescptr), abi.tydesc_field_drop_glue_off); // Then free the body. @@ -1223,17 +1219,12 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result { vec(C_int(0), C_int(abi.box_rc_field_body))); - auto bindings = - cx.build.GEP(body, - vec(C_int(0), - C_int(abi.closure_elt_bindings))); - auto tydescptr = cx.build.GEP(body, vec(C_int(0), C_int(abi.closure_elt_tydesc))); - call_tydesc_glue_full(cx, bindings, cx.build.Load(tydescptr), + call_tydesc_glue_full(cx, body, cx.build.Load(tydescptr), abi.tydesc_field_drop_glue_off); @@ -3659,9 +3650,9 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, vec(0, abi.obj_body_elt_tydesc)); bcx = body_tydesc.bcx; - auto fields_tydesc = get_tydesc(bcx, fields_ty); - bcx = fields_tydesc.bcx; - bcx.build.Store(fields_tydesc.val, body_tydesc.val); + auto body_td = get_tydesc(bcx, body_ty); + bcx = body_td.bcx; + bcx.build.Store(body_td.val, body_tydesc.val); // Copy args into body fields. auto body_fields = -- cgit v1.2.3 From c863427b64f51fd55cc6191ed08cbfb88034d05b Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Feb 2011 16:22:11 -0800 Subject: Hack to work around apparent LLVM bug? --- src/comp/middle/trans.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 36f54ea8..3db5be5f 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3229,7 +3229,13 @@ fn new_block_ctxt(@fn_ctxt cx, block_parent parent, // Use this when you're at the top block of a function or the like. fn new_top_block_ctxt(@fn_ctxt fcx) -> @block_ctxt { - ret new_block_ctxt(fcx, parent_none, SCOPE_BLOCK, "function top level"); + auto cx = new_block_ctxt(fcx, parent_none, SCOPE_BLOCK, + "function top level"); + + // FIXME: hack to give us some spill room to make up for an LLVM + // bug where it destroys its own callee-saves. + cx.build.Alloca(T_array(T_int(), 10u)); + ret cx; } // Use this when you're at a curly-brace or similar lexical scope. -- cgit v1.2.3 From ce17fe2a90737425eed9305cd24e4c6f71b78dbd Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Feb 2011 17:49:15 -0800 Subject: Attempt to put out burning tinderbox. --- src/comp/middle/trans.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 3db5be5f..b1c84ace 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1218,13 +1218,17 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result { cx.build.GEP(v, vec(C_int(0), C_int(abi.box_rc_field_body))); + auto bindings = + cx.build.GEP(body, + vec(C_int(0), + C_int(abi.closure_elt_bindings))); auto tydescptr = cx.build.GEP(body, vec(C_int(0), C_int(abi.closure_elt_tydesc))); - call_tydesc_glue_full(cx, body, cx.build.Load(tydescptr), + call_tydesc_glue_full(cx, bindings, cx.build.Load(tydescptr), abi.tydesc_field_drop_glue_off); -- cgit v1.2.3 From be97a77be81d286b1ae90c1050da1c7c0477ea3f Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 3 Feb 2011 14:40:57 -0800 Subject: Capture typarams into obj, independent of body tydesc. --- src/comp/back/abi.rs | 3 +- src/comp/middle/trans.rs | 95 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 79 insertions(+), 19 deletions(-) diff --git a/src/comp/back/abi.rs b/src/comp/back/abi.rs index db17b942..82a85a6c 100644 --- a/src/comp/back/abi.rs +++ b/src/comp/back/abi.rs @@ -44,7 +44,8 @@ const int obj_field_vtbl = 0; const int obj_field_box = 1; const int obj_body_elt_tydesc = 0; -const int obj_body_elt_fields = 1; +const int obj_body_elt_typarams = 1; +const int obj_body_elt_fields = 2; const int fn_field_code = 0; const int fn_field_box = 1; diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index b1c84ace..4610cef6 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -75,6 +75,7 @@ state type crate_ctxt = rec(session.session sess, hashmap[ast.def_id, ValueRef] consts, hashmap[ast.def_id,()] obj_methods, hashmap[@ty.t, ValueRef] tydescs, + vec[ast.ty_param] obj_typarams, vec[ast.obj_field] obj_fields, @glue_fns glues, namegen names, @@ -327,6 +328,24 @@ fn T_opaque_closure_ptr() -> TypeRef { T_nil()); } +fn T_captured_tydescs(uint n) -> TypeRef { + ret T_struct(_vec.init_elt[TypeRef](T_ptr(T_tydesc()), n)); +} + +fn T_obj(uint n_captured_tydescs, TypeRef llfields_ty) -> TypeRef { + ret T_struct(vec(T_ptr(T_tydesc()), + T_captured_tydescs(n_captured_tydescs), + llfields_ty)); +} + +fn T_obj_ptr(uint n_captured_tydescs, TypeRef llfields_ty) -> TypeRef { + ret T_ptr(T_box(T_obj(n_captured_tydescs, llfields_ty))); +} + +fn T_opaque_obj_ptr() -> TypeRef { + ret T_obj_ptr(0u, T_nil()); +} + fn type_of(@crate_ctxt cx, @ty.t t) -> TypeRef { let TypeRef llty = type_of_inner(cx, t); @@ -455,11 +474,9 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { mtys += T_ptr(mty); } let TypeRef vtbl = T_struct(mtys); - let TypeRef body = T_struct(vec(T_ptr(T_tydesc()), - T_nil())); - let TypeRef pair = - T_struct(vec(T_ptr(vtbl), - T_ptr(T_box(body)))); + let TypeRef pair = T_struct(vec(T_ptr(vtbl), + T_opaque_obj_ptr())); + auto abs_pair = llvm.LLVMResolveTypeHandle(th.llth); llvm.LLVMRefineType(abs_pair, pair); abs_pair = llvm.LLVMResolveTypeHandle(th.llth); @@ -963,6 +980,7 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { // Is the supplied type a type param? If so, return the passed-in tydesc. alt (ty.type_param(t)) { case (some[ast.def_id](?id)) { + check (cx.fcx.lltydescs.contains_key(id)); ret res(cx, cx.fcx.lltydescs.get(id)); } case (none[ast.def_id]) { /* fall through */ } @@ -3474,7 +3492,7 @@ fn ret_ty_of_fn(ast.ann ann) -> @ty.t { ret ret_ty_of_fn_ty(ty.ann_to_type(ann)); } -fn create_llobjfields_for_fields(@block_ctxt cx, ValueRef llself) { +fn populate_fn_ctxt_from_llself(@block_ctxt cx, ValueRef llself) { let vec[TypeRef] llfield_tys = vec(); @@ -3482,11 +3500,9 @@ fn create_llobjfields_for_fields(@block_ctxt cx, ValueRef llself) { llfield_tys += node_type(cx.fcx.ccx, f.ann); } - let TypeRef llfields_ty = T_struct(llfield_tys); - let TypeRef lltydesc_ty = T_ptr(T_tydesc()); - let TypeRef llobj_body_ty = T_struct(vec(lltydesc_ty, - llfields_ty)); - let TypeRef llobj_box_ty = T_ptr(T_box(llobj_body_ty)); + auto n_typarams = _vec.len[ast.ty_param](cx.fcx.ccx.obj_typarams); + let TypeRef llobj_box_ty = T_obj_ptr(n_typarams, + T_struct(llfield_tys)); auto box_cell = cx.build.GEP(llself, @@ -3497,12 +3513,28 @@ fn create_llobjfields_for_fields(@block_ctxt cx, ValueRef llself) { box_ptr = cx.build.PointerCast(box_ptr, llobj_box_ty); + auto obj_typarams = cx.build.GEP(box_ptr, + vec(C_int(0), + C_int(abi.box_rc_field_body), + C_int(abi.obj_body_elt_typarams))); + auto obj_fields = cx.build.GEP(box_ptr, vec(C_int(0), C_int(abi.box_rc_field_body), C_int(abi.obj_body_elt_fields))); let int i = 0; + + for (ast.ty_param p in cx.fcx.ccx.obj_typarams) { + let ValueRef lltyparam = cx.build.GEP(obj_typarams, + vec(C_int(0), + C_int(i))); + lltyparam = cx.build.Load(lltyparam); + cx.fcx.lltydescs.insert(p.id, lltyparam); + i += 1; + } + + i = 0; for (ast.obj_field f in cx.fcx.ccx.obj_fields) { let ValueRef llfield = cx.build.GEP(obj_fields, vec(C_int(0), @@ -3529,7 +3561,7 @@ fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid, alt (fcx.llself) { case (some[ValueRef](?llself)) { - create_llobjfields_for_fields(bcx, llself); + populate_fn_ctxt_from_llself(bcx, llself); } case (_) { } @@ -3623,10 +3655,11 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, C_int(abi.obj_field_box))); bcx.build.Store(vtbl, pair_vtbl); - let TypeRef llbox_ty = T_ptr(T_box(T_struct(vec(T_ptr(T_tydesc()), - T_nil())))); - if (_vec.len[ty.arg](arg_tys) == 0u) { - // Store null into pair, if no args. + let TypeRef llbox_ty = T_opaque_obj_ptr(); + + if (_vec.len[ast.ty_param](ty_params) == 0u && + _vec.len[ty.arg](arg_tys) == 0u) { + // Store null into pair, if no args or typarams. bcx.build.Store(C_null(llbox_ty), pair_box); } else { // Malloc a box for the body and copy args in. @@ -3636,8 +3669,16 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, } // Synthesize an obj body type. + auto tydesc_ty = plain_ty(ty.ty_type); + let vec[@ty.t] tps = vec(); + for (ast.ty_param tp in ty_params) { + append[@ty.t](tps, tydesc_ty); + } + + let @ty.t typarams_ty = plain_ty(ty.ty_tup(tps)); let @ty.t fields_ty = plain_ty(ty.ty_tup(obj_fields)); - let @ty.t body_ty = plain_ty(ty.ty_tup(vec(plain_ty(ty.ty_type), + let @ty.t body_ty = plain_ty(ty.ty_tup(vec(tydesc_ty, + typarams_ty, fields_ty))); let @ty.t boxed_body_ty = plain_ty(ty.ty_box(body_ty)); @@ -3664,13 +3705,28 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, bcx = body_td.bcx; bcx.build.Store(body_td.val, body_tydesc.val); + // Copy typarams into captured typarams. + auto body_typarams = + GEP_tup_like(bcx, body_ty, body.val, + vec(0, abi.obj_body_elt_typarams)); + bcx = body_typarams.bcx; + let int i = 0; + for (ast.ty_param tp in ty_params) { + auto typaram = bcx.fcx.lltydescs.get(tp.id); + auto capture = GEP_tup_like(bcx, typarams_ty, body_typarams.val, + vec(0, i)); + bcx = capture.bcx; + bcx = copy_ty(bcx, INIT, capture.val, typaram, tydesc_ty).bcx; + i += 1; + } + // Copy args into body fields. auto body_fields = GEP_tup_like(bcx, body_ty, body.val, vec(0, abi.obj_body_elt_fields)); bcx = body_fields.bcx; - let int i = 0; + i = 0; for (ast.obj_field f in ob.fields) { auto arg = bcx.fcx.llargs.get(f.id); arg = load_scalar_or_boxed(bcx, arg, arg_tys.(i).ty); @@ -3792,6 +3848,7 @@ fn trans_item(@crate_ctxt cx, &ast.item item) { } case (ast.item_obj(?name, ?ob, ?tps, ?oid, ?ann)) { auto sub_cx = @rec(path=cx.path + "." + name, + obj_typarams=tps, obj_fields=ob.fields with *cx); trans_obj(sub_cx, ob, oid, tps, ann); } @@ -4353,6 +4410,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, auto hasher = ty.hash_ty; auto eqer = ty.eq_ty; auto tydescs = map.mk_hashmap[@ty.t,ValueRef](hasher, eqer); + let vec[ast.ty_param] obj_typarams = vec(); let vec[ast.obj_field] obj_fields = vec(); auto cx = @rec(sess = sess, @@ -4369,6 +4427,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, consts = new_def_hash[ValueRef](), obj_methods = new_def_hash[()](), tydescs = tydescs, + obj_typarams = obj_typarams, obj_fields = obj_fields, glues = glues, names = namegen(0), -- cgit v1.2.3 From 302cafa81dcc868e840c78f2bfbf41929de8a487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Fri, 4 Feb 2011 09:46:10 -0500 Subject: Factor the parsing of "type foo" into parse_type_decl. --- src/comp/front/parser.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index c088e68d..1d54a6e1 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1577,15 +1577,12 @@ impure fn parse_item_mod(parser p) -> @ast.item { ret @spanned(lo, hi, item); } - impure fn parse_item_native_type(parser p) -> @ast.native_item { - auto lo = p.get_span(); - expect(p, token.TYPE); - auto id = parse_ident(p); + auto t = parse_type_decl(p); auto hi = p.get_span(); expect(p, token.SEMI); - auto item = ast.native_item_ty(id, p.next_def_id()); - ret @spanned(lo, hi, item); + auto item = ast.native_item_ty(t._1, p.next_def_id()); + ret @spanned(t._0, hi, item); } impure fn parse_native_item(parser p) -> @ast.native_item { @@ -1624,18 +1621,23 @@ impure fn parse_item_native_mod(parser p) -> @ast.item { ret @spanned(lo, hi, item); } -impure fn parse_item_type(parser p) -> @ast.item { +impure fn parse_type_decl(parser p) -> tup(span, ast.ident) { auto lo = p.get_span(); expect(p, token.TYPE); auto id = parse_ident(p); + ret tup(lo, id); +} + +impure fn parse_item_type(parser p) -> @ast.item { + auto t = parse_type_decl(p); auto tps = parse_ty_params(p); expect(p, token.EQ); auto ty = parse_ty(p); auto hi = p.get_span(); expect(p, token.SEMI); - auto item = ast.item_ty(id, ty, tps, p.next_def_id(), ast.ann_none); - ret @spanned(lo, hi, item); + auto item = ast.item_ty(t._1, ty, tps, p.next_def_id(), ast.ann_none); + ret @spanned(t._0, hi, item); } impure fn parse_item_tag(parser p) -> @ast.item { -- cgit v1.2.3 From 57bb9d809bb029caf7b38042a433153bb965e1fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Fri, 4 Feb 2011 11:10:04 -0500 Subject: Parse function declarations. --- src/comp/front/ast.rs | 11 +++++--- src/comp/front/parser.rs | 38 +++++++++++++++++++++------- src/comp/middle/fold.rs | 60 +++++++++++++++++++++++++++++++++----------- src/comp/middle/resolve.rs | 2 +- src/comp/middle/trans.rs | 4 +-- src/comp/middle/typeck.rs | 28 ++++++++++----------- src/test/run-pass/native2.rs | 1 + 7 files changed, 101 insertions(+), 43 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 7b22e700..1220d6ab 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -201,10 +201,11 @@ tag ty_ { } type arg = rec(mode mode, @ty ty, ident ident, def_id id); -type _fn = rec(effect effect, +type fn_decl = rec(effect effect, + vec[arg] inputs, + @ty output); +type _fn = rec(fn_decl decl, bool is_iter, - vec[arg] inputs, - @ty output, block body); @@ -254,6 +255,7 @@ tag item_ { type native_item = spanned[native_item_]; tag native_item_ { native_item_ty(ident, def_id); + native_item_fn(ident, fn_decl, vec[ty_param], def_id); } fn index_view_item(mod_index index, @view_item it) { @@ -304,6 +306,9 @@ fn index_native_item(native_mod_index index, @native_item it) { case (ast.native_item_ty(?id, _)) { index.insert(id, it); } + case (ast.native_item_fn(?id, _, _, _)) { + index.insert(id, it); + } } } diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 1d54a6e1..e04b8221 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1441,7 +1441,7 @@ impure fn parse_ty_params(parser p) -> vec[ast.ty_param] { ret ty_params; } -impure fn parse_fn(parser p, ast.effect eff, bool is_iter) -> ast._fn { +impure fn parse_fn_decl(parser p, ast.effect eff) -> ast.fn_decl { auto pf = parse_arg; let util.common.spanned[vec[ast.arg]] inputs = // FIXME: passing parse_arg as an lval doesn't work at the @@ -1459,18 +1459,19 @@ impure fn parse_fn(parser p, ast.effect eff, bool is_iter) -> ast._fn { } else { output = @spanned(inputs.span, inputs.span, ast.ty_nil); } + ret rec(effect=eff, inputs=inputs.node, output=output); +} +impure fn parse_fn(parser p, ast.effect eff, bool is_iter) -> ast._fn { + auto decl = parse_fn_decl(p, eff); auto body = parse_block(p); - - ret rec(effect = eff, + ret rec(decl = decl, is_iter = is_iter, - inputs = inputs.node, - output = output, body = body); } -impure fn parse_item_fn_or_iter(parser p, ast.effect eff, - bool is_iter) -> @ast.item { +impure fn parse_fn_header(parser p, bool is_iter) -> tup(span, ast.ident, + vec[ast.ty_param]) { auto lo = p.get_span(); if (is_iter) { expect(p, token.ITER); @@ -1479,10 +1480,16 @@ impure fn parse_item_fn_or_iter(parser p, ast.effect eff, } auto id = parse_ident(p); auto ty_params = parse_ty_params(p); + ret tup(lo, id, ty_params); +} + +impure fn parse_item_fn_or_iter(parser p, ast.effect eff, + bool is_iter) -> @ast.item { + auto t = parse_fn_header(p, is_iter); auto f = parse_fn(p, eff, is_iter); - auto item = ast.item_fn(id, f, ty_params, + auto item = ast.item_fn(t._1, f, t._2, p.next_def_id(), ast.ann_none); - ret @spanned(lo, f.body.span, item); + ret @spanned(t._0, f.body.span, item); } @@ -1585,11 +1592,24 @@ impure fn parse_item_native_type(parser p) -> @ast.native_item { ret @spanned(t._0, hi, item); } +impure fn parse_item_native_fn(parser p, ast.effect eff) -> @ast.native_item { + auto t = parse_fn_header(p, false); + auto decl = parse_fn_decl(p, eff); + auto hi = p.get_span(); + expect(p, token.SEMI); + auto item = ast.native_item_fn(t._1, decl, t._2, p.next_def_id()); + ret @spanned(t._0, hi, item); +} + impure fn parse_native_item(parser p) -> @ast.native_item { + let ast.effect eff = parse_effect(p); alt (p.peek()) { case (token.TYPE) { ret parse_item_native_type(p); } + case (token.FN) { + ret parse_item_native_fn(p, eff); + } } } diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index b9027836..688d21d2 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -10,6 +10,7 @@ import util.common.ty_mach; import util.common.append; import front.ast; +import front.ast.fn_decl; import front.ast.ident; import front.ast.path; import front.ast.mutability; @@ -194,6 +195,11 @@ type ast_fold[ENV] = vec[ast.ty_param] ty_params, def_id id, ann a) -> @item) fold_item_fn, + (fn(&ENV e, &span sp, ident ident, + &ast.fn_decl decl, + vec[ast.ty_param] ty_params, + def_id id) -> @native_item) fold_native_item_fn, + (fn(&ENV e, &span sp, ident ident, &ast._mod m, def_id id) -> @item) fold_item_mod, @@ -229,10 +235,13 @@ type ast_fold[ENV] = (fn(&ENV e, &span sp, &ast.block_) -> block) fold_block, - (fn(&ENV e, ast.effect effect, + (fn(&ENV e, &fn_decl decl, bool is_iter, + &block body) -> ast._fn) fold_fn, + + (fn(&ENV e, ast.effect effect, vec[arg] inputs, - @ty output, &block body) -> ast._fn) fold_fn, + @ty output) -> ast.fn_decl) fold_fn_decl, (fn(&ENV e, &ast._mod m) -> ast._mod) fold_mod, @@ -688,17 +697,22 @@ fn fold_arg[ENV](&ENV env, ast_fold[ENV] fld, &arg a) -> arg { ret rec(ty=ty with a); } - -fn fold_fn[ENV](&ENV env, ast_fold[ENV] fld, &ast._fn f) -> ast._fn { - +fn fold_fn_decl[ENV](&ENV env, ast_fold[ENV] fld, + &ast.fn_decl decl) -> ast.fn_decl { let vec[ast.arg] inputs = vec(); - for (ast.arg a in f.inputs) { + for (ast.arg a in decl.inputs) { inputs += fold_arg(env, fld, a); } - auto output = fold_ty[ENV](env, fld, f.output); + auto output = fold_ty[ENV](env, fld, decl.output); + ret fld.fold_fn_decl(env, decl.effect, inputs, output); +} + +fn fold_fn[ENV](&ENV env, ast_fold[ENV] fld, &ast._fn f) -> ast._fn { + auto decl = fold_fn_decl(env, fld, f.decl); + auto body = fold_block[ENV](env, fld, f.body); - ret fld.fold_fn(env, f.effect, f.is_iter, inputs, output, body); + ret fld.fold_fn(env, decl, f.is_iter, body); } @@ -857,6 +871,10 @@ fn fold_native_item[ENV](&ENV env, ast_fold[ENV] fld, case (ast.native_item_ty(?ident, ?id)) { ret fld.fold_native_item_ty(env_, i.span, ident, id); } + case (ast.native_item_fn(?ident, ?fn_decl, ?ty_params, ?id)) { + ret fld.fold_native_item_fn(env_, i.span, ident, fn_decl, + ty_params, id); + } } } @@ -1144,6 +1162,13 @@ fn identity_fold_item_fn[ENV](&ENV e, &span sp, ident i, ret @respan(sp, ast.item_fn(i, f, ty_params, id, a)); } +fn identity_fold_native_item_fn[ENV](&ENV e, &span sp, ident i, + &ast.fn_decl decl, + vec[ast.ty_param] ty_params, + def_id id) -> @native_item { + ret @respan(sp, ast.native_item_fn(i, decl, ty_params, id)); +} + fn identity_fold_item_mod[ENV](&ENV e, &span sp, ident i, &ast._mod m, def_id id) -> @item { ret @respan(sp, ast.item_mod(i, m, id)); @@ -1199,14 +1224,18 @@ fn identity_fold_block[ENV](&ENV e, &span sp, &ast.block_ blk) -> block { ret respan(sp, blk); } +fn identity_fold_fn_decl[ENV](&ENV e, + ast.effect effect, + vec[arg] inputs, + @ty output) -> ast.fn_decl { + ret rec(effect=effect, inputs=inputs, output=output); +} + fn identity_fold_fn[ENV](&ENV e, - ast.effect effect, + &fn_decl decl, bool is_iter, - vec[arg] inputs, - @ast.ty output, &block body) -> ast._fn { - ret rec(effect=effect, is_iter=is_iter, inputs=inputs, - output=output, body=body); + ret rec(decl=decl, is_iter=is_iter, body=body); } fn identity_fold_mod[ENV](&ENV e, &ast._mod m) -> ast._mod { @@ -1343,6 +1372,8 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_item_const= bind identity_fold_item_const[ENV](_,_,_,_,_,_,_), fold_item_fn = bind identity_fold_item_fn[ENV](_,_,_,_,_,_,_), + fold_native_item_fn = + bind identity_fold_native_item_fn[ENV](_,_,_,_,_,_), fold_item_mod = bind identity_fold_item_mod[ENV](_,_,_,_,_), fold_item_native_mod = bind identity_fold_item_native_mod[ENV](_,_,_,_,_), @@ -1358,7 +1389,8 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { bind identity_fold_view_item_import[ENV](_,_,_,_,_,_), fold_block = bind identity_fold_block[ENV](_,_,_), - fold_fn = bind identity_fold_fn[ENV](_,_,_,_,_,_), + fold_fn = bind identity_fold_fn[ENV](_,_,_,_), + fold_fn_decl = bind identity_fold_fn_decl[ENV](_,_,_,_), fold_mod = bind identity_fold_mod[ENV](_,_), fold_native_mod = bind identity_fold_native_mod[ENV](_,_), fold_crate = bind identity_fold_crate[ENV](_,_,_), diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 1af3b205..2cfbcc83 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -283,7 +283,7 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] { case (scope_item(?it)) { alt (it.node) { case (ast.item_fn(_, ?f, ?ty_params, _, _)) { - for (ast.arg a in f.inputs) { + for (ast.arg a in f.decl.inputs) { if (_str.eq(a.ident, i)) { auto t = ast.def_arg(a.id); ret some(def_wrap_other(t)); diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4610cef6..22f4109f 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3553,10 +3553,10 @@ fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid, auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); create_llargs_for_fn_args(fcx, ty_self, ret_ty_of_fn(ann), - f.inputs, ty_params); + f.decl.inputs, ty_params); auto bcx = new_top_block_ctxt(fcx); - copy_args_to_allocas(bcx, ty_self, f.inputs, + copy_args_to_allocas(bcx, ty_self, f.decl.inputs, arg_tys_of_fn(ann)); alt (fcx.llself) { diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 43d35b37..5412f131 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -285,8 +285,8 @@ fn collect_item_types(session.session sess, @ast.crate crate) auto get = bind getter(id_to_ty_item, item_to_ty, _); auto convert = bind ast_ty_to_ty(get, _); auto f = bind ty_of_arg(id_to_ty_item, item_to_ty, _); - auto inputs = _vec.map[ast.arg,arg](f, m.node.meth.inputs); - auto output = convert(m.node.meth.output); + auto inputs = _vec.map[ast.arg,arg](f, m.node.meth.decl.inputs); + auto output = convert(m.node.meth.decl.output); ret rec(ident=m.node.ident, inputs=inputs, output=output); } @@ -339,8 +339,9 @@ fn collect_item_types(session.session sess, @ast.crate crate) // TODO: handle ty-params auto f = bind ty_of_arg(id_to_ty_item, item_to_ty, _); - auto input_tys = _vec.map[ast.arg,arg](f, fn_info.inputs); - auto output_ty = convert(fn_info.output); + auto input_tys = _vec.map[ast.arg,arg](f, + fn_info.decl.inputs); + auto output_ty = convert(fn_info.decl.output); auto t_fn = plain_ty(ty.ty_fn(input_tys, output_ty)); item_to_ty.insert(def_id, t_fn); @@ -1773,9 +1774,8 @@ fn check_const(&@crate_ctxt ccx, &span sp, ast.ident ident, @ast.ty t, ret @fold.respan[ast.item_](sp, item); } -fn check_fn(&@crate_ctxt ccx, ast.effect effect, - bool is_iter, vec[ast.arg] inputs, - @ast.ty output, &ast.block body) -> ast._fn { +fn check_fn(&@crate_ctxt ccx, &ast.fn_decl decl, + bool is_iter, &ast.block body) -> ast._fn { auto local_ty_table = @common.new_def_hash[@ty.t](); // FIXME: duplicate work: the item annotation already has the arg types @@ -1789,12 +1789,12 @@ fn check_fn(&@crate_ctxt ccx, ast.effect effect, } // Store the type of each argument in the table. - for (ast.arg arg in inputs) { + for (ast.arg arg in decl.inputs) { auto input_ty = ast_ty_to_ty_crate(ccx, arg.ty); local_ty_table.insert(arg.id, input_ty); } - let @fn_ctxt fcx = @rec(ret_ty = ast_ty_to_ty_crate(ccx, output), + let @fn_ctxt fcx = @rec(ret_ty = ast_ty_to_ty_crate(ccx, decl.output), locals = local_ty_table, ccx = ccx); @@ -1802,8 +1802,8 @@ fn check_fn(&@crate_ctxt ccx, ast.effect effect, auto block_t = check_block(fcx, body); auto block_wb = writeback(fcx, block_t); - auto fn_t = rec(effect=effect, is_iter=is_iter, - inputs=inputs, output=output, body=block_wb); + auto fn_t = rec(decl=decl, is_iter=is_iter, + body=block_wb); ret fn_t; } @@ -1816,12 +1816,12 @@ fn check_item_fn(&@crate_ctxt ccx, &span sp, ast.ident ident, &ast._fn f, // again here, we can extract them. let vec[arg] inputs = vec(); - for (ast.arg arg in f.inputs) { + for (ast.arg arg in f.decl.inputs) { auto input_ty = ast_ty_to_ty_crate(ccx, arg.ty); inputs += vec(rec(mode=arg.mode, ty=input_ty)); } - auto output_ty = ast_ty_to_ty_crate(ccx, f.output); + auto output_ty = ast_ty_to_ty_crate(ccx, f.decl.output); auto fn_sty = ty.ty_fn(inputs, output_ty); auto fn_ann = ast.ann_type(plain_ty(fn_sty)); @@ -1854,7 +1854,7 @@ fn check_crate(session.session sess, @ast.crate crate) -> @ast.crate { auto fld = fold.new_identity_fold[@crate_ctxt](); fld = @rec(update_env_for_item = bind update_obj_fields(_, _), - fold_fn = bind check_fn(_,_,_,_,_,_), + fold_fn = bind check_fn(_,_,_,_), fold_item_fn = bind check_item_fn(_,_,_,_,_,_,_) with *fld); ret fold.fold_crate[@crate_ctxt](ccx, fld, result._0); diff --git a/src/test/run-pass/native2.rs b/src/test/run-pass/native2.rs index b848ec8c..a6df93f5 100644 --- a/src/test/run-pass/native2.rs +++ b/src/test/run-pass/native2.rs @@ -1,5 +1,6 @@ native "rust" mod rustrt { type vbuf; + fn vec_buf[T](vec[T] v, uint offset) -> vbuf; } fn main(vec[str] args) { -- cgit v1.2.3 From 8122e0c54280545c28e8067c0e3a19253fe3aa9b Mon Sep 17 00:00:00 2001 From: Rafael Avila de Espindola Date: Mon, 7 Feb 2011 12:46:28 -0500 Subject: Add support for native mod foo = "bar" ... --- src/comp/front/parser.rs | 13 ++++++++++++- src/test/run-pass/native2.rs | 4 ++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index e04b8221..8d130935 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1630,9 +1630,20 @@ impure fn parse_native_mod_items(parser p, impure fn parse_item_native_mod(parser p) -> @ast.item { auto lo = p.get_span(); expect(p, token.NATIVE); - auto native_name = parse_str_lit(p); + auto has_eq; + auto native_name = ""; + if (p.peek() == token.MOD) { + has_eq = true; + } else { + native_name = parse_str_lit(p); + has_eq = false; + } expect(p, token.MOD); auto id = parse_ident(p); + if (has_eq) { + expect(p, token.EQ); + native_name = parse_str_lit(p); + } expect(p, token.LBRACE); auto m = parse_native_mod_items(p, native_name); auto hi = p.get_span(); diff --git a/src/test/run-pass/native2.rs b/src/test/run-pass/native2.rs index a6df93f5..4d2f0ad9 100644 --- a/src/test/run-pass/native2.rs +++ b/src/test/run-pass/native2.rs @@ -3,5 +3,9 @@ native "rust" mod rustrt { fn vec_buf[T](vec[T] v, uint offset) -> vbuf; } +native mod libc = "libc.dylib" { + fn write(int fd, rustrt.vbuf buf, uint count) -> int; +} + fn main(vec[str] args) { } -- cgit v1.2.3 From ff6864aa5ca14795ae0e23e97e0e67b1122a6b68 Mon Sep 17 00:00:00 2001 From: Rafael Avila de Espindola Date: Mon, 7 Feb 2011 14:57:34 -0500 Subject: Fix expressions with paths with more than one element. --- src/comp/middle/resolve.rs | 3 +-- src/test/run-pass/path.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/path.rs diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 2cfbcc83..97a52284 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -432,8 +432,7 @@ fn fold_expr_path(&env e, &span sp, &ast.path p, &option.t[def] d, path_len = n_idents - remaining + 1u; } case (def_wrap_other(_)) { - check (n_idents == 1u); - path_len = 1u; + path_len = n_idents; } case (def_wrap_mod(?m)) { e.sess.span_err(sp, diff --git a/src/test/run-pass/path.rs b/src/test/run-pass/path.rs new file mode 100644 index 00000000..e94d32eb --- /dev/null +++ b/src/test/run-pass/path.rs @@ -0,0 +1,8 @@ +mod foo { + fn bar(uint offset) { + } +} + +fn main(vec[str] args) { + foo.bar(0u); +} -- cgit v1.2.3 From 3e613c1648141ac757d1f0608ad845686ebbe97e Mon Sep 17 00:00:00 2001 From: Rafael Avila de Espindola Date: Mon, 7 Feb 2011 15:07:27 -0500 Subject: Add native modules to resolve. With this hello world gets to typecheck. --- src/comp/front/ast.rs | 2 ++ src/comp/middle/resolve.rs | 77 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 1220d6ab..5f315e58 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -36,6 +36,8 @@ tag def { def_ty_arg(def_id); def_binding(def_id); def_use(def_id); + def_native_ty(def_id); + def_native_fn(def_id); } type crate = spanned[crate_]; diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 97a52284..0a8f238d 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -34,6 +34,7 @@ tag def_wrap { def_wrap_use(@ast.view_item); def_wrap_import(@ast.view_item); def_wrap_mod(@ast.item); + def_wrap_native_mod(@ast.item); def_wrap_other(def); def_wrap_expr_field(uint, def); def_wrap_resolving; @@ -103,6 +104,29 @@ fn find_final_def(&env e, import_map index, // should return what a.b.c.d points to in the end. fn found_something(&env e, import_map index, &span sp, vec[ident] idents, def_wrap d) -> def_wrap { + + fn found_mod(&env e, &import_map index, &span sp, + vec[ident] idents, @ast.item i) -> def_wrap { + auto len = _vec.len[ident](idents); + auto rest_idents = _vec.slice[ident](idents, 1u, len); + auto empty_e = rec(scopes = nil[scope], + sess = e.sess); + auto tmp_e = update_env_for_item(empty_e, i); + auto next_i = rest_idents.(0); + auto next_ = lookup_name_wrapped(tmp_e, next_i); + alt (next_) { + case (none[tup(@env, def_wrap)]) { + e.sess.span_err(sp, "unresolved name: " + next_i); + fail; + } + case (some[tup(@env, def_wrap)](?next)) { + auto combined_e = update_env_for_item(e, i); + ret found_something(combined_e, index, sp, + rest_idents, next._1); + } + } + } + alt (d) { case (def_wrap_import(?imp)) { alt (imp.node) { @@ -122,23 +146,10 @@ fn find_final_def(&env e, import_map index, } alt (d) { case (def_wrap_mod(?i)) { - auto rest_idents = _vec.slice[ident](idents, 1u, len); - auto empty_e = rec(scopes = nil[scope], - sess = e.sess); - auto tmp_e = update_env_for_item(empty_e, i); - auto next_i = rest_idents.(0); - auto next_ = lookup_name_wrapped(tmp_e, next_i); - alt (next_) { - case (none[tup(@env, def_wrap)]) { - e.sess.span_err(sp, "unresolved name: " + next_i); - fail; - } - case (some[tup(@env, def_wrap)](?next)) { - auto combined_e = update_env_for_item(e, i); - ret found_something(combined_e, index, sp, - rest_idents, next._1); - } - } + ret found_mod(e, index, sp, idents, i); + } + case (def_wrap_native_mod(?i)) { + ret found_mod(e, index, sp, idents, i); } case (def_wrap_use(?c)) { e.sess.span_err(sp, "Crate access is not implemented"); @@ -201,6 +212,9 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] { case (ast.item_mod(_, _, ?id)) { ret def_wrap_mod(i); } + case (ast.item_native_mod(_, _, ?id)) { + ret def_wrap_native_mod(i); + } case (ast.item_ty(_, _, _, ?id, _)) { ret def_wrap_other(ast.def_ty(id)); } @@ -213,6 +227,17 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] { } } + fn found_def_native_item(@ast.native_item i) -> def_wrap { + alt (i.node) { + case (ast.native_item_ty(_, ?id)) { + ret def_wrap_other(ast.def_native_ty(id)); + } + case (ast.native_item_fn(_, _, _, ?id)) { + ret def_wrap_other(ast.def_native_fn(id)); + } + } + } + fn found_decl_stmt(@ast.stmt s) -> def_wrap { alt (s.node) { case (ast.stmt_decl(?d)) { @@ -267,11 +292,22 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] { } } } - case (none[ast.mod_index_entry]) { /* fall through */ } + case (none[ast.mod_index_entry]) { + ret none[def_wrap]; + } } - ret none[def_wrap]; } + fn check_native_mod(ast.ident i, ast.native_mod m) -> option.t[def_wrap] { + alt (m.index.find(i)) { + case (some[@ast.native_item](?item)) { + ret some(found_def_native_item(item)); + } + case (_) { + ret none[def_wrap]; + } + } + } fn in_scope(ast.ident i, &scope s) -> option.t[def_wrap] { alt (s) { @@ -313,6 +349,9 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] { case (ast.item_mod(_, ?m, _)) { ret check_mod(i, m); } + case (ast.item_native_mod(_, ?m, _)) { + ret check_native_mod(i, m); + } case (ast.item_ty(_, _, ?ty_params, _, _)) { for (ast.ty_param tp in ty_params) { if (_str.eq(tp.ident, i)) { -- cgit v1.2.3 From d7f118135b8a3eee7c8788052542e6e1c205a3d9 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 7 Feb 2011 14:11:43 -0800 Subject: Iterate type unification to drive the types a bit further down into the leaves of results with residual vars. Cheap but kinda works. --- src/comp/middle/ty.rs | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 2f14aae6..92fa1399 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -551,6 +551,24 @@ fn count_ty_params(@t ty) -> uint { ret _vec.len[ast.def_id](*param_ids); } +fn type_contains_ty_vars(@t ty) -> bool { + state obj checker(@mutable bool has_vars) { + fn fold_simple_ty(@t ty) -> @t { + alt (ty.struct) { + case (ty_var(_)) { + *has_vars = true; + } + case (_) {} + } + ret ty; + } + } + + let @mutable bool b = @mutable false; + fold_ty(checker(b), ty); + ret *b; +} + // Type accessors for substructures of types fn ty_fn_args(@t fty) -> vec[arg] { @@ -1197,7 +1215,21 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) auto eqer = eq_int; auto bindings = map.mk_hashmap[int,@ty.t](hasher, eqer); - ret unify_step(bindings, expected, actual, handler); + auto ures = unify_step(bindings, expected, actual, handler); + while (true) { + alt (ures) { + case (ures_ok(?t)) { + if (!type_contains_ty_vars(t)) { + ret ures; + } + ures = unify_step(bindings, t, actual, handler); + } + case (_) { + ret ures; + } + } + } + fail; } fn type_err_to_str(&ty.type_err err) -> str { -- cgit v1.2.3 From 9d576993f31349f2a7dbf8e40ccdaff9cf66144d Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 7 Feb 2011 14:16:40 -0800 Subject: Add a fixme for last commit. --- src/comp/middle/ty.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 92fa1399..c3b0e687 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -1215,6 +1215,10 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) auto eqer = eq_int; auto bindings = map.mk_hashmap[int,@ty.t](hasher, eqer); + // FIXME: this is a slow way of driving types into residual vars that + // occur up in the leaves of result type; it can likely be done better + // when unification is actually ... down in the leaves. + auto ures = unify_step(bindings, expected, actual, handler); while (true) { alt (ures) { -- cgit v1.2.3 From 74f71d387eceb4235bae89a400292ad6ecde8ca1 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 8 Feb 2011 11:47:53 -0800 Subject: Overhaul ABI. All retptrs, all the time. --- src/comp/middle/trans.rs | 478 ++++++++++++++++++++++------------------------- 1 file changed, 224 insertions(+), 254 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 22f4109f..9e59cf57 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -83,9 +83,9 @@ state type crate_ctxt = rec(session.session sess, state type fn_ctxt = rec(ValueRef llfn, ValueRef lltaskptr, - ValueRef llclosure, + ValueRef llenv, + ValueRef llretptr, mutable option.t[ValueRef] llself, - mutable option.t[ValueRef] llretptr, hashmap[ast.def_id, ValueRef] llargs, hashmap[ast.def_id, ValueRef] llobjfields, hashmap[ast.def_id, ValueRef] lllocals, @@ -239,13 +239,23 @@ fn T_task() -> TypeRef { )); } +fn T_glue_fn() -> TypeRef { + // Bit of a kludge: pick the fn typeref out of the tydesc.. + let vec[TypeRef] tydesc_elts = _vec.init_elt[TypeRef](T_nil(), 10u); + llvm.LLVMGetStructElementTypes(T_tydesc(), + _vec.buf[TypeRef](tydesc_elts)); + ret llvm.LLVMGetElementType(tydesc_elts.(abi.tydesc_field_drop_glue_off)); +} + fn T_tydesc() -> TypeRef { auto th = mk_type_handle(); auto abs_tydesc = llvm.LLVMResolveTypeHandle(th.llth); auto tydescpp = T_ptr(T_ptr(abs_tydesc)); auto pvoid = T_ptr(T_i8()); - auto glue_fn_ty = T_ptr(T_fn(vec(T_taskptr(), + auto glue_fn_ty = T_ptr(T_fn(vec(T_ptr(T_nil()), + T_taskptr(), + T_ptr(T_nil()), tydescpp, pvoid), T_void())); auto tydesc = T_struct(vec(tydescpp, // first_param @@ -354,25 +364,31 @@ fn type_of(@crate_ctxt cx, @ty.t t) -> TypeRef { ret llty; } -// NB: this must match trans_args and create_llargs_for_fn_args. + +// NB: must keep 4 fns in sync: +// +// - type_of_fn_full +// - create_llargs_for_fn_args. +// - new_fn_ctxt +// - trans_args + fn type_of_fn_full(@crate_ctxt cx, option.t[TypeRef] obj_self, vec[ty.arg] inputs, @ty.t output) -> TypeRef { - let vec[TypeRef] atys = vec(T_taskptr()); - - auto fn_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; - } + let vec[TypeRef] atys = vec(); + // Arg 0: Output pointer. if (ty.type_has_dynamic_size(output)) { atys += T_typaram_ptr(); + } else { + atys += T_ptr(type_of(cx, output)); } + // Arg 1: Task pointer. + atys += T_taskptr(); + + // Arg 2: Env (closure-bindings / self-obj) alt (obj_self) { case (some[TypeRef](?t)) { check (t as int != 0); @@ -383,6 +399,16 @@ fn type_of_fn_full(@crate_ctxt cx, } } + // Args >3: ty params ... + auto ty_param_count = + ty.count_ty_params(plain_ty(ty.ty_fn(inputs, output))); + auto i = 0u; + while (i < ty_param_count) { + atys += T_ptr(T_tydesc()); + i += 1u; + } + + // ... then explicit args. for (ty.arg arg in inputs) { if (ty.type_has_dynamic_size(arg.ty)) { check (arg.mode == ast.alias); @@ -399,14 +425,7 @@ fn type_of_fn_full(@crate_ctxt cx, } } - auto ret_ty; - if (ty.type_is_nil(output) || ty.type_has_dynamic_size(output)) { - ret_ty = llvm.LLVMVoidType(); - } else { - ret_ty = type_of(cx, output); - } - - ret T_fn(atys, ret_ty); + ret T_fn(atys, llvm.LLVMVoidType()); } fn type_of_fn(@crate_ctxt cx, vec[ty.arg] inputs, @ty.t output) -> TypeRef { @@ -663,9 +682,11 @@ fn trans_upcall(@block_ctxt cx, str name, vec[ValueRef] args) -> result { let ValueRef llglue = cx.fcx.ccx.glues.upcall_glues.(n); let vec[ValueRef] call_args = vec(cx.fcx.lltaskptr, llupcall); + for (ValueRef a in args) { call_args += cx.build.ZExtOrBitCast(a, T_int()); } + ret res(cx, cx.build.FastCall(llglue, call_args)); } @@ -1044,10 +1065,7 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { auto drop_glue = make_generic_glue(cx, t, "drop", dg, typaram_defs); auto llty = type_of(cx, t); - auto pvoid = T_ptr(T_i8()); - auto glue_fn_ty = T_ptr(T_fn(vec(T_taskptr(), - T_ptr(T_ptr(T_tydesc())), - pvoid), T_void())); + auto glue_fn_ty = T_ptr(T_glue_fn()); // FIXME: this adjustment has to do with the ridiculous encoding of // glue-pointer-constants in the tydesc records: They are tydesc-relative @@ -1082,9 +1100,7 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { fn make_generic_glue(@crate_ctxt cx, @ty.t t, str name, val_and_ty_fn helper, vec[ast.def_id] typaram_defs) -> ValueRef { - auto llfnty = T_fn(vec(T_taskptr(), - T_ptr(T_ptr(T_tydesc())), - T_ptr(T_i8())), T_void()); + auto llfnty = T_glue_fn(); auto fn_name = cx.names.next("_rust_" + name) + "." + ty.ty_to_str(t); fn_name = sanitize(fn_name); @@ -1102,7 +1118,7 @@ fn make_generic_glue(@crate_ctxt cx, @ty.t t, str name, llty = type_of(cx, t); } - auto lltyparams = llvm.LLVMGetParam(llfn, 1u); + auto lltyparams = llvm.LLVMGetParam(llfn, 3u); auto p = 0; for (ast.def_id d in typaram_defs) { auto llparam = bcx.build.GEP(lltyparams, vec(C_int(p))); @@ -1111,7 +1127,7 @@ fn make_generic_glue(@crate_ctxt cx, @ty.t t, str name, p += 1; } - auto llrawptr = llvm.LLVMGetParam(llfn, 2u); + auto llrawptr = llvm.LLVMGetParam(llfn, 4u); auto llval = bcx.build.BitCast(llrawptr, llty); re = helper(bcx, llval, t); @@ -1582,7 +1598,11 @@ fn call_tydesc_glue_full(@block_ctxt cx, ValueRef v, cx.build.PtrToInt(tydesc, T_int())), val_ty(llfn)); - cx.build.FastCall(llfn, vec(cx.fcx.lltaskptr, lltydescs, llrawptr)); + cx.build.FastCall(llfn, vec(C_null(T_ptr(T_nil())), + cx.fcx.lltaskptr, + C_null(T_ptr(T_nil())), + lltydescs, + llrawptr)); } fn call_tydesc_glue(@block_ctxt cx, ValueRef v, @ty.t t, int field) { @@ -2467,103 +2487,6 @@ fn trans_cast(@block_ctxt cx, @ast.expr e, &ast.ann ann) -> result { ret e_res; } - -// NB: this must match type_of_fn_full and create_llargs_for_fn_args. -fn trans_args(@block_ctxt cx, - ValueRef llclosure, - option.t[ValueRef] llobj, - option.t[generic_info] gen, - &vec[@ast.expr] es, - @ty.t fn_ty) - -> tup(@block_ctxt, vec[ValueRef], option.t[ValueRef]) { - let vec[ValueRef] vs = vec(cx.fcx.lltaskptr); - let @block_ctxt bcx = cx; - - let vec[ty.arg] args = ty.ty_fn_args(fn_ty); - - let option.t[ValueRef] llretslot_opt = none[ValueRef]; - - alt (gen) { - case (some[generic_info](?g)) { - for (ValueRef t in g.tydescs) { - vs += t; - } - args = ty.ty_fn_args(g.item_type); - if (ty.type_has_dynamic_size(ty.ty_fn_ret(g.item_type))) { - auto retty = ty.ty_fn_ret(fn_ty); - auto llretty = type_of(cx.fcx.ccx, retty); - auto llretslot = cx.build.Alloca(llretty); - vs += cx.build.PointerCast(llretslot, T_ptr(T_i8())); - llretslot_opt = some[ValueRef](llretslot); - } - } - case (_) { } - } - - alt (llobj) { - case (some[ValueRef](?ob)) { - // Every object is always found in memory, - // and not-yet-loaded (as part of an lval x.y - // doted method-call). - vs += cx.build.Load(ob); - } - case (_) { - vs += llclosure; - } - } - - auto i = 0u; - for (@ast.expr e in es) { - auto mode = args.(i).mode; - - auto val; - if (ty.type_is_structural(ty.expr_ty(e))) { - auto re = trans_expr(bcx, e); - val = re.val; - bcx = re.bcx; - if (mode == ast.val) { - // Until here we've been treating structures by pointer; - // we are now passing it as an arg, so need to load it. - val = bcx.build.Load(val); - } - } else if (mode == ast.alias) { - let lval_result lv; - if (ty.is_lval(e)) { - lv = trans_lval(bcx, e); - } else { - auto r = trans_expr(bcx, e); - lv = lval_val(r.bcx, r.val); - } - bcx = lv.res.bcx; - - if (lv.is_mem) { - val = lv.res.val; - } else { - // Non-mem but we're trying to alias; synthesize an - // alloca, spill to it and pass its address. - auto llty = val_ty(lv.res.val); - auto llptr = lv.res.bcx.build.Alloca(llty); - lv.res.bcx.build.Store(lv.res.val, llptr); - val = llptr; - } - - } else { - auto re = trans_expr(bcx, e); - val = re.val; - bcx = re.bcx; - } - - if (ty.type_has_dynamic_size(args.(i).ty)) { - val = bcx.build.PointerCast(val, T_typaram_ptr()); - } - - vs += val; - i += 1u; - } - - ret tup(bcx, vs, llretslot_opt); -} - fn trans_bind_thunk(@crate_ctxt cx, @ty.t incoming_fty, @ty.t outgoing_fty, @@ -2577,15 +2500,13 @@ fn trans_bind_thunk(@crate_ctxt cx, let TypeRef llthunk_ty = get_pair_fn_ty(type_of(cx, incoming_fty)); let ValueRef llthunk = decl_fastcall_fn(cx.llmod, s, llthunk_ty); - let @ty.t rty = ret_ty_of_fn_ty(incoming_fty); - // FIXME: handle ty params properly. let vec[ast.ty_param] ty_params = vec(); auto fcx = new_fn_ctxt(cx, s, llthunk); auto bcx = new_top_block_ctxt(fcx); - auto llclosure = bcx.build.PointerCast(fcx.llclosure, llclosure_ty); + auto llclosure = bcx.build.PointerCast(fcx.llenv, llclosure_ty); auto llbody = bcx.build.GEP(llclosure, vec(C_int(0), @@ -2603,7 +2524,8 @@ fn trans_bind_thunk(@crate_ctxt cx, vec(C_int(0), C_int(abi.fn_field_box))); lltargetclosure = bcx.build.Load(lltargetclosure); - let vec[ValueRef] llargs = vec(fcx.lltaskptr, + let vec[ValueRef] llargs = vec(fcx.llretptr, + fcx.lltaskptr, lltargetclosure); let uint a = 0u; let int b = 0; @@ -2635,20 +2557,7 @@ fn trans_bind_thunk(@crate_ctxt cx, C_int(abi.fn_field_code))); lltargetfn = bcx.build.Load(lltargetfn); auto r = bcx.build.FastCall(lltargetfn, llargs); - - alt (fcx.llretptr) { - case (some[ValueRef](?llptr)) { - bcx.build.Store(bcx.build.Load(r), llptr); - bcx.build.RetVoid(); - } - case (none[ValueRef]) { - if (ty.type_is_nil(rty)) { - bcx.build.RetVoid(); - } else { - bcx.build.Ret(r); - } - } - } + bcx.build.RetVoid(); ret llthunk; } @@ -2766,11 +2675,123 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, } } +// NB: must keep 4 fns in sync: +// +// - type_of_fn_full +// - create_llargs_for_fn_args. +// - new_fn_ctxt +// - trans_args + +fn trans_args(@block_ctxt cx, + ValueRef llenv, + option.t[ValueRef] llobj, + option.t[generic_info] gen, + &vec[@ast.expr] es, + @ty.t fn_ty) + -> tup(@block_ctxt, vec[ValueRef], ValueRef) { + + let vec[ty.arg] args = ty.ty_fn_args(fn_ty); + let vec[ValueRef] llargs = vec(); + let vec[ValueRef] lltydescs = vec(); + let @block_ctxt bcx = cx; + + + // Arg 0: Output pointer. + auto retty = ty.ty_fn_ret(fn_ty); + auto llretslot = cx.build.Alloca(type_of(cx.fcx.ccx, retty)); + alt (gen) { + case (some[generic_info](?g)) { + lltydescs = g.tydescs; + args = ty.ty_fn_args(g.item_type); + retty = ty.ty_fn_ret(g.item_type); + } + case (_) { + } + } + if (ty.type_has_dynamic_size(retty)) { + llargs += cx.build.PointerCast(llretslot, T_typaram_ptr()); + } else { + llargs += llretslot; + } + + + // Arg 1: Task pointer. + llargs += cx.fcx.lltaskptr; + + // Arg 2: Env (closure-bindings / self-obj) + alt (llobj) { + case (some[ValueRef](?ob)) { + // Every object is always found in memory, + // and not-yet-loaded (as part of an lval x.y + // doted method-call). + llargs += cx.build.Load(ob); + } + case (_) { + llargs += llenv; + } + } + + // Args >3: ty_params ... + llargs += lltydescs; + + // ... then explicit args. + auto i = 0u; + for (@ast.expr e in es) { + auto mode = args.(i).mode; + + auto val; + if (ty.type_is_structural(ty.expr_ty(e))) { + auto re = trans_expr(bcx, e); + val = re.val; + bcx = re.bcx; + if (mode == ast.val) { + // Until here we've been treating structures by pointer; + // we are now passing it as an arg, so need to load it. + val = bcx.build.Load(val); + } + } else if (mode == ast.alias) { + let lval_result lv; + if (ty.is_lval(e)) { + lv = trans_lval(bcx, e); + } else { + auto r = trans_expr(bcx, e); + lv = lval_val(r.bcx, r.val); + } + bcx = lv.res.bcx; + + if (lv.is_mem) { + val = lv.res.val; + } else { + // Non-mem but we're trying to alias; synthesize an + // alloca, spill to it and pass its address. + auto llty = val_ty(lv.res.val); + auto llptr = lv.res.bcx.build.Alloca(llty); + lv.res.bcx.build.Store(lv.res.val, llptr); + val = llptr; + } + + } else { + auto re = trans_expr(bcx, e); + val = re.val; + bcx = re.bcx; + } + + if (ty.type_has_dynamic_size(args.(i).ty)) { + val = bcx.build.PointerCast(val, T_typaram_ptr()); + } + + llargs += val; + i += 1u; + } + + ret tup(bcx, llargs, llretslot); +} + fn trans_call(@block_ctxt cx, @ast.expr f, vec[@ast.expr] args, &ast.ann ann) -> result { auto f_res = trans_lval(cx, f); auto faddr = f_res.res.val; - auto llclosure = C_null(T_opaque_closure_ptr()); + auto llenv = C_null(T_opaque_closure_ptr()); alt (f_res.llobj) { case (some[ValueRef](_)) { @@ -2785,52 +2806,34 @@ fn trans_call(@block_ctxt cx, @ast.expr f, C_int(abi.fn_field_code))); faddr = bcx.build.Load(faddr); - llclosure = bcx.build.GEP(pair, vec(C_int(0), - C_int(abi.fn_field_box))); - llclosure = bcx.build.Load(llclosure); + auto llclosure = bcx.build.GEP(pair, + vec(C_int(0), + C_int(abi.fn_field_box))); + llenv = bcx.build.Load(llclosure); } } auto fn_ty = ty.expr_ty(f); auto ret_ty = ty.ann_to_type(ann); auto args_res = trans_args(f_res.res.bcx, - llclosure, f_res.llobj, + llenv, f_res.llobj, f_res.generic, args, fn_ty); auto bcx = args_res._0; - auto real_retval = bcx.build.FastCall(faddr, args_res._1); - auto retval = real_retval; - - if (ty.type_is_nil(ret_ty)) { - retval = C_nil(); + auto llargs = args_res._1; + auto llretslot = args_res._2; + + bcx.build.FastCall(faddr, llargs); + auto retval = C_nil(); + + if (!ty.type_is_nil(ret_ty)) { + retval = load_scalar_or_boxed(bcx, llretslot, ret_ty); + // Retval doesn't correspond to anything really tangible in the frame, + // but it's a ref all the same, so we put a note here to drop it when + // we're done in this scope. + find_scope_cx(cx).cleanups += clean(bind drop_ty(_, retval, ret_ty)); } - // Check for a generic retslot. - alt (args_res._2) { - - case (some[ValueRef](?llretslot)) { - retval = load_scalar_or_boxed(bcx, llretslot, ret_ty); - } - - case (none[ValueRef]) { - if (! (ty.type_is_scalar(ret_ty) || - ty.type_is_boxed(ret_ty))) { - // 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. - auto local = bcx.build.Alloca(type_of(cx.fcx.ccx, ret_ty)); - bcx.build.Store(retval, local); - retval = local; - } - } - } - - // Retval doesn't correspond to anything really tangible in the frame, but - // it's a ref all the same, so we put a note here to drop it when we're - // done in this scope. - find_scope_cx(cx).cleanups += clean(bind drop_ty(_, retval, ret_ty)); - ret res(bcx, retval); } @@ -3091,18 +3094,7 @@ fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result { auto r = trans_expr(cx, x); bcx = r.bcx; val = r.val; - - // A return is an implicit copy into a newborn anonymous - // 'return value' in the caller frame. - bcx = incr_all_refcnts(bcx, val, t).bcx; - - 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 - // value here (which makes sense; the frame is going away!) - val = r.bcx.build.Load(val); - } + bcx = copy_ty(bcx, INIT, cx.fcx.llretptr, val, t).bcx; } case (_) { /* fall through */ } } @@ -3122,34 +3114,6 @@ fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result { } } - alt (e) { - case (some[@ast.expr](?ex)) { - auto t = ty.expr_ty(ex); - - if (ty.type_is_nil(t)) { - bcx.build.RetVoid(); - val = C_nil(); - ret res(bcx, val); // FIXME: early return needed due to - // typestate bug - } - - alt (cx.fcx.llretptr) { - case (some[ValueRef](?llptr)) { - // Generic return via tydesc + retptr. - bcx = copy_ty(bcx, INIT, llptr, val, t).bcx; - bcx.build.RetVoid(); - } - case (none[ValueRef]) { - val = bcx.build.Ret(val); - } - } - ret res(bcx, val); - } - case (_) { /* fall through */ } - } - - // FIXME: until LLVM has a unit type, we are moving around - // C_nil values rather than their void type. bcx.build.RetVoid(); ret res(bcx, C_nil()); } @@ -3360,12 +3324,20 @@ fn trans_block(@block_ctxt cx, &ast.block b) -> result { ret res(bcx, r.val); } +// NB: must keep 4 fns in sync: +// +// - type_of_fn_full +// - create_llargs_for_fn_args. +// - new_fn_ctxt +// - trans_args + fn new_fn_ctxt(@crate_ctxt cx, str name, ValueRef llfndecl) -> @fn_ctxt { - let ValueRef lltaskptr = llvm.LLVMGetParam(llfndecl, 0u); - let ValueRef llclosure = llvm.LLVMGetParam(llfndecl, 1u); + let ValueRef llretptr = llvm.LLVMGetParam(llfndecl, 0u); + let ValueRef lltaskptr = llvm.LLVMGetParam(llfndecl, 1u); + let ValueRef llenv = llvm.LLVMGetParam(llfndecl, 2u); let hashmap[ast.def_id, ValueRef] llargs = new_def_hash[ValueRef](); let hashmap[ast.def_id, ValueRef] llobjfields = new_def_hash[ValueRef](); @@ -3374,9 +3346,9 @@ fn new_fn_ctxt(@crate_ctxt cx, ret @rec(llfn=llfndecl, lltaskptr=lltaskptr, - llclosure=llclosure, + llenv=llenv, + llretptr=llretptr, mutable llself=none[ValueRef], - mutable llretptr=none[ValueRef], llargs=llargs, llobjfields=llobjfields, lllocals=lllocals, @@ -3384,13 +3356,28 @@ fn new_fn_ctxt(@crate_ctxt cx, ccx=cx); } -// NB: this must match trans_args and type_of_fn_full. +// NB: must keep 4 fns in sync: +// +// - type_of_fn_full +// - create_llargs_for_fn_args. +// - new_fn_ctxt +// - trans_args + fn create_llargs_for_fn_args(&@fn_ctxt cx, option.t[TypeRef] ty_self, @ty.t ret_ty, &vec[ast.arg] args, &vec[ast.ty_param] ty_params) { - let uint arg_n = 1u; + + alt (ty_self) { + case (some[TypeRef](_)) { + cx.llself = some[ValueRef](cx.llenv); + } + case (_) { + } + } + + auto arg_n = 3u; for (ast.ty_param tp in ty_params) { auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n); @@ -3399,23 +3386,6 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx, arg_n += 1u; } - if (ty.type_has_dynamic_size(ret_ty)) { - cx.llretptr = some[ValueRef](llvm.LLVMGetParam(cx.llfn, arg_n)); - arg_n += 1u; - } - - alt (ty_self) { - case (some[TypeRef](_)) { - auto llself = llvm.LLVMGetParam(cx.llfn, arg_n); - check (llself as int != 0); - cx.llself = some[ValueRef](llself); - arg_n += 1u; - } - case (_) { - // llclosure, we don't know what it is. - arg_n += 1u; - } - } for (ast.arg arg in args) { auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n); @@ -3645,7 +3615,7 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, copy_args_to_allocas(bcx, none[TypeRef], fn_args, arg_tys); auto llself_ty = type_of(cx, ret_ty_of_fn(ann)); - auto pair = bcx.build.Alloca(llself_ty); + auto pair = bcx.fcx.llretptr; auto vtbl = trans_vtbl(cx, llself_ty, ob, ty_params); auto pair_vtbl = bcx.build.GEP(pair, vec(C_int(0), @@ -3740,7 +3710,7 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, auto p = bcx.build.PointerCast(box.val, llbox_ty); bcx.build.Store(p, pair_box); } - bcx.build.Ret(bcx.build.Load(pair)); + bcx.build.RetVoid(); } fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, @@ -3779,11 +3749,12 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, // FIXME: better name. llvm.LLVMAddTypeName(cx.llmod, _str.buf("tag"), lltagty); - auto lltagptr = bcx.build.Alloca(lltagty); - auto lldiscrimptr = bcx.build.GEP(lltagptr, vec(C_int(0), C_int(0))); + auto lldiscrimptr = bcx.build.GEP(fcx.llretptr, + vec(C_int(0), C_int(0))); bcx.build.Store(C_int(index), lldiscrimptr); - auto llblobptr = bcx.build.GEP(lltagptr, vec(C_int(0), C_int(1))); + auto llblobptr = bcx.build.GEP(fcx.llretptr, + vec(C_int(0), C_int(1))); // First, generate the union type. let vec[TypeRef] llargtys = vec(); @@ -3804,9 +3775,8 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, i += 1u; } - auto lltagval = bcx.build.Load(lltagptr); bcx = trans_block_cleanups(bcx, find_scope_cx(bcx)); - bcx.build.Ret(lltagval); + bcx.build.RetVoid(); } // FIXME: this should do some structural hash-consing to avoid @@ -4142,9 +4112,9 @@ fn trans_exit_task_glue(@crate_ctxt cx) { let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 0u); auto fcx = @rec(llfn=llfn, lltaskptr=lltaskptr, - llclosure=C_null(T_opaque_closure_ptr()), + llenv=C_null(T_opaque_closure_ptr()), + llretptr=C_null(T_ptr(T_nil())), mutable llself=none[ValueRef], - mutable llretptr=none[ValueRef], llargs=new_def_hash[ValueRef](), llobjfields=new_def_hash[ValueRef](), lllocals=new_def_hash[ValueRef](), -- cgit v1.2.3 From 2f25d9c983c5730d79cc14278e666b8eb6531b10 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 8 Feb 2011 17:05:53 -0800 Subject: Handle subtle view-shift on outptr in generic calls. Can construct generic objs now. --- src/comp/middle/trans.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9e59cf57..4401f885 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2710,6 +2710,14 @@ fn trans_args(@block_ctxt cx, } if (ty.type_has_dynamic_size(retty)) { llargs += cx.build.PointerCast(llretslot, T_typaram_ptr()); + } else if (ty.count_ty_params(retty) != 0u) { + // It's possible that the callee has some generic-ness somewhere in + // its return value -- say a method signature within an obj or a fn + // type deep in a structure -- which the caller has a concrete view + // of. If so, cast the caller's view of the restlot to the callee's + // view, for the sake of making a type-compatible call. + llargs += cx.build.PointerCast(llretslot, + T_ptr(type_of(cx.fcx.ccx, retty))); } else { llargs += llretslot; } -- cgit v1.2.3 From 467a628ffaf41844a90e6664c2ecd481eef1dc85 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 8 Feb 2011 18:09:50 -0800 Subject: Add the single instruction required in activate glue to fix burning darwin tinderbox. And transplant 100 lines of comments from the ML code. --- src/comp/back/x86.rs | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 2 deletions(-) diff --git a/src/comp/back/x86.rs b/src/comp/back/x86.rs index ac52fca5..907cb32e 100644 --- a/src/comp/back/x86.rs +++ b/src/comp/back/x86.rs @@ -41,20 +41,117 @@ fn store_esp_to_runtime_sp() -> vec[str] { ret vec("movl %esp, " + wstr(abi.task_field_runtime_sp) + "(%ecx)"); } +/* + * This is a bit of glue-code. It should be emitted once per + * compilation unit. + * + * - save regs on C stack + * - align sp on a 16-byte boundary + * - save sp to task.runtime_sp (runtime_sp is thus always aligned) + * - load saved task sp (switch stack) + * - restore saved task regs + * - return to saved task pc + * + * Our incoming stack looks like this: + * + * *esp+4 = [arg1 ] = task ptr + * *esp = [retpc ] + */ + fn rust_activate_glue() -> vec[str] { ret vec("movl 4(%esp), %ecx # ecx = rust_task") + save_callee_saves() + store_esp_to_runtime_sp() + load_esp_from_rust_sp() - // This 'add' instruction is a bit surprising. - // See lengthy comment in boot/be/x86.ml activate_glue. + /* + * There are two paths we can arrive at this code from: + * + * + * 1. We are activating a task for the first time. When we switch + * into the task stack and 'ret' to its first instruction, we'll + * start doing whatever the first instruction says. Probably + * saving registers and starting to establish a frame. Harmless + * stuff, doesn't look at task->rust_sp again except when it + * clobbers it during a later upcall. + * + * + * 2. We are resuming a task that was descheduled by the yield glue + * below. When we switch into the task stack and 'ret', we'll be + * ret'ing to a very particular instruction: + * + * "esp <- task->rust_sp" + * + * this is the first instruction we 'ret' to after this glue, + * because it is the first instruction following *any* upcall, + * and the task we are activating was descheduled mid-upcall. + * + * Unfortunately for us, we have already restored esp from + * task->rust_sp and are about to eat the 5 words off the top of + * it. + * + * + * | ... | <-- where esp will be once we restore + ret, below, + * | retpc | and where we'd *like* task->rust_sp to wind up. + * | ebp | + * | edi | + * | esi | + * | ebx | <-- current task->rust_sp == current esp + * + * + * This is a problem. If we return to "esp <- task->rust_sp" it + * will push esp back down by 5 words. This manifests as a rust + * stack that grows by 5 words on each yield/reactivate. Not + * good. + * + * So what we do here is just adjust task->rust_sp up 5 words as + * well, to mirror the movement in esp we're about to + * perform. That way the "esp <- task->rust_sp" we 'ret' to below + * will be a no-op. Esp won't move, and the task's stack won't + * grow. + */ + vec("addl $20, " + wstr(abi.task_field_rust_sp) + "(%ecx)") + + /* + * In most cases, the function we're returning to (activating) + * will have saved any caller-saves before it yielded via upcalling, + * so no work to do here. With one exception: when we're initially + * activating, the task needs to be in the fastcall 2nd parameter + * expected by the rust main function. That's edx. + */ + + vec("mov %ecx, %edx") + + restore_callee_saves() + vec("ret"); } +/* More glue code, this time the 'bottom half' of yielding. + * + * We arrived here because an upcall decided to deschedule the + * running task. So the upcall's return address got patched to the + * first instruction of this glue code. + * + * When the upcall does 'ret' it will come here, and its esp will be + * pointing to the last argument pushed on the C stack before making + * the upcall: the 0th argument to the upcall, which is always the + * task ptr performing the upcall. That's where we take over. + * + * Our goal is to complete the descheduling + * + * - Switch over to the task stack temporarily. + * + * - Save the task's callee-saves onto the task stack. + * (the task is now 'descheduled', safe to set aside) + * + * - Switch *back* to the C stack. + * + * - Restore the C-stack callee-saves. + * + * - Return to the caller on the C stack that activated the task. + * + */ + fn rust_yield_glue() -> vec[str] { ret vec("movl 0(%esp), %ecx # ecx = rust_task") + load_esp_from_rust_sp() -- cgit v1.2.3 From 8c0d35066bcc0ab0eb35818f4de63bccee097e5c Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 9 Feb 2011 09:54:58 -0800 Subject: Elide passed-typarams when tydescs are captured. Un-XFAIL generic-obj.rs. --- src/Makefile | 1 + src/comp/middle/trans.rs | 28 ++++++++++++++++------------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/Makefile b/src/Makefile index 221ec9ff..bd7b616f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -455,6 +455,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ generic-fn.rs \ generic-fn-infer.rs \ generic-drop-glue.rs \ + generic-obj.rs \ generic-tup.rs \ generic-type.rs \ hello.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4401f885..2a9c32da 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -399,13 +399,15 @@ fn type_of_fn_full(@crate_ctxt cx, } } - // Args >3: ty params ... - auto ty_param_count = - ty.count_ty_params(plain_ty(ty.ty_fn(inputs, output))); - auto i = 0u; - while (i < ty_param_count) { - atys += T_ptr(T_tydesc()); - i += 1u; + // Args >3: ty params, if not acquired via capture... + if (obj_self == none[TypeRef]) { + auto ty_param_count = + ty.count_ty_params(plain_ty(ty.ty_fn(inputs, output))); + auto i = 0u; + while (i < ty_param_count) { + atys += T_ptr(T_tydesc()); + i += 1u; + } } // ... then explicit args. @@ -3387,11 +3389,13 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx, auto arg_n = 3u; - for (ast.ty_param tp in ty_params) { - auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n); - check (llarg as int != 0); - cx.lltydescs.insert(tp.id, llarg); - arg_n += 1u; + if (ty_self == none[TypeRef]) { + for (ast.ty_param tp in ty_params) { + auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n); + check (llarg as int != 0); + cx.lltydescs.insert(tp.id, llarg); + arg_n += 1u; + } } -- cgit v1.2.3 From 6e39102299eb962ac3c381e73ed7fcca68192f45 Mon Sep 17 00:00:00 2001 From: Rob Arnold Date: Thu, 3 Feb 2011 22:59:04 -0800 Subject: Add FreeBSD support in the Makefile --- src/Makefile | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Makefile b/src/Makefile index bd7b616f..0c3bf6d3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -32,6 +32,26 @@ CFG_RUSTC_FLAGS := -nowarn # embedded into the executable, so use a no-op command. DSYMUTIL := true +ifeq ($(CFG_OSTYPE), FreeBSD) + CFG_RUNTIME := librustrt.so + CFG_STDLIB := libstd.so + CFG_GCC_CFLAGS += -fPIC -march=i686 -I/usr/local/include + CFG_GCC_LINK_FLAGS += -shared -fPIC -lpthread -lrt + ifeq ($(CFG_CPUTYPE), x86_64) + CFG_GCC_CFLAGS += -m32 + CFG_GCC_LINK_FLAGS += -m32 + endif + CFG_NATIVE := 1 + CFG_UNIXY := 1 + CFG_VALGRIND := $(shell which valgrind) + ifdef CFG_VALGRIND + CFG_VALGRIND += --leak-check=full \ + --error-exitcode=1 \ + --quiet --vex-iropt-level=0 \ + --suppressions=etc/x86.supp + endif +endif + ifeq ($(CFG_OSTYPE), Linux) CFG_RUNTIME := librustrt.so CFG_STDLIB := libstd.so -- cgit v1.2.3 From 6466795a70df56f89405df1ed438c8f8b58fed3a Mon Sep 17 00:00:00 2001 From: Rob Arnold Date: Wed, 9 Feb 2011 10:23:07 -0800 Subject: Add FreeBSD_x86_elf target to rustboot --- src/boot/driver/lib.ml | 4 ++++ src/boot/driver/main.ml | 29 +++++++++++++++++++++++------ src/boot/fe/cexp.ml | 1 + src/boot/util/common.ml | 1 + 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/boot/driver/lib.ml b/src/boot/driver/lib.ml index a4769e83..00b1b834 100644 --- a/src/boot/driver/lib.ml +++ b/src/boot/driver/lib.ml @@ -249,6 +249,7 @@ let get_ar Win32_x86_pe -> Pe.sniff | MacOS_x86_macho -> Macho.sniff | Linux_x86_elf -> Elf.sniff + | FreeBSD_x86_elf -> Elf.sniff in sniff sess filename end @@ -270,6 +271,7 @@ let get_sects Win32_x86_pe -> Pe.get_sections | MacOS_x86_macho -> Macho.get_sections | Linux_x86_elf -> Elf.get_sections + | FreeBSD_x86_elf -> Elf.get_sections in Some (ar, (get_sections sess ar)) end @@ -350,6 +352,7 @@ let get_mod Win32_x86_pe -> ".dll" | MacOS_x86_macho -> ".dylib" | Linux_x86_elf -> ".so" + | FreeBSD_x86_elf -> ".so" in let rec meta_matches i f_meta = if i >= (Array.length meta) @@ -447,6 +450,7 @@ let infer_lib_name Win32_x86_pe -> ident ^ ".dll" | MacOS_x86_macho -> "lib" ^ ident ^ ".dylib" | Linux_x86_elf -> "lib" ^ ident ^ ".so" + | FreeBSD_x86_elf -> "lib" ^ ident ^ ".so" ;; diff --git a/src/boot/driver/main.ml b/src/boot/driver/main.ml index 2bbc832b..9705f1ee 100644 --- a/src/boot/driver/main.ml +++ b/src/boot/driver/main.ml @@ -8,12 +8,21 @@ let _ = let (targ:Common.target) = match Sys.os_type with - "Unix" when Unix.system "test `uname -s` = 'Darwin'" = Unix.WEXITED 0 -> - MacOS_x86_macho - | "Unix" -> Linux_x86_elf - | "Win32" -> Win32_x86_pe + + | "Win32" | "Cygwin" -> Win32_x86_pe - | _ -> Linux_x86_elf + + | "Unix" + when Unix.system "test `uname -s` = 'Linux'" = Unix.WEXITED 0 -> + Linux_x86_elf + | "Unix" + when Unix.system "test `uname -s` = 'Darwin'" = Unix.WEXITED 0 -> + MacOS_x86_macho + | "Unix" + when Unix.system "test `uname -s` = 'FreeBSD'" = Unix.WEXITED 0 -> + FreeBSD_x86_elf + | _ -> + Linux_x86_elf ;; let (abi:Abi.abi) = X86.abi;; @@ -96,6 +105,7 @@ let default_output_filename (sess:Session.sess) : filename option = else base ^ (match sess.Session.sess_targ with Linux_x86_elf -> "" + | FreeBSD_x86_elf -> "" | MacOS_x86_macho -> "" | Win32_x86_pe -> ".exe") in @@ -144,16 +154,21 @@ let flag f opt desc = let argspecs = [ - ("-t", Arg.Symbol (["linux-x86-elf"; "win32-x86-pe"; "macos-x86-macho"], + ("-t", Arg.Symbol (["linux-x86-elf"; + "win32-x86-pe"; + "macos-x86-macho"; + "freebsd-x86-elf"], fun s -> (sess.Session.sess_targ <- (match s with "win32-x86-pe" -> Win32_x86_pe | "macos-x86-macho" -> MacOS_x86_macho + | "freebsd-x86-elf" -> FreeBSD_x86_elf | _ -> Linux_x86_elf))), (" target (default: " ^ (match sess.Session.sess_targ with Win32_x86_pe -> "win32-x86-pe" | Linux_x86_elf -> "linux-x86-elf" | MacOS_x86_macho -> "macos-x86-macho" + | FreeBSD_x86_elf -> "freebsd-x86-elf" ) ^ ")")); ("-o", Arg.String (fun s -> sess.Session.sess_out <- Some s), "file to output (default: " @@ -320,6 +335,7 @@ let parse_input_crate let depfile = match sess.Session.sess_targ with Linux_x86_elf + | FreeBSD_x86_elf | MacOS_x86_macho -> outfile ^ ".d" | Win32_x86_pe -> (Filename.chop_extension outfile) ^ ".d" in @@ -473,6 +489,7 @@ let main_pipeline _ = Win32_x86_pe -> Pe.emit_file | MacOS_x86_macho -> Macho.emit_file | Linux_x86_elf -> Elf.emit_file + | FreeBSD_x86_elf -> Elf.emit_file in Session.time_inner "emit" sess (fun _ -> emitter sess crate code data sem_cx dwarf); diff --git a/src/boot/fe/cexp.ml b/src/boot/fe/cexp.ml index 56f3e878..0f216fc2 100644 --- a/src/boot/fe/cexp.ml +++ b/src/boot/fe/cexp.ml @@ -628,6 +628,7 @@ let parse_crate_file let (os, arch, libc) = match sess.Session.sess_targ with Linux_x86_elf -> ("linux", "x86", "libc.so.6") + | FreeBSD_x86_elf -> ("freebsd", "x86", "libc.so.7") | Win32_x86_pe -> ("win32", "x86", "msvcrt.dll") | MacOS_x86_macho -> ("macos", "x86", "libc.dylib") in diff --git a/src/boot/util/common.ml b/src/boot/util/common.ml index f9b18246..c76da0de 100644 --- a/src/boot/util/common.ml +++ b/src/boot/util/common.ml @@ -56,6 +56,7 @@ type target = Linux_x86_elf | Win32_x86_pe | MacOS_x86_macho + | FreeBSD_x86_elf ;; type ty_mach = -- cgit v1.2.3 From a1cc5ac63c7d2b7da595cbc31253389a991824bd Mon Sep 17 00:00:00 2001 From: Rob Arnold Date: Sat, 5 Feb 2011 01:09:35 -0800 Subject: Adapt elf.ml to handle differences between Linux and FreeBSD. --- src/boot/be/elf.ml | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/boot/be/elf.ml b/src/boot/be/elf.ml index 406508e4..a1706082 100644 --- a/src/boot/be/elf.ml +++ b/src/boot/be/elf.ml @@ -44,7 +44,7 @@ type ei_data = ;; -let elf_identification ei_class ei_data = +let elf_identification sess ei_class ei_data = SEQ [| STRING "\x7fELF"; @@ -58,9 +58,17 @@ let elf_identification ei_class ei_data = ELFDATANONE -> 0 | ELFDATA2LSB -> 1 | ELFDATA2MSB -> 2); + 1; (* EI_VERSION = EV_CURRENT *) - 0; (* EI_PAD #7 *) - 0; (* EI_PAD #8 *) + + (* EI_OSABI *) + (match sess.Session.sess_targ with + FreeBSD_x86_elf -> 9 + | Linux_x86_elf -> 3 + | _ -> 0); + + 0; (* EI_ABIVERSION *) + 0; (* EI_PAD #9 *) 0; (* EI_PAD #A *) 0; (* EI_PAD #B *) @@ -117,7 +125,7 @@ let elf32_header in DEF (elf_header_fixup, - SEQ [| elf_identification ELFCLASS32 ei_data; + SEQ [| elf_identification sess ELFCLASS32 ei_data; WORD (TY_u16, (IMM (match e_type with ET_NONE -> 0L | ET_REL -> 1L @@ -1290,7 +1298,11 @@ let elf32_linux_x86_file in let interp_section = - DEF (interp_section_fixup, ZSTRING "/lib/ld-linux.so.2") + + DEF (interp_section_fixup, ZSTRING + (if sess.Session.sess_targ = FreeBSD_x86_elf + then "/libexec/ld-elf.so.1" + else "/lib/ld-linux.so.2")) in let text_section = @@ -1584,7 +1596,9 @@ let emit_file let needed_libs = [| - "libc.so.6"; + if sess.Session.sess_targ = FreeBSD_x86_elf + then "libc.so.7" + else "libc.so.6"; "librustrt.so" |] in -- cgit v1.2.3 From 60635999f313981abe157318025a19d60d8d310a Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 9 Feb 2011 11:30:50 -0800 Subject: Add .bss fragment support to elf. --- src/boot/be/elf.ml | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/boot/be/elf.ml b/src/boot/be/elf.ml index a1706082..f17541ee 100644 --- a/src/boot/be/elf.ml +++ b/src/boot/be/elf.ml @@ -488,6 +488,7 @@ let elf32_linux_x86_file ~(entry_name:string) ~(text_frags:(string option, frag) Hashtbl.t) ~(data_frags:(string option, frag) Hashtbl.t) + ~(bss_frags:(string option, frag) Hashtbl.t) ~(rodata_frags:(string option, frag) Hashtbl.t) ~(required_fixups:(string, fixup) Hashtbl.t) ~(dwarf:Dwarf.debug_records) @@ -652,7 +653,7 @@ let elf32_linux_x86_file (* let gotpltndx = 8L in *) (* Section index of .got.plt *) (* let relapltndx = 9L in *) (* Section index of .rela.plt *) let datandx = 10L in (* Section index of .data *) - (* let bssndx = 11L in *) (* Section index of .bss *) + let bssndx = 11L in (* Section index of .bss *) (* let dynamicndx = 12L in *) (* Section index of .dynamic *) let shstrtabndx = 13L in (* Section index of .shstrtab *) @@ -999,6 +1000,22 @@ let elf32_linux_x86_file (strtab_entry, symtab_entry) in + let bss_sym name st_bind fixup = + let name_fixup = new_fixup ("bss symbol name fixup: '" ^ name ^ "'") in + let strtab_entry = DEF (name_fixup, ZSTRING name) in + let symtab_entry = + symbol + ~string_table_fixup: dynstr_section_fixup + ~name_string_fixup: name_fixup + ~sym_target_fixup: (Some fixup) + ~st_bind + ~st_type: STT_OBJECT + ~st_shndx: bssndx + in + incr n_syms; + (strtab_entry, symtab_entry) + in + let rodata_sym name st_bind fixup = let name_fixup = new_fixup ("rodata symbol name fixup: '" ^ name ^ "'") in let strtab_entry = DEF (name_fixup, ZSTRING name) in @@ -1220,6 +1237,12 @@ let elf32_linux_x86_file Hashtbl.fold (frags_of_symbol data_sym STB_GLOBAL) data_frags ([],[],[]) in + let (bss_strtab_frags, + bss_symtab_frags, + bss_body_frags) = + Hashtbl.fold (frags_of_symbol bss_sym STB_GLOBAL) bss_frags ([],[],[]) + in + let (_, require_strtab_frags, require_symtab_frags, @@ -1285,7 +1308,8 @@ let elf32_linux_x86_file global_text_symtab_frags @ local_text_symtab_frags @ rodata_symtab_frags @ - data_symtab_frags)) + data_symtab_frags @ + bss_symtab_frags)) in let dynstr_frags = (null_strtab_frag :: @@ -1294,6 +1318,7 @@ let elf32_linux_x86_file local_text_strtab_frags @ rodata_strtab_frags @ data_strtab_frags @ + bss_strtab_frags @ (Array.to_list dynamic_needed_strtab_frags))) in @@ -1319,7 +1344,7 @@ let elf32_linux_x86_file in let bss_section = DEF (bss_section_fixup, - SEQ [| |]) + SEQ (Array.of_list bss_body_frags)) in let dynsym_section = DEF (dynsym_section_fixup, @@ -1498,6 +1523,7 @@ let emit_file let text_frags = Hashtbl.create 4 in let rodata_frags = Hashtbl.create 4 in let data_frags = Hashtbl.create 4 in + let bss_frags = Hashtbl.create 4 in let required_fixups = Hashtbl.create 4 in (* @@ -1630,6 +1656,7 @@ let emit_file end sem.Semant.ctxt_native_required in + let all_frags = elf32_linux_x86_file ~sess @@ -1637,6 +1664,7 @@ let emit_file ~entry_name: "_start" ~text_frags ~data_frags + ~bss_frags ~dwarf ~sem ~rodata_frags -- cgit v1.2.3 From eb854ffb4423c053451882fdc204fd717bb07ad4 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 9 Feb 2011 11:31:44 -0800 Subject: Add several 1-word .bss fragments for FreeBSD. --- src/boot/be/elf.ml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/boot/be/elf.ml b/src/boot/be/elf.ml index f17541ee..3cc936c0 100644 --- a/src/boot/be/elf.ml +++ b/src/boot/be/elf.ml @@ -1644,6 +1644,27 @@ let emit_file htab_put text_frags None code; htab_put rodata_frags None data; + if sess.Session.sess_targ = FreeBSD_x86_elf + then + (* + * FreeBSD wants some extra symbols in .bss so its libc can fill + * them in, I think. + *) + List.iter + (fun x -> htab_put bss_frags (Some x) (WORD (TY_u32, (IMM 0L)))) + [ + "environ"; + "optind"; + "optarg"; + "_CurrentRuneLocale"; + "__stack_chk_guard"; + "__mb_sb_limit"; + "__isthreaded"; + "__stdinp"; + "__stderrp"; + "__stdoutp"; + ]; + Hashtbl.iter begin fun _ tab -> -- cgit v1.2.3 From 71e3ac873a2a0261828a927450934422ada1ead3 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 9 Feb 2011 11:30:14 -0800 Subject: Re-indent a bit of elf. --- src/boot/be/elf.ml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/boot/be/elf.ml b/src/boot/be/elf.ml index 3cc936c0..f3e1440a 100644 --- a/src/boot/be/elf.ml +++ b/src/boot/be/elf.ml @@ -1703,16 +1703,16 @@ let sniff : asm_reader option = try let stat = Unix.stat filename in - if (stat.Unix.st_kind = Unix.S_REG) && - (stat.Unix.st_size > 4) - then - let ar = new_asm_reader sess filename in - let _ = log sess "sniffing ELF file" in - if (ar.asm_get_zstr_padded 4) = elf_magic - then (ar.asm_seek 0; Some ar) - else None - else - None + if (stat.Unix.st_kind = Unix.S_REG) && + (stat.Unix.st_size > 4) + then + let ar = new_asm_reader sess filename in + let _ = log sess "sniffing ELF file" in + if (ar.asm_get_zstr_padded 4) = elf_magic + then (ar.asm_seek 0; Some ar) + else None + else + None with _ -> None ;; -- cgit v1.2.3 From b7dfbc9db079a6c55d9e716d295f87597752b668 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 9 Feb 2011 13:19:20 -0800 Subject: Fix bug in test and un-XFAIL 4 tests now passing on rustc. --- src/Makefile | 4 ++++ src/test/run-pass/generic-type-synonym.rs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 0c3bf6d3..02bd8708 100644 --- a/src/Makefile +++ b/src/Makefile @@ -474,10 +474,12 @@ TEST_XFAILS_RUSTC := $(filter-out \ fun-indirect-call.rs \ generic-fn.rs \ generic-fn-infer.rs \ + generic-exterior-box.rs \ generic-drop-glue.rs \ generic-obj.rs \ generic-tup.rs \ generic-type.rs \ + generic-type-synonym.rs \ hello.rs \ int.rs \ i32-sub.rs \ @@ -489,6 +491,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ import6.rs \ import7.rs \ import8.rs \ + inner-module.rs \ item-name-overload.rs \ large-records.rs \ lazy-init.rs \ @@ -505,6 +508,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ opeq.rs \ output-slot-variants.rs \ over-constrained-vregs.rs \ + path.rs \ readalias.rs \ rec.rs \ rec-auto.rs \ diff --git a/src/test/run-pass/generic-type-synonym.rs b/src/test/run-pass/generic-type-synonym.rs index 4ddc8946..c3d2a9d5 100644 --- a/src/test/run-pass/generic-type-synonym.rs +++ b/src/test/run-pass/generic-type-synonym.rs @@ -1,4 +1,4 @@ type foo[T] = tup(T); type bar[T] = foo[T]; -fn takebar[T](bar[T] b) {} +fn takebar[T](&bar[T] b) {} fn main() {} \ No newline at end of file -- cgit v1.2.3 From c4a56f7368404265a1189d3f3202f4dedfd5d0f1 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Feb 2011 11:29:47 -0800 Subject: Commit the trap-failure hack to the runtime, since I keep using it in my workspace anyways. --- src/rt/rust_upcall.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 7e2fac10..46e53048 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -253,6 +253,10 @@ upcall_fail(rust_task *task, task->log(rust_log::UPCALL | rust_log::ERR, "upcall fail '%s', %s:%" PRIdPTR, expr, file, line); task->fail(4); + if (getenv("RUST_TRAP_FAILURE")) { + // FIXME: x86-ism. + __asm__("int3"); + } } /** -- cgit v1.2.3 From 3d63aa14e0db38afa06467db8e17722c4f744eac Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Feb 2011 11:30:29 -0800 Subject: Handle instantiations where some type parameters remain parameters (eg. derived typedefs). --- src/comp/middle/typeck.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 5412f131..5b14eea4 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -86,7 +86,11 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t { fn fold_simple_ty(@ty.t t) -> @ty.t { alt (t.struct) { case (ty.ty_param(?param_def)) { - ret param_map.get(param_def); + if (param_map.contains_key(param_def)) { + ret param_map.get(param_def); + } else { + ret t; + } } case (_) { ret t; -- cgit v1.2.3 From 580d527aa2972ad1f7cbe65f2a98a0dbc92d14f7 Mon Sep 17 00:00:00 2001 From: Rafael Avila de Espindola Date: Thu, 10 Feb 2011 14:32:22 -0500 Subject: Add missing fold of native functions. --- src/comp/middle/fold.rs | 3 ++- src/comp/middle/resolve.rs | 47 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 688d21d2..7e5c2d26 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -872,7 +872,8 @@ fn fold_native_item[ENV](&ENV env, ast_fold[ENV] fld, ret fld.fold_native_item_ty(env_, i.span, ident, id); } case (ast.native_item_fn(?ident, ?fn_decl, ?ty_params, ?id)) { - ret fld.fold_native_item_fn(env_, i.span, ident, fn_decl, + auto d = fold_fn_decl[ENV](env_, fld, fn_decl); + ret fld.fold_native_item_fn(env_, i.span, ident, d, ty_params, id); } } diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 0a8f238d..8384906d 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -18,6 +18,7 @@ import std._vec; tag scope { scope_crate(@ast.crate); scope_item(@ast.item); + scope_native_item(@ast.native_item); scope_loop(@ast.decl); // there's only 1 decl per loop. scope_block(ast.block); scope_arm(ast.arm); @@ -309,6 +310,23 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] { } } + fn handle_fn_decl(ast.ident i, &ast.fn_decl decl, + &vec[ast.ty_param] ty_params) -> option.t[def_wrap] { + for (ast.arg a in decl.inputs) { + if (_str.eq(a.ident, i)) { + auto t = ast.def_arg(a.id); + ret some(def_wrap_other(t)); + } + } + for (ast.ty_param tp in ty_params) { + if (_str.eq(tp.ident, i)) { + auto t = ast.def_ty_arg(tp.id); + ret some(def_wrap_other(t)); + } + } + ret none[def_wrap]; + } + fn in_scope(ast.ident i, &scope s) -> option.t[def_wrap] { alt (s) { @@ -319,18 +337,7 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] { case (scope_item(?it)) { alt (it.node) { case (ast.item_fn(_, ?f, ?ty_params, _, _)) { - for (ast.arg a in f.decl.inputs) { - if (_str.eq(a.ident, i)) { - auto t = ast.def_arg(a.id); - ret some(def_wrap_other(t)); - } - } - for (ast.ty_param tp in ty_params) { - if (_str.eq(tp.ident, i)) { - auto t = ast.def_ty_arg(tp.id); - ret some(def_wrap_other(t)); - } - } + ret handle_fn_decl(i, f.decl, ty_params); } case (ast.item_obj(_, ?ob, ?ty_params, _, _)) { for (ast.obj_field f in ob.fields) { @@ -364,6 +371,14 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] { } } + case (scope_native_item(?it)) { + alt (it.node) { + case (ast.native_item_fn(_, ?decl, ?ty_params, _)) { + ret handle_fn_decl(i, decl, ty_params); + } + } + } + case (scope_loop(?d)) { alt (d.node) { case (ast.decl_local(?local)) { @@ -529,6 +544,10 @@ fn update_env_for_item(&env e, @ast.item i) -> env { ret rec(scopes = cons[scope](scope_item(i), @e.scopes) with e); } +fn update_env_for_native_item(&env e, @ast.native_item i) -> env { + ret rec(scopes = cons[scope](scope_native_item(i), @e.scopes) with e); +} + fn update_env_for_block(&env e, &ast.block b) -> env { ret rec(scopes = cons[scope](scope_block(b), @e.scopes) with e); } @@ -555,6 +574,8 @@ fn resolve_imports(session.session sess, @ast.crate crate) -> @ast.crate { = bind fold_view_item_import(_,_,import_index,_,_,_,_), update_env_for_crate = bind update_env_for_crate(_,_), update_env_for_item = bind update_env_for_item(_,_), + update_env_for_native_item = + bind update_env_for_native_item(_,_), update_env_for_block = bind update_env_for_block(_,_), update_env_for_arm = bind update_env_for_arm(_,_), update_env_for_expr = bind update_env_for_expr(_,_) @@ -577,6 +598,8 @@ fn resolve_crate(session.session sess, @ast.crate crate) -> @ast.crate { fold_ty_path = bind fold_ty_path(_,_,_,_), update_env_for_crate = bind update_env_for_crate(_,_), update_env_for_item = bind update_env_for_item(_,_), + update_env_for_native_item = + bind update_env_for_native_item(_,_), update_env_for_block = bind update_env_for_block(_,_), update_env_for_arm = bind update_env_for_arm(_,_), update_env_for_expr = bind update_env_for_expr(_,_) -- cgit v1.2.3 From c0f997be21ae6b98aa77818dc90bff07544f1c20 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 9 Feb 2011 21:52:14 -0500 Subject: Revert EI_OSABI ELF header field back to 0 for Linux --- src/boot/be/elf.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/boot/be/elf.ml b/src/boot/be/elf.ml index f3e1440a..99b68042 100644 --- a/src/boot/be/elf.ml +++ b/src/boot/be/elf.ml @@ -64,7 +64,6 @@ let elf_identification sess ei_class ei_data = (* EI_OSABI *) (match sess.Session.sess_targ with FreeBSD_x86_elf -> 9 - | Linux_x86_elf -> 3 | _ -> 0); 0; (* EI_ABIVERSION *) -- cgit v1.2.3 From 378c0087ca7572cd17726c704fe04d57bf4687af Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 30 Jan 2011 17:18:19 -0500 Subject: Parse 'be' statement. Pass tailcall tests. No actual tailcalls yet. --- src/Makefile | 3 +++ src/comp/front/ast.rs | 1 + src/comp/front/parser.rs | 7 +++++++ src/comp/middle/fold.rs | 13 +++++++++++++ src/comp/middle/trans.rs | 9 +++++++++ src/comp/middle/typeck.rs | 15 +++++++++++++++ 6 files changed, 48 insertions(+) diff --git a/src/Makefile b/src/Makefile index 02bd8708..5c3f297f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -517,6 +517,9 @@ TEST_XFAILS_RUSTC := $(filter-out \ simple-obj.rs \ stateful-obj.rs \ str-idx.rs \ + tail-call-arg-leak.rs \ + tail-cps.rs \ + tail-direct.rs \ type-in-nested-module.rs \ type-param.rs \ tup.rs \ diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 5f315e58..756a7ad1 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -116,6 +116,7 @@ type stmt = spanned[stmt_]; tag stmt_ { stmt_decl(@decl); stmt_ret(option.t[@expr]); + stmt_be(@expr); stmt_log(@expr); stmt_check_expr(@expr); stmt_fail; diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 8d130935..a1b519ba 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1200,6 +1200,12 @@ impure fn parse_stmt(parser p) -> @ast.stmt { } } + case (token.BE) { + p.bump(); + auto e = parse_expr(p); + ret @spanned(lo, e.span, ast.stmt_be(e)); + } + case (token.LET) { auto decl = parse_let(p); auto hi = p.get_span(); @@ -1340,6 +1346,7 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool { } } case (ast.stmt_ret(_)) { ret true; } + case (ast.stmt_be(_)) { ret true; } case (ast.stmt_log(_)) { ret true; } case (ast.stmt_check_expr(_)) { ret true; } case (ast.stmt_fail) { ret true; } diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 7e5c2d26..9194f734 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -176,6 +176,9 @@ type ast_fold[ENV] = (fn(&ENV e, &span sp, &option.t[@expr] rv) -> @stmt) fold_stmt_ret, + (fn(&ENV e, &span sp, + @expr e) -> @stmt) fold_stmt_be, + (fn(&ENV e, &span sp, @expr e) -> @stmt) fold_stmt_log, @@ -636,6 +639,11 @@ fn fold_stmt[ENV](&ENV env, ast_fold[ENV] fld, &@stmt s) -> @stmt { ret fld.fold_stmt_ret(env_, s.span, oee); } + case (ast.stmt_be(?e)) { + auto ee = fold_expr(env_, fld, e); + ret fld.fold_stmt_be(env_, s.span, ee); + } + case (ast.stmt_log(?e)) { auto ee = fold_expr(env_, fld, e); ret fld.fold_stmt_log(env_, s.span, ee); @@ -1136,6 +1144,10 @@ fn identity_fold_stmt_ret[ENV](&ENV env, &span sp, ret @respan(sp, ast.stmt_ret(rv)); } +fn identity_fold_stmt_be[ENV](&ENV env, &span sp, @expr x) -> @stmt { + ret @respan(sp, ast.stmt_be(x)); +} + fn identity_fold_stmt_log[ENV](&ENV e, &span sp, @expr x) -> @stmt { ret @respan(sp, ast.stmt_log(x)); } @@ -1366,6 +1378,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_stmt_decl = bind identity_fold_stmt_decl[ENV](_,_,_), fold_stmt_ret = bind identity_fold_stmt_ret[ENV](_,_,_), + fold_stmt_be = bind identity_fold_stmt_be[ENV](_,_,_), fold_stmt_log = bind identity_fold_stmt_log[ENV](_,_,_), fold_stmt_check_expr = bind identity_fold_stmt_check_expr[ENV](_,_,_), diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2a9c32da..499ab027 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3128,6 +3128,11 @@ fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result { ret res(bcx, C_nil()); } +fn trans_be(@block_ctxt cx, @ast.expr e) -> result { + // FIXME: So this isn't actually a tail call + ret trans_ret(cx, some(e)); +} + fn init_local(@block_ctxt cx, @ast.local local) -> result { // Make a note to drop this slot on the way out. @@ -3178,6 +3183,10 @@ fn trans_stmt(@block_ctxt cx, &ast.stmt s) -> result { bcx = trans_ret(cx, e).bcx; } + case (ast.stmt_be(?e)) { + bcx = trans_be(cx, e).bcx; + } + case (ast.stmt_expr(?e)) { bcx = trans_expr(cx, e).bcx; } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 5b14eea4..7a2b0616 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1719,6 +1719,21 @@ fn check_stmt(&@fn_ctxt fcx, &@ast.stmt stmt) -> @ast.stmt { } } + case (ast.stmt_be(?expr)) { + alt (expr.node) { + case (ast.expr_call(_, _, _)) { + auto expr_0 = check_expr(fcx, expr); + auto expr_1 = demand_expr(fcx, fcx.ret_ty, expr_0); + ret @fold.respan[ast.stmt_](stmt.span, + ast.stmt_be(expr_1)); + } + case (_) { + fcx.ccx.sess.err("Non-call expression in tail call"); + fail; + } + } + } + case (ast.stmt_log(?expr)) { auto expr_t = check_expr(fcx, expr); ret @fold.respan[ast.stmt_](stmt.span, ast.stmt_log(expr_t)); -- cgit v1.2.3 From 6461cf30de748fbe310640cd9c195965fc3da229 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 30 Jan 2011 17:38:46 -0500 Subject: Add compile-fail tests for tail calls --- src/Makefile | 3 +++ src/test/compile-fail/tail-non-call.rs | 10 ++++++++++ src/test/compile-fail/tail-typeck.rs | 13 +++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 src/test/compile-fail/tail-non-call.rs create mode 100644 src/test/compile-fail/tail-typeck.rs diff --git a/src/Makefile b/src/Makefile index 5c3f297f..7a31c24a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -434,6 +434,7 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \ test/compile-fail/bad-recv.rs \ test/compile-fail/bad-send.rs \ test/compile-fail/infinite-vec-type-recursion.rs \ + test/compile-fail/tail-non-call.rs \ test/compile-fail/writing-through-read-alias.rs # Same strategy here for the time being: just list the ones that @@ -555,6 +556,8 @@ TEST_XFAILS_RUSTC := $(filter-out \ multiline-comment-line-tracking.rs \ output-type-mismatch.rs \ rec-missing-fields.rs \ + tail-non-call.rs \ + tail-typeck.rs \ type-shadow.rs \ while-type-error.rs \ wrong-ret-type.rs \ diff --git a/src/test/compile-fail/tail-non-call.rs b/src/test/compile-fail/tail-non-call.rs new file mode 100644 index 00000000..2742d1fe --- /dev/null +++ b/src/test/compile-fail/tail-non-call.rs @@ -0,0 +1,10 @@ +// error-pattern: Non-call expression in tail call + +fn f() -> int { + auto x = 1; + be x; +} + +fn main() { + auto y = f(); +} \ No newline at end of file diff --git a/src/test/compile-fail/tail-typeck.rs b/src/test/compile-fail/tail-typeck.rs new file mode 100644 index 00000000..10b95546 --- /dev/null +++ b/src/test/compile-fail/tail-typeck.rs @@ -0,0 +1,13 @@ +// error-pattern: mismatched types + +fn f() -> int { + be g(); +} + +fn g() -> uint { + ret 0u; +} + +fn main() { + auto y = f(); +} \ No newline at end of file -- cgit v1.2.3 From f17a3421e01399bcc1a6f8540273d7b4440397a1 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 9 Feb 2011 22:36:37 -0500 Subject: Cleanup for 'be' statement and comments about future typestate --- src/comp/front/ast.rs | 11 +++++++++++ src/comp/front/parser.rs | 8 +++++++- src/comp/middle/trans.rs | 5 ++++- src/comp/middle/typeck.rs | 18 ++++++------------ src/test/compile-fail/tail-non-call.rs | 2 +- src/test/compile-fail/tail-typeck.rs | 2 +- 6 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 756a7ad1..61a7bdc1 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -315,6 +315,17 @@ fn index_native_item(native_mod_index index, @native_item it) { } } +fn is_call_expr(@expr e) -> bool { + alt (e.node) { + case (expr_call(_, _, _)) { + ret true; + } + case (_) { + ret false; + } + } +} + // // Local Variables: // mode: rust diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index a1b519ba..ea4cf12c 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1203,7 +1203,13 @@ impure fn parse_stmt(parser p) -> @ast.stmt { case (token.BE) { p.bump(); auto e = parse_expr(p); - ret @spanned(lo, e.span, ast.stmt_be(e)); + // FIXME: Is this the right place for this check? + if /*check*/ (ast.is_call_expr(e)) { + ret @spanned(lo, e.span, ast.stmt_be(e)); + } + else { + p.err("Non-call expression in tail call"); + } } case (token.LET) { diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 499ab027..45d54e6a 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3129,7 +3129,10 @@ fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result { } fn trans_be(@block_ctxt cx, @ast.expr e) -> result { - // FIXME: So this isn't actually a tail call + // FIXME: This should be a typestate precondition + check ast.is_call_expr(e); + // FIXME: Turn this into a real tail call once + // calling convention issues are settled ret trans_ret(cx, some(e)); } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 7a2b0616..4c3903a7 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1720,18 +1720,12 @@ fn check_stmt(&@fn_ctxt fcx, &@ast.stmt stmt) -> @ast.stmt { } case (ast.stmt_be(?expr)) { - alt (expr.node) { - case (ast.expr_call(_, _, _)) { - auto expr_0 = check_expr(fcx, expr); - auto expr_1 = demand_expr(fcx, fcx.ret_ty, expr_0); - ret @fold.respan[ast.stmt_](stmt.span, - ast.stmt_be(expr_1)); - } - case (_) { - fcx.ccx.sess.err("Non-call expression in tail call"); - fail; - } - } + /* FIXME: prove instead of check */ + check ast.is_call_expr(expr); + auto expr_0 = check_expr(fcx, expr); + auto expr_1 = demand_expr(fcx, fcx.ret_ty, expr_0); + ret @fold.respan[ast.stmt_](stmt.span, + ast.stmt_be(expr_1)); } case (ast.stmt_log(?expr)) { diff --git a/src/test/compile-fail/tail-non-call.rs b/src/test/compile-fail/tail-non-call.rs index 2742d1fe..00a451f6 100644 --- a/src/test/compile-fail/tail-non-call.rs +++ b/src/test/compile-fail/tail-non-call.rs @@ -7,4 +7,4 @@ fn f() -> int { fn main() { auto y = f(); -} \ No newline at end of file +} diff --git a/src/test/compile-fail/tail-typeck.rs b/src/test/compile-fail/tail-typeck.rs index 10b95546..64beedb9 100644 --- a/src/test/compile-fail/tail-typeck.rs +++ b/src/test/compile-fail/tail-typeck.rs @@ -10,4 +10,4 @@ fn g() -> uint { fn main() { auto y = f(); -} \ No newline at end of file +} -- cgit v1.2.3 From 140d6fd96468c51746d0d44bd6a9c4fdb6de30a9 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Feb 2011 14:59:20 -0800 Subject: Switch "." to "_" in name mangling, makes gdb happier. Also factor out into sep() helper. --- src/comp/middle/trans.rs | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 45d54e6a..dbcdaed1 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -121,6 +121,10 @@ tag block_parent { state type result = rec(mutable @block_ctxt bcx, mutable ValueRef val); +fn sep() -> str { + ret "_"; +} + fn res(@block_ctxt bcx, ValueRef val) -> result { ret rec(mutable bcx = bcx, mutable val = val); @@ -1104,7 +1108,7 @@ fn make_generic_glue(@crate_ctxt cx, @ty.t t, str name, vec[ast.def_id] typaram_defs) -> ValueRef { auto llfnty = T_glue_fn(); - auto fn_name = cx.names.next("_rust_" + name) + "." + ty.ty_to_str(t); + auto fn_name = cx.names.next("_rust_" + name) + sep() + ty.ty_to_str(t); fn_name = sanitize(fn_name); auto llfn = decl_fastcall_fn(cx.llmod, fn_name, llfnty); @@ -2498,7 +2502,7 @@ fn trans_bind_thunk(@crate_ctxt cx, // Construct a thunk-call with signature incoming_fty, and that copies // args forward into a call to outgoing_fty. - let str s = cx.names.next("_rust_thunk") + "." + cx.path; + let str s = cx.names.next("_rust_thunk") + sep() + cx.path; let TypeRef llthunk_ty = get_pair_fn_ty(type_of(cx, incoming_fty)); let ValueRef llthunk = decl_fastcall_fn(cx.llmod, s, llthunk_ty); @@ -3592,10 +3596,10 @@ fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty, } } - let @crate_ctxt mcx = @rec(path=cx.path + "." + m.node.ident + let @crate_ctxt mcx = @rec(path=cx.path + sep() + m.node.ident with *cx); - let str s = cx.names.next("_rust_method") + "." + mcx.path; + let str s = cx.names.next("_rust_method") + sep() + mcx.path; let ValueRef llfn = decl_fastcall_fn(cx.llmod, s, llfnty); cx.item_ids.insert(m.node.id, llfn); @@ -3606,7 +3610,7 @@ fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty, auto vtbl = C_struct(methods); auto gvar = llvm.LLVMAddGlobal(cx.llmod, val_ty(vtbl), - _str.buf("_rust_vtbl" + "." + cx.path)); + _str.buf("_rust_vtbl" + sep() + cx.path)); llvm.LLVMSetInitializer(gvar, vtbl); llvm.LLVMSetGlobalConstant(gvar, True); llvm.LLVMSetLinkage(gvar, lib.llvm.LLVMPrivateLinkage @@ -3837,21 +3841,21 @@ fn trans_const(@crate_ctxt cx, @ast.expr e, fn trans_item(@crate_ctxt cx, &ast.item item) { alt (item.node) { case (ast.item_fn(?name, ?f, ?tps, ?fid, ?ann)) { - auto sub_cx = @rec(path=cx.path + "." + name with *cx); + auto sub_cx = @rec(path=cx.path + sep() + name with *cx); trans_fn(sub_cx, f, fid, none[TypeRef], tps, ann); } case (ast.item_obj(?name, ?ob, ?tps, ?oid, ?ann)) { - auto sub_cx = @rec(path=cx.path + "." + name, + auto sub_cx = @rec(path=cx.path + sep() + name, obj_typarams=tps, obj_fields=ob.fields with *cx); trans_obj(sub_cx, ob, oid, tps, ann); } case (ast.item_mod(?name, ?m, _)) { - auto sub_cx = @rec(path=cx.path + "." + name with *cx); + auto sub_cx = @rec(path=cx.path + sep() + name with *cx); trans_mod(sub_cx, m); } case (ast.item_tag(?name, ?variants, ?tps, ?tag_id)) { - auto sub_cx = @rec(path=cx.path + "." + name with *cx); + auto sub_cx = @rec(path=cx.path + sep() + name with *cx); auto i = 0; for (ast.variant variant in variants) { trans_tag_variant(sub_cx, tag_id, variant, i, tps); @@ -3859,7 +3863,7 @@ fn trans_item(@crate_ctxt cx, &ast.item item) { } } case (ast.item_const(?name, _, ?expr, ?cid, ?ann)) { - auto sub_cx = @rec(path=cx.path + "." + name with *cx); + auto sub_cx = @rec(path=cx.path + sep() + name with *cx); trans_const(sub_cx, expr, cid, ann); } case (_) { /* fall through */ } @@ -3890,11 +3894,11 @@ fn decl_fn_and_pair(@crate_ctxt cx, auto llfty = get_pair_fn_ty(llpairty); // Declare the function itself. - let str s = cx.names.next("_rust_" + kind) + "." + name; + let str s = cx.names.next("_rust_" + kind) + sep() + name; let ValueRef llfn = decl_fastcall_fn(cx.llmod, s, llfty); // Declare the global constant pair that points to it. - let str ps = cx.names.next("_rust_" + kind + "_pair") + "." + name; + let str ps = cx.names.next("_rust_" + kind + "_pair") + sep() + name; let ValueRef gvar = llvm.LLVMAddGlobal(cx.llmod, llpairty, _str.buf(ps)); auto pair = C_struct(vec(llfn, @@ -4208,8 +4212,8 @@ fn trans_main_fn(@crate_ctxt cx, ValueRef llcrate) { auto llargc = llvm.LLVMGetParam(llmain, 0u); auto llargv = llvm.LLVMGetParam(llmain, 1u); - check (cx.item_names.contains_key("_rust.main")); - auto llrust_main = cx.item_names.get("_rust.main"); + check (cx.item_names.contains_key("_rust" + sep() + "main")); + auto llrust_main = cx.item_names.get("_rust" + sep() + "main"); // // Emit the moral equivalent of: -- cgit v1.2.3 From c958eebf5d17f5fd52805ed08e4a7efc6c3caf21 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Feb 2011 15:00:16 -0800 Subject: Change more of trans to rely on tydescs when dealing with generics. --- src/comp/middle/trans.rs | 103 ++++++++++++++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 37 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index dbcdaed1..6399b900 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2704,7 +2704,10 @@ fn trans_args(@block_ctxt cx, // Arg 0: Output pointer. auto retty = ty.ty_fn_ret(fn_ty); - auto llretslot = cx.build.Alloca(type_of(cx.fcx.ccx, retty)); + auto llretslot_res = alloc_ty(bcx, retty); + bcx = llretslot_res.bcx; + auto llretslot = llretslot_res.val; + alt (gen) { case (some[generic_info](?g)) { lltydescs = g.tydescs; @@ -2715,7 +2718,7 @@ fn trans_args(@block_ctxt cx, } } if (ty.type_has_dynamic_size(retty)) { - llargs += cx.build.PointerCast(llretslot, T_typaram_ptr()); + llargs += bcx.build.PointerCast(llretslot, T_typaram_ptr()); } else if (ty.count_ty_params(retty) != 0u) { // It's possible that the callee has some generic-ness somewhere in // its return value -- say a method signature within an obj or a fn @@ -2723,14 +2726,14 @@ fn trans_args(@block_ctxt cx, // of. If so, cast the caller's view of the restlot to the callee's // view, for the sake of making a type-compatible call. llargs += cx.build.PointerCast(llretslot, - T_ptr(type_of(cx.fcx.ccx, retty))); + T_ptr(type_of(bcx.fcx.ccx, retty))); } else { llargs += llretslot; } // Arg 1: Task pointer. - llargs += cx.fcx.lltaskptr; + llargs += bcx.fcx.lltaskptr; // Arg 2: Env (closure-bindings / self-obj) alt (llobj) { @@ -2738,7 +2741,7 @@ fn trans_args(@block_ctxt cx, // Every object is always found in memory, // and not-yet-loaded (as part of an lval x.y // doted method-call). - llargs += cx.build.Load(ob); + llargs += bcx.build.Load(ob); } case (_) { llargs += llenv; @@ -2848,25 +2851,32 @@ fn trans_call(@block_ctxt cx, @ast.expr f, find_scope_cx(cx).cleanups += clean(bind drop_ty(_, retval, ret_ty)); } + // log "call-result type: " + val_str(retval); ret res(bcx, retval); } fn trans_tup(@block_ctxt cx, vec[ast.elt] elts, &ast.ann ann) -> result { - auto t = node_ann_type(cx.fcx.ccx, ann); - auto llty = type_of(cx.fcx.ccx, t); - auto tup_val = cx.build.Alloca(llty); + auto bcx = cx; + auto t = node_ann_type(bcx.fcx.ccx, ann); + auto llty = type_of(bcx.fcx.ccx, t); + auto tup_res = alloc_ty(bcx, t); + auto tup_val = tup_res.val; + bcx = tup_res.bcx; + 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 = 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, INIT, dst_elt, src_res.val, t); + auto e_ty = ty.expr_ty(e.expr); + auto src_res = trans_expr(bcx, e.expr); + bcx = src_res.bcx; + auto dst_res = GEP_tup_like(bcx, t, tup_val, vec(0, i)); + bcx = dst_res.bcx; + bcx = copy_ty(src_res.bcx, INIT, dst_res.val, src_res.val, e_ty).bcx; i += 1; } - ret res(r.bcx, tup_val); + ret res(bcx, tup_val); } fn trans_vec(@block_ctxt cx, vec[@ast.expr] args, @@ -2891,44 +2901,58 @@ fn trans_vec(@block_ctxt cx, vec[@ast.expr] args, // FIXME: pass tydesc properly. auto sub = trans_upcall(bcx, "upcall_new_vec", vec(data_sz, C_int(0))); + bcx = sub.bcx; auto llty = type_of(bcx.fcx.ccx, t); - auto vec_val = sub.bcx.build.IntToPtr(sub.val, llty); + auto vec_val = bcx.build.IntToPtr(sub.val, llty); find_scope_cx(bcx).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))); + auto body = bcx.build.GEP(vec_val, vec(C_int(0), + C_int(abi.vec_elt_data))); + + auto pseudo_tup_ty = + plain_ty(ty.ty_tup(_vec.init_elt[@ty.t](unit_ty, + _vec.len[@ast.expr](args)))); let int i = 0; + for (@ast.expr e in args) { - auto src_res = trans_expr(sub.bcx, e); - auto dst_elt = sub.bcx.build.GEP(body, vec(C_int(0), C_int(i))); - sub = copy_ty(src_res.bcx, INIT, dst_elt, src_res.val, unit_ty); + auto src_res = trans_expr(bcx, e); + bcx = src_res.bcx; + auto dst_res = GEP_tup_like(bcx, pseudo_tup_ty, body, vec(0, i)); + bcx = dst_res.bcx; + bcx = copy_ty(bcx, INIT, dst_res.val, src_res.val, unit_ty).bcx; i += 1; } - auto fill = sub.bcx.build.GEP(vec_val, - vec(C_int(0), C_int(abi.vec_elt_fill))); - sub.bcx.build.Store(data_sz, fill); + auto fill = bcx.build.GEP(vec_val, + vec(C_int(0), C_int(abi.vec_elt_fill))); + bcx.build.Store(data_sz, fill); - ret res(sub.bcx, vec_val); + ret res(bcx, vec_val); } fn trans_rec(@block_ctxt cx, vec[ast.field] fields, &ast.ann ann) -> result { - auto t = node_ann_type(cx.fcx.ccx, ann); - auto llty = type_of(cx.fcx.ccx, t); - auto rec_val = cx.build.Alloca(llty); + + auto bcx = cx; + auto t = node_ann_type(bcx.fcx.ccx, ann); + auto llty = type_of(bcx.fcx.ccx, t); + auto rec_res = alloc_ty(bcx, t); + auto rec_val = rec_res.val; + bcx = rec_res.bcx; + 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 = 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. - r = copy_ty(src_res.bcx, INIT, dst_elt, src_res.val, t); + auto e_ty = ty.expr_ty(f.expr); + auto src_res = trans_expr(bcx, f.expr); + bcx = src_res.bcx; + auto dst_res = GEP_tup_like(bcx, t, rec_val, vec(0, i)); + bcx = dst_res.bcx; + bcx = copy_ty(src_res.bcx, INIT, dst_res.val, src_res.val, e_ty).bcx; i += 1; } - ret res(r.bcx, rec_val); + ret res(bcx, rec_val); } @@ -3300,8 +3324,7 @@ iter block_locals(&ast.block b) -> @ast.local { } } -fn alloc_local(@block_ctxt cx, @ast.local local) -> result { - auto t = node_ann_type(cx.fcx.ccx, local.ann); +fn alloc_ty(@block_ctxt cx, @ty.t t) -> result { auto val = C_int(0); auto bcx = cx; if (ty.type_has_dynamic_size(t)) { @@ -3311,10 +3334,16 @@ fn alloc_local(@block_ctxt cx, @ast.local local) -> result { } else { val = bcx.build.Alloca(type_of(cx.fcx.ccx, t)); } - bcx.fcx.lllocals.insert(local.id, val); ret res(bcx, val); } +fn alloc_local(@block_ctxt cx, @ast.local local) -> result { + auto t = node_ann_type(cx.fcx.ccx, local.ann); + auto r = alloc_ty(cx, t); + r.bcx.fcx.lllocals.insert(local.id, r.val); + ret r; +} + fn trans_block(@block_ctxt cx, &ast.block b) -> result { auto bcx = cx; -- cgit v1.2.3 From 2b669008a8bcfcf0d1ed41cecd243e59cded4ded Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Feb 2011 15:04:11 -0800 Subject: Un-XFAIL generic-derived-type.rs. --- src/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile b/src/Makefile index 7a31c24a..a1c38bb9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -473,6 +473,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ fn-lval.rs \ fun-call-variants.rs \ fun-indirect-call.rs \ + generic-derived-type.rs \ generic-fn.rs \ generic-fn-infer.rs \ generic-exterior-box.rs \ -- cgit v1.2.3 From 0d27eb13415d442a4f643c8cf4c0d839c0460744 Mon Sep 17 00:00:00 2001 From: Rafael Avila de Espindola Date: Thu, 10 Feb 2011 18:39:55 -0500 Subject: Add type checking for native types. --- src/comp/middle/ty.rs | 2 + src/comp/middle/typeck.rs | 158 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 126 insertions(+), 34 deletions(-) diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index c3b0e687..6dd229fb 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -43,6 +43,7 @@ tag sty { ty_local(ast.def_id); // type of a local var ty_param(ast.def_id); // fn type param ty_type; + ty_native; // TODO: ty_fn_arg(@t), for a possibly-aliased function argument } @@ -286,6 +287,7 @@ fn fold_ty(ty_fold fld, @t ty) -> @t { 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)) { ret rewrap(ty, ty_box(fold_ty(fld, subty))); } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 4c3903a7..d21d4ed2 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -31,7 +31,13 @@ import std.option.none; import std.option.some; type ty_table = hashmap[ast.def_id, @ty.t]; -type ty_item_table = hashmap[ast.def_id,@ast.item]; + +tag any_item { + any_item_rust(@ast.item); + any_item_native(@ast.native_item); +} + +type ty_item_table = hashmap[ast.def_id,any_item]; type crate_ctxt = rec(session.session sess, @ty_table item_types, @@ -161,6 +167,9 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t { case (ast.def_ty(?id)) { sty = instantiate(getter, id, path.node.types).struct; } + case (ast.def_native_ty(?id)) { + sty = instantiate(getter, id, path.node.types).struct; + } case (ast.def_obj(?id)) { sty = instantiate(getter, id, path.node.types).struct; } @@ -196,23 +205,36 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t { ret @rec(struct=sty, mut=mut, cname=cname); } +fn actual_type(@ty.t t, @ast.item item) -> @ty.t { + alt (item.node) { + case (ast.item_obj(_,_,_,_,_)) { + // An obj used as a type name refers to the output type of the + // item (constructor). + ret middle.ty.ty_fn_ret(t); + } + case (_) { } + } + + ret t; +} + // 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.t { fn getter(@crate_ctxt ccx, ast.def_id id) -> ty_and_params { check (ccx.item_items.contains_key(id)); check (ccx.item_types.contains_key(id)); - auto item = ccx.item_items.get(id); + auto it = ccx.item_items.get(id); auto ty = ccx.item_types.get(id); - auto params = ty_params_of_item(item); - - alt (item.node) { - case (ast.item_obj(_,_,_,_,_)) { - // An obj used as a type name refers to the output type of the - // item (constructor). - ty = middle.ty.ty_fn_ret(ty); + auto params; + alt (it) { + case (any_item_rust(?item)) { + ty = actual_type(ty, item); + params = ty_params_of_item(item); } - case (_) { } + case (any_item_native(?native_item)) { + params = ty_params_of_native_item(native_item); + } } ret rec(params = params, ty = ty); @@ -242,6 +264,18 @@ fn ty_params_of_item(@ast.item item) -> vec[ast.ty_param] { } } +fn ty_params_of_native_item(@ast.native_item item) -> vec[ast.ty_param] { + alt (item.node) { + case (ast.native_item_fn(_, _, ?p, _)) { + ret p; + } + case (_) { + let vec[ast.ty_param] r = vec(); + ret r; + } + } +} + // Item collection - a pair of bootstrap passes: // // 1. Collect the IDs of all type items (typedefs) and store them in a table. @@ -253,6 +287,19 @@ fn ty_params_of_item(@ast.item item) -> vec[ast.ty_param] { // We then annotate the AST with the resulting types and return the annotated // AST, along with a table mapping item IDs to their types. +fn ty_of_fn_decl(@ty_item_table id_to_ty_item, + @ty_table item_to_ty, + fn(&@ast.ty ast_ty) -> @ty.t convert, + fn(&ast.arg a) -> arg ty_of_arg, + &ast.fn_decl decl, + ast.def_id def_id) -> @ty.t { + auto input_tys = _vec.map[ast.arg,arg](ty_of_arg, decl.inputs); + auto output_ty = convert(decl.output); + auto t_fn = plain_ty(ty.ty_fn(input_tys, output_ty)); + item_to_ty.insert(def_id, t_fn); + ret t_fn; +} + fn collect_item_types(session.session sess, @ast.crate crate) -> tup(@ast.crate, @ty_table, @ty_item_table) { @@ -260,17 +307,20 @@ fn collect_item_types(session.session sess, @ast.crate crate) @ty_table item_to_ty, ast.def_id id) -> ty_and_params { check (id_to_ty_item.contains_key(id)); - auto item = id_to_ty_item.get(id); - auto ty = ty_of_item(id_to_ty_item, item_to_ty, item); - auto params = ty_params_of_item(item); - - alt (item.node) { - case (ast.item_obj(_,_,_,_,_)) { - // An obj used as a type name refers to the output type of the - // item (constructor). - ty = middle.ty.ty_fn_ret(ty); + auto it = id_to_ty_item.get(id); + auto ty; + auto params; + alt (it) { + case (any_item_rust(?item)) { + ty = ty_of_item(id_to_ty_item, item_to_ty, item); + ty = actual_type(ty, item); + params = ty_params_of_item(item); + } + case (any_item_native(?native_item)) { + ty = ty_of_native_item(id_to_ty_item, item_to_ty, + native_item); + params = ty_params_of_native_item(native_item); } - case (_) { } } ret rec(params = params, ty = ty); @@ -340,16 +390,9 @@ fn collect_item_types(session.session sess, @ast.crate crate) } case (ast.item_fn(?ident, ?fn_info, _, ?def_id, _)) { - // TODO: handle ty-params - auto f = bind ty_of_arg(id_to_ty_item, item_to_ty, _); - auto input_tys = _vec.map[ast.arg,arg](f, - fn_info.decl.inputs); - auto output_ty = convert(fn_info.decl.output); - - auto t_fn = plain_ty(ty.ty_fn(input_tys, output_ty)); - item_to_ty.insert(def_id, t_fn); - ret t_fn; + ret ty_of_fn_decl(id_to_ty_item, item_to_ty, convert, f, + fn_info.decl, def_id); } case (ast.item_obj(?ident, ?obj_info, _, ?def_id, _)) { @@ -385,6 +428,30 @@ fn collect_item_types(session.session sess, @ast.crate crate) } } + fn ty_of_native_item(@ty_item_table id_to_ty_item, + @ty_table item_to_ty, + @ast.native_item it) -> @ty.t { + alt (it.node) { + case (ast.native_item_fn(?ident, ?fn_decl, ?params, ?def_id)) { + auto get = bind getter(id_to_ty_item, item_to_ty, _); + auto convert = bind ast_ty_to_ty(get, _); + auto f = bind ty_of_arg(id_to_ty_item, item_to_ty, _); + ret ty_of_fn_decl(id_to_ty_item, item_to_ty, convert, f, + fn_decl, def_id); + } + case (ast.native_item_ty(_, ?def_id)) { + if (item_to_ty.contains_key(def_id)) { + // Avoid repeating work. + ret item_to_ty.get(def_id); + } + auto x = + @rec(struct=ty.ty_native, mut=ast.imm, cname=none[str]); + item_to_ty.insert(def_id, x); + ret x; + } + } + } + fn get_tag_variant_types(@ty_item_table id_to_ty_item, @ty_table item_to_ty, &ast.def_id tag_id, @@ -422,25 +489,38 @@ fn collect_item_types(session.session sess, @ast.crate crate) // First pass: collect all type item IDs. auto module = crate.node.module; - auto id_to_ty_item = @common.new_def_hash[@ast.item](); + auto id_to_ty_item = @common.new_def_hash[any_item](); fn collect(&@ty_item_table id_to_ty_item, @ast.item i) -> @ty_item_table { alt (i.node) { case (ast.item_ty(_, _, _, ?def_id, _)) { - id_to_ty_item.insert(def_id, i); + id_to_ty_item.insert(def_id, any_item_rust(i)); } case (ast.item_tag(_, _, _, ?def_id)) { - id_to_ty_item.insert(def_id, i); + id_to_ty_item.insert(def_id, any_item_rust(i)); } case (ast.item_obj(_, _, _, ?def_id, _)) { - id_to_ty_item.insert(def_id, i); + id_to_ty_item.insert(def_id, any_item_rust(i)); } case (_) { /* empty */ } } ret id_to_ty_item; } + fn collect_native(&@ty_item_table id_to_ty_item, @ast.native_item i) + -> @ty_item_table { + alt (i.node) { + case (ast.native_item_ty(_, ?def_id)) { + id_to_ty_item.insert(def_id, any_item_native(i)); + } + case (ast.native_item_fn(_, _, _, ?def_id)) { + id_to_ty_item.insert(def_id, any_item_native(i)); + } + } + ret id_to_ty_item; + } auto fld_1 = fold.new_identity_fold[@ty_item_table](); - fld_1 = @rec(update_env_for_item = bind collect(_, _) + fld_1 = @rec(update_env_for_item = bind collect(_, _), + update_env_for_native_item = bind collect_native(_, _) with *fld_1); fold.fold_crate[@ty_item_table](id_to_ty_item, fld_1, crate); @@ -473,6 +553,11 @@ fn collect_item_types(session.session sess, @ast.crate crate) ret e; } + fn convert_native(&@env e, @ast.native_item i) -> @env { + ty_of_native_item(e.id_to_ty_item, e.item_to_ty, i); + ret e; + } + fn fold_item_const(&@env e, &span sp, ast.ident i, @ast.ty t, @ast.expr ex, ast.def_id id, ast.ann a) -> @ast.item { @@ -575,6 +660,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) auto fld_2 = fold.new_identity_fold[@env](); fld_2 = @rec(update_env_for_item = bind convert(_,_), + update_env_for_native_item = bind convert_native(_,_), fold_item_const = bind fold_item_const(_,_,_,_,_,_,_), fold_item_fn = bind fold_item_fn(_,_,_,_,_,_,_), fold_item_obj = bind fold_item_obj(_,_,_,_,_,_,_), @@ -1150,6 +1236,10 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { check (fcx.ccx.item_types.contains_key(id)); t = generalize_ty(fcx.ccx, fcx.ccx.item_types.get(id)); } + case (ast.def_native_fn(?id)) { + check (fcx.ccx.item_types.contains_key(id)); + t = generalize_ty(fcx.ccx, fcx.ccx.item_types.get(id)); + } case (ast.def_const(?id)) { check (fcx.ccx.item_types.contains_key(id)); t = fcx.ccx.item_types.get(id); -- cgit v1.2.3 From 7c25fb5628c398b79b9293b6b31d62936dcba613 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Feb 2011 17:33:08 -0800 Subject: Fix bug in trans_field, un-XFAIL two more tests. --- src/Makefile | 2 ++ src/comp/middle/trans.rs | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Makefile b/src/Makefile index a1c38bb9..c1f33b91 100644 --- a/src/Makefile +++ b/src/Makefile @@ -449,6 +449,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ arith-0.rs \ arith-1.rs \ arith-2.rs \ + auto-instantiate.rs \ autoderef-full-lval.rs \ bind-exterior.rs \ bind-interior.rs \ @@ -479,6 +480,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ generic-exterior-box.rs \ generic-drop-glue.rs \ generic-obj.rs \ + generic-obj-with-derived-type.rs \ generic-tup.rs \ generic-type.rs \ generic-type-synonym.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 6399b900..4135a6e5 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2376,10 +2376,8 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, fn trans_field(@block_ctxt cx, &ast.span sp, @ast.expr base, &ast.ident field, &ast.ann ann) -> lval_result { - auto lv = trans_lval(cx, base); - auto r = lv.res; + auto r = trans_expr(cx, base); r = autoderef(r.bcx, r.val, ty.expr_ty(base)); - check (lv.is_mem); auto t = ty.expr_ty(base); alt (t.struct) { case (ty.ty_tup(?fields)) { -- cgit v1.2.3 From b59d98ccb9de56a49768586961ce745d462e0697 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Feb 2011 18:58:58 -0800 Subject: Parse effects and layers in a couple contexts; drop on floor as we have nowhere to put them yet. --- src/comp/front/parser.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index ea4cf12c..97e86b7f 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -173,6 +173,10 @@ impure fn parse_ty_obj(parser p, &mutable ast.span hi) -> ast.ty_ { expect(p, token.OBJ); impure fn parse_method_sig(parser p) -> ast.ty_method { auto flo = p.get_span(); + + // FIXME: do something with this, currently it's dropped on the floor. + let ast.effect eff = parse_effect(p); + expect(p, token.FN); auto ident = parse_ident(p); auto f = parse_ty_fn(p, flo); @@ -204,6 +208,12 @@ impure fn parse_ty(parser p) -> @ast.ty { auto lo = p.get_span(); auto hi = lo; let ast.ty_ t; + + // FIXME: do something with these; currently they're + // dropped on the floor. + let ast.effect eff = parse_effect(p); + let ast.layer lyr = parse_layer(p); + alt (p.peek()) { case (token.BOOL) { p.bump(); t = ast.ty_bool; } case (token.INT) { p.bump(); t = ast.ty_int; } -- cgit v1.2.3 From a396652766bc6aa2b4526ddd9807439ecd12033a Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Feb 2011 18:59:23 -0800 Subject: Add pat_lit to ast, and support parsing it. --- src/comp/front/ast.rs | 1 + src/comp/front/parser.rs | 43 +++++++++++++++++++++---------------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 61a7bdc1..6aac7b50 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -57,6 +57,7 @@ type pat = spanned[pat_]; tag pat_ { pat_wild(ann); pat_bind(ident, def_id, ann); + pat_lit(@lit, ann); pat_tag(path, vec[@pat], option.t[variant_def], ann); } diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 97e86b7f..2fa4afeb 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -351,9 +351,9 @@ impure fn parse_seq[T](token.token bra, ret spanned(lo, hi, v); } -impure fn parse_lit(parser p) -> option.t[ast.lit] { +impure fn parse_lit(parser p) -> ast.lit { auto lo = p.get_span(); - let ast.lit_ lit; + let ast.lit_ lit = ast.lit_nil; alt (p.peek()) { case (token.LIT_INT(?i)) { p.bump(); @@ -379,12 +379,11 @@ impure fn parse_lit(parser p) -> option.t[ast.lit] { p.bump(); lit = ast.lit_str(s); } - case (_) { - lit = ast.lit_nil; // FIXME: typestate bug requires this - ret none[ast.lit]; + case (?t) { + unexpected(p, t); } } - ret some(spanned(lo, lo, lit)); + ret spanned(lo, lo, lit); } fn is_ident(token.token t) -> bool { @@ -565,15 +564,9 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr { } case (_) { - alt (parse_lit(p)) { - case (some[ast.lit](?lit)) { - hi = lit.span; - ex = ast.expr_lit(@lit, ast.ann_none); - } - case (none[ast.lit]) { - p.err("expecting expression"); - } - } + auto lit = parse_lit(p); + hi = lit.span; + ex = ast.expr_lit(@lit, ast.ann_none); } } @@ -1081,10 +1074,12 @@ impure fn parse_initializer(parser p) -> option.t[@ast.expr] { impure fn parse_pat(parser p) -> @ast.pat { auto lo = p.get_span(); - + auto hi = lo; auto pat = ast.pat_wild(ast.ann_none); // FIXME: typestate bug + alt (p.peek()) { case (token.UNDERSCORE) { + hi = p.get_span(); p.bump(); pat = ast.pat_wild(ast.ann_none); } @@ -1092,6 +1087,7 @@ impure fn parse_pat(parser p) -> @ast.pat { p.bump(); alt (p.peek()) { case (token.IDENT(?id)) { + hi = p.get_span(); p.bump(); pat = ast.pat_bind(id, p.next_def_id(), ast.ann_none); } @@ -1104,13 +1100,16 @@ impure fn parse_pat(parser p) -> @ast.pat { } case (token.IDENT(?id)) { auto tag_path = parse_path(p, GREEDY); + hi = tag_path.span; let vec[@ast.pat] args; alt (p.peek()) { case (token.LPAREN) { auto f = parse_pat; - args = parse_seq[@ast.pat](token.LPAREN, token.RPAREN, - some(token.COMMA), f, p).node; + auto a = parse_seq[@ast.pat](token.LPAREN, token.RPAREN, + some(token.COMMA), f, p); + args = a.node; + hi = a.span; } case (_) { args = vec(); } } @@ -1118,13 +1117,13 @@ impure fn parse_pat(parser p) -> @ast.pat { pat = ast.pat_tag(tag_path, args, none[ast.variant_def], ast.ann_none); } - case (?tok) { - p.err("expected pattern but found " + token.to_str(tok)); - fail; + case (_) { + auto lit = parse_lit(p); + hi = lit.span; + pat = ast.pat_lit(@lit, ast.ann_none); } } - auto hi = p.get_span(); ret @spanned(lo, hi, pat); } -- cgit v1.2.3 From c89460bb659e1af1a3618cfe8d7fa304e531916d Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Feb 2011 19:04:37 -0800 Subject: Support indexing pat_lit. --- src/comp/front/parser.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 2fa4afeb..87bbe57f 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1331,6 +1331,7 @@ fn index_arm(@ast.pat pat) -> hashmap[ast.ident,ast.def_id] { alt (pat.node) { case (ast.pat_bind(?i, ?def_id, _)) { index.insert(i, def_id); } case (ast.pat_wild(_)) { /* empty */ } + case (ast.pat_lit(_, _)) { /* empty */ } case (ast.pat_tag(_, ?pats, _, _)) { for (@ast.pat p in pats) { do_index_arm(index, p); -- cgit v1.2.3 From 277334890dabd85c1015da666e2700dfe9950e2d Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Feb 2011 19:13:39 -0800 Subject: Add alt-pattern-lit.rs test. --- src/test/run-pass/alt-pattern-lit.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/test/run-pass/alt-pattern-lit.rs diff --git a/src/test/run-pass/alt-pattern-lit.rs b/src/test/run-pass/alt-pattern-lit.rs new file mode 100644 index 00000000..91190260 --- /dev/null +++ b/src/test/run-pass/alt-pattern-lit.rs @@ -0,0 +1,17 @@ +fn altlit(int f) -> int { + alt (f) { + case (10) { + log "case 10"; + ret 20; + } + case (11) { + log "case 11"; + ret 22; + } + } +} + +fn main() { + check (altlit(10) == 20); + check (altlit(11) == 22); +} -- cgit v1.2.3 From f951b52e91c5c0487ad4d3a5454b193f15146d6a Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Feb 2011 19:13:47 -0800 Subject: Add support to pat_lit to fold. --- src/comp/middle/fold.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 9194f734..5930ba75 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -160,6 +160,9 @@ type ast_fold[ENV] = (fn(&ENV e, &span sp, ann a) -> @pat) fold_pat_wild, + (fn(&ENV e, &span sp, + @ast.lit lit, ann a) -> @pat) fold_pat_lit, + (fn(&ENV e, &span sp, ident i, def_id did, ann a) -> @pat) fold_pat_bind, @@ -421,6 +424,9 @@ fn fold_pat[ENV](&ENV env, ast_fold[ENV] fld, @ast.pat p) -> @ast.pat { alt (p.node) { case (ast.pat_wild(?t)) { ret fld.fold_pat_wild(env_, p.span, t); } + case (ast.pat_lit(?lt, ?t)) { + ret fld.fold_pat_lit(env_, p.span, lt, t); + } case (ast.pat_bind(?id, ?did, ?t)) { ret fld.fold_pat_bind(env_, p.span, id, did, t); } @@ -1122,6 +1128,10 @@ fn identity_fold_pat_wild[ENV](&ENV e, &span sp, ann a) -> @pat { ret @respan(sp, ast.pat_wild(a)); } +fn identity_fold_pat_lit[ENV](&ENV e, &span sp, @ast.lit lit, ann a) -> @pat { + ret @respan(sp, ast.pat_lit(lit, a)); +} + fn identity_fold_pat_bind[ENV](&ENV e, &span sp, ident i, def_id did, ann a) -> @pat { ret @respan(sp, ast.pat_bind(i, did, a)); @@ -1373,6 +1383,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_decl_item = bind identity_fold_decl_item[ENV](_,_,_), fold_pat_wild = bind identity_fold_pat_wild[ENV](_,_,_), + fold_pat_lit = bind identity_fold_pat_lit[ENV](_,_,_,_), fold_pat_bind = bind identity_fold_pat_bind[ENV](_,_,_,_,_), fold_pat_tag = bind identity_fold_pat_tag[ENV](_,_,_,_,_,_), -- cgit v1.2.3 From c9956a65b49f9cf2b1a691f2b88d61ada753d271 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Feb 2011 19:22:30 -0800 Subject: Teach ty and typeck about pat_lit. --- src/comp/middle/ty.rs | 1 + src/comp/middle/typeck.rs | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 6dd229fb..2bb65fe0 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -656,6 +656,7 @@ fn block_ty(&ast.block b) -> @t { fn pat_ty(@ast.pat pat) -> @t { alt (pat.node) { case (ast.pat_wild(?ann)) { ret ann_to_type(ann); } + case (ast.pat_lit(_, ?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); } } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index d21d4ed2..97453436 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -807,6 +807,10 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { auto t = demand(fcx, pat.span, expected, ann_to_type(ann)); p_1 = ast.pat_wild(ast.ann_type(t)); } + case (ast.pat_lit(?lit, ?ann)) { + auto t = demand(fcx, pat.span, expected, ann_to_type(ann)); + p_1 = ast.pat_lit(lit, ast.ann_type(t)); + } case (ast.pat_bind(?id, ?did, ?ann)) { auto t = demand(fcx, pat.span, expected, ann_to_type(ann)); fcx.locals.insert(did, t); @@ -1093,6 +1097,9 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat { case (ast.pat_wild(_)) { new_pat = ast.pat_wild(ast.ann_type(next_ty_var(fcx.ccx))); } + case (ast.pat_lit(?lt, _)) { + new_pat = ast.pat_lit(lt, ast.ann_type(check_lit(lt))); + } case (ast.pat_bind(?id, ?def_id, _)) { auto ann = ast.ann_type(next_ty_var(fcx.ccx)); new_pat = ast.pat_bind(id, def_id, ann); -- cgit v1.2.3 From 7446af747d83622c849ec9f29c0365aa7bf4e697 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 10 Feb 2011 19:40:02 -0800 Subject: Translate pat_lit, un-XFAIL alt-pattern-lit.rs for rustc. --- src/Makefile | 1 + src/comp/middle/trans.rs | 42 ++++++++++++++++++++++++++++++------------ 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/Makefile b/src/Makefile index c1f33b91..d55a63c2 100644 --- a/src/Makefile +++ b/src/Makefile @@ -444,6 +444,7 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \ TEST_XFAILS_RUSTC := $(filter-out \ $(addprefix test/run-pass/, \ alt-path.rs \ + alt-pattern-lit.rs \ alt-pattern-simple.rs \ alt-tag.rs \ arith-0.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4135a6e5..bedfad97 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1838,6 +1838,24 @@ fn trans_unary(@block_ctxt cx, ast.unop op, fail; } +// FIXME: implement proper structural comparison. + +fn trans_compare(@block_ctxt cx, ast.binop op, + ValueRef lhs, ValueRef rhs) -> ValueRef { + auto cmp = lib.llvm.LLVMIntEQ; + alt (op) { + case (ast.eq) { cmp = lib.llvm.LLVMIntEQ; } + case (ast.ne) { cmp = lib.llvm.LLVMIntNE; } + + // FIXME (issue #57): switch by signedness. + case (ast.lt) { cmp = lib.llvm.LLVMIntSLT; } + case (ast.le) { cmp = lib.llvm.LLVMIntSLE; } + case (ast.ge) { cmp = lib.llvm.LLVMIntSGE; } + case (ast.gt) { cmp = lib.llvm.LLVMIntSGT; } + } + ret cx.build.ICmp(cmp, lhs, rhs); +} + fn trans_eager_binop(@block_ctxt cx, ast.binop op, ValueRef lhs, ValueRef rhs) -> ValueRef { @@ -1857,18 +1875,7 @@ fn trans_eager_binop(@block_ctxt cx, ast.binop op, case (ast.lsr) { ret cx.build.LShr(lhs, rhs); } case (ast.asr) { ret cx.build.AShr(lhs, rhs); } case (_) { - auto cmp = lib.llvm.LLVMIntEQ; - alt (op) { - case (ast.eq) { cmp = lib.llvm.LLVMIntEQ; } - case (ast.ne) { cmp = lib.llvm.LLVMIntNE; } - - // FIXME (issue #57): switch by signedness. - case (ast.lt) { cmp = lib.llvm.LLVMIntSLT; } - case (ast.le) { cmp = lib.llvm.LLVMIntSLE; } - case (ast.ge) { cmp = lib.llvm.LLVMIntSGE; } - case (ast.gt) { cmp = lib.llvm.LLVMIntSGT; } - } - ret cx.build.ICmp(cmp, lhs, rhs); + ret trans_compare(cx, op, lhs, rhs); } } fail; @@ -2132,6 +2139,16 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, alt (pat.node) { case (ast.pat_wild(_)) { ret res(cx, llval); } case (ast.pat_bind(_, _, _)) { ret res(cx, llval); } + + case (ast.pat_lit(?lt, ?ann)) { + auto lllit = trans_lit(cx.fcx.ccx, *lt, ann); + auto lleq = trans_compare(cx, ast.eq, llval, lllit); + + auto matched_cx = new_sub_block_ctxt(cx, "matched_cx"); + cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb); + ret res(matched_cx, llval); + } + case (ast.pat_tag(?id, ?subpats, ?vdef_opt, ?ann)) { auto lltagptr = cx.build.GEP(llval, vec(C_int(0), C_int(0))); auto lltag = cx.build.Load(lltagptr); @@ -2184,6 +2201,7 @@ fn trans_pat_binding(@block_ctxt cx, @ast.pat pat, ValueRef llval) -> result { alt (pat.node) { case (ast.pat_wild(_)) { ret res(cx, llval); } + case (ast.pat_lit(_, _)) { ret res(cx, llval); } case (ast.pat_bind(?id, ?def_id, ?ann)) { auto ty = node_ann_type(cx.fcx.ccx, ann); auto llty = type_of(cx.fcx.ccx, ty); -- cgit v1.2.3 From bd56dd9f2aca1967c92d3cc613dcc199c878026c Mon Sep 17 00:00:00 2001 From: Rafael Avila de Espindola Date: Mon, 14 Feb 2011 11:22:10 -0500 Subject: Add missing case to unify. This gets hello world to codegen. --- src/comp/middle/ty.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 2bb65fe0..b9753474 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -968,6 +968,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) case (ty.ty_char) { ret struct_cmp(expected, actual); } case (ty.ty_str) { ret struct_cmp(expected, actual); } case (ty.ty_type) { ret struct_cmp(expected, actual); } + case (ty.ty_native) { ret struct_cmp(expected, actual); } case (ty.ty_tag(?expected_id)) { alt (actual.struct) { -- cgit v1.2.3 From 0ebfb8227c190609e80af3fb52b9813c4b282cc0 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 13 Feb 2011 00:49:04 -0500 Subject: Add support for unsigned binops. Closes #57 --- src/Makefile | 2 ++ src/comp/middle/trans.rs | 70 ++++++++++++++++++++++++++++--------- src/test/run-pass/arith-unsigned.rs | 24 +++++++++++++ 3 files changed, 80 insertions(+), 16 deletions(-) create mode 100644 src/test/run-pass/arith-unsigned.rs diff --git a/src/Makefile b/src/Makefile index d55a63c2..3457864c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -408,6 +408,7 @@ TASK_XFAILS := test/run-pass/task-comm-8.rs \ TEST_XFAILS_BOOT := $(TASK_XFAILS) \ $(NOMINAL_TAG_XFAILS) \ $(CONST_TAG_XFAILS) \ + test/run-pass/arith-unsigned.rs \ test/run-pass/child-outlives-parent.rs \ test/run-pass/clone-with-exterior.rs \ test/run-pass/constrained-type.rs \ @@ -450,6 +451,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ arith-0.rs \ arith-1.rs \ arith-2.rs \ + arith-unsigned.rs \ auto-instantiate.rs \ autoderef-full-lval.rs \ bind-exterior.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index bedfad97..c1a4aa6f 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1840,33 +1840,67 @@ fn trans_unary(@block_ctxt cx, ast.unop op, // FIXME: implement proper structural comparison. -fn trans_compare(@block_ctxt cx, ast.binop op, +fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t intype, ValueRef lhs, ValueRef rhs) -> ValueRef { auto cmp = lib.llvm.LLVMIntEQ; alt (op) { case (ast.eq) { cmp = lib.llvm.LLVMIntEQ; } case (ast.ne) { cmp = lib.llvm.LLVMIntNE; } - // FIXME (issue #57): switch by signedness. - case (ast.lt) { cmp = lib.llvm.LLVMIntSLT; } - case (ast.le) { cmp = lib.llvm.LLVMIntSLE; } - case (ast.ge) { cmp = lib.llvm.LLVMIntSGE; } - case (ast.gt) { cmp = lib.llvm.LLVMIntSGT; } + case (ast.lt) { + if (ty.type_is_signed(intype)) { + cmp = lib.llvm.LLVMIntSLT; + } else { + cmp = lib.llvm.LLVMIntULT; + } + } + case (ast.le) { + if (ty.type_is_signed(intype)) { + cmp = lib.llvm.LLVMIntSLE; + } else { + cmp = lib.llvm.LLVMIntULE; + } + } + case (ast.gt) { + if (ty.type_is_signed(intype)) { + cmp = lib.llvm.LLVMIntSGT; + } else { + cmp = lib.llvm.LLVMIntUGT; + } + } + case (ast.ge) { + if (ty.type_is_signed(intype)) { + cmp = lib.llvm.LLVMIntSGE; + } else { + cmp = lib.llvm.LLVMIntUGE; + } + } } ret cx.build.ICmp(cmp, lhs, rhs); } -fn trans_eager_binop(@block_ctxt cx, ast.binop op, +fn trans_eager_binop(@block_ctxt cx, ast.binop op, @ty.t intype, ValueRef lhs, ValueRef rhs) -> ValueRef { alt (op) { case (ast.add) { ret cx.build.Add(lhs, rhs); } case (ast.sub) { ret cx.build.Sub(lhs, rhs); } - // FIXME (issue #57): switch by signedness. case (ast.mul) { ret cx.build.Mul(lhs, rhs); } - case (ast.div) { ret cx.build.SDiv(lhs, rhs); } - case (ast.rem) { ret cx.build.SRem(lhs, rhs); } + case (ast.div) { + if (ty.type_is_signed(intype)) { + ret cx.build.SDiv(lhs, rhs); + } else { + ret cx.build.UDiv(lhs, rhs); + } + } + case (ast.rem) { + if (ty.type_is_signed(intype)) { + ret cx.build.SRem(lhs, rhs); + } else { + ret cx.build.URem(lhs, rhs); + } + } case (ast.bitor) { ret cx.build.Or(lhs, rhs); } case (ast.bitand) { ret cx.build.And(lhs, rhs); } @@ -1875,7 +1909,7 @@ fn trans_eager_binop(@block_ctxt cx, ast.binop op, case (ast.lsr) { ret cx.build.LShr(lhs, rhs); } case (ast.asr) { ret cx.build.AShr(lhs, rhs); } case (_) { - ret trans_compare(cx, op, lhs, rhs); + ret trans_compare(cx, op, intype, lhs, rhs); } } fail; @@ -1950,10 +1984,12 @@ fn trans_binary(@block_ctxt cx, ast.binop op, case (_) { // Remaining cases are eager: auto lhs = trans_expr(cx, a); - lhs = autoderef(lhs.bcx, lhs.val, ty.expr_ty(a)); + auto lhty = ty.expr_ty(a); + lhs = autoderef(lhs.bcx, lhs.val, lhty); auto rhs = trans_expr(lhs.bcx, b); - rhs = autoderef(rhs.bcx, rhs.val, ty.expr_ty(b)); - ret res(rhs.bcx, trans_eager_binop(rhs.bcx, op, + auto rhty = ty.expr_ty(b); + rhs = autoderef(rhs.bcx, rhs.val, rhty); + ret res(rhs.bcx, trans_eager_binop(rhs.bcx, op, lhty, lhs.val, rhs.val)); } } @@ -2142,7 +2178,8 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, case (ast.pat_lit(?lt, ?ann)) { auto lllit = trans_lit(cx.fcx.ccx, *lt, ann); - auto lleq = trans_compare(cx, ast.eq, llval, lllit); + auto lltype = ty.ann_to_type(ann); + auto lleq = trans_compare(cx, ast.eq, lltype, llval, lllit); auto matched_cx = new_sub_block_ctxt(cx, "matched_cx"); cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb); @@ -3035,7 +3072,8 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { auto lhs_val = load_scalar_or_boxed(lhs_res.res.bcx, lhs_res.res.val, t); auto rhs_res = trans_expr(lhs_res.res.bcx, src); - auto v = trans_eager_binop(rhs_res.bcx, op, lhs_val, rhs_res.val); + auto v = trans_eager_binop(rhs_res.bcx, op, t, + lhs_val, rhs_res.val); // FIXME: calculate copy init-ness in typestate. ret copy_ty(rhs_res.bcx, DROP_EXISTING, lhs_res.res.val, v, t); diff --git a/src/test/run-pass/arith-unsigned.rs b/src/test/run-pass/arith-unsigned.rs new file mode 100644 index 00000000..3fac3714 --- /dev/null +++ b/src/test/run-pass/arith-unsigned.rs @@ -0,0 +1,24 @@ +// Unsigned integer operations + +fn main() { + check (0u8 < 255u8); + check (0u8 <= 255u8); + check (255u8 > 0u8); + check (255u8 >= 0u8); + check (250u8 / 10u8 == 25u8); + check (255u8 % 10u8 == 5u8); + check (0u16 < 60000u16); + check (0u16 <= 60000u16); + check (60000u16 > 0u16); + check (60000u16 >= 0u16); + check (60000u16 / 10u16 == 6000u16); + check (60005u16 % 10u16 == 5u16); + check (0u32 < 4000000000u32); + check (0u32 <= 4000000000u32); + check (4000000000u32 > 0u32); + check (4000000000u32 >= 0u32); + check (4000000000u32 / 10u32 == 400000000u32); + check (4000000005u32 % 10u32 == 5u32); + + // 64-bit numbers have some flakiness yet. Not tested +} -- cgit v1.2.3 From 0043f99f8388ce0df316d7193a00b63d200c2a07 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 14 Feb 2011 13:36:20 -0800 Subject: Teach resolve about ty params on tags. --- src/comp/middle/resolve.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 8384906d..96be838c 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -353,6 +353,14 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] { } } } + case (ast.item_tag(_, _, ?ty_params, _)) { + for (ast.ty_param tp in ty_params) { + if (_str.eq(tp.ident, i)) { + auto t = ast.def_ty_arg(tp.id); + ret some(def_wrap_other(t)); + } + } + } case (ast.item_mod(_, ?m, _)) { ret check_mod(i, m); } -- cgit v1.2.3 From 6393a34e6e4cfc7638d698353659643e63549532 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 14 Feb 2011 14:14:28 -0800 Subject: Teach typeck about generic tags. --- src/comp/middle/typeck.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 97453436..748dd879 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1253,7 +1253,8 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } case (ast.def_variant(_, ?variant_id)) { check (fcx.ccx.item_types.contains_key(variant_id)); - t = fcx.ccx.item_types.get(variant_id); + t = generalize_ty(fcx.ccx, + fcx.ccx.item_types.get(variant_id)); } case (ast.def_binding(?id)) { check (fcx.locals.contains_key(id)); -- cgit v1.2.3 From 59bce06a967b3806c3d874b8956857f0f01287e1 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 14 Feb 2011 15:52:38 -0800 Subject: Expand expr_rec to take its optional trailing 'with' parameter. --- src/comp/front/ast.rs | 2 +- src/comp/front/parser.rs | 41 ++++++++++++++++++++++++++++++++--------- src/comp/middle/fold.rs | 21 +++++++++++++++------ src/comp/middle/trans.rs | 9 ++++++--- src/comp/middle/ty.rs | 2 +- src/comp/middle/typeck.rs | 18 ++++++++++++++---- 6 files changed, 69 insertions(+), 24 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 6aac7b50..3aec3226 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -146,7 +146,7 @@ type expr = spanned[expr_]; tag expr_ { expr_vec(vec[@expr], ann); expr_tup(vec[elt], ann); - expr_rec(vec[field], ann); + expr_rec(vec[field], option.t[@expr], ann); expr_call(@expr, vec[@expr], ann); expr_bind(@expr, vec[option.t[@expr]], ann); expr_binary(binop, @expr, @expr, ann); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 87bbe57f..2f037dfb 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -529,14 +529,37 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr { case (token.REC) { p.bump(); - auto pf = parse_field; - auto fs = - parse_seq[ast.field](token.LPAREN, - token.RPAREN, - some(token.COMMA), - pf, p); - hi = fs.span; - ex = ast.expr_rec(fs.node, ast.ann_none); + expect(p, token.LPAREN); + auto fields = vec(parse_field(p)); + + auto more = true; + auto base = none[@ast.expr]; + while (more) { + alt (p.peek()) { + case (token.RPAREN) { + hi = p.get_span(); + p.bump(); + more = false; + } + case (token.WITH) { + p.bump(); + base = some[@ast.expr](parse_expr(p)); + hi = p.get_span(); + expect(p, token.RPAREN); + more = false; + } + case (token.COMMA) { + p.bump(); + fields += parse_field(p); + } + case (?t) { + unexpected(p, t); + } + } + + } + + ex = ast.expr_rec(fields, base, ast.ann_none); } case (token.BIND) { @@ -1370,7 +1393,7 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool { alt (e.node) { case (ast.expr_vec(_,_)) { ret true; } case (ast.expr_tup(_,_)) { ret true; } - case (ast.expr_rec(_,_)) { ret true; } + case (ast.expr_rec(_,_,_)) { ret true; } case (ast.expr_call(_,_,_)) { ret true; } case (ast.expr_binary(_,_,_,_)) { ret true; } case (ast.expr_unary(_,_,_)) { ret true; } diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 5930ba75..4ba65a7b 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -75,7 +75,8 @@ type ast_fold[ENV] = vec[ast.elt] es, ann a) -> @expr) fold_expr_tup, (fn(&ENV e, &span sp, - vec[ast.field] fields, ann a) -> @expr) fold_expr_rec, + vec[ast.field] fields, + option.t[@expr] base, ann a) -> @expr) fold_expr_rec, (fn(&ENV e, &span sp, @expr f, vec[@expr] args, @@ -479,12 +480,19 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr { ret fld.fold_expr_tup(env_, e.span, elts, t); } - case (ast.expr_rec(?fs, ?t)) { + case (ast.expr_rec(?fs, ?base, ?t)) { let vec[ast.field] fields = vec(); + let option.t[@expr] b = none[@expr]; for (ast.field f in fs) { fields += fold_rec_field(env, fld, f); } - ret fld.fold_expr_rec(env_, e.span, fields, t); + alt (base) { + case (none[@ast.expr]) { } + case (some[@ast.expr](?eb)) { + b = some[@expr](fold_expr(env_, fld, eb)); + } + } + ret fld.fold_expr_rec(env_, e.span, fields, b, t); } case (ast.expr_call(?f, ?args, ?t)) { @@ -1011,8 +1019,9 @@ fn identity_fold_expr_tup[ENV](&ENV env, &span sp, } fn identity_fold_expr_rec[ENV](&ENV env, &span sp, - vec[ast.field] fields, ann a) -> @expr { - ret @respan(sp, ast.expr_rec(fields, a)); + vec[ast.field] fields, + option.t[@expr] base, ann a) -> @expr { + ret @respan(sp, ast.expr_rec(fields, base, a)); } fn identity_fold_expr_call[ENV](&ENV env, &span sp, @expr f, @@ -1358,7 +1367,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_expr_vec = bind identity_fold_expr_vec[ENV](_,_,_,_), fold_expr_tup = bind identity_fold_expr_tup[ENV](_,_,_,_), - fold_expr_rec = bind identity_fold_expr_rec[ENV](_,_,_,_), + fold_expr_rec = bind identity_fold_expr_rec[ENV](_,_,_,_,_), fold_expr_call = bind identity_fold_expr_call[ENV](_,_,_,_,_), fold_expr_bind = bind identity_fold_expr_bind[ENV](_,_,_,_,_), fold_expr_binary = bind identity_fold_expr_binary[ENV](_,_,_,_,_,_), diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c1a4aa6f..972683e9 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2984,7 +2984,10 @@ fn trans_vec(@block_ctxt cx, vec[@ast.expr] args, } fn trans_rec(@block_ctxt cx, vec[ast.field] fields, - &ast.ann ann) -> result { + option.t[@ast.expr] base, &ast.ann ann) -> result { + + // FIXME: handle presence of a nonempty base. + check (base == none[@ast.expr]); auto bcx = cx; auto t = node_ann_type(bcx.fcx.ccx, ann); @@ -3099,8 +3102,8 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { ret trans_tup(cx, args, ann); } - case (ast.expr_rec(?args, ?ann)) { - ret trans_rec(cx, args, ann); + case (ast.expr_rec(?args, ?base, ?ann)) { + ret trans_rec(cx, args, base, ann); } // lval cases fall through to trans_lval and then diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index b9753474..2083ef2b 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -667,7 +667,7 @@ 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_rec(_, _, ?ann)) { ret ann_to_type(ann); } case (ast.expr_bind(_, _, ?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); } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 748dd879..19e4a9b2 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -910,7 +910,12 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, } e_1 = ast.expr_tup(elts_1, ast.ann_type(t)); } - case (ast.expr_rec(?fields_0, ?ann)) { + case (ast.expr_rec(?fields_0, ?base_0, ?ann)) { + + // FIXME: handle presence of a nonempty base. + check (base_0 == none[@ast.expr]); + auto base_1 = base_0; + auto t = demand(fcx, e.span, expected, ann_to_type(ann)); let vec[ast.field] fields_1 = vec(); alt (t.struct) { @@ -931,7 +936,7 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, fail; } } - e_1 = ast.expr_rec(fields_1, ast.ann_type(t)); + e_1 = ast.expr_rec(fields_1, base_1, ast.ann_type(t)); } case (ast.expr_bind(?sube, ?es, ?ann)) { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); @@ -1610,7 +1615,12 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { ast.expr_tup(elts_1, ann)); } - case (ast.expr_rec(?fields, _)) { + case (ast.expr_rec(?fields, ?base, _)) { + + // FIXME: handle presence of a nonempty base. + check (base == none[@ast.expr]); + auto base_1 = base; + let vec[ast.field] fields_1 = vec(); let vec[field] fields_t = vec(); @@ -1626,7 +1636,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { 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)); + ast.expr_rec(fields_1, base_1, ann)); } case (ast.expr_field(?base, ?field, _)) { -- cgit v1.2.3 From 890d027b653edd1722b186a5723944e622736313 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 14 Feb 2011 16:33:25 -0800 Subject: Add parse support for expr_ext. --- src/comp/front/ast.rs | 1 + src/comp/front/parser.rs | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 3aec3226..820bbbfa 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -164,6 +164,7 @@ tag expr_ { expr_field(@expr, ident, ann); expr_index(@expr, @expr, ann); expr_path(path, option.t[def], ann); + expr_ext(vec[@expr], option.t[@expr], ann); } type lit = spanned[lit_]; diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 2f037dfb..e5ea673a 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -586,6 +586,17 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr { ex = ast.expr_bind(e, es.node, ast.ann_none); } + case (token.POUND) { + p.bump(); + auto pf = parse_expr; + auto es = parse_seq[@ast.expr](token.LPAREN, + token.RPAREN, + some(token.COMMA), + pf, p); + hi = es.span; + ex = ast.expr_ext(es.node, none[@ast.expr], ast.ann_none); + } + case (_) { auto lit = parse_lit(p); hi = lit.span; -- cgit v1.2.3 From 84dd64b6cf047444e03b94e63e00508ecc4046aa Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 14 Feb 2011 16:33:51 -0800 Subject: Switch ast.is_call_expr check in trans to non-typestate form. --- src/comp/middle/trans.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 972683e9..1bf278a7 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3215,7 +3215,7 @@ fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result { fn trans_be(@block_ctxt cx, @ast.expr e) -> result { // FIXME: This should be a typestate precondition - check ast.is_call_expr(e); + check (ast.is_call_expr(e)); // FIXME: Turn this into a real tail call once // calling convention issues are settled ret trans_ret(cx, some(e)); -- cgit v1.2.3 From c7e3f951e6942443e497e0394261eae537b80c5c Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 14 Feb 2011 16:34:12 -0800 Subject: Disable TRACK_ALLOCATIONS by default, it's a bit heavy-handed. --- src/rt/memory_region.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rt/memory_region.cpp b/src/rt/memory_region.cpp index fb19620f..7ede3761 100644 --- a/src/rt/memory_region.cpp +++ b/src/rt/memory_region.cpp @@ -1,7 +1,7 @@ #include "rust_internal.h" #include "memory_region.h" -#define TRACK_ALLOCATIONS +// #define TRACK_ALLOCATIONS memory_region::memory_region(rust_srv *srv, bool synchronized) : _srv(srv), _parent(NULL), _live_allocations(0), -- cgit v1.2.3 From 88cb9663639e915d2b69cef7ec514043ed39e5f4 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 14 Feb 2011 16:35:08 -0800 Subject: Adjust commented-out diagnostic log statement in parser.rs. --- src/comp/front/parser.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index e5ea673a..1296113a 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -41,11 +41,12 @@ impure fn new_parser(session.session sess, lexer.reader rdr) { fn peek() -> token.token { - // log token.to_str(tok); ret tok; } impure fn bump() { + // log rdr.get_filename() + // + ":" + common.istr(lo.line as int); tok = lexer.next_token(rdr); lo = rdr.get_mark_pos(); hi = rdr.get_curr_pos(); -- cgit v1.2.3 From f1f33abdeba156523d6db1752bbff75dc4088724 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 14 Feb 2011 17:46:28 -0800 Subject: Move all non-decl/non-expr stmts to exprs. --- src/comp/front/ast.rs | 10 ++-- src/comp/front/parser.rs | 116 +++++++++++++++++++-------------------- src/comp/middle/fold.rs | 136 ++++++++++++++++++++++++---------------------- src/comp/middle/trans.rs | 40 +++++++------- src/comp/middle/ty.rs | 6 ++ src/comp/middle/typeck.rs | 97 +++++++++++++++++---------------- 6 files changed, 212 insertions(+), 193 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 820bbbfa..53ffdd87 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -116,11 +116,6 @@ tag mode { type stmt = spanned[stmt_]; tag stmt_ { stmt_decl(@decl); - stmt_ret(option.t[@expr]); - stmt_be(@expr); - stmt_log(@expr); - stmt_check_expr(@expr); - stmt_fail; stmt_expr(@expr); } @@ -165,6 +160,11 @@ tag expr_ { expr_index(@expr, @expr, ann); expr_path(path, option.t[def], ann); expr_ext(vec[@expr], option.t[@expr], ann); + expr_fail; + expr_ret(option.t[@expr]); + expr_be(@expr); + expr_log(@expr); + expr_check_expr(@expr); } type lit = spanned[lit_]; diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 1296113a..5ffaca19 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -598,6 +598,59 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr { ex = ast.expr_ext(es.node, none[@ast.expr], ast.ann_none); } + case (token.FAIL) { + p.bump(); + ex = ast.expr_fail; + } + + case (token.LOG) { + p.bump(); + auto e = parse_expr(p); + auto hi = e.span; + ex = ast.expr_log(e); + } + + case (token.CHECK) { + p.bump(); + alt (p.peek()) { + case (token.LPAREN) { + auto e = parse_expr(p); + auto hi = e.span; + ex = ast.expr_check_expr(e); + } + case (_) { + p.get_session().unimpl("constraint-check stmt"); + } + } + } + + case (token.RET) { + p.bump(); + alt (p.peek()) { + case (token.SEMI) { + ex = ast.expr_ret(none[@ast.expr]); + } + case (_) { + auto e = parse_expr(p); + hi = e.span; + ex = ast.expr_ret(some[@ast.expr](e)); + } + } + } + + case (token.BE) { + p.bump(); + auto e = parse_expr(p); + // FIXME: Is this the right place for this check? + if /*check*/ (ast.is_call_expr(e)) { + hi = e.span; + ex = ast.expr_be(e); + } + else { + p.err("Non-call expression in tail call"); + } + } + case (_) { auto lit = parse_lit(p); hi = lit.span; @@ -1203,59 +1256,6 @@ impure fn parse_stmt(parser p) -> @ast.stmt { auto lo = p.get_span(); alt (p.peek()) { - case (token.LOG) { - p.bump(); - auto e = parse_expr(p); - auto hi = p.get_span(); - ret @spanned(lo, hi, ast.stmt_log(e)); - } - - case (token.CHECK) { - p.bump(); - alt (p.peek()) { - case (token.LPAREN) { - auto e = parse_expr(p); - auto hi = p.get_span(); - ret @spanned(lo, hi, ast.stmt_check_expr(e)); - } - case (_) { - p.get_session().unimpl("constraint-check stmt"); - } - } - } - - case (token.FAIL) { - p.bump(); - ret @spanned(lo, p.get_span(), ast.stmt_fail); - } - - case (token.RET) { - p.bump(); - alt (p.peek()) { - case (token.SEMI) { - ret @spanned(lo, p.get_span(), - ast.stmt_ret(none[@ast.expr])); - } - case (_) { - auto e = parse_expr(p); - ret @spanned(lo, e.span, - ast.stmt_ret(some[@ast.expr](e))); - } - } - } - - case (token.BE) { - p.bump(); - auto e = parse_expr(p); - // FIXME: Is this the right place for this check? - if /*check*/ (ast.is_call_expr(e)) { - ret @spanned(lo, e.span, ast.stmt_be(e)); - } - else { - p.err("Non-call expression in tail call"); - } - } - case (token.LET) { auto decl = parse_let(p); auto hi = p.get_span(); @@ -1396,11 +1396,6 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool { case (ast.decl_item(_)) { ret false; } } } - case (ast.stmt_ret(_)) { ret true; } - case (ast.stmt_be(_)) { ret true; } - case (ast.stmt_log(_)) { ret true; } - case (ast.stmt_check_expr(_)) { ret true; } - case (ast.stmt_fail) { ret true; } case (ast.stmt_expr(?e)) { alt (e.node) { case (ast.expr_vec(_,_)) { ret true; } @@ -1423,6 +1418,11 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool { case (ast.expr_field(_,_,_)) { ret true; } case (ast.expr_index(_,_,_)) { ret true; } case (ast.expr_path(_,_,_)) { ret true; } + case (ast.expr_fail) { ret true; } + case (ast.expr_ret(_)) { ret true; } + case (ast.expr_be(_)) { ret true; } + case (ast.expr_log(_)) { ret true; } + case (ast.expr_check_expr(_)) { ret true; } } } } diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 4ba65a7b..4e8ea317 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -149,6 +149,20 @@ type ast_fold[ENV] = &option.t[def] d, ann a) -> @expr) fold_expr_path, + (fn(&ENV e, &span sp) -> @expr) fold_expr_fail, + + (fn(&ENV e, &span sp, + &option.t[@expr] rv) -> @expr) fold_expr_ret, + + (fn(&ENV e, &span sp, + @expr e) -> @expr) fold_expr_be, + + (fn(&ENV e, &span sp, + @expr e) -> @expr) fold_expr_log, + + (fn(&ENV e, &span sp, + @expr e) -> @expr) fold_expr_check_expr, + // Decl folds. (fn(&ENV e, &span sp, @ast.local local) -> @decl) fold_decl_local, @@ -177,18 +191,6 @@ type ast_fold[ENV] = (fn(&ENV e, &span sp, @decl decl) -> @stmt) fold_stmt_decl, - (fn(&ENV e, &span sp, - &option.t[@expr] rv) -> @stmt) fold_stmt_ret, - - (fn(&ENV e, &span sp, - @expr e) -> @stmt) fold_stmt_be, - - (fn(&ENV e, &span sp, - @expr e) -> @stmt) fold_stmt_log, - - (fn(&ENV e, &span sp, - @expr e) -> @stmt) fold_stmt_check_expr, - (fn(&ENV e, &span sp, @expr e) -> @stmt) fold_stmt_expr, @@ -622,6 +624,37 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr { auto p_ = fold_path(env_, fld, p); ret fld.fold_expr_path(env_, e.span, p_, r, t); } + + case (ast.expr_fail) { + ret fld.fold_expr_fail(env_, e.span); + } + + case (ast.expr_ret(?oe)) { + auto oee = none[@expr]; + alt (oe) { + case (some[@expr](?x)) { + oee = some(fold_expr(env_, fld, x)); + } + case (_) { /* fall through */ } + } + ret fld.fold_expr_ret(env_, e.span, oee); + } + + case (ast.expr_be(?x)) { + auto ee = fold_expr(env_, fld, x); + ret fld.fold_expr_be(env_, e.span, ee); + } + + case (ast.expr_log(?x)) { + auto ee = fold_expr(env_, fld, x); + ret fld.fold_expr_log(env_, e.span, ee); + } + + case (ast.expr_check_expr(?x)) { + auto ee = fold_expr(env_, fld, x); + ret fld.fold_expr_check_expr(env_, e.span, ee); + } + } ret e; @@ -642,36 +675,6 @@ fn fold_stmt[ENV](&ENV env, ast_fold[ENV] fld, &@stmt s) -> @stmt { ret fld.fold_stmt_decl(env_, s.span, dd); } - case (ast.stmt_ret(?oe)) { - auto oee = none[@expr]; - alt (oe) { - case (some[@expr](?e)) { - oee = some(fold_expr(env_, fld, e)); - } - case (_) { /* fall through */ } - } - ret fld.fold_stmt_ret(env_, s.span, oee); - } - - case (ast.stmt_be(?e)) { - auto ee = fold_expr(env_, fld, e); - ret fld.fold_stmt_be(env_, s.span, ee); - } - - case (ast.stmt_log(?e)) { - auto ee = fold_expr(env_, fld, e); - ret fld.fold_stmt_log(env_, s.span, ee); - } - - case (ast.stmt_check_expr(?e)) { - auto ee = fold_expr(env_, fld, e); - ret fld.fold_stmt_check_expr(env_, s.span, ee); - } - - case (ast.stmt_fail) { - ret s; - } - case (ast.stmt_expr(?e)) { auto ee = fold_expr(env_, fld, e); ret fld.fold_stmt_expr(env_, s.span, ee); @@ -1118,6 +1121,27 @@ fn identity_fold_expr_path[ENV](&ENV env, &span sp, ret @respan(sp, ast.expr_path(p, d, a)); } +fn identity_fold_expr_fail[ENV](&ENV env, &span sp) -> @expr { + ret @respan(sp, ast.expr_fail); +} + +fn identity_fold_expr_ret[ENV](&ENV env, &span sp, + &option.t[@expr] rv) -> @expr { + ret @respan(sp, ast.expr_ret(rv)); +} + +fn identity_fold_expr_be[ENV](&ENV env, &span sp, @expr x) -> @expr { + ret @respan(sp, ast.expr_be(x)); +} + +fn identity_fold_expr_log[ENV](&ENV e, &span sp, @expr x) -> @expr { + ret @respan(sp, ast.expr_log(x)); +} + +fn identity_fold_expr_check_expr[ENV](&ENV e, &span sp, @expr x) -> @expr { + ret @respan(sp, ast.expr_check_expr(x)); +} + // Decl identities. @@ -1158,23 +1182,6 @@ fn identity_fold_stmt_decl[ENV](&ENV env, &span sp, @decl d) -> @stmt { ret @respan(sp, ast.stmt_decl(d)); } -fn identity_fold_stmt_ret[ENV](&ENV env, &span sp, - &option.t[@expr] rv) -> @stmt { - ret @respan(sp, ast.stmt_ret(rv)); -} - -fn identity_fold_stmt_be[ENV](&ENV env, &span sp, @expr x) -> @stmt { - ret @respan(sp, ast.stmt_be(x)); -} - -fn identity_fold_stmt_log[ENV](&ENV e, &span sp, @expr x) -> @stmt { - ret @respan(sp, ast.stmt_log(x)); -} - -fn identity_fold_stmt_check_expr[ENV](&ENV e, &span sp, @expr x) -> @stmt { - ret @respan(sp, ast.stmt_check_expr(x)); -} - fn identity_fold_stmt_expr[ENV](&ENV e, &span sp, @expr x) -> @stmt { ret @respan(sp, ast.stmt_expr(x)); } @@ -1387,6 +1394,12 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_expr_field = bind identity_fold_expr_field[ENV](_,_,_,_,_), fold_expr_index = bind identity_fold_expr_index[ENV](_,_,_,_,_), fold_expr_path = bind identity_fold_expr_path[ENV](_,_,_,_,_), + fold_expr_fail = bind identity_fold_expr_fail[ENV](_,_), + fold_expr_ret = bind identity_fold_expr_ret[ENV](_,_,_), + fold_expr_be = bind identity_fold_expr_be[ENV](_,_,_), + fold_expr_log = bind identity_fold_expr_log[ENV](_,_,_), + fold_expr_check_expr + = bind identity_fold_expr_check_expr[ENV](_,_,_), fold_decl_local = bind identity_fold_decl_local[ENV](_,_,_), fold_decl_item = bind identity_fold_decl_item[ENV](_,_,_), @@ -1397,11 +1410,6 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_pat_tag = bind identity_fold_pat_tag[ENV](_,_,_,_,_,_), fold_stmt_decl = bind identity_fold_stmt_decl[ENV](_,_,_), - fold_stmt_ret = bind identity_fold_stmt_ret[ENV](_,_,_), - fold_stmt_be = bind identity_fold_stmt_be[ENV](_,_,_), - fold_stmt_log = bind identity_fold_stmt_log[ENV](_,_,_), - fold_stmt_check_expr - = bind identity_fold_stmt_check_expr[ENV](_,_,_), fold_stmt_expr = bind identity_fold_stmt_expr[ENV](_,_,_), fold_item_const= bind identity_fold_item_const[ENV](_,_,_,_,_,_,_), diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 1bf278a7..e140ddcc 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3106,6 +3106,26 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { ret trans_rec(cx, args, base, ann); } + case (ast.expr_fail) { + ret trans_fail(cx, e.span, "explicit failure"); + } + + case (ast.expr_log(?a)) { + ret trans_log(cx, a); + } + + case (ast.expr_check_expr(?a)) { + ret trans_check_expr(cx, a); + } + + case (ast.expr_ret(?e)) { + ret trans_ret(cx, e); + } + + case (ast.expr_be(?e)) { + ret trans_be(cx, e); + } + // lval cases fall through to trans_lval and then // possibly load the result (if it's non-structural). @@ -3255,26 +3275,6 @@ fn init_local(@block_ctxt cx, @ast.local local) -> result { fn trans_stmt(@block_ctxt cx, &ast.stmt s) -> result { auto bcx = cx; alt (s.node) { - case (ast.stmt_log(?a)) { - bcx = trans_log(cx, a).bcx; - } - - case (ast.stmt_check_expr(?a)) { - bcx = trans_check_expr(cx, a).bcx; - } - - case (ast.stmt_fail) { - bcx = trans_fail(cx, s.span, "explicit failure").bcx; - } - - case (ast.stmt_ret(?e)) { - bcx = trans_ret(cx, e).bcx; - } - - case (ast.stmt_be(?e)) { - bcx = trans_be(cx, e).bcx; - } - case (ast.stmt_expr(?e)) { bcx = trans_expr(cx, e).bcx; } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 2083ef2b..58529d0d 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -686,6 +686,12 @@ fn expr_ty(@ast.expr expr) -> @t { case (ast.expr_field(_, _, ?ann)) { ret ann_to_type(ann); } case (ast.expr_index(_, _, ?ann)) { ret ann_to_type(ann); } case (ast.expr_path(_, _, ?ann)) { ret ann_to_type(ann); } + + case (ast.expr_fail) { ret plain_ty(ty_nil); } + case (ast.expr_log(_)) { ret plain_ty(ty_nil); } + case (ast.expr_check_expr(_)) { ret plain_ty(ty_nil); } + case (ast.expr_ret(_)) { ret plain_ty(ty_nil); } + case (ast.expr_be(_)) { ret plain_ty(ty_nil); } } fail; } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 19e4a9b2..d0043c43 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1037,6 +1037,11 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, ann_to_type(ann), adk); e_1 = ast.expr_path(pth, d, ast.ann_type(t)); } + case (ast.expr_fail) { e_1 = e.node; } + case (ast.expr_log(_)) { e_1 = e.node; } + case (ast.expr_ret(_)) { e_1 = e.node; } + case (ast.expr_be(_)) { e_1 = e.node; } + case (ast.expr_check_expr(_)) { e_1 = e.node; } } ret @fold.respan[ast.expr_](e.span, e_1); @@ -1287,6 +1292,52 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { ast.ann_type(t))); } + case (ast.expr_fail) { + ret expr; + } + + case (ast.expr_ret(?expr_opt)) { + alt (expr_opt) { + case (none[@ast.expr]) { + 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"); + } + + ret expr; + } + + case (some[@ast.expr](?e)) { + auto expr_0 = check_expr(fcx, e); + auto expr_1 = demand_expr(fcx, fcx.ret_ty, expr_0); + ret @fold.respan[ast.expr_](expr.span, + ast.expr_ret(some(expr_1))); + } + } + } + + case (ast.expr_be(?e)) { + /* FIXME: prove instead of check */ + check ast.is_call_expr(e); + auto expr_0 = check_expr(fcx, e); + auto expr_1 = demand_expr(fcx, fcx.ret_ty, expr_0); + ret @fold.respan[ast.expr_](expr.span, + ast.expr_be(expr_1)); + } + + case (ast.expr_log(?e)) { + auto expr_t = check_expr(fcx, e); + ret @fold.respan[ast.expr_](expr.span, ast.expr_log(expr_t)); + } + + case (ast.expr_check_expr(?e)) { + auto expr_t = check_expr(fcx, e); + demand(fcx, expr.span, plain_ty(ty.ty_bool), expr_ty(expr_t)); + ret @fold.respan[ast.expr_](expr.span, + ast.expr_check_expr(expr_t)); + } + case (ast.expr_assign(?lhs, ?rhs, _)) { auto lhs_0 = check_expr(fcx, lhs); auto rhs_0 = check_expr(fcx, rhs); @@ -1806,52 +1857,6 @@ fn check_stmt(&@fn_ctxt fcx, &@ast.stmt stmt) -> @ast.stmt { ret stmt; } - case (ast.stmt_ret(?expr_opt)) { - alt (expr_opt) { - case (none[@ast.expr]) { - 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"); - } - - ret stmt; - } - - case (some[@ast.expr](?expr)) { - auto expr_0 = check_expr(fcx, expr); - auto expr_1 = demand_expr(fcx, fcx.ret_ty, expr_0); - ret @fold.respan[ast.stmt_](stmt.span, - ast.stmt_ret(some(expr_1))); - } - } - } - - case (ast.stmt_be(?expr)) { - /* FIXME: prove instead of check */ - check ast.is_call_expr(expr); - auto expr_0 = check_expr(fcx, expr); - auto expr_1 = demand_expr(fcx, fcx.ret_ty, expr_0); - ret @fold.respan[ast.stmt_](stmt.span, - ast.stmt_be(expr_1)); - } - - case (ast.stmt_log(?expr)) { - auto expr_t = check_expr(fcx, expr); - ret @fold.respan[ast.stmt_](stmt.span, ast.stmt_log(expr_t)); - } - - case (ast.stmt_check_expr(?expr)) { - auto expr_t = check_expr(fcx, expr); - 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)); - } - - case (ast.stmt_fail) { - ret stmt; - } - case (ast.stmt_expr(?expr)) { auto expr_t = check_expr(fcx, expr); ret @fold.respan[ast.stmt_](stmt.span, ast.stmt_expr(expr_t)); -- cgit v1.2.3 From 15a01f5c3691a152793d8933a7be9d16a0fc7030 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 14 Feb 2011 17:58:32 -0800 Subject: Add basic front-end support for expr_put. --- src/comp/front/ast.rs | 1 + src/comp/front/parser.rs | 15 +++++++++++++++ src/comp/middle/fold.rs | 20 ++++++++++++++++++++ src/comp/middle/trans.rs | 9 +++++++++ src/comp/middle/ty.rs | 1 + src/comp/middle/typeck.rs | 22 ++++++++++++++++++++++ 6 files changed, 68 insertions(+) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 53ffdd87..cb2df2a5 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -162,6 +162,7 @@ tag expr_ { expr_ext(vec[@expr], option.t[@expr], ann); expr_fail; expr_ret(option.t[@expr]); + expr_put(option.t[@expr]); expr_be(@expr); expr_log(@expr); expr_check_expr(@expr); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 5ffaca19..a779d013 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -638,6 +638,20 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr { } } + case (token.PUT) { + p.bump(); + alt (p.peek()) { + case (token.SEMI) { + ex = ast.expr_put(none[@ast.expr]); + } + case (_) { + auto e = parse_expr(p); + hi = e.span; + ex = ast.expr_put(some[@ast.expr](e)); + } + } + } + case (token.BE) { p.bump(); auto e = parse_expr(p); @@ -1420,6 +1434,7 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool { case (ast.expr_path(_,_,_)) { ret true; } case (ast.expr_fail) { ret true; } case (ast.expr_ret(_)) { ret true; } + case (ast.expr_put(_)) { ret true; } case (ast.expr_be(_)) { ret true; } case (ast.expr_log(_)) { ret true; } case (ast.expr_check_expr(_)) { ret true; } diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 4e8ea317..4d3c2e2d 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -154,6 +154,9 @@ type ast_fold[ENV] = (fn(&ENV e, &span sp, &option.t[@expr] rv) -> @expr) fold_expr_ret, + (fn(&ENV e, &span sp, + &option.t[@expr] rv) -> @expr) fold_expr_put, + (fn(&ENV e, &span sp, @expr e) -> @expr) fold_expr_be, @@ -640,6 +643,17 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr { ret fld.fold_expr_ret(env_, e.span, oee); } + case (ast.expr_put(?oe)) { + auto oee = none[@expr]; + alt (oe) { + case (some[@expr](?x)) { + oee = some(fold_expr(env_, fld, x)); + } + case (_) { /* fall through */ } + } + ret fld.fold_expr_put(env_, e.span, oee); + } + case (ast.expr_be(?x)) { auto ee = fold_expr(env_, fld, x); ret fld.fold_expr_be(env_, e.span, ee); @@ -1130,6 +1144,11 @@ fn identity_fold_expr_ret[ENV](&ENV env, &span sp, ret @respan(sp, ast.expr_ret(rv)); } +fn identity_fold_expr_put[ENV](&ENV env, &span sp, + &option.t[@expr] rv) -> @expr { + ret @respan(sp, ast.expr_put(rv)); +} + fn identity_fold_expr_be[ENV](&ENV env, &span sp, @expr x) -> @expr { ret @respan(sp, ast.expr_be(x)); } @@ -1396,6 +1415,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_expr_path = bind identity_fold_expr_path[ENV](_,_,_,_,_), fold_expr_fail = bind identity_fold_expr_fail[ENV](_,_), fold_expr_ret = bind identity_fold_expr_ret[ENV](_,_,_), + fold_expr_put = bind identity_fold_expr_put[ENV](_,_,_), fold_expr_be = bind identity_fold_expr_be[ENV](_,_,_), fold_expr_log = bind identity_fold_expr_log[ENV](_,_,_), fold_expr_check_expr diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index e140ddcc..c8f21dff 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3122,6 +3122,10 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { ret trans_ret(cx, e); } + case (ast.expr_ret(?e)) { + ret trans_put(cx, e); + } + case (ast.expr_be(?e)) { ret trans_be(cx, e); } @@ -3199,6 +3203,11 @@ fn trans_fail(@block_ctxt cx, common.span sp, str fail_str) -> result { ret trans_upcall(cx, "upcall_fail", args); } +fn trans_put(@block_ctxt cx, &option.t[@ast.expr] e) -> result { + cx.fcx.ccx.sess.unimpl("put expr"); + fail; +} + fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result { auto bcx = cx; auto val = C_nil(); diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 58529d0d..f9b2bd9d 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -691,6 +691,7 @@ fn expr_ty(@ast.expr expr) -> @t { case (ast.expr_log(_)) { ret plain_ty(ty_nil); } case (ast.expr_check_expr(_)) { ret plain_ty(ty_nil); } case (ast.expr_ret(_)) { ret plain_ty(ty_nil); } + case (ast.expr_put(_)) { ret plain_ty(ty_nil); } case (ast.expr_be(_)) { ret plain_ty(ty_nil); } } fail; diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index d0043c43..5109adb2 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1040,6 +1040,7 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, case (ast.expr_fail) { e_1 = e.node; } case (ast.expr_log(_)) { e_1 = e.node; } case (ast.expr_ret(_)) { e_1 = e.node; } + case (ast.expr_put(_)) { e_1 = e.node; } case (ast.expr_be(_)) { e_1 = e.node; } case (ast.expr_check_expr(_)) { e_1 = e.node; } } @@ -1317,6 +1318,27 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } } + case (ast.expr_put(?expr_opt)) { + alt (expr_opt) { + case (none[@ast.expr]) { + auto nil = plain_ty(ty.ty_nil); + if (!are_compatible(fcx, fcx.ret_ty, nil)) { + fcx.ccx.sess.err("put; in function " + + "putting non-nil"); + } + + ret expr; + } + + case (some[@ast.expr](?e)) { + auto expr_0 = check_expr(fcx, e); + auto expr_1 = demand_expr(fcx, fcx.ret_ty, expr_0); + ret @fold.respan[ast.expr_](expr.span, + ast.expr_put(some(expr_1))); + } + } + } + case (ast.expr_be(?e)) { /* FIXME: prove instead of check */ check ast.is_call_expr(e); -- cgit v1.2.3 From 4a72a23171d87fb5a0f9b7ad039944856b93bf0f Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 14 Feb 2011 18:17:31 -0800 Subject: Add basic front-end support for 'for each' loops. --- src/comp/front/ast.rs | 1 + src/comp/front/parser.rs | 17 ++++++++++++++++- src/comp/middle/fold.rs | 19 +++++++++++++++++++ src/comp/middle/resolve.rs | 3 +++ src/comp/middle/trans.rs | 13 +++++++++++++ src/comp/middle/ty.rs | 2 ++ src/comp/middle/typeck.rs | 15 +++++++++++++++ 7 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index cb2df2a5..9e43d349 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -151,6 +151,7 @@ tag expr_ { expr_if(@expr, block, vec[tup(@expr, block)], option.t[block], ann); expr_while(@expr, block, ann); expr_for(@decl, @expr, block, ann); + expr_for_each(@decl, @expr, block, ann); expr_do_while(block, @expr, ann); expr_alt(@expr, vec[arm], ann); expr_block(block, ann); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index a779d013..ddadc789 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1049,8 +1049,14 @@ impure fn parse_head_local(parser p) -> @ast.decl { impure fn parse_for_expr(parser p) -> @ast.expr { auto lo = p.get_span(); auto hi = lo; + auto is_each = false; expect(p, token.FOR); + if (p.peek() == token.EACH) { + is_each = true; + p.bump(); + } + expect (p, token.LPAREN); auto decl = parse_head_local(p); @@ -1060,9 +1066,16 @@ impure fn parse_for_expr(parser p) -> @ast.expr { expect(p, token.RPAREN); auto body = parse_block(p); hi = body.span; - ret @spanned(lo, hi, ast.expr_for(decl, seq, body, ast.ann_none)); + if (is_each) { + ret @spanned(lo, hi, ast.expr_for_each(decl, seq, body, + ast.ann_none)); + } else { + ret @spanned(lo, hi, ast.expr_for(decl, seq, body, + ast.ann_none)); + } } + impure fn parse_while_expr(parser p) -> @ast.expr { auto lo = p.get_span(); auto hi = lo; @@ -1422,6 +1435,8 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool { case (ast.expr_cast(_,_,_)) { ret true; } case (ast.expr_if(_,_,_,_,_)) { ret false; } case (ast.expr_for(_,_,_,_)) { ret false; } + case (ast.expr_for_each(_,_,_,_)) + { ret false; } case (ast.expr_while(_,_,_)) { ret false; } case (ast.expr_do_while(_,_,_)) { ret false; } case (ast.expr_alt(_,_,_)) { ret false; } diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 4d3c2e2d..3cafa961 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -112,6 +112,10 @@ type ast_fold[ENV] = @decl decl, @expr seq, &block body, ann a) -> @expr) fold_expr_for, + (fn(&ENV e, &span sp, + @decl decl, @expr seq, &block body, + ann a) -> @expr) fold_expr_for_each, + (fn(&ENV e, &span sp, @expr cond, &block body, ann a) -> @expr) fold_expr_while, @@ -574,6 +578,13 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr { ret fld.fold_expr_for(env_, e.span, ddecl, sseq, bbody, t); } + case (ast.expr_for_each(?decl, ?seq, ?body, ?t)) { + auto ddecl = fold_decl(env_, fld, decl); + auto sseq = fold_expr(env_, fld, seq); + auto bbody = fold_block(env_, fld, body); + ret fld.fold_expr_for_each(env_, e.span, ddecl, sseq, bbody, t); + } + case (ast.expr_while(?cnd, ?body, ?t)) { auto ccnd = fold_expr(env_, fld, cnd); auto bbody = fold_block(env_, fld, body); @@ -1087,6 +1098,12 @@ fn identity_fold_expr_for[ENV](&ENV env, &span sp, ret @respan(sp, ast.expr_for(d, seq, body, a)); } +fn identity_fold_expr_for_each[ENV](&ENV env, &span sp, + @decl d, @expr seq, + &block body, ann a) -> @expr { + ret @respan(sp, ast.expr_for_each(d, seq, body, a)); +} + fn identity_fold_expr_while[ENV](&ENV env, &span sp, @expr cond, &block body, ann a) -> @expr { ret @respan(sp, ast.expr_while(cond, body, a)); @@ -1402,6 +1419,8 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_expr_cast = bind identity_fold_expr_cast[ENV](_,_,_,_,_), fold_expr_if = bind identity_fold_expr_if[ENV](_,_,_,_,_,_,_), fold_expr_for = bind identity_fold_expr_for[ENV](_,_,_,_,_,_), + fold_expr_for_each + = bind identity_fold_expr_for_each[ENV](_,_,_,_,_,_), fold_expr_while = bind identity_fold_expr_while[ENV](_,_,_,_,_), fold_expr_do_while = bind identity_fold_expr_do_while[ENV](_,_,_,_,_), diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 96be838c..d4ad907e 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -565,6 +565,9 @@ fn update_env_for_expr(&env e, @ast.expr x) -> env { case (ast.expr_for(?d, _, _, _)) { ret rec(scopes = cons[scope](scope_loop(d), @e.scopes) with e); } + case (ast.expr_for_each(?d, _, _, _)) { + ret rec(scopes = cons[scope](scope_loop(d), @e.scopes) with e); + } case (_) { } } ret e; diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c8f21dff..c4e5c9c4 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2116,6 +2116,15 @@ fn trans_for(@block_ctxt cx, bind inner(_, local, _, _, body)); } +fn trans_for_each(@block_ctxt cx, + @ast.decl decl, + @ast.expr seq, + &ast.block body) -> result { + cx.fcx.ccx.sess.unimpl("for each loop"); + fail; +} + + fn trans_while(@block_ctxt cx, @ast.expr cond, &ast.block body) -> result { @@ -3035,6 +3044,10 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { ret trans_for(cx, decl, seq, body); } + case (ast.expr_for_each(?decl, ?seq, ?body, _)) { + ret trans_for_each(cx, decl, seq, body); + } + case (ast.expr_while(?cond, ?body, _)) { ret trans_while(cx, cond, body); } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index f9b2bd9d..499ed74d 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -676,6 +676,8 @@ fn expr_ty(@ast.expr expr) -> @t { case (ast.expr_cast(_, _, ?ann)) { ret ann_to_type(ann); } case (ast.expr_if(_, _, _, _, ?ann)) { ret ann_to_type(ann); } case (ast.expr_for(_, _, _, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_for_each(_, _, _, ?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); } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 5109adb2..a062f79d 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -995,6 +995,10 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, auto t = demand(fcx, e.span, expected, ann_to_type(ann)); e_1 = ast.expr_for(decl, seq, bloc, ast.ann_type(t)); } + case (ast.expr_for_each(?decl, ?seq, ?bloc, ?ann)) { + auto t = demand(fcx, e.span, expected, ann_to_type(ann)); + e_1 = ast.expr_for_each(decl, seq, bloc, ast.ann_type(t)); + } case (ast.expr_while(?cond, ?bloc, ?ann)) { auto t = demand(fcx, e.span, expected, ann_to_type(ann)); e_1 = ast.expr_while(cond, bloc, ast.ann_type(t)); @@ -1448,6 +1452,17 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { body_1, ann)); } + case (ast.expr_for_each(?decl, ?seq, ?body, _)) { + auto decl_1 = check_decl_local(fcx, decl); + auto seq_1 = check_expr(fcx, seq); + auto body_1 = check_block(fcx, body); + + auto ann = ast.ann_type(plain_ty(ty.ty_nil)); + ret @fold.respan[ast.expr_](expr.span, + ast.expr_for_each(decl_1, seq_1, + body_1, ann)); + } + case (ast.expr_while(?cond, ?body, _)) { auto cond_0 = check_expr(fcx, cond); auto cond_1 = demand_expr(fcx, plain_ty(ty.ty_bool), cond_0); -- cgit v1.2.3 From 2bba49a9feed613c2f018d5aa751df3c7a49a3d6 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 15 Feb 2011 12:20:13 -0800 Subject: Fix missing path in expr_ext. --- src/comp/front/ast.rs | 2 +- src/comp/front/parser.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 9e43d349..520f5557 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -160,7 +160,7 @@ tag expr_ { expr_field(@expr, ident, ann); expr_index(@expr, @expr, ann); expr_path(path, option.t[def], ann); - expr_ext(vec[@expr], option.t[@expr], ann); + expr_ext(path, vec[@expr], option.t[@expr], ann); expr_fail; expr_ret(option.t[@expr]); expr_put(option.t[@expr]); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index ddadc789..085255a4 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -589,13 +589,14 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr { case (token.POUND) { p.bump(); + auto pth = parse_path(p, GREEDY); auto pf = parse_expr; auto es = parse_seq[@ast.expr](token.LPAREN, token.RPAREN, some(token.COMMA), pf, p); hi = es.span; - ex = ast.expr_ext(es.node, none[@ast.expr], ast.ann_none); + ex = ast.expr_ext(pth, es.node, none[@ast.expr], ast.ann_none); } case (token.FAIL) { -- cgit v1.2.3 From 9ae89bd404803be6b820189d8e0480b3395d05ee Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 15 Feb 2011 12:20:30 -0800 Subject: Add _mutable unop. --- src/comp/front/ast.rs | 1 + src/comp/front/parser.rs | 7 +++++++ src/comp/middle/trans.rs | 3 +++ src/comp/middle/typeck.rs | 3 +++ 4 files changed, 14 insertions(+) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 520f5557..03ccc216 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -106,6 +106,7 @@ tag unop { bitnot; not; neg; + _mutable; } tag mode { diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 085255a4..8acc8897 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -811,6 +811,13 @@ impure fn parse_prefix_expr(parser p) -> @ast.expr { ex = ast.expr_unary(ast.box, e, ast.ann_none); } + case (token.MUTABLE) { + p.bump(); + auto e = parse_prefix_expr(p); + hi = e.span; + ex = ast.expr_unary(ast._mutable, e, ast.ann_none); + } + case (_) { ret parse_dot_or_call_expr(p); } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c4e5c9c4..72a4fe5c 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1834,6 +1834,9 @@ fn trans_unary(@block_ctxt cx, ast.unop op, } ret res(sub.bcx, val); } + case (ast._mutable) { + ret trans_expr(cx, e); + } } fail; } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index a062f79d..e1b8d464 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1229,6 +1229,9 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } } } + case (ast._mutable) { + oper_t = @rec(mut=ast.mut with *oper_t); + } case (_) { oper_t = strip_boxes(oper_t); } } ret @fold.respan[ast.expr_](expr.span, -- cgit v1.2.3 From 7a02798d1b3ccb04ee450b1171f31319f0c05467 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 15 Feb 2011 12:30:09 -0800 Subject: Change another typestate check to an expr check. --- src/comp/middle/typeck.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index e1b8d464..83caf891 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1348,7 +1348,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { case (ast.expr_be(?e)) { /* FIXME: prove instead of check */ - check ast.is_call_expr(e); + check (ast.is_call_expr(e)); auto expr_0 = check_expr(fcx, e); auto expr_1 = demand_expr(fcx, fcx.ret_ty, expr_0); ret @fold.respan[ast.expr_](expr.span, -- cgit v1.2.3 From 370c1ad00eaa0ff95c4e09a6e0545bf833d6668a Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 15 Feb 2011 15:07:55 -0800 Subject: Handle record update in typeck. --- src/Makefile | 1 + src/comp/middle/typeck.rs | 94 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 81 insertions(+), 14 deletions(-) diff --git a/src/Makefile b/src/Makefile index 3457864c..11c7bee8 100644 --- a/src/Makefile +++ b/src/Makefile @@ -553,6 +553,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ bad-expr-path.rs \ bad-expr-path2.rs \ bogus-tag.rs \ + fru-extra-field.rs \ import.rs \ import2.rs \ import3.rs \ diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 83caf891..9b7c9439 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -912,23 +912,48 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, } case (ast.expr_rec(?fields_0, ?base_0, ?ann)) { - // FIXME: handle presence of a nonempty base. - check (base_0 == none[@ast.expr]); auto base_1 = base_0; auto t = demand(fcx, e.span, expected, ann_to_type(ann)); let vec[ast.field] fields_1 = vec(); alt (t.struct) { 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)); - auto e_1 = demand_expr(fcx, field_tys.(i).ty, - field_0.expr); - fields_1 += vec(rec(mut=field_0.mut, - ident=field_0.ident, - expr=e_1)); - i += 1u; + alt (base_0) { + case (none[@ast.expr]) { + auto i = 0u; + for (ast.field field_0 in fields_0) { + check (_str.eq(field_0.ident, + field_tys.(i).ident)); + auto e_1 = demand_expr(fcx, + field_tys.(i).ty, + field_0.expr); + fields_1 += vec(rec(mut=field_0.mut, + ident=field_0.ident, + expr=e_1)); + i += 1u; + } + } + case (some[@ast.expr](?bx)) { + + base_1 = + some[@ast.expr](demand_expr(fcx, t, bx)); + + let vec[field] base_fields = vec(); + + for (ast.field field_0 in fields_0) { + + for (ty.field ft in field_tys) { + if (_str.eq(field_0.ident, ft.ident)) { + auto e_1 = demand_expr(fcx, ft.ty, + field_0.expr); + fields_1 += + vec(rec(mut=field_0.mut, + ident=field_0.ident, + expr=e_1)); + } + } + } + } } } case (_) { @@ -1708,8 +1733,6 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { case (ast.expr_rec(?fields, ?base, _)) { - // FIXME: handle presence of a nonempty base. - check (base == none[@ast.expr]); auto base_1 = base; let vec[ast.field] fields_1 = vec(); @@ -1725,7 +1748,50 @@ 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.ty_rec(fields_t))); + auto ann = ast.ann_none; + + alt (base) { + case (none[@ast.expr]) { + ann = ast.ann_type(plain_ty(ty.ty_rec(fields_t))); + } + + case (some[@ast.expr](?bexpr)) { + auto bexpr_1 = check_expr(fcx, bexpr); + auto bexpr_t = expr_ty(bexpr_1); + + let vec[field] base_fields = vec(); + + alt (bexpr_t.struct) { + case (ty.ty_rec(?flds)) { + base_fields = flds; + } + case (_) { + fcx.ccx.sess.span_err + (expr.span, + "record update non-record base"); + } + } + + ann = ast.ann_type(bexpr_t); + + for (ty.field f in fields_t) { + auto found = false; + for (ty.field bf in base_fields) { + if (_str.eq(f.ident, bf.ident)) { + demand(fcx, expr.span, f.ty, bf.ty); + found = true; + } + } + if (!found) { + fcx.ccx.sess.span_err + (expr.span, + "unknown field in record update: " + + f.ident); + } + } + } + } + ret @fold.respan[ast.expr_](expr.span, ast.expr_rec(fields_1, base_1, ann)); } -- cgit v1.2.3 From d4bf67dde638fdeea4361daf16bee421d479628e Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 15 Feb 2011 18:16:13 -0800 Subject: Translate record extension. --- src/Makefile | 1 + src/comp/middle/trans.rs | 44 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/Makefile b/src/Makefile index 11c7bee8..544075fa 100644 --- a/src/Makefile +++ b/src/Makefile @@ -519,6 +519,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ readalias.rs \ rec.rs \ rec-auto.rs \ + rec-extend.rs \ rec-tup.rs \ return-nil.rs \ simple-obj.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 72a4fe5c..7d3f9997 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2998,9 +2998,6 @@ fn trans_vec(@block_ctxt cx, vec[@ast.expr] args, fn trans_rec(@block_ctxt cx, vec[ast.field] fields, option.t[@ast.expr] base, &ast.ann ann) -> result { - // FIXME: handle presence of a nonempty base. - check (base == none[@ast.expr]); - auto bcx = cx; auto t = node_ann_type(bcx.fcx.ccx, ann); auto llty = type_of(bcx.fcx.ccx, t); @@ -3011,13 +3008,44 @@ fn trans_rec(@block_ctxt cx, vec[ast.field] fields, find_scope_cx(cx).cleanups += clean(bind drop_ty(_, rec_val, t)); let int i = 0; - for (ast.field f in fields) { - auto e_ty = ty.expr_ty(f.expr); - auto src_res = trans_expr(bcx, f.expr); - bcx = src_res.bcx; + auto base_val = C_nil(); + + alt (base) { + case (none[@ast.expr]) { } + case (some[@ast.expr](?bexp)) { + auto base_res = trans_expr(bcx, bexp); + bcx = base_res.bcx; + base_val = base_res.val; + } + } + + let vec[ty.field] ty_fields = vec(); + alt (t.struct) { + case (ty.ty_rec(?flds)) { ty_fields = flds; } + } + + for (ty.field tf in ty_fields) { + auto e_ty = tf.ty; auto dst_res = GEP_tup_like(bcx, t, rec_val, vec(0, i)); bcx = dst_res.bcx; - bcx = copy_ty(src_res.bcx, INIT, dst_res.val, src_res.val, e_ty).bcx; + + auto expr_provided = false; + auto src_res = res(bcx, C_nil()); + + for (ast.field f in fields) { + if (_str.eq(f.ident, tf.ident)) { + expr_provided = true; + src_res = trans_expr(bcx, f.expr); + } + } + if (!expr_provided) { + src_res = GEP_tup_like(bcx, t, base_val, vec(0, i)); + src_res = res(src_res.bcx, + load_scalar_or_boxed(bcx, src_res.val, e_ty)); + } + + bcx = src_res.bcx; + bcx = copy_ty(bcx, INIT, dst_res.val, src_res.val, e_ty).bcx; i += 1; } ret res(bcx, rec_val); -- cgit v1.2.3 From 012fa69ea500aa31cb3dd2cd3df67ecd3eefd44e Mon Sep 17 00:00:00 2001 From: Rafael Avila de Espindola Date: Wed, 16 Feb 2011 14:02:02 -0500 Subject: More typechecking for native types and the needed plumbing in codegen. --- src/comp/front/ast.rs | 4 ++-- src/comp/front/parser.rs | 3 ++- src/comp/middle/fold.rs | 12 ++++++------ src/comp/middle/resolve.rs | 4 ++-- src/comp/middle/trans.rs | 24 +++++++++++++++++++++++- src/comp/middle/ty.rs | 16 ++++++++++++++++ src/comp/middle/typeck.rs | 18 ++++++++++++++---- 7 files changed, 65 insertions(+), 16 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 03ccc216..ee358432 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -263,7 +263,7 @@ tag item_ { type native_item = spanned[native_item_]; tag native_item_ { native_item_ty(ident, def_id); - native_item_fn(ident, fn_decl, vec[ty_param], def_id); + native_item_fn(ident, fn_decl, vec[ty_param], def_id, ann); } fn index_view_item(mod_index index, @view_item it) { @@ -314,7 +314,7 @@ fn index_native_item(native_mod_index index, @native_item it) { case (ast.native_item_ty(?id, _)) { index.insert(id, it); } - case (ast.native_item_fn(?id, _, _, _)) { + case (ast.native_item_fn(?id, _, _, _, _)) { index.insert(id, it); } } diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 8acc8897..a108d243 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1693,7 +1693,8 @@ impure fn parse_item_native_fn(parser p, ast.effect eff) -> @ast.native_item { auto decl = parse_fn_decl(p, eff); auto hi = p.get_span(); expect(p, token.SEMI); - auto item = ast.native_item_fn(t._1, decl, t._2, p.next_def_id()); + auto item = ast.native_item_fn(t._1, decl, t._2, p.next_def_id(), + ast.ann_none); ret @spanned(t._0, hi, item); } diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 3cafa961..db215ea9 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -214,7 +214,7 @@ type ast_fold[ENV] = (fn(&ENV e, &span sp, ident ident, &ast.fn_decl decl, vec[ast.ty_param] ty_params, - def_id id) -> @native_item) fold_native_item_fn, + def_id id, ann a) -> @native_item) fold_native_item_fn, (fn(&ENV e, &span sp, ident ident, &ast._mod m, def_id id) -> @item) fold_item_mod, @@ -921,10 +921,10 @@ fn fold_native_item[ENV](&ENV env, ast_fold[ENV] fld, case (ast.native_item_ty(?ident, ?id)) { ret fld.fold_native_item_ty(env_, i.span, ident, id); } - case (ast.native_item_fn(?ident, ?fn_decl, ?ty_params, ?id)) { + case (ast.native_item_fn(?ident, ?fn_decl, ?ty_params, ?id, ?ann)) { auto d = fold_fn_decl[ENV](env_, fld, fn_decl); ret fld.fold_native_item_fn(env_, i.span, ident, d, - ty_params, id); + ty_params, id, ann); } } } @@ -1240,8 +1240,8 @@ fn identity_fold_item_fn[ENV](&ENV e, &span sp, ident i, fn identity_fold_native_item_fn[ENV](&ENV e, &span sp, ident i, &ast.fn_decl decl, vec[ast.ty_param] ty_params, - def_id id) -> @native_item { - ret @respan(sp, ast.native_item_fn(i, decl, ty_params, id)); + def_id id, ann a) -> @native_item { + ret @respan(sp, ast.native_item_fn(i, decl, ty_params, id, a)); } fn identity_fold_item_mod[ENV](&ENV e, &span sp, ident i, @@ -1454,7 +1454,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_item_const= bind identity_fold_item_const[ENV](_,_,_,_,_,_,_), fold_item_fn = bind identity_fold_item_fn[ENV](_,_,_,_,_,_,_), fold_native_item_fn = - bind identity_fold_native_item_fn[ENV](_,_,_,_,_,_), + bind identity_fold_native_item_fn[ENV](_,_,_,_,_,_,_), fold_item_mod = bind identity_fold_item_mod[ENV](_,_,_,_,_), fold_item_native_mod = bind identity_fold_item_native_mod[ENV](_,_,_,_,_), diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index d4ad907e..a2f4da63 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -233,7 +233,7 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] { case (ast.native_item_ty(_, ?id)) { ret def_wrap_other(ast.def_native_ty(id)); } - case (ast.native_item_fn(_, _, _, ?id)) { + case (ast.native_item_fn(_, _, _, ?id, _)) { ret def_wrap_other(ast.def_native_fn(id)); } } @@ -381,7 +381,7 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] { case (scope_native_item(?it)) { alt (it.node) { - case (ast.native_item_fn(_, ?decl, ?ty_params, _)) { + case (ast.native_item_fn(_, ?decl, ?ty_params, _, _)) { ret handle_fn_decl(i, decl, ty_params); } } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 7d3f9997..037fd69f 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -70,6 +70,7 @@ state type crate_ctxt = rec(session.session sess, hashmap[str, ValueRef] item_names, hashmap[ast.def_id, ValueRef] item_ids, hashmap[ast.def_id, @ast.item] items, + hashmap[ast.def_id, @ast.native_item] native_items, hashmap[ast.def_id, @tag_info] tags, hashmap[ast.def_id, ValueRef] fn_pairs, hashmap[ast.def_id, ValueRef] consts, @@ -440,6 +441,7 @@ fn type_of_fn(@crate_ctxt cx, vec[ty.arg] inputs, @ty.t output) -> TypeRef { fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { alt (t.struct) { + case (ty.ty_native) { ret T_ptr(T_i8()); } case (ty.ty_nil) { ret T_nil(); } case (ty.ty_bool) { ret T_bool(); } case (ty.ty_int) { ret T_int(); } @@ -2429,6 +2431,12 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, check (cx.fcx.ccx.consts.contains_key(did)); ret lval_mem(cx, cx.fcx.ccx.consts.get(did)); } + case (ast.def_native_fn(?did)) { + check (cx.fcx.ccx.native_items.contains_key(did)); + auto fn_item = cx.fcx.ccx.native_items.get(did); + ret lval_generic_fn(cx, ty.native_item_ty(fn_item), + did, ann); + } case (_) { cx.fcx.ccx.sess.unimpl("def variant in trans"); } @@ -4053,6 +4061,18 @@ fn decl_fn_and_pair(@crate_ctxt cx, cx.fn_pairs.insert(id, gvar); } +fn collect_native_item(&@crate_ctxt cx, @ast.native_item i) -> @crate_ctxt { + alt (i.node) { + case (ast.native_item_fn(?name, _, _, ?fid, ?ann)) { + cx.native_items.insert(fid, i); + if (! cx.obj_methods.contains_key(fid)) { + decl_fn_and_pair(cx, "fn", name, ann, fid); + } + } + case (_) { /* fall through */ } + } + ret cx; +} fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { @@ -4101,7 +4121,8 @@ fn collect_items(@crate_ctxt cx, @ast.crate crate) { let fold.ast_fold[@crate_ctxt] fld = fold.new_identity_fold[@crate_ctxt](); - fld = @rec( update_env_for_item = bind collect_item(_,_) + fld = @rec( update_env_for_item = bind collect_item(_,_), + update_env_for_native_item = bind collect_native_item(_,_) with *fld ); fold.fold_crate[@crate_ctxt](cx, fld, crate); @@ -4559,6 +4580,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, item_names = new_str_hash[ValueRef](), item_ids = new_def_hash[ValueRef](), items = new_def_hash[@ast.item](), + native_items = new_def_hash[@ast.native_item](), tags = new_def_hash[@tag_info](), fn_pairs = new_def_hash[ValueRef](), consts = new_def_hash[ValueRef](), diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 499ed74d..21b68fb5 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -599,6 +599,22 @@ fn is_fn_ty(@t fty) -> bool { // Given an item, returns the associated type as well as a list of the IDs of // its type parameters. type ty_params_and_ty = tup(vec[ast.def_id], @t); +fn native_item_ty(@ast.native_item it) -> ty_params_and_ty { + auto ty_params; + auto result_ty; + alt (it.node) { + case (ast.native_item_fn(_, _, ?tps, _, ?ann)) { + ty_params = tps; + result_ty = ann_to_type(ann); + } + } + let vec[ast.def_id] ty_param_ids = vec(); + for (ast.ty_param tp in ty_params) { + ty_param_ids += vec(tp.id); + } + ret tup(ty_param_ids, result_ty); +} + fn item_ty(@ast.item it) -> ty_params_and_ty { let vec[ast.ty_param] ty_params; auto result_ty; diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 9b7c9439..7ddc1d05 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -266,7 +266,7 @@ fn ty_params_of_item(@ast.item item) -> vec[ast.ty_param] { fn ty_params_of_native_item(@ast.native_item item) -> vec[ast.ty_param] { alt (item.node) { - case (ast.native_item_fn(_, _, ?p, _)) { + case (ast.native_item_fn(_, _, ?p, _, _)) { ret p; } case (_) { @@ -432,7 +432,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) @ty_table item_to_ty, @ast.native_item it) -> @ty.t { alt (it.node) { - case (ast.native_item_fn(?ident, ?fn_decl, ?params, ?def_id)) { + case (ast.native_item_fn(?ident, ?fn_decl, ?params, ?def_id, _)) { auto get = bind getter(id_to_ty_item, item_to_ty, _); auto convert = bind ast_ty_to_ty(get, _); auto f = bind ty_of_arg(id_to_ty_item, item_to_ty, _); @@ -512,8 +512,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) case (ast.native_item_ty(_, ?def_id)) { id_to_ty_item.insert(def_id, any_item_native(i)); } - case (ast.native_item_fn(_, _, _, ?def_id)) { - id_to_ty_item.insert(def_id, any_item_native(i)); + case (_) { } } ret id_to_ty_item; @@ -578,6 +577,16 @@ fn collect_item_types(session.session sess, @ast.crate crate) ret @fold.respan[ast.item_](sp, item); } + fn fold_native_item_fn(&@env e, &span sp, ast.ident i, + &ast.fn_decl d, vec[ast.ty_param] ty_params, + ast.def_id id, ast.ann a) -> @ast.native_item { + check (e.item_to_ty.contains_key(id)); + auto ty = e.item_to_ty.get(id); + auto item = ast.native_item_fn(i, d, ty_params, id, + ast.ann_type(ty)); + ret @fold.respan[ast.native_item_](sp, item); + } + fn get_ctor_obj_methods(@ty.t t) -> vec[method] { alt (t.struct) { case (ty.ty_fn(_,?tobj)) { @@ -663,6 +672,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) update_env_for_native_item = bind convert_native(_,_), fold_item_const = bind fold_item_const(_,_,_,_,_,_,_), fold_item_fn = bind fold_item_fn(_,_,_,_,_,_,_), + fold_native_item_fn = bind fold_native_item_fn(_,_,_,_,_,_,_), fold_item_obj = bind fold_item_obj(_,_,_,_,_,_,_), fold_item_ty = bind fold_item_ty(_,_,_,_,_,_,_), fold_item_tag = bind fold_item_tag(_,_,_,_,_,_) -- cgit v1.2.3 From f50caa75c20f997a578d70c696cc9c1bf9fa40fe Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 16 Feb 2011 11:33:14 -0800 Subject: Wrap long line in last commit. --- src/comp/middle/trans.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 037fd69f..282a62d6 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -70,7 +70,8 @@ state type crate_ctxt = rec(session.session sess, hashmap[str, ValueRef] item_names, hashmap[ast.def_id, ValueRef] item_ids, hashmap[ast.def_id, @ast.item] items, - hashmap[ast.def_id, @ast.native_item] native_items, + hashmap[ast.def_id, + @ast.native_item] native_items, hashmap[ast.def_id, @tag_info] tags, hashmap[ast.def_id, ValueRef] fn_pairs, hashmap[ast.def_id, ValueRef] consts, -- cgit v1.2.3 From 293637139fe55990397849badfb60c96d4211b31 Mon Sep 17 00:00:00 2001 From: Rafael Avila de Espindola Date: Wed, 16 Feb 2011 15:00:40 -0500 Subject: Add missing case to ty_to_str. Disable test that now fails because we produce undefined references to the native functions. --- src/Makefile | 1 - src/comp/middle/ty.rs | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 544075fa..85867532 100644 --- a/src/Makefile +++ b/src/Makefile @@ -507,7 +507,6 @@ TEST_XFAILS_RUSTC := $(filter-out \ linear-for-loop.rs \ multiline-comment.rs \ mutual-recursion-group.rs \ - native2.rs \ obj-drop.rs \ obj-recursion.rs \ obj-with-vec.rs \ diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 21b68fb5..a9be0c36 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -210,6 +210,7 @@ fn ty_to_str(&@t typ) -> str { } alt (typ.struct) { + case (ty_native) { s = "native"; } case (ty_nil) { s = "()"; } case (ty_bool) { s = "bool"; } case (ty_int) { s = "int"; } -- cgit v1.2.3 From a63696dfe2bd47d34925a3ad44db9d2ede949e36 Mon Sep 17 00:00:00 2001 From: Rafael Avila de Espindola Date: Wed, 16 Feb 2011 15:34:59 -0500 Subject: Add a more specialized decl_native_fn_and_pair. Native functions now have the right name. --- src/Makefile | 1 + src/comp/middle/trans.rs | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 85867532..544075fa 100644 --- a/src/Makefile +++ b/src/Makefile @@ -507,6 +507,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ linear-for-loop.rs \ multiline-comment.rs \ mutual-recursion-group.rs \ + native2.rs \ obj-drop.rs \ obj-recursion.rs \ obj-with-vec.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 282a62d6..94fa9f91 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4062,12 +4062,24 @@ fn decl_fn_and_pair(@crate_ctxt cx, cx.fn_pairs.insert(id, gvar); } +fn decl_native_fn_and_pair(@crate_ctxt cx, + str name, + &ast.ann ann, + ast.def_id id) { + + auto llpairty = node_type(cx, ann); + auto llfty = get_pair_fn_ty(llpairty); + + let ValueRef llfn = decl_fastcall_fn(cx.llmod, name, llfty); + cx.item_ids.insert(id, llfn); +} + fn collect_native_item(&@crate_ctxt cx, @ast.native_item i) -> @crate_ctxt { alt (i.node) { case (ast.native_item_fn(?name, _, _, ?fid, ?ann)) { cx.native_items.insert(fid, i); if (! cx.obj_methods.contains_key(fid)) { - decl_fn_and_pair(cx, "fn", name, ann, fid); + decl_native_fn_and_pair(cx, name, ann, fid); } } case (_) { /* fall through */ } -- cgit v1.2.3 From 07c7888037cb74ca33459946145608a854aae6ed Mon Sep 17 00:00:00 2001 From: Rafael Avila de Espindola Date: Wed, 16 Feb 2011 16:16:11 -0500 Subject: Don't add the rust arguments to native functions. We now produce the correct arguments for native functions. --- src/comp/middle/trans.rs | 45 ++++++++++++++++++++++++++++++--------------- src/comp/middle/ty.rs | 5 +++++ src/comp/middle/typeck.rs | 17 +++++++++++++++-- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 94fa9f91..e3e68d4b 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -370,6 +370,26 @@ fn type_of(@crate_ctxt cx, @ty.t t) -> TypeRef { ret llty; } +fn type_of_explicit_args(@crate_ctxt cx, + vec[ty.arg] inputs) -> vec[TypeRef] { + let vec[TypeRef] atys = vec(); + for (ty.arg arg in inputs) { + if (ty.type_has_dynamic_size(arg.ty)) { + check (arg.mode == ast.alias); + atys += T_typaram_ptr(); + } else { + let TypeRef t = type_of(cx, arg.ty); + alt (arg.mode) { + case (ast.alias) { + t = T_ptr(t); + } + case (_) { /* fall through */ } + } + atys += t; + } + } + ret atys; +} // NB: must keep 4 fns in sync: // @@ -417,21 +437,7 @@ fn type_of_fn_full(@crate_ctxt cx, } // ... then explicit args. - for (ty.arg arg in inputs) { - if (ty.type_has_dynamic_size(arg.ty)) { - check (arg.mode == ast.alias); - atys += T_typaram_ptr(); - } else { - let TypeRef t = type_of(cx, arg.ty); - alt (arg.mode) { - case (ast.alias) { - t = T_ptr(t); - } - case (_) { /* fall through */ } - } - atys += t; - } - } + atys += type_of_explicit_args(cx, inputs); ret T_fn(atys, llvm.LLVMVoidType()); } @@ -440,6 +446,12 @@ fn type_of_fn(@crate_ctxt cx, vec[ty.arg] inputs, @ty.t output) -> TypeRef { ret type_of_fn_full(cx, none[TypeRef], inputs, output); } +fn type_of_native_fn(@crate_ctxt cx, vec[ty.arg] inputs, + @ty.t output) -> TypeRef { + let vec[TypeRef] atys = type_of_explicit_args(cx, inputs); + ret T_fn(atys, llvm.LLVMVoidType()); +} + fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { alt (t.struct) { case (ty.ty_native) { ret T_ptr(T_i8()); } @@ -489,6 +501,9 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { case (ty.ty_fn(?args, ?out)) { ret T_fn_pair(type_of_fn(cx, args, out)); } + case (ty.ty_native_fn(?args, ?out)) { + ret T_fn_pair(type_of_native_fn(cx, args, out)); + } case (ty.ty_obj(?meths)) { auto th = mk_type_handle(); auto self_ty = llvm.LLVMResolveTypeHandle(th.llth); diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index a9be0c36..adda5a8c 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -38,6 +38,7 @@ tag sty { ty_tup(vec[@t]); ty_rec(vec[field]); ty_fn(vec[arg], @t); // TODO: effect + ty_native_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 @@ -243,6 +244,10 @@ fn ty_to_str(&@t typ) -> str { s = fn_to_str(none[ast.ident], inputs, output); } + case (ty_native_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); diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 7ddc1d05..3dab25a7 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -300,6 +300,19 @@ fn ty_of_fn_decl(@ty_item_table id_to_ty_item, ret t_fn; } +fn ty_of_native_fn_decl(@ty_item_table id_to_ty_item, + @ty_table item_to_ty, + fn(&@ast.ty ast_ty) -> @ty.t convert, + fn(&ast.arg a) -> arg ty_of_arg, + &ast.fn_decl decl, + ast.def_id def_id) -> @ty.t { + auto input_tys = _vec.map[ast.arg,arg](ty_of_arg, decl.inputs); + auto output_ty = convert(decl.output); + auto t_fn = plain_ty(ty.ty_native_fn(input_tys, output_ty)); + item_to_ty.insert(def_id, t_fn); + ret t_fn; +} + fn collect_item_types(session.session sess, @ast.crate crate) -> tup(@ast.crate, @ty_table, @ty_item_table) { @@ -436,8 +449,8 @@ fn collect_item_types(session.session sess, @ast.crate crate) auto get = bind getter(id_to_ty_item, item_to_ty, _); auto convert = bind ast_ty_to_ty(get, _); auto f = bind ty_of_arg(id_to_ty_item, item_to_ty, _); - ret ty_of_fn_decl(id_to_ty_item, item_to_ty, convert, f, - fn_decl, def_id); + ret ty_of_native_fn_decl(id_to_ty_item, item_to_ty, convert, + f, fn_decl, def_id); } case (ast.native_item_ty(_, ?def_id)) { if (item_to_ty.contains_key(def_id)) { -- cgit v1.2.3 From e867d8ea993945803d96396bcba9c07d61d7c95d Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 16 Feb 2011 14:34:10 -0800 Subject: Un-XFAIL mutable-vec-drop.rs. --- src/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile b/src/Makefile index 544075fa..c468ded0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -506,6 +506,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ leak-box-as-tydesc.rs \ linear-for-loop.rs \ multiline-comment.rs \ + mutable-vec-drop.rs \ mutual-recursion-group.rs \ native2.rs \ obj-drop.rs \ -- cgit v1.2.3 From 79d3ceaac0b4a6ca83f0ff7b8b533649fc5165a1 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 17 Feb 2011 12:20:55 -0800 Subject: Steps toward implementing iterators. --- src/comp/middle/trans.rs | 123 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 116 insertions(+), 7 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index e3e68d4b..62b5a415 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -88,6 +88,7 @@ state type fn_ctxt = rec(ValueRef llfn, ValueRef llenv, ValueRef llretptr, mutable option.t[ValueRef] llself, + mutable option.t[ValueRef] lliterbody, hashmap[ast.def_id, ValueRef] llargs, hashmap[ast.def_id, ValueRef] llobjfields, hashmap[ast.def_id, ValueRef] lllocals, @@ -399,6 +400,8 @@ fn type_of_explicit_args(@crate_ctxt cx, // - trans_args fn type_of_fn_full(@crate_ctxt cx, + // FIXME: change bool flag to tag + bool is_iter, option.t[TypeRef] obj_self, vec[ty.arg] inputs, @ty.t output) -> TypeRef { @@ -436,14 +439,26 @@ fn type_of_fn_full(@crate_ctxt cx, } } + if (is_iter) { + // If it's an iter, the 'output' type of the iter is actually the + // *input* type of the function we're given as our iter-block + // argument. + atys += T_fn_pair(type_of_fn_full(cx, false, none[TypeRef], + vec(rec(mode=ast.val, ty=output)), + plain_ty(ty.ty_nil))); + } + // ... then explicit args. atys += type_of_explicit_args(cx, inputs); ret T_fn(atys, llvm.LLVMVoidType()); } -fn type_of_fn(@crate_ctxt cx, vec[ty.arg] inputs, @ty.t output) -> TypeRef { - ret type_of_fn_full(cx, none[TypeRef], inputs, output); +fn type_of_fn(@crate_ctxt cx, + // FIXME: change bool flag to tag + bool is_iter, + vec[ty.arg] inputs, @ty.t output) -> TypeRef { + ret type_of_fn_full(cx, is_iter, none[TypeRef], inputs, output); } fn type_of_native_fn(@crate_ctxt cx, vec[ty.arg] inputs, @@ -499,7 +514,8 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { ret T_struct(tys); } case (ty.ty_fn(?args, ?out)) { - ret T_fn_pair(type_of_fn(cx, args, out)); + // FIXME: put iter in ty_fn. + ret T_fn_pair(type_of_fn(cx, false, args, out)); } case (ty.ty_native_fn(?args, ?out)) { ret T_fn_pair(type_of_native_fn(cx, args, out)); @@ -512,6 +528,8 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { for (ty.method m in meths) { let TypeRef mty = type_of_fn_full(cx, + // FIXME: support method iters + false, some[TypeRef](self_ty), m.inputs, m.output); mtys += T_ptr(mty); @@ -2141,7 +2159,83 @@ fn trans_for_each(@block_ctxt cx, @ast.decl decl, @ast.expr seq, &ast.block body) -> result { - cx.fcx.ccx.sess.unimpl("for each loop"); + + /* + * The translation is a little .. complex here. Code like: + * + * let ty1 p = ...; + * + * let ty1 q = ...; + * + * foreach (ty v in foo(a,b)) { body(p,q,v) } + * + * + * Turns into a something like so (C/Rust mishmash): + * + * type env = { *ty1 p, *ty2 q, ... }; + * + * let env e = { &p, &q, ... }; + * + * fn foreach123_body(env* e, ty v) { body(*(e->p),*(e->q),v) } + * + * foo([foreach123_body, env*], a, b); + * + */ + + // Step 1: walk body and figure out which references it makes + // escape. This could be determined upstream, and probably ought + // to be so, eventualy. For first cut, skip this. Null env. + + auto env_ty = T_struct(vec(T_ptr(T_i8()))); + + + // Step 2: Declare foreach body function. + + // FIXME: possibly support alias-mode here? + auto decl_ty = plain_ty(ty.ty_nil); + alt (decl.node) { + case (ast.decl_local(?local)) { + decl_ty = node_ann_type(cx.fcx.ccx, local.ann); + } + } + + let str s = + cx.fcx.ccx.names.next("_rust_foreach") + + sep() + cx.fcx.ccx.path; + + // The 'env' arg entering the body function is a fake env member (as in + // the env-part of the normal rust calling convention) that actually + // points to a stack allocated env in this frame. We bundle that env + // pointer along with the foreach-body-fn pointer into a 'normal' fn pair + // and pass it in as a first class fn-arg to the iterator. + + auto foreach_llty = type_of_fn_full(cx.fcx.ccx, false, none[TypeRef], + vec(rec(mode=ast.val, ty=decl_ty)), + plain_ty(ty.ty_nil)); + + let ValueRef llforeach = decl_fastcall_fn(cx.fcx.ccx.llmod, + s, foreach_llty); + + // FIXME: handle ty params properly. + let vec[ast.ty_param] ty_params = vec(); + + auto fcx = new_fn_ctxt(cx.fcx.ccx, s, llforeach); + auto bcx = new_top_block_ctxt(fcx); + + // FIXME: populate lllocals from llenv here. + auto res = trans_block(bcx, body); + res.bcx.build.RetVoid(); + + + // Step 3: Call iter passing [llforeach, llenv], plus other args. + + alt (seq.node) { + case (ast.expr_call(?f, ?args, ?ann)) { + // FIXME_ finish here by transferring to trans_call, + // suitably refactored. + cx.fcx.ccx.sess.unimpl("for each loop in trans"); + } + } fail; } @@ -3538,6 +3632,7 @@ fn new_fn_ctxt(@crate_ctxt cx, llenv=llenv, llretptr=llretptr, mutable llself=none[ValueRef], + mutable lliterbody=none[ValueRef], llargs=llargs, llobjfields=llobjfields, lllocals=lllocals, @@ -3553,6 +3648,8 @@ fn new_fn_ctxt(@crate_ctxt cx, // - trans_args fn create_llargs_for_fn_args(&@fn_ctxt cx, + // FIXME: change bool flag to tag + bool is_iter, option.t[TypeRef] ty_self, @ty.t ret_ty, &vec[ast.arg] args, @@ -3577,6 +3674,12 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx, } } + if (is_iter) { + auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n); + check (llarg as int != 0); + cx.lliterbody = some[ValueRef](llarg); + arg_n += 1u; + } for (ast.arg arg in args) { auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n); @@ -3713,7 +3816,8 @@ fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid, cx.item_names.insert(cx.path, llfndecl); auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); - create_llargs_for_fn_args(fcx, ty_self, ret_ty_of_fn(ann), + create_llargs_for_fn_args(fcx, f.is_iter, + ty_self, ret_ty_of_fn(ann), f.decl.inputs, ty_params); auto bcx = new_top_block_ctxt(fcx); @@ -3754,6 +3858,8 @@ fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty, alt (node_ann_type(cx, m.node.ann).struct) { case (ty.ty_fn(?inputs, ?output)) { llfnty = type_of_fn_full(cx, + // FIXME: support method iters. + false, some[TypeRef](self_ty), inputs, output); } @@ -3797,7 +3903,8 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, } auto fcx = new_fn_ctxt(cx, cx.path, llctor_decl); - create_llargs_for_fn_args(fcx, none[TypeRef], ret_ty_of_fn(ann), + create_llargs_for_fn_args(fcx, false, + none[TypeRef], ret_ty_of_fn(ann), fn_args, ty_params); auto bcx = new_top_block_ctxt(fcx); @@ -3925,7 +4032,8 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, let ValueRef llfndecl = cx.item_ids.get(variant.id); auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); - create_llargs_for_fn_args(fcx, none[TypeRef], ret_ty_of_fn(variant.ann), + create_llargs_for_fn_args(fcx, false, + none[TypeRef], ret_ty_of_fn(variant.ann), fn_args, ty_params); auto bcx = new_top_block_ctxt(fcx); @@ -4331,6 +4439,7 @@ fn trans_exit_task_glue(@crate_ctxt cx) { llenv=C_null(T_opaque_closure_ptr()), llretptr=C_null(T_ptr(T_nil())), mutable llself=none[ValueRef], + mutable lliterbody=none[ValueRef], llargs=new_def_hash[ValueRef](), llobjfields=new_def_hash[ValueRef](), lllocals=new_def_hash[ValueRef](), -- cgit v1.2.3 From 10befcd9a4d9f68e2dbec84c4a86450a021143fb Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 17 Feb 2011 16:23:31 -0800 Subject: Add type parameters to tag types --- src/comp/middle/trans.rs | 6 ++- src/comp/middle/ty.rs | 87 ++++++++++++++++++++++++++++++---------- src/comp/middle/typeck.rs | 38 +++++++++++++----- 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 = ""; + 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 +} -- cgit v1.2.3 From 0ddb832a4e34dfd0edcd22529e16732d7cb15f88 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 17 Feb 2011 18:16:51 -0800 Subject: Teach trans and llvm to cooperate on producing tidier diagnostic names in trans.ty_str. --- src/comp/lib/llvm.rs | 71 +++++++++++-- src/comp/middle/trans.rs | 268 +++++++++++++++++++++++++++++------------------ 2 files changed, 226 insertions(+), 113 deletions(-) diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs index 624c56f9..751507d6 100644 --- a/src/comp/lib/llvm.rs +++ b/src/comp/lib/llvm.rs @@ -1151,18 +1151,70 @@ fn mk_type_handle() -> type_handle { ret rec(llth=th, dtor=type_handle_dtor(th)); } -fn type_to_str(TypeRef ty) -> str { + +state obj type_names(std.map.hashmap[TypeRef, str] type_names, + std.map.hashmap[str, TypeRef] named_types) { + + fn associate(str s, TypeRef t) { + check (!named_types.contains_key(s)); + check (!type_names.contains_key(t)); + type_names.insert(t, s); + named_types.insert(s, t); + } + + fn type_has_name(TypeRef t) -> bool { + ret type_names.contains_key(t); + } + + fn get_name(TypeRef t) -> str { + ret type_names.get(t); + } + + fn name_has_type(str s) -> bool { + ret named_types.contains_key(s); + } + + fn get_type(str s) -> TypeRef { + ret named_types.get(s); + } +} + +fn mk_type_names() -> type_names { + auto nt = util.common.new_str_hash[TypeRef](); + + fn hash(&TypeRef t) -> uint { + ret t as uint; + } + + fn eq(&TypeRef a, &TypeRef b) -> bool { + ret (a as uint) == (b as uint); + } + + let std.map.hashfn[TypeRef] hasher = hash; + let std.map.eqfn[TypeRef] eqer = eq; + auto tn = std.map.mk_hashmap[TypeRef,str](hasher, eqer); + + ret type_names(tn, nt); +} + +fn type_to_str(type_names names, TypeRef ty) -> str { let vec[TypeRef] v = vec(); - ret type_to_str_inner(v, ty); + ret type_to_str_inner(names, v, ty); } -fn type_to_str_inner(vec[TypeRef] outer0, TypeRef ty) -> str { +fn type_to_str_inner(type_names names, + vec[TypeRef] outer0, TypeRef ty) -> str { + + if (names.type_has_name(ty)) { + ret names.get_name(ty); + } auto outer = outer0 + vec(ty); let int kind = llvm.LLVMGetTypeKind(ty); - fn tys_str(vec[TypeRef] outer, vec[TypeRef] tys) -> str { + fn tys_str(type_names names, + vec[TypeRef] outer, vec[TypeRef] tys) -> str { let str s = ""; let bool first = true; for (TypeRef t in tys) { @@ -1171,7 +1223,7 @@ fn type_to_str_inner(vec[TypeRef] outer0, TypeRef ty) -> str { } else { s += ", "; } - s += type_to_str_inner(outer, t); + s += type_to_str_inner(names, outer, t); } ret s; } @@ -1200,9 +1252,9 @@ fn type_to_str_inner(vec[TypeRef] outer0, TypeRef ty) -> str { let vec[TypeRef] args = _vec.init_elt[TypeRef](0 as TypeRef, n_args); llvm.LLVMGetParamTypes(ty, _vec.buf[TypeRef](args)); - s += tys_str(outer, args); + s += tys_str(names, outer, args); s += ") -> "; - s += type_to_str_inner(outer, out_ty); + s += type_to_str_inner(names, outer, out_ty); ret s; } @@ -1212,7 +1264,7 @@ fn type_to_str_inner(vec[TypeRef] outer0, TypeRef ty) -> str { let vec[TypeRef] elts = _vec.init_elt[TypeRef](0 as TypeRef, n_elts); llvm.LLVMGetStructElementTypes(ty, _vec.buf[TypeRef](elts)); - s += tys_str(outer, elts); + s += tys_str(names, outer, elts); s += "}"; ret s; } @@ -1228,7 +1280,8 @@ fn type_to_str_inner(vec[TypeRef] outer0, TypeRef ty) -> str { ret "*\\" + util.common.istr(n as int); } } - ret "*" + type_to_str_inner(outer, llvm.LLVMGetElementType(ty)); + ret "*" + type_to_str_inner(names, outer, + llvm.LLVMGetElementType(ty)); } case (12) { ret "Opaque"; } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9d336f22..538dfdbe 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -28,9 +28,11 @@ import lib.llvm.llvm; import lib.llvm.builder; import lib.llvm.target_data; import lib.llvm.type_handle; +import lib.llvm.type_names; import lib.llvm.mk_pass_manager; import lib.llvm.mk_target_data; import lib.llvm.mk_type_handle; +import lib.llvm.mk_type_names; import lib.llvm.llvm.ModuleRef; import lib.llvm.llvm.ValueRef; import lib.llvm.llvm.TypeRef; @@ -64,6 +66,7 @@ type tag_info = rec(type_handle th, state type crate_ctxt = rec(session.session sess, ModuleRef llmod, target_data td, + type_names tn, ValueRef crate_ptr, hashmap[str, ValueRef] upcalls, hashmap[str, ValueRef] intrinsics, @@ -133,16 +136,16 @@ fn res(@block_ctxt bcx, ValueRef val) -> result { mutable val = val); } -fn ty_str(TypeRef t) -> str { - ret lib.llvm.type_to_str(t); +fn ty_str(type_names tn, TypeRef t) -> str { + ret lib.llvm.type_to_str(tn, t); } fn val_ty(ValueRef v) -> TypeRef { ret llvm.LLVMTypeOf(v); } -fn val_str(ValueRef v) -> str { - ret ty_str(val_ty(v)); +fn val_str(type_names tn, ValueRef v) -> str { + ret ty_str(tn, val_ty(v)); } @@ -215,9 +218,9 @@ fn T_fn(vec[TypeRef] inputs, TypeRef output) -> TypeRef { False); } -fn T_fn_pair(TypeRef tfn) -> TypeRef { +fn T_fn_pair(type_names tn, TypeRef tfn) -> TypeRef { ret T_struct(vec(T_ptr(tfn), - T_opaque_closure_ptr())); + T_opaque_closure_ptr(tn))); } fn T_ptr(TypeRef t) -> TypeRef { @@ -234,34 +237,55 @@ fn T_opaque() -> TypeRef { ret llvm.LLVMOpaqueType(); } -fn T_task() -> TypeRef { - ret T_struct(vec(T_int(), // Refcount - T_int(), // Delegate pointer - T_int(), // Stack segment pointer - T_int(), // Runtime SP - T_int(), // Rust SP - T_int(), // GC chain - T_int(), // Domain pointer - T_int() // Crate cache pointer - )); +fn T_task(type_names tn) -> TypeRef { + auto s = "task"; + if (tn.name_has_type(s)) { + ret tn.get_type(s); + } + + auto t = T_struct(vec(T_int(), // Refcount + T_int(), // Delegate pointer + T_int(), // Stack segment pointer + T_int(), // Runtime SP + T_int(), // Rust SP + T_int(), // GC chain + T_int(), // Domain pointer + T_int() // Crate cache pointer + )); + tn.associate(s, t); + ret t; } -fn T_glue_fn() -> TypeRef { +fn T_glue_fn(type_names tn) -> TypeRef { + auto s = "glue_fn"; + if (tn.name_has_type(s)) { + ret tn.get_type(s); + } + // Bit of a kludge: pick the fn typeref out of the tydesc.. let vec[TypeRef] tydesc_elts = _vec.init_elt[TypeRef](T_nil(), 10u); - llvm.LLVMGetStructElementTypes(T_tydesc(), + llvm.LLVMGetStructElementTypes(T_tydesc(tn), _vec.buf[TypeRef](tydesc_elts)); - ret llvm.LLVMGetElementType(tydesc_elts.(abi.tydesc_field_drop_glue_off)); + auto t = + llvm.LLVMGetElementType + (tydesc_elts.(abi.tydesc_field_drop_glue_off)); + tn.associate(s, t); + ret t; } -fn T_tydesc() -> TypeRef { +fn T_tydesc(type_names tn) -> TypeRef { + + auto s = "tydesc"; + if (tn.name_has_type(s)) { + ret tn.get_type(s); + } auto th = mk_type_handle(); auto abs_tydesc = llvm.LLVMResolveTypeHandle(th.llth); auto tydescpp = T_ptr(T_ptr(abs_tydesc)); auto pvoid = T_ptr(T_i8()); auto glue_fn_ty = T_ptr(T_fn(vec(T_ptr(T_nil()), - T_taskptr(), + T_taskptr(tn), T_ptr(T_nil()), tydescpp, pvoid), T_void())); @@ -277,7 +301,9 @@ fn T_tydesc() -> TypeRef { glue_fn_ty)); // is_stateful llvm.LLVMRefineType(abs_tydesc, tydesc); - ret llvm.LLVMResolveTypeHandle(th.llth); + auto t = llvm.LLVMResolveTypeHandle(th.llth); + tn.associate(s, t); + ret t; } fn T_array(TypeRef t, uint n) -> TypeRef { @@ -300,67 +326,90 @@ fn T_box(TypeRef t) -> TypeRef { ret T_struct(vec(T_int(), t)); } -fn T_crate() -> TypeRef { - ret T_struct(vec(T_int(), // ptrdiff_t image_base_off - T_int(), // uintptr_t self_addr - T_int(), // ptrdiff_t debug_abbrev_off - T_int(), // size_t debug_abbrev_sz - T_int(), // ptrdiff_t debug_info_off - T_int(), // size_t debug_info_sz - T_int(), // size_t activate_glue_off - T_int(), // size_t yield_glue_off - T_int(), // size_t unwind_glue_off - T_int(), // size_t gc_glue_off - T_int(), // size_t main_exit_task_glue_off - T_int(), // int n_rust_syms - T_int(), // int n_c_syms - T_int() // int n_libs - )); +fn T_crate(type_names tn) -> TypeRef { + auto s = "crate"; + if (tn.name_has_type(s)) { + ret tn.get_type(s); + } + + auto t = T_struct(vec(T_int(), // ptrdiff_t image_base_off + T_int(), // uintptr_t self_addr + T_int(), // ptrdiff_t debug_abbrev_off + T_int(), // size_t debug_abbrev_sz + T_int(), // ptrdiff_t debug_info_off + T_int(), // size_t debug_info_sz + T_int(), // size_t activate_glue_off + T_int(), // size_t yield_glue_off + T_int(), // size_t unwind_glue_off + T_int(), // size_t gc_glue_off + T_int(), // size_t main_exit_task_glue_off + T_int(), // int n_rust_syms + T_int(), // int n_c_syms + T_int() // int n_libs + )); + tn.associate(s, t); + ret t; } fn T_double() -> TypeRef { ret llvm.LLVMDoubleType(); } -fn T_taskptr() -> TypeRef { - ret T_ptr(T_task()); +fn T_taskptr(type_names tn) -> TypeRef { + ret T_ptr(T_task(tn)); } -fn T_typaram_ptr() -> TypeRef { - ret T_ptr(T_i8()); +fn T_typaram_ptr(type_names tn) -> TypeRef { + auto s = "typaram"; + if (tn.name_has_type(s)) { + ret tn.get_type(s); + } + + auto t = T_ptr(T_i8()); + tn.associate(s, t); + ret t; } -fn T_closure_ptr(TypeRef lltarget_ty, +fn T_closure_ptr(type_names tn, + TypeRef lltarget_ty, TypeRef llbindings_ty) -> TypeRef { - ret T_ptr(T_box(T_struct(vec(T_ptr(T_tydesc()), + ret T_ptr(T_box(T_struct(vec(T_ptr(T_tydesc(tn)), lltarget_ty, llbindings_ty) // FIXME: add captured typarams. ))); } -fn T_opaque_closure_ptr() -> TypeRef { - ret T_closure_ptr(T_struct(vec(T_ptr(T_nil()), - T_ptr(T_nil()))), - T_nil()); +fn T_opaque_closure_ptr(type_names tn) -> TypeRef { + auto s = "*closure"; + if (tn.name_has_type(s)) { + ret tn.get_type(s); + } + auto t = T_closure_ptr(tn, T_struct(vec(T_ptr(T_nil()), + T_ptr(T_nil()))), + T_nil()); + tn.associate(s, t); + ret t; } -fn T_captured_tydescs(uint n) -> TypeRef { - ret T_struct(_vec.init_elt[TypeRef](T_ptr(T_tydesc()), n)); +fn T_captured_tydescs(type_names tn, uint n) -> TypeRef { + ret T_struct(_vec.init_elt[TypeRef](T_ptr(T_tydesc(tn)), n)); } -fn T_obj(uint n_captured_tydescs, TypeRef llfields_ty) -> TypeRef { - ret T_struct(vec(T_ptr(T_tydesc()), - T_captured_tydescs(n_captured_tydescs), +fn T_obj(type_names tn, uint n_captured_tydescs, + TypeRef llfields_ty) -> TypeRef { + ret T_struct(vec(T_ptr(T_tydesc(tn)), + T_captured_tydescs(tn, n_captured_tydescs), llfields_ty)); } -fn T_obj_ptr(uint n_captured_tydescs, TypeRef llfields_ty) -> TypeRef { - ret T_ptr(T_box(T_obj(n_captured_tydescs, llfields_ty))); +fn T_obj_ptr(type_names tn, uint n_captured_tydescs, + TypeRef llfields_ty) -> TypeRef { + ret T_ptr(T_box(T_obj(tn, n_captured_tydescs, llfields_ty))); } -fn T_opaque_obj_ptr() -> TypeRef { - ret T_obj_ptr(0u, T_nil()); +fn T_opaque_obj_ptr(type_names tn) -> TypeRef { + ret T_obj_ptr(tn, 0u, T_nil()); } @@ -377,7 +426,7 @@ fn type_of_explicit_args(@crate_ctxt cx, for (ty.arg arg in inputs) { if (ty.type_has_dynamic_size(arg.ty)) { check (arg.mode == ast.alias); - atys += T_typaram_ptr(); + atys += T_typaram_ptr(cx.tn); } else { let TypeRef t = type_of(cx, arg.ty); alt (arg.mode) { @@ -409,13 +458,13 @@ fn type_of_fn_full(@crate_ctxt cx, // Arg 0: Output pointer. if (ty.type_has_dynamic_size(output)) { - atys += T_typaram_ptr(); + atys += T_typaram_ptr(cx.tn); } else { atys += T_ptr(type_of(cx, output)); } // Arg 1: Task pointer. - atys += T_taskptr(); + atys += T_taskptr(cx.tn); // Arg 2: Env (closure-bindings / self-obj) alt (obj_self) { @@ -424,7 +473,7 @@ fn type_of_fn_full(@crate_ctxt cx, atys += t; } case (_) { - atys += T_opaque_closure_ptr(); + atys += T_opaque_closure_ptr(cx.tn); } } @@ -434,7 +483,7 @@ fn type_of_fn_full(@crate_ctxt cx, ty.count_ty_params(plain_ty(ty.ty_fn(inputs, output))); auto i = 0u; while (i < ty_param_count) { - atys += T_ptr(T_tydesc()); + atys += T_ptr(T_tydesc(cx.tn)); i += 1u; } } @@ -443,7 +492,8 @@ fn type_of_fn_full(@crate_ctxt cx, // If it's an iter, the 'output' type of the iter is actually the // *input* type of the function we're given as our iter-block // argument. - atys += T_fn_pair(type_of_fn_full(cx, false, none[TypeRef], + atys += T_fn_pair(cx.tn, + type_of_fn_full(cx, false, none[TypeRef], vec(rec(mode=ast.val, ty=output)), plain_ty(ty.ty_nil))); } @@ -515,10 +565,10 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { } case (ty.ty_fn(?args, ?out)) { // FIXME: put iter in ty_fn. - ret T_fn_pair(type_of_fn(cx, false, args, out)); + ret T_fn_pair(cx.tn, type_of_fn(cx, false, args, out)); } case (ty.ty_native_fn(?args, ?out)) { - ret T_fn_pair(type_of_native_fn(cx, args, out)); + ret T_fn_pair(cx.tn, type_of_native_fn(cx, args, out)); } case (ty.ty_obj(?meths)) { auto th = mk_type_handle(); @@ -536,7 +586,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { } let TypeRef vtbl = T_struct(mtys); let TypeRef pair = T_struct(vec(T_ptr(vtbl), - T_opaque_obj_ptr())); + T_opaque_obj_ptr(cx.tn))); auto abs_pair = llvm.LLVMResolveTypeHandle(th.llth); llvm.LLVMRefineType(abs_pair, pair); @@ -548,9 +598,9 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { fail; } case (ty.ty_param(_)) { - ret T_typaram_ptr(); + ret T_typaram_ptr(cx.tn); } - case (ty.ty_type) { ret T_ptr(T_tydesc()); } + case (ty.ty_type) { ret T_ptr(T_tydesc(cx.tn)); } } fail; } @@ -686,11 +736,11 @@ fn decl_fastcall_fn(ModuleRef llmod, str name, TypeRef llty) -> ValueRef { ret decl_fn(llmod, name, lib.llvm.LLVMFastCallConv, llty); } -fn decl_glue(ModuleRef llmod, str s) -> ValueRef { - ret decl_cdecl_fn(llmod, s, T_fn(vec(T_taskptr()), T_void())); +fn decl_glue(ModuleRef llmod, type_names tn, str s) -> ValueRef { + ret decl_cdecl_fn(llmod, s, T_fn(vec(T_taskptr(tn)), T_void())); } -fn decl_upcall_glue(ModuleRef llmod, uint _n) -> ValueRef { +fn decl_upcall_glue(ModuleRef llmod, type_names tn, uint _n) -> ValueRef { // It doesn't actually matter what type we come up with here, at the // moment, as we cast the upcall function pointers to int before passing // them to the indirect upcall-invocation glue. But eventually we'd like @@ -698,7 +748,7 @@ fn decl_upcall_glue(ModuleRef llmod, uint _n) -> ValueRef { let int n = _n as int; let str s = abi.upcall_glue_name(n); let vec[TypeRef] args = - vec(T_taskptr(), // taskptr + vec(T_taskptr(tn), // taskptr T_int()) // callee + _vec.init_elt[TypeRef](T_int(), n as uint); @@ -709,7 +759,7 @@ fn get_upcall(@crate_ctxt cx, str name, int n_args) -> ValueRef { if (cx.upcalls.contains_key(name)) { ret cx.upcalls.get(name); } - auto inputs = vec(T_taskptr()); + auto inputs = vec(T_taskptr(cx.tn)); inputs += _vec.init_elt[TypeRef](T_int(), n_args as uint); auto output = T_int(); auto f = decl_cdecl_fn(cx.llmod, name, T_fn(inputs, output)); @@ -1064,7 +1114,8 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { auto root = cx.fcx.ccx.tydescs.get(t); - auto tydescs = cx.build.Alloca(T_array(T_ptr(T_tydesc()), n_params)); + auto tydescs = cx.build.Alloca(T_array(T_ptr(T_tydesc(cx.fcx.ccx.tn)), + n_params)); auto i = 0; auto tdp = cx.build.GEP(tydescs, vec(C_int(0), C_int(i))); @@ -1089,7 +1140,8 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { C_int((1u + n_params) as int), bcx.build.PtrToInt(tydescs, T_int()))); - ret res(v.bcx, v.bcx.build.IntToPtr(v.val, T_ptr(T_tydesc()))); + ret res(v.bcx, v.bcx.build.IntToPtr(v.val, + T_ptr(T_tydesc(cx.fcx.ccx.tn)))); } // Otherwise, generate a tydesc if necessary, and return it. @@ -1107,7 +1159,7 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { auto drop_glue = make_generic_glue(cx, t, "drop", dg, typaram_defs); auto llty = type_of(cx, t); - auto glue_fn_ty = T_ptr(T_glue_fn()); + auto glue_fn_ty = T_ptr(T_glue_fn(cx.tn)); // FIXME: this adjustment has to do with the ridiculous encoding of // glue-pointer-constants in the tydesc records: They are tydesc-relative @@ -1120,8 +1172,9 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { } auto name = sanitize(cx.names.next("tydesc_" + ty.ty_to_str(t))); - auto gvar = llvm.LLVMAddGlobal(cx.llmod, T_tydesc(), _str.buf(name)); - auto tydesc = C_struct(vec(C_null(T_ptr(T_ptr(T_tydesc()))), + auto gvar = llvm.LLVMAddGlobal(cx.llmod, T_tydesc(cx.tn), + _str.buf(name)); + auto tydesc = C_struct(vec(C_null(T_ptr(T_ptr(T_tydesc(cx.tn)))), llsize_of(llty), llalign_of(llty), off(gvar, take_glue), // take_glue_off @@ -1142,7 +1195,7 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { fn make_generic_glue(@crate_ctxt cx, @ty.t t, str name, val_and_ty_fn helper, vec[ast.def_id] typaram_defs) -> ValueRef { - auto llfnty = T_glue_fn(); + auto llfnty = T_glue_fn(cx.tn); auto fn_name = cx.names.next("_rust_" + name) + sep() + ty.ty_to_str(t); fn_name = sanitize(fn_name); @@ -2793,7 +2846,8 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, let @ty.t bindings_ty = plain_ty(ty.ty_tup(bound_tys)); let TypeRef lltarget_ty = type_of(bcx.fcx.ccx, ty.expr_ty(f)); let TypeRef llbindings_ty = type_of(bcx.fcx.ccx, bindings_ty); - let TypeRef llclosure_ty = T_closure_ptr(lltarget_ty, + let TypeRef llclosure_ty = T_closure_ptr(cx.fcx.ccx.tn, + lltarget_ty, llbindings_ty); // Malloc a box for the body. @@ -2854,9 +2908,11 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, auto pair_box = bcx.build.GEP(pair_v, vec(C_int(0), C_int(abi.fn_field_box))); - bcx.build.Store(bcx.build.PointerCast(box, - T_opaque_closure_ptr()), - pair_box); + bcx.build.Store + (bcx.build.PointerCast + (box, + T_opaque_closure_ptr(bcx.fcx.ccx.tn)), + pair_box); find_scope_cx(cx).cleanups += clean(bind drop_slot(_, pair_v, pair_ty)); @@ -2903,7 +2959,8 @@ fn trans_args(@block_ctxt cx, } } if (ty.type_has_dynamic_size(retty)) { - llargs += bcx.build.PointerCast(llretslot, T_typaram_ptr()); + llargs += bcx.build.PointerCast(llretslot, + T_typaram_ptr(cx.fcx.ccx.tn)); } else if (ty.count_ty_params(retty) != 0u) { // It's possible that the callee has some generic-ness somewhere in // its return value -- say a method signature within an obj or a fn @@ -2979,7 +3036,8 @@ fn trans_args(@block_ctxt cx, } if (ty.type_has_dynamic_size(args.(i).ty)) { - val = bcx.build.PointerCast(val, T_typaram_ptr()); + val = bcx.build.PointerCast(val, + T_typaram_ptr(cx.fcx.ccx.tn)); } llargs += val; @@ -2993,7 +3051,7 @@ fn trans_call(@block_ctxt cx, @ast.expr f, vec[@ast.expr] args, &ast.ann ann) -> result { auto f_res = trans_lval(cx, f); auto faddr = f_res.res.val; - auto llenv = C_null(T_opaque_closure_ptr()); + auto llenv = C_null(T_opaque_closure_ptr(cx.fcx.ccx.tn)); alt (f_res.llobj) { case (some[ValueRef](_)) { @@ -3036,7 +3094,6 @@ fn trans_call(@block_ctxt cx, @ast.expr f, find_scope_cx(cx).cleanups += clean(bind drop_ty(_, retval, ret_ty)); } - // log "call-result type: " + val_str(retval); ret res(bcx, retval); } @@ -3767,7 +3824,7 @@ fn populate_fn_ctxt_from_llself(@block_ctxt cx, ValueRef llself) { } auto n_typarams = _vec.len[ast.ty_param](cx.fcx.ccx.obj_typarams); - let TypeRef llobj_box_ty = T_obj_ptr(n_typarams, + let TypeRef llobj_box_ty = T_obj_ptr(cx.fcx.ccx.tn, n_typarams, T_struct(llfield_tys)); auto box_cell = @@ -3925,7 +3982,7 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, C_int(abi.obj_field_box))); bcx.build.Store(vtbl, pair_vtbl); - let TypeRef llbox_ty = T_opaque_obj_ptr(); + let TypeRef llbox_ty = T_opaque_obj_ptr(cx.tn); if (_vec.len[ast.ty_param](ty_params) == 0u && _vec.len[ty.arg](arg_tys) == 0u) { @@ -4175,7 +4232,7 @@ fn decl_fn_and_pair(@crate_ctxt cx, let ValueRef gvar = llvm.LLVMAddGlobal(cx.llmod, llpairty, _str.buf(ps)); auto pair = C_struct(vec(llfn, - C_null(T_opaque_closure_ptr()))); + C_null(T_opaque_closure_ptr(cx.tn)))); llvm.LLVMSetInitializer(gvar, pair); llvm.LLVMSetGlobalConstant(gvar, True); @@ -4438,7 +4495,7 @@ fn trans_exit_task_glue(@crate_ctxt cx) { let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 0u); auto fcx = @rec(llfn=llfn, lltaskptr=lltaskptr, - llenv=C_null(T_opaque_closure_ptr()), + llenv=C_null(T_opaque_closure_ptr(cx.tn)), llretptr=C_null(T_ptr(T_nil())), mutable llself=none[ValueRef], mutable lliterbody=none[ValueRef], @@ -4454,9 +4511,9 @@ fn trans_exit_task_glue(@crate_ctxt cx) { } fn create_typedefs(@crate_ctxt cx) { - llvm.LLVMAddTypeName(cx.llmod, _str.buf("rust_crate"), T_crate()); - llvm.LLVMAddTypeName(cx.llmod, _str.buf("rust_task"), T_task()); - llvm.LLVMAddTypeName(cx.llmod, _str.buf("rust_tydesc"), T_tydesc()); + llvm.LLVMAddTypeName(cx.llmod, _str.buf("crate"), T_crate(cx.tn)); + llvm.LLVMAddTypeName(cx.llmod, _str.buf("task"), T_task(cx.tn)); + llvm.LLVMAddTypeName(cx.llmod, _str.buf("tydesc"), T_tydesc(cx.tn)); } fn create_crate_constant(@crate_ctxt cx) { @@ -4568,8 +4625,8 @@ fn check_module(ModuleRef llmod) { // TODO: run the linter here also, once there are llvm-c bindings for it. } -fn make_no_op_type_glue(ModuleRef llmod) -> ValueRef { - auto ty = T_fn(vec(T_taskptr(), T_ptr(T_i8())), T_void()); +fn make_no_op_type_glue(ModuleRef llmod, type_names tn) -> ValueRef { + auto ty = T_fn(vec(T_taskptr(tn), T_ptr(T_i8())), T_void()); auto fun = decl_fastcall_fn(llmod, abi.no_op_type_glue_name(), ty); auto bb_name = _str.buf("_rust_no_op_type_glue_bb"); auto llbb = llvm.LLVMAppendBasicBlock(fun, bb_name); @@ -4663,9 +4720,9 @@ fn make_bzero_glue(ModuleRef llmod) -> ValueRef { ret fun; } -fn make_glues(ModuleRef llmod) -> @glue_fns { - ret @rec(activate_glue = decl_glue(llmod, abi.activate_glue_name()), - yield_glue = decl_glue(llmod, abi.yield_glue_name()), +fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns { + ret @rec(activate_glue = decl_glue(llmod, tn, abi.activate_glue_name()), + yield_glue = decl_glue(llmod, tn, abi.yield_glue_name()), /* * Note: the signature passed to decl_cdecl_fn here looks unusual * because it is. It corresponds neither to an upcall signature @@ -4677,12 +4734,13 @@ fn make_glues(ModuleRef llmod) -> @glue_fns { * this is the signature required to retrieve it. */ exit_task_glue = decl_cdecl_fn(llmod, abi.exit_task_glue_name(), - T_fn(vec(T_taskptr()), T_void())), + T_fn(vec(T_taskptr(tn)), + T_void())), upcall_glues = - _vec.init_fn[ValueRef](bind decl_upcall_glue(llmod, _), + _vec.init_fn[ValueRef](bind decl_upcall_glue(llmod, tn, _), abi.n_upcall_glues as uint), - no_op_type_glue = make_no_op_type_glue(llmod), + no_op_type_glue = make_no_op_type_glue(llmod, tn), memcpy_glue = make_memcpy_glue(llmod), bzero_glue = make_bzero_glue(llmod)); } @@ -4696,14 +4754,15 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, llvm.LLVMSetDataLayout(llmod, _str.buf(x86.get_data_layout())); llvm.LLVMSetTarget(llmod, _str.buf(x86.get_target_triple())); auto td = mk_target_data(x86.get_data_layout()); + auto tn = mk_type_names(); let ValueRef crate_ptr = - llvm.LLVMAddGlobal(llmod, T_crate(), _str.buf("rust_crate")); + llvm.LLVMAddGlobal(llmod, T_crate(tn), _str.buf("rust_crate")); llvm.LLVMSetModuleInlineAsm(llmod, _str.buf(x86.get_module_asm())); auto intrinsics = declare_intrinsics(llmod); - auto glues = make_glues(llmod); + auto glues = make_glues(llmod, tn); auto hasher = ty.hash_ty; auto eqer = ty.eq_ty; auto tydescs = map.mk_hashmap[@ty.t,ValueRef](hasher, eqer); @@ -4713,6 +4772,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, auto cx = @rec(sess = sess, llmod = llmod, td = td, + tn = tn, crate_ptr = crate_ptr, upcalls = new_str_hash[ValueRef](), intrinsics = intrinsics, -- cgit v1.2.3 From 3aba50ff331f4d97b1ca2a60091b03e012837b98 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 18 Feb 2011 14:52:33 -0800 Subject: Implement Robinson's algorithm for type unification. Closes #227. --- src/comp/middle/ty.rs | 145 ++++++++++++++++++++++++-------------------------- 1 file changed, 70 insertions(+), 75 deletions(-) diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index e8f5b046..a9a4e936 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -570,24 +570,6 @@ fn count_ty_params(@t ty) -> uint { ret _vec.len[ast.def_id](*param_ids); } -fn type_contains_ty_vars(@t ty) -> bool { - state obj checker(@mutable bool has_vars) { - fn fold_simple_ty(@t ty) -> @t { - alt (ty.struct) { - case (ty_var(_)) { - *has_vars = true; - } - case (_) {} - } - ret ty; - } - } - - let @mutable bool b = @mutable false; - fold_ty(checker(b), ty); - ret *b; -} - // Type accessors for substructures of types fn ty_fn_args(@t fty) -> vec[arg] { @@ -802,7 +784,10 @@ fn is_lval(@ast.expr expr) -> bool { } } -// Type unification +// Type unification via Robinson's algorithm (Robinson 1965). Implemented as +// described in Hoder and Voronkov: +// +// http://www.cs.man.ac.uk/~hoderk/ubench/unification_full.pdf fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) -> unify_result { @@ -822,7 +807,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) ret ures_err(terr_mismatch, expected, actual); } - fn unify_fn(&hashmap[int,@ty.t] bindings, + fn unify_fn(@hashmap[int,@ty.t] bindings, @ty.t expected, @ty.t actual, &unify_handler handler, @@ -891,7 +876,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) } - fn unify_obj(&hashmap[int,@ty.t] bindings, + fn unify_obj(@hashmap[int,@ty.t] bindings, @ty.t expected, @ty.t actual, &unify_handler handler, @@ -952,27 +937,44 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) ret ures_ok(t); } - fn unify_step(&hashmap[int,@ty.t] bindings, @ty.t expected, @ty.t actual, - &unify_handler handler) -> unify_result { + fn resolve(@hashmap[int,@t] bindings, @t typ) -> @t { + alt (typ.struct) { + case (ty_var(?id)) { + alt (bindings.find(id)) { + case (some[@t](?typ2)) { + ret resolve(bindings, typ2); + } + case (none[@t]) { + // fall through + } + } + } + case (_) { + // fall through + } + } + ret typ; + } + + fn unify_step(@hashmap[int,@ty.t] bindings, @ty.t in_expected, + @ty.t in_actual, &unify_handler handler) -> unify_result { + + // Resolve any bindings. + auto expected = resolve(bindings, in_expected); + auto actual = resolve(bindings, in_actual); + // TODO: rewrite this using tuple pattern matching when available, to // avoid all this rightward drift and spikiness. + // TODO: occurs check, to make sure we don't loop forever when + // unifying e.g. 'a and option['a] + alt (actual.struct) { // If the RHS is a variable type, then just do the appropriate // binding. case (ty.ty_var(?actual_id)) { - alt (bindings.find(actual_id)) { - case (some[@ty.t](?actual_ty)) { - // FIXME: change the binding here? - // FIXME: "be" - ret unify_step(bindings, expected, actual_ty, - handler); - } - case (none[@ty.t]) { - bindings.insert(actual_id, expected); - ret ures_ok(expected); - } - } + bindings.insert(actual_id, expected); + ret ures_ok(expected); } case (ty.ty_local(?actual_id)) { auto actual_ty = handler.resolve_local(actual_id); @@ -1077,8 +1079,6 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) } } - // TODO: ty_var - case (_) { ret ures_err(terr_mismatch, expected, actual); } @@ -1102,8 +1102,6 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) } } - // TODO: ty_var - case (_) { ret ures_err(terr_mismatch, expected, actual); } @@ -1152,8 +1150,6 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) ret ures_ok(plain_ty(ty.ty_tup(result_elems))); } - // TODO: ty_var - case (_) { ret ures_err(terr_mismatch, expected, actual); } @@ -1213,8 +1209,6 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) ret ures_ok(plain_ty(ty.ty_rec(result_fields))); } - // TODO: ty_var - case (_) { ret ures_err(terr_mismatch, expected, actual); } @@ -1248,20 +1242,9 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) } case (ty.ty_var(?expected_id)) { - alt (bindings.find(expected_id)) { - case (some[@ty.t](?expected_ty)) { - // FIXME: change the binding here? - // FIXME: "be" - ret unify_step(bindings, - expected_ty, - actual, - handler); - } - case (none[@ty.t]) { - bindings.insert(expected_id, actual); - ret ures_ok(actual); - } - } + // Add a binding. + bindings.insert(expected_id, actual); + ret ures_ok(actual); } case (ty.ty_local(?expected_id)) { @@ -1289,31 +1272,43 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) fail; } + // Performs type binding substitution. + fn substitute(@hashmap[int,@t] bindings, @t typ) -> @t { + state obj folder(@hashmap[int,@t] bindings) { + fn fold_simple_ty(@t typ) -> @t { + alt (typ.struct) { + case (ty_var(?id)) { + alt (bindings.find(id)) { + case (some[@t](?typ2)) { + ret substitute(bindings, typ2); + } + case (none[@t]) { + ret typ; + } + } + } + case (_) { + ret typ; + } + } + } + } + + ret ty.fold_ty(folder(bindings), typ); + } + fn hash_int(&int x) -> uint { ret x as uint; } 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.t](hasher, eqer); - - // FIXME: this is a slow way of driving types into residual vars that - // occur up in the leaves of result type; it can likely be done better - // when unification is actually ... down in the leaves. + auto bindings = @map.mk_hashmap[int,@ty.t](hasher, eqer); auto ures = unify_step(bindings, expected, actual, handler); - while (true) { - alt (ures) { - case (ures_ok(?t)) { - if (!type_contains_ty_vars(t)) { - ret ures; - } - ures = unify_step(bindings, t, actual, handler); - } - case (_) { - ret ures; - } - } + alt (ures) { + case (ures_ok(?t)) { ret ures_ok(substitute(bindings, t)); } + case (_) { ret ures; } } - fail; + fail; // not reached } fn type_err_to_str(&ty.type_err err) -> str { -- cgit v1.2.3 From 34c60b6edb810d9f142d248b27d8e6e34c95d63c Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 18 Feb 2011 17:30:57 -0800 Subject: Make a tag for iterness / fnness, teach many places about it. --- src/comp/front/ast.rs | 12 ++- src/comp/front/parser.rs | 90 +++++++++-------- src/comp/middle/fold.rs | 38 ++++---- src/comp/middle/trans.rs | 102 +++++++++++-------- src/comp/middle/ty.rs | 243 ++++++++++++++++++++++++++-------------------- src/comp/middle/typeck.rs | 46 +++++---- 6 files changed, 303 insertions(+), 228 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index ee358432..01739d19 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -78,6 +78,11 @@ tag effect { eff_unsafe; } +tag proto { + proto_iter; + proto_fn; +} + tag binop { add; sub; @@ -187,7 +192,8 @@ tag lit_ { type ty_field = rec(ident ident, @ty ty); type ty_arg = rec(mode mode, @ty ty); // TODO: effect -type ty_method = rec(ident ident, vec[ty_arg] inputs, @ty output); +type ty_method = rec(proto proto, ident ident, + vec[ty_arg] inputs, @ty output); type ty = spanned[ty_]; tag ty_ { ty_nil; @@ -201,7 +207,7 @@ tag ty_ { ty_vec(@ty); ty_tup(vec[@ty]); ty_rec(vec[ty_field]); - ty_fn(vec[ty_arg], @ty); // TODO: effect + ty_fn(proto, vec[ty_arg], @ty); // TODO: effect ty_obj(vec[ty_method]); ty_path(path, option.t[def]); ty_mutable(@ty); @@ -210,10 +216,10 @@ tag ty_ { type arg = rec(mode mode, @ty ty, ident ident, def_id id); type fn_decl = rec(effect effect, + proto proto, vec[arg] inputs, @ty output); type _fn = rec(fn_decl decl, - bool is_iter, block body); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index a108d243..71b06b45 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -133,7 +133,8 @@ impure fn parse_str_lit(parser p) -> ast.ident { } -impure fn parse_ty_fn(parser p, ast.span lo) -> ast.ty_ { +impure fn parse_ty_fn(ast.proto proto, parser p, + ast.span lo) -> ast.ty_ { impure fn parse_fn_input_ty(parser p) -> rec(ast.mode mode, @ast.ty ty) { auto mode; if (p.peek() == token.BINOP(token.AND)) { @@ -167,7 +168,16 @@ impure fn parse_ty_fn(parser p, ast.span lo) -> ast.ty_ { output = @spanned(lo, inputs.span, ast.ty_nil); } - ret ast.ty_fn(inputs.node, output); + ret ast.ty_fn(proto, inputs.node, output); +} + +impure fn parse_proto(parser p) -> ast.proto { + alt (p.peek()) { + case (token.ITER) { p.bump(); ret ast.proto_iter; } + case (token.FN) { p.bump(); ret ast.proto_fn; } + case (?t) { unexpected(p, t); } + } + fail; } impure fn parse_ty_obj(parser p, &mutable ast.span hi) -> ast.ty_ { @@ -177,14 +187,14 @@ impure fn parse_ty_obj(parser p, &mutable ast.span hi) -> ast.ty_ { // FIXME: do something with this, currently it's dropped on the floor. let ast.effect eff = parse_effect(p); - - expect(p, token.FN); + let ast.proto proto = parse_proto(p); auto ident = parse_ident(p); - auto f = parse_ty_fn(p, flo); + auto f = parse_ty_fn(proto, p, flo); expect(p, token.SEMI); alt (f) { - case (ast.ty_fn(?inputs, ?output)) { - ret rec(ident=ident, inputs=inputs, output=output); + case (ast.ty_fn(?proto, ?inputs, ?output)) { + ret rec(proto=proto, ident=ident, + inputs=inputs, output=output); } } fail; @@ -286,9 +296,20 @@ impure fn parse_ty(parser p) -> @ast.ty { case (token.FN) { auto flo = p.get_span(); p.bump(); - t = parse_ty_fn(p, flo); + t = parse_ty_fn(ast.proto_fn, p, flo); alt (t) { - case (ast.ty_fn(_, ?out)) { + case (ast.ty_fn(_, _, ?out)) { + hi = out.span; + } + } + } + + case (token.ITER) { + auto flo = p.get_span(); + p.bump(); + t = parse_ty_fn(ast.proto_iter, p, flo); + alt (t) { + case (ast.ty_fn(_, _, ?out)) { hi = out.span; } } @@ -1537,7 +1558,8 @@ impure fn parse_ty_params(parser p) -> vec[ast.ty_param] { ret ty_params; } -impure fn parse_fn_decl(parser p, ast.effect eff) -> ast.fn_decl { +impure fn parse_fn_decl(parser p, ast.proto proto, + ast.effect eff) -> ast.fn_decl { auto pf = parse_arg; let util.common.spanned[vec[ast.arg]] inputs = // FIXME: passing parse_arg as an lval doesn't work at the @@ -1555,35 +1577,30 @@ impure fn parse_fn_decl(parser p, ast.effect eff) -> ast.fn_decl { } else { output = @spanned(inputs.span, inputs.span, ast.ty_nil); } - ret rec(effect=eff, inputs=inputs.node, output=output); + ret rec(effect=eff, proto=proto, + inputs=inputs.node, output=output); } -impure fn parse_fn(parser p, ast.effect eff, bool is_iter) -> ast._fn { - auto decl = parse_fn_decl(p, eff); +impure fn parse_fn(parser p, ast.effect eff, ast.proto proto) -> ast._fn { + auto decl = parse_fn_decl(p, proto, eff); auto body = parse_block(p); ret rec(decl = decl, - is_iter = is_iter, body = body); } -impure fn parse_fn_header(parser p, bool is_iter) -> tup(span, ast.ident, - vec[ast.ty_param]) { +impure fn parse_fn_header(parser p) + -> tup(span, ast.proto, ast.ident, vec[ast.ty_param]) { auto lo = p.get_span(); - if (is_iter) { - expect(p, token.ITER); - } else { - expect(p, token.FN); - } + auto proto = parse_proto(p); auto id = parse_ident(p); auto ty_params = parse_ty_params(p); - ret tup(lo, id, ty_params); + ret tup(lo, proto, id, ty_params); } -impure fn parse_item_fn_or_iter(parser p, ast.effect eff, - bool is_iter) -> @ast.item { - auto t = parse_fn_header(p, is_iter); - auto f = parse_fn(p, eff, is_iter); - auto item = ast.item_fn(t._1, f, t._2, +impure fn parse_item_fn_or_iter(parser p, ast.effect eff) -> @ast.item { + auto t = parse_fn_header(p); + auto f = parse_fn(p, eff, t._1); + auto item = ast.item_fn(t._2, f, t._3, p.next_def_id(), ast.ann_none); ret @spanned(t._0, f.body.span, item); } @@ -1598,14 +1615,9 @@ impure fn parse_obj_field(parser p) -> ast.obj_field { impure fn parse_method(parser p) -> @ast.method { auto lo = p.get_span(); auto eff = parse_effect(p); - auto is_iter = false; - alt (p.peek()) { - case (token.FN) { p.bump(); } - case (token.ITER) { p.bump(); is_iter = true; } - case (?t) { unexpected(p, t); } - } + auto proto = parse_proto(p); auto ident = parse_ident(p); - auto f = parse_fn(p, eff, is_iter); + auto f = parse_fn(p, eff, proto); auto meth = rec(ident=ident, meth=f, id=p.next_def_id(), ann=ast.ann_none); ret @spanned(lo, f.body.span, meth); @@ -1689,11 +1701,11 @@ impure fn parse_item_native_type(parser p) -> @ast.native_item { } impure fn parse_item_native_fn(parser p, ast.effect eff) -> @ast.native_item { - auto t = parse_fn_header(p, false); - auto decl = parse_fn_decl(p, eff); + auto t = parse_fn_header(p); + auto decl = parse_fn_decl(p, t._1, eff); auto hi = p.get_span(); expect(p, token.SEMI); - auto item = ast.native_item_fn(t._1, decl, t._2, p.next_def_id(), + auto item = ast.native_item_fn(t._2, decl, t._3, p.next_def_id(), ast.ann_none); ret @spanned(t._0, hi, item); } @@ -1883,11 +1895,11 @@ impure fn parse_item(parser p) -> @ast.item { case (token.FN) { check (lyr == ast.layer_value); - ret parse_item_fn_or_iter(p, eff, false); + ret parse_item_fn_or_iter(p, eff); } case (token.ITER) { check (lyr == ast.layer_value); - ret parse_item_fn_or_iter(p, eff, true); + ret parse_item_fn_or_iter(p, eff); } case (token.MOD) { check (eff == ast.eff_pure); diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index db215ea9..abe94b89 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -59,6 +59,7 @@ type ast_fold[ENV] = vec[ast.ty_method] meths) -> @ty) fold_ty_obj, (fn(&ENV e, &span sp, + ast.proto proto, vec[rec(ast.mode mode, @ty ty)] inputs, @ty output) -> @ty) fold_ty_fn, @@ -252,11 +253,10 @@ type ast_fold[ENV] = &ast.block_) -> block) fold_block, (fn(&ENV e, &fn_decl decl, - bool is_iter, &block body) -> ast._fn) fold_fn, (fn(&ENV e, ast.effect effect, - vec[arg] inputs, + ast.proto proto, vec[arg] inputs, @ty output) -> ast.fn_decl) fold_fn_decl, (fn(&ENV e, &ast._mod m) -> ast._mod) fold_mod, @@ -349,11 +349,13 @@ fn fold_ty[ENV](&ENV env, ast_fold[ENV] fld, @ty t) -> @ty { case (ast.ty_obj(?meths)) { let vec[ast.ty_method] meths_ = vec(); for (ast.ty_method m in meths) { - auto tfn = fold_ty_fn(env_, fld, t.span, m.inputs, m.output); + auto tfn = fold_ty_fn(env_, fld, t.span, m.proto, + m.inputs, m.output); alt (tfn.node) { - case (ast.ty_fn(?ins, ?out)) { + case (ast.ty_fn(?p, ?ins, ?out)) { append[ast.ty_method] - (meths_, rec(inputs=ins, output=out with m)); + (meths_, rec(proto=p, inputs=ins, output=out + with m)); } } } @@ -370,13 +372,14 @@ fn fold_ty[ENV](&ENV env, ast_fold[ENV] fld, @ty t) -> @ty { ret fld.fold_ty_mutable(env_, t.span, ty_); } - case (ast.ty_fn(?inputs, ?output)) { - ret fold_ty_fn(env_, fld, t.span, inputs, output); + case (ast.ty_fn(?proto, ?inputs, ?output)) { + ret fold_ty_fn(env_, fld, t.span, proto, inputs, output); } } } fn fold_ty_fn[ENV](&ENV env, ast_fold[ENV] fld, &span sp, + ast.proto proto, vec[rec(ast.mode mode, @ty ty)] inputs, @ty output) -> @ty { auto output_ = fold_ty(env, fld, output); @@ -386,7 +389,7 @@ fn fold_ty_fn[ENV](&ENV env, ast_fold[ENV] fld, &span sp, auto input_ = rec(ty=ty_ with input); inputs_ += vec(input_); } - ret fld.fold_ty_fn(env, sp, inputs_, output_); + ret fld.fold_ty_fn(env, sp, proto, inputs_, output_); } fn fold_decl[ENV](&ENV env, ast_fold[ENV] fld, @decl d) -> @decl { @@ -754,7 +757,7 @@ fn fold_fn_decl[ENV](&ENV env, ast_fold[ENV] fld, inputs += fold_arg(env, fld, a); } auto output = fold_ty[ENV](env, fld, decl.output); - ret fld.fold_fn_decl(env, decl.effect, inputs, output); + ret fld.fold_fn_decl(env, decl.effect, decl.proto, inputs, output); } fn fold_fn[ENV](&ENV env, ast_fold[ENV] fld, &ast._fn f) -> ast._fn { @@ -762,7 +765,7 @@ fn fold_fn[ENV](&ENV env, ast_fold[ENV] fld, &ast._fn f) -> ast._fn { auto body = fold_block[ENV](env, fld, f.body); - ret fld.fold_fn(env, decl, f.is_iter, body); + ret fld.fold_fn(env, decl, body); } @@ -1019,9 +1022,10 @@ fn identity_fold_ty_obj[ENV](&ENV env, &span sp, } fn identity_fold_ty_fn[ENV](&ENV env, &span sp, + ast.proto proto, vec[rec(ast.mode mode, @ty ty)] inputs, @ty output) -> @ty { - ret @respan(sp, ast.ty_fn(inputs, output)); + ret @respan(sp, ast.ty_fn(proto, inputs, output)); } fn identity_fold_ty_path[ENV](&ENV env, &span sp, ast.path p, @@ -1301,16 +1305,16 @@ fn identity_fold_block[ENV](&ENV e, &span sp, &ast.block_ blk) -> block { fn identity_fold_fn_decl[ENV](&ENV e, ast.effect effect, + ast.proto proto, vec[arg] inputs, @ty output) -> ast.fn_decl { - ret rec(effect=effect, inputs=inputs, output=output); + ret rec(effect=effect, proto=proto, inputs=inputs, output=output); } fn identity_fold_fn[ENV](&ENV e, &fn_decl decl, - bool is_iter, &block body) -> ast._fn { - ret rec(decl=decl, is_iter=is_iter, body=body); + ret rec(decl=decl, body=body); } fn identity_fold_mod[ENV](&ENV e, &ast._mod m) -> ast._mod { @@ -1404,7 +1408,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_ty_tup = bind identity_fold_ty_tup[ENV](_,_,_), fold_ty_rec = bind identity_fold_ty_rec[ENV](_,_,_), fold_ty_obj = bind identity_fold_ty_obj[ENV](_,_,_), - fold_ty_fn = bind identity_fold_ty_fn[ENV](_,_,_,_), + fold_ty_fn = bind identity_fold_ty_fn[ENV](_,_,_,_,_), fold_ty_path = bind identity_fold_ty_path[ENV](_,_,_,_), fold_ty_mutable = bind identity_fold_ty_mutable[ENV](_,_,_), @@ -1470,8 +1474,8 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { bind identity_fold_view_item_import[ENV](_,_,_,_,_,_), fold_block = bind identity_fold_block[ENV](_,_,_), - fold_fn = bind identity_fold_fn[ENV](_,_,_,_), - fold_fn_decl = bind identity_fold_fn_decl[ENV](_,_,_,_), + fold_fn = bind identity_fold_fn[ENV](_,_,_), + fold_fn_decl = bind identity_fold_fn_decl[ENV](_,_,_,_,_), fold_mod = bind identity_fold_mod[ENV](_,_), fold_native_mod = bind identity_fold_native_mod[ENV](_,_), fold_crate = bind identity_fold_crate[ENV](_,_,_), diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 538dfdbe..03d1fad9 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -449,8 +449,7 @@ fn type_of_explicit_args(@crate_ctxt cx, // - trans_args fn type_of_fn_full(@crate_ctxt cx, - // FIXME: change bool flag to tag - bool is_iter, + ast.proto proto, option.t[TypeRef] obj_self, vec[ty.arg] inputs, @ty.t output) -> TypeRef { @@ -480,7 +479,9 @@ fn type_of_fn_full(@crate_ctxt cx, // Args >3: ty params, if not acquired via capture... if (obj_self == none[TypeRef]) { auto ty_param_count = - ty.count_ty_params(plain_ty(ty.ty_fn(inputs, output))); + ty.count_ty_params(plain_ty(ty.ty_fn(proto, + inputs, + output))); auto i = 0u; while (i < ty_param_count) { atys += T_ptr(T_tydesc(cx.tn)); @@ -488,12 +489,12 @@ fn type_of_fn_full(@crate_ctxt cx, } } - if (is_iter) { + if (proto == ast.proto_iter) { // If it's an iter, the 'output' type of the iter is actually the // *input* type of the function we're given as our iter-block // argument. atys += T_fn_pair(cx.tn, - type_of_fn_full(cx, false, none[TypeRef], + type_of_fn_full(cx, ast.proto_fn, none[TypeRef], vec(rec(mode=ast.val, ty=output)), plain_ty(ty.ty_nil))); } @@ -505,10 +506,9 @@ fn type_of_fn_full(@crate_ctxt cx, } fn type_of_fn(@crate_ctxt cx, - // FIXME: change bool flag to tag - bool is_iter, + ast.proto proto, vec[ty.arg] inputs, @ty.t output) -> TypeRef { - ret type_of_fn_full(cx, is_iter, none[TypeRef], inputs, output); + ret type_of_fn_full(cx, proto, none[TypeRef], inputs, output); } fn type_of_native_fn(@crate_ctxt cx, vec[ty.arg] inputs, @@ -563,9 +563,8 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { } ret T_struct(tys); } - case (ty.ty_fn(?args, ?out)) { - // FIXME: put iter in ty_fn. - ret T_fn_pair(cx.tn, type_of_fn(cx, false, args, out)); + case (ty.ty_fn(?proto, ?args, ?out)) { + ret T_fn_pair(cx.tn, type_of_fn(cx, proto, args, out)); } case (ty.ty_native_fn(?args, ?out)) { ret T_fn_pair(cx.tn, type_of_native_fn(cx, args, out)); @@ -577,9 +576,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { let vec[TypeRef] mtys = vec(); for (ty.method m in meths) { let TypeRef mty = - type_of_fn_full(cx, - // FIXME: support method iters - false, + type_of_fn_full(cx, m.proto, some[TypeRef](self_ty), m.inputs, m.output); mtys += T_ptr(mty); @@ -1339,7 +1336,7 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result { T_int(), C_int(0)); } - case (ty.ty_fn(_,_)) { + case (ty.ty_fn(_,_,_)) { fn hit_zero(@block_ctxt cx, ValueRef v) -> result { // Call through the closure's own fields-drop glue first. @@ -1440,7 +1437,7 @@ 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 (ty.ann_to_type(v.ann).struct) { - case (ty.ty_fn(?args, _)) { + case (ty.ty_fn(_, ?args, _)) { for (ty.arg arg in args) { lltys += vec(type_of(cx, arg.ty)); } @@ -1547,7 +1544,7 @@ fn iter_structural_ty(@block_ctxt cx, auto fn_ty = ty.ann_to_type(variants.(i).ann); alt (fn_ty.struct) { - case (ty.ty_fn(?args, _)) { + case (ty.ty_fn(_, ?args, _)) { auto llvarp = variant_cx.build. TruncOrBitCast(llunion_ptr, T_ptr(llvarty)); @@ -1584,7 +1581,7 @@ fn iter_structural_ty(@block_ctxt cx, ret res(next_cx, C_nil()); } - case (ty.ty_fn(_,_)) { + case (ty.ty_fn(_,_,_)) { auto box_cell = cx.build.GEP(v, vec(C_int(0), @@ -2264,17 +2261,18 @@ fn trans_for_each(@block_ctxt cx, // pointer along with the foreach-body-fn pointer into a 'normal' fn pair // and pass it in as a first class fn-arg to the iterator. - auto foreach_llty = type_of_fn_full(cx.fcx.ccx, false, none[TypeRef], - vec(rec(mode=ast.val, ty=decl_ty)), - plain_ty(ty.ty_nil)); + auto iter_body_llty = type_of_fn_full(cx.fcx.ccx, ast.proto_fn, + none[TypeRef], + vec(rec(mode=ast.val, ty=decl_ty)), + plain_ty(ty.ty_nil)); - let ValueRef llforeach = decl_fastcall_fn(cx.fcx.ccx.llmod, - s, foreach_llty); + let ValueRef lliterbody = decl_fastcall_fn(cx.fcx.ccx.llmod, + s, iter_body_llty); // FIXME: handle ty params properly. let vec[ast.ty_param] ty_params = vec(); - auto fcx = new_fn_ctxt(cx.fcx.ccx, s, llforeach); + auto fcx = new_fn_ctxt(cx.fcx.ccx, s, lliterbody); auto bcx = new_top_block_ctxt(fcx); // FIXME: populate lllocals from llenv here. @@ -2282,13 +2280,16 @@ fn trans_for_each(@block_ctxt cx, res.bcx.build.RetVoid(); - // Step 3: Call iter passing [llforeach, llenv], plus other args. + // Step 3: Call iter passing [lliterbody, llenv], plus other args. alt (seq.node) { case (ast.expr_call(?f, ?args, ?ann)) { - // FIXME_ finish here by transferring to trans_call, - // suitably refactored. - cx.fcx.ccx.sess.unimpl("for each loop in trans"); + + // log "lliterbody: " + val_str(cx.fcx.ccx.tn, lliterbody); + ret trans_call(cx, f, + some[ValueRef](lliterbody), + args, + ann); } } fail; @@ -2933,6 +2934,7 @@ fn trans_args(@block_ctxt cx, ValueRef llenv, option.t[ValueRef] llobj, option.t[generic_info] gen, + option.t[ValueRef] lliterbody, &vec[@ast.expr] es, @ty.t fn_ty) -> tup(@block_ctxt, vec[ValueRef], ValueRef) { @@ -2993,6 +2995,14 @@ fn trans_args(@block_ctxt cx, // Args >3: ty_params ... llargs += lltydescs; + // ... then possibly an lliterbody argument. + alt (lliterbody) { + case (none[ValueRef]) {} + case (some[ValueRef](?lli)) { + llargs += lli; + } + } + // ... then explicit args. auto i = 0u; for (@ast.expr e in es) { @@ -3048,7 +3058,9 @@ fn trans_args(@block_ctxt cx, } fn trans_call(@block_ctxt cx, @ast.expr f, - vec[@ast.expr] args, &ast.ann ann) -> result { + option.t[ValueRef] lliterbody, + vec[@ast.expr] args, + &ast.ann ann) -> result { auto f_res = trans_lval(cx, f); auto faddr = f_res.res.val; auto llenv = C_null(T_opaque_closure_ptr(cx.fcx.ccx.tn)); @@ -3077,12 +3089,21 @@ fn trans_call(@block_ctxt cx, @ast.expr f, auto args_res = trans_args(f_res.res.bcx, llenv, f_res.llobj, f_res.generic, + lliterbody, args, fn_ty); auto bcx = args_res._0; auto llargs = args_res._1; auto llretslot = args_res._2; + /* + log "calling: " + val_str(cx.fcx.ccx.tn, faddr); + + for (ValueRef arg in llargs) { + log "arg: " + val_str(cx.fcx.ccx.tn, arg); + } + */ + bcx.build.FastCall(faddr, llargs); auto retval = C_nil(); @@ -3308,7 +3329,7 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { } case (ast.expr_call(?f, ?args, ?ann)) { - ret trans_call(cx, f, args, ann); + ret trans_call(cx, f, none[ValueRef], args, ann); } case (ast.expr_cast(?e, _, ?ann)) { @@ -3707,8 +3728,7 @@ fn new_fn_ctxt(@crate_ctxt cx, // - trans_args fn create_llargs_for_fn_args(&@fn_ctxt cx, - // FIXME: change bool flag to tag - bool is_iter, + ast.proto proto, option.t[TypeRef] ty_self, @ty.t ret_ty, &vec[ast.arg] args, @@ -3733,7 +3753,7 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx, } } - if (is_iter) { + if (proto == ast.proto_iter) { auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n); check (llarg as int != 0); cx.lliterbody = some[ValueRef](llarg); @@ -3794,7 +3814,7 @@ fn is_terminated(@block_ctxt cx) -> bool { fn arg_tys_of_fn(ast.ann ann) -> vec[ty.arg] { alt (ty.ann_to_type(ann).struct) { - case (ty.ty_fn(?arg_tys, _)) { + case (ty.ty_fn(_, ?arg_tys, _)) { ret arg_tys; } } @@ -3803,7 +3823,7 @@ fn arg_tys_of_fn(ast.ann ann) -> vec[ty.arg] { fn ret_ty_of_fn_ty(@ty.t t) -> @ty.t { alt (t.struct) { - case (ty.ty_fn(_, ?ret_ty)) { + case (ty.ty_fn(_, _, ?ret_ty)) { ret ret_ty; } } @@ -3875,7 +3895,7 @@ fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid, cx.item_names.insert(cx.path, llfndecl); auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); - create_llargs_for_fn_args(fcx, f.is_iter, + create_llargs_for_fn_args(fcx, f.decl.proto, ty_self, ret_ty_of_fn(ann), f.decl.inputs, ty_params); auto bcx = new_top_block_ctxt(fcx); @@ -3915,10 +3935,8 @@ fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty, auto llfnty = T_nil(); alt (node_ann_type(cx, m.node.ann).struct) { - case (ty.ty_fn(?inputs, ?output)) { - llfnty = type_of_fn_full(cx, - // FIXME: support method iters. - false, + case (ty.ty_fn(?proto, ?inputs, ?output)) { + llfnty = type_of_fn_full(cx, proto, some[TypeRef](self_ty), inputs, output); } @@ -3962,7 +3980,7 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, } auto fcx = new_fn_ctxt(cx, cx.path, llctor_decl); - create_llargs_for_fn_args(fcx, false, + create_llargs_for_fn_args(fcx, ast.proto_fn, none[TypeRef], ret_ty_of_fn(ann), fn_args, ty_params); @@ -4091,7 +4109,7 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, let ValueRef llfndecl = cx.item_ids.get(variant.id); auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); - create_llargs_for_fn_args(fcx, false, + create_llargs_for_fn_args(fcx, ast.proto_fn, none[TypeRef], ret_ty_of_fn(variant.ann), fn_args, ty_params); diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index a9a4e936..68c21140 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -19,7 +19,10 @@ import util.common.span; 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); +type method = rec(ast.proto proto, + 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. @@ -37,7 +40,7 @@ tag sty { ty_vec(@t); ty_tup(vec[@t]); ty_rec(vec[field]); - ty_fn(vec[arg], @t); // TODO: effect + ty_fn(ast.proto, vec[arg], @t); // TODO: effect ty_native_fn(vec[arg], @t); // TODO: effect ty_obj(vec[method]); ty_var(int); // ephemeral type var @@ -122,9 +125,13 @@ fn ast_ty_to_str(&@ast.ty ty) -> str { s += ")"; } - case (ast.ty_fn(?inputs, ?output)) { + case (ast.ty_fn(?proto, ?inputs, ?output)) { auto f = ast_fn_input_to_str; - s = "fn("; + if (proto == ast.proto_fn) { + s = "fn("; + } else { + s = "iter("; + } auto is = _vec.map[rec(ast.mode mode, @ast.ty ty),str](f, inputs); s += _str.connect(is, ", "); s += ")"; @@ -175,10 +182,14 @@ fn ty_to_str(&@t typ) -> str { ret s + ty_to_str(input.ty); } - fn fn_to_str(option.t[ast.ident] ident, + fn fn_to_str(ast.proto proto, + option.t[ast.ident] ident, vec[arg] inputs, @t output) -> str { auto f = fn_input_to_str; auto s = "fn"; + if (proto == ast.proto_iter) { + s = "iter"; + } alt (ident) { case (some[ast.ident](?i)) { s += " "; @@ -198,7 +209,8 @@ fn ty_to_str(&@t typ) -> str { } fn method_to_str(&method m) -> str { - ret fn_to_str(some[ast.ident](m.ident), m.inputs, m.output) + ";"; + ret fn_to_str(m.proto, some[ast.ident](m.ident), + m.inputs, m.output) + ";"; } fn field_to_str(&field f) -> str { @@ -245,12 +257,12 @@ fn ty_to_str(&@t typ) -> str { } } - case (ty_fn(?inputs, ?output)) { - s = fn_to_str(none[ast.ident], inputs, output); + case (ty_fn(?proto, ?inputs, ?output)) { + s = fn_to_str(proto, none[ast.ident], inputs, output); } case (ty_native_fn(?inputs, ?output)) { - s = fn_to_str(none[ast.ident], inputs, output); + s = fn_to_str(ast.proto_fn, none[ast.ident], inputs, output); } case (ty_obj(?meths)) { @@ -326,13 +338,13 @@ fn fold_ty(ty_fold fld, @t ty) -> @t { } ret rewrap(ty, ty_rec(new_fields)); } - case (ty_fn(?args, ?ret_ty)) { + case (ty_fn(?proto, ?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))); + ret rewrap(ty, ty_fn(proto, new_args, fold_ty(fld, ret_ty))); } case (ty_obj(?methods)) { let vec[method] new_methods = vec(); @@ -341,7 +353,8 @@ fn fold_ty(ty_fold fld, @t ty) -> @t { 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, + new_methods += vec(rec(proto=m.proto, ident=m.ident, + inputs=new_args, output=fold_ty(fld, m.output))); } ret rewrap(ty, ty_obj(new_methods)); @@ -378,7 +391,7 @@ fn type_is_structural(@t ty) -> bool { case (ty_tup(_)) { ret true; } case (ty_rec(_)) { ret true; } case (ty_tag(_,_)) { ret true; } - case (ty_fn(_,_)) { ret true; } + case (ty_fn(_,_,_)) { ret true; } case (ty_obj(_)) { ret true; } case (_) { ret false; } } @@ -573,23 +586,29 @@ fn count_ty_params(@t ty) -> uint { // Type accessors for substructures of types fn ty_fn_args(@t fty) -> vec[arg] { - alt (fty.struct) { - case (ty.ty_fn(?a, _)) { ret a; } - } + alt (fty.struct) { + case (ty.ty_fn(_, ?a, _)) { ret a; } + } +} + +fn ty_fn_proto(@t fty) -> ast.proto { + alt (fty.struct) { + case (ty.ty_fn(?p, _, _)) { ret p; } + } } fn ty_fn_ret(@t fty) -> @t { - alt (fty.struct) { - case (ty.ty_fn(_, ?r)) { ret r; } - } + alt (fty.struct) { + case (ty.ty_fn(_, _, ?r)) { ret r; } + } } fn is_fn_ty(@t fty) -> bool { - alt (fty.struct) { - case (ty.ty_fn(_, _)) { ret true; } - case (_) { ret false; } - } - ret false; + alt (fty.struct) { + case (ty.ty_fn(_, _, _)) { ret true; } + case (_) { ret false; } + } + ret false; } @@ -808,80 +827,87 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) } fn unify_fn(@hashmap[int,@ty.t] bindings, + ast.proto e_proto, + ast.proto a_proto, @ty.t expected, @ty.t actual, &unify_handler handler, vec[arg] expected_inputs, @t expected_output, vec[arg] actual_inputs, @t actual_output) - -> unify_result { - auto expected_len = _vec.len[arg](expected_inputs); - auto actual_len = _vec.len[arg](actual_inputs); - if (expected_len != actual_len) { - ret ures_err(terr_arg_count, expected, actual); - } + -> unify_result { - // TODO: as above, we should have an iter2 iterator. - let vec[arg] result_ins = vec(); - auto i = 0u; - while (i < expected_len) { - auto expected_input = expected_inputs.(i); - auto actual_input = actual_inputs.(i); - - // This should be safe, I think? - auto result_mode; - if (mode_is_alias(expected_input.mode) || - mode_is_alias(actual_input.mode)) { - result_mode = ast.alias; - } else { - result_mode = ast.val; + if (e_proto != a_proto) { + ret ures_err(terr_mismatch, expected, actual); } - auto result = unify_step(bindings, - actual_input.ty, - expected_input.ty, - handler); + auto expected_len = _vec.len[arg](expected_inputs); + auto actual_len = _vec.len[arg](actual_inputs); + if (expected_len != actual_len) { + ret ures_err(terr_arg_count, expected, actual); + } - alt (result) { - case (ures_ok(?rty)) { - result_ins += vec(rec(mode=result_mode, - ty=rty)); - } + // TODO: as above, we should have an iter2 iterator. + let vec[arg] result_ins = vec(); + auto i = 0u; + while (i < expected_len) { + auto expected_input = expected_inputs.(i); + auto actual_input = actual_inputs.(i); - case (_) { - ret result; - } - } + // This should be safe, I think? + auto result_mode; + if (mode_is_alias(expected_input.mode) || + mode_is_alias(actual_input.mode)) { + result_mode = ast.alias; + } else { + result_mode = ast.val; + } - i += 1u; - } + auto result = unify_step(bindings, + actual_input.ty, + expected_input.ty, + handler); - // Check the output. - auto result_out; - auto result = unify_step(bindings, - expected_output, - actual_output, - handler); - alt (result) { - case (ures_ok(?rty)) { - result_out = rty; + alt (result) { + case (ures_ok(?rty)) { + result_ins += vec(rec(mode=result_mode, + ty=rty)); + } + + case (_) { + ret result; + } + } + + i += 1u; } - case (_) { - ret result; + // Check the output. + auto result_out; + auto result = unify_step(bindings, + expected_output, + actual_output, + handler); + alt (result) { + case (ures_ok(?rty)) { + result_out = rty; + } + + case (_) { + ret result; + } } - } - auto t = plain_ty(ty.ty_fn(result_ins, result_out)); - ret ures_ok(t); + auto t = plain_ty(ty.ty_fn(e_proto, result_ins, result_out)); + ret ures_ok(t); } fn unify_obj(@hashmap[int,@ty.t] bindings, - @ty.t expected, - @ty.t actual, - &unify_handler handler, - vec[method] expected_meths, - vec[method] actual_meths) -> unify_result { + @ty.t expected, + @ty.t actual, + &unify_handler handler, + vec[method] expected_meths, + vec[method] actual_meths) -> unify_result { let vec[method] result_meths = vec(); let uint i = 0u; let uint expected_len = _vec.len[method](expected_meths); @@ -893,28 +919,28 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) // FIXME: work around buggy typestate logic for 'alt', sigh. fn is_ok(&unify_result r) -> bool { - alt (r) { - case (ures_ok(?tfn)) { - ret true; + alt (r) { + case (ures_ok(?tfn)) { + ret true; + } + case (_) {} } - case (_) {} - } - ret false; + ret false; } fn append_if_ok(&method e_meth, &unify_result r, &mutable vec[method] result_meths) { - alt (r) { - case (ures_ok(?tfn)) { - alt (tfn.struct) { - case (ty_fn(?ins, ?out)) { - result_meths += vec(rec(inputs = ins, - output = out - with e_meth)); + alt (r) { + case (ures_ok(?tfn)) { + alt (tfn.struct) { + case (ty_fn(?proto, ?ins, ?out)) { + result_meths += vec(rec(inputs = ins, + output = out + with e_meth)); + } + } } - } } - } } while (i < expected_len) { @@ -924,7 +950,9 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) ret ures_err(terr_obj_meths(e_meth.ident, a_meth.ident), expected, actual); } - auto r = unify_fn(bindings, expected, actual, handler, + auto r = unify_fn(bindings, + e_meth.proto, a_meth.proto, + expected, actual, handler, e_meth.inputs, e_meth.output, a_meth.inputs, a_meth.output); if (!is_ok(r)) { @@ -1215,12 +1243,13 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) } } - case (ty.ty_fn(?expected_inputs, ?expected_output)) { + case (ty.ty_fn(?ep, ?expected_inputs, ?expected_output)) { alt (actual.struct) { - case (ty.ty_fn(?actual_inputs, ?actual_output)) { - ret unify_fn(bindings, expected, actual, handler, - expected_inputs, expected_output, - actual_inputs, actual_output); + case (ty.ty_fn(?ap, ?actual_inputs, ?actual_output)) { + ret unify_fn(bindings, ep, ap, + expected, actual, handler, + expected_inputs, expected_output, + actual_inputs, actual_output); } case (_) { @@ -1230,15 +1259,15 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) } case (ty.ty_obj(?expected_meths)) { - alt (actual.struct) { - case (ty.ty_obj(?actual_meths)) { - ret unify_obj(bindings, expected, actual, handler, - expected_meths, actual_meths); - } - case (_) { - ret ures_err(terr_mismatch, expected, actual); + alt (actual.struct) { + case (ty.ty_obj(?actual_meths)) { + ret unify_obj(bindings, expected, actual, handler, + expected_meths, actual_meths); + } + case (_) { + ret ures_err(terr_mismatch, expected, actual); + } } - } } case (ty.ty_var(?expected_id)) { diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index aa5e9fe5..ee92d8d7 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -155,10 +155,10 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t { sty = ty.ty_rec(flds); } - case (ast.ty_fn(?inputs, ?output)) { + case (ast.ty_fn(?proto, ?inputs, ?output)) { auto f = bind ast_arg_to_arg(getter, _); auto i = _vec.map[ast.ty_arg, arg](f, inputs); - sty = ty.ty_fn(i, ast_ty_to_ty(getter, output)); + sty = ty.ty_fn(proto, i, ast_ty_to_ty(getter, output)); } case (ast.ty_path(?path, ?def)) { @@ -194,7 +194,8 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t { auto ins = _vec.map[ast.ty_arg, arg](f, m.inputs); auto out = ast_ty_to_ty(getter, m.output); append[ty.method](tmeths, - rec(ident=m.ident, + rec(proto=m.proto, + ident=m.ident, inputs=ins, output=out)); } @@ -295,7 +296,7 @@ fn ty_of_fn_decl(@ty_item_table id_to_ty_item, ast.def_id def_id) -> @ty.t { auto input_tys = _vec.map[ast.arg,arg](ty_of_arg, decl.inputs); auto output_ty = convert(decl.output); - auto t_fn = plain_ty(ty.ty_fn(input_tys, output_ty)); + auto t_fn = plain_ty(ty.ty_fn(decl.proto, input_tys, output_ty)); item_to_ty.insert(def_id, t_fn); ret t_fn; } @@ -354,7 +355,8 @@ fn collect_item_types(session.session sess, @ast.crate crate) auto f = bind ty_of_arg(id_to_ty_item, item_to_ty, _); auto inputs = _vec.map[ast.arg,arg](f, m.node.meth.decl.inputs); auto output = convert(m.node.meth.decl.output); - ret rec(ident=m.node.ident, inputs=inputs, output=output); + ret rec(proto=m.node.meth.decl.proto, ident=m.node.ident, + inputs=inputs, output=output); } fn ty_of_obj(@ty_item_table id_to_ty_item, @@ -385,7 +387,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) auto t_field = ast_ty_to_ty(g, f.ty); append[arg](t_inputs, rec(mode=ast.alias, ty=t_field)); } - auto t_fn = plain_ty(ty.ty_fn(t_inputs, t_obj)); + auto t_fn = plain_ty(ty.ty_fn(ast.proto_fn, t_inputs, t_obj)); ret t_fn; } @@ -501,7 +503,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) args += vec(rec(mode=ast.alias, ty=arg_ty)); } auto tag_t = plain_ty(ty.ty_tag(tag_id, ty_param_tys)); - result_ty = plain_ty(ty.ty_fn(args, tag_t)); + result_ty = plain_ty(ty.ty_fn(ast.proto_fn, args, tag_t)); } item_to_ty.insert(variant.id, result_ty); @@ -615,7 +617,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) fn get_ctor_obj_methods(@ty.t t) -> vec[method] { alt (t.struct) { - case (ty.ty_fn(_,?tobj)) { + case (ty.ty_fn(_,_,?tobj)) { alt (tobj.struct) { case (ty.ty_obj(?tm)) { ret tm; @@ -650,7 +652,8 @@ fn collect_item_types(session.session sess, @ast.crate crate) let method meth_ty = meth_tys.(ix); let ast.method_ m_; let @ast.method m; - auto meth_tfn = plain_ty(ty.ty_fn(meth_ty.inputs, + auto meth_tfn = plain_ty(ty.ty_fn(meth_ty.proto, + meth_ty.inputs, meth_ty.output)); m_ = rec(ann=ast.ann_type(meth_tfn) with meth.node); m = @rec(node=m_ with *meth); @@ -877,7 +880,7 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { check (subpats_len == 0u); p_1 = ast.pat_tag(id, subpats, vdef_opt, ast.ann_type(t)); } - case (ty.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) { @@ -1189,7 +1192,7 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat { auto last_id = p.node.idents.(len - 1u); alt (t.struct) { // N-ary variants have function types. - case (ty.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) { @@ -1628,6 +1631,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { ty_to_str(t_0)); } + let ast.proto proto = ty.ty_fn_proto(t_0); let vec[arg] arg_tys_0 = ty.ty_fn_args(t_0); let @ty.t rt_0 = ty.ty_fn_ret(t_0); let vec[option.t[@ast.expr]] args_1 = vec(); @@ -1654,7 +1658,8 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { i += 1u; } - let @ty.t t_1 = plain_ty(ty.ty_fn(residual_args, rt_0)); + let @ty.t t_1 = plain_ty(ty.ty_fn(proto, + residual_args, rt_0)); ret @fold.respan[ast.expr_](expr.span, ast.expr_bind(f_0, args_1, ast.ann_type(t_1))); @@ -1677,7 +1682,8 @@ 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.ty_fn(arg_tys_0, rt_0)); + auto t_0 = plain_ty(ty.ty_fn(ty.ty_fn_proto(expr_ty(f_0)), + arg_tys_0, rt_0)); // Unify and write back to the function. auto f_1 = demand_expr(fcx, t_0, f_0); @@ -1877,7 +1883,8 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { "bad index on obj"); } auto meth = methods.(ix); - auto t = plain_ty(ty.ty_fn(meth.inputs, meth.output)); + auto t = plain_ty(ty.ty_fn(meth.proto, + meth.inputs, meth.output)); auto ann = ast.ann_type(t); ret @fold.respan[ast.expr_](expr.span, ast.expr_field(base_1, @@ -2047,8 +2054,7 @@ fn check_const(&@crate_ctxt ccx, &span sp, ast.ident ident, @ast.ty t, ret @fold.respan[ast.item_](sp, item); } -fn check_fn(&@crate_ctxt ccx, &ast.fn_decl decl, - bool is_iter, &ast.block body) -> ast._fn { +fn check_fn(&@crate_ctxt ccx, &ast.fn_decl decl, &ast.block body) -> ast._fn { auto local_ty_table = @common.new_def_hash[@ty.t](); // FIXME: duplicate work: the item annotation already has the arg types @@ -2075,8 +2081,8 @@ fn check_fn(&@crate_ctxt ccx, &ast.fn_decl decl, auto block_t = check_block(fcx, body); auto block_wb = writeback(fcx, block_t); - auto fn_t = rec(decl=decl, is_iter=is_iter, - body=block_wb); + auto fn_t = rec(decl=decl, + body=block_wb); ret fn_t; } @@ -2095,7 +2101,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.decl.output); - auto fn_sty = ty.ty_fn(inputs, output_ty); + auto fn_sty = ty.ty_fn(f.decl.proto, 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); @@ -2127,7 +2133,7 @@ fn check_crate(session.session sess, @ast.crate crate) -> @ast.crate { auto fld = fold.new_identity_fold[@crate_ctxt](); fld = @rec(update_env_for_item = bind update_obj_fields(_, _), - fold_fn = bind check_fn(_,_,_,_), + fold_fn = bind check_fn(_,_,_), fold_item_fn = bind check_item_fn(_,_,_,_,_,_,_) with *fld); ret fold.fold_crate[@crate_ctxt](ccx, fld, result._0); -- cgit v1.2.3 From 80c67268fc007d55fa0ff193ac0be6ab83640aa6 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 18 Feb 2011 18:04:37 -0800 Subject: Pass correct lliterbody; can compile and run no-put iters. --- src/comp/middle/trans.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 03d1fad9..59d6ad7f 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2238,7 +2238,7 @@ fn trans_for_each(@block_ctxt cx, // escape. This could be determined upstream, and probably ought // to be so, eventualy. For first cut, skip this. Null env. - auto env_ty = T_struct(vec(T_ptr(T_i8()))); + auto env_ty = T_opaque_closure_ptr(cx.fcx.ccx.tn); // Step 2: Declare foreach body function. @@ -2283,11 +2283,19 @@ fn trans_for_each(@block_ctxt cx, // Step 3: Call iter passing [lliterbody, llenv], plus other args. alt (seq.node) { + case (ast.expr_call(?f, ?args, ?ann)) { + auto pair = cx.build.Alloca(T_fn_pair(cx.fcx.ccx.tn, + iter_body_llty)); + auto code_cell = cx.build.GEP(pair, + vec(C_int(0), + C_int(abi.fn_field_code))); + cx.build.Store(lliterbody, code_cell); + // log "lliterbody: " + val_str(cx.fcx.ccx.tn, lliterbody); ret trans_call(cx, f, - some[ValueRef](lliterbody), + some[ValueRef](cx.build.Load(pair)), args, ann); } @@ -3364,7 +3372,7 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { ret trans_ret(cx, e); } - case (ast.expr_ret(?e)) { + case (ast.expr_put(?e)) { ret trans_put(cx, e); } -- cgit v1.2.3 From 5508c28ff0e27d1027ddf372410cc5e1609662bd Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 18 Feb 2011 18:10:07 -0800 Subject: Factor out the call typechecking logic so that bind can use it --- src/comp/middle/typeck.rs | 143 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 101 insertions(+), 42 deletions(-) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index ee92d8d7..b259fb4e 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1244,6 +1244,87 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat { } fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { + // A generic function to factor out common logic from call and bind + // expressions. + fn check_call_or_bind(&@fn_ctxt fcx, &@ast.expr f, + &vec[option.t[@ast.expr]] args) + -> tup(@ast.expr, vec[option.t[@ast.expr]]) { + + // Check the function. + auto f_0 = check_expr(fcx, f); + + // Check the arguments and generate the argument signature. + let vec[option.t[@ast.expr]] args_0 = vec(); + let vec[arg] arg_tys_0 = vec(); + for (option.t[@ast.expr] a_opt in args) { + alt (a_opt) { + case (some[@ast.expr](?a)) { + auto a_0 = check_expr(fcx, a); + args_0 += vec(some[@ast.expr](a_0)); + + // FIXME: this breaks aliases. We need a ty_fn_arg. + auto arg_ty = rec(mode=ast.val, ty=expr_ty(a_0)); + append[arg](arg_tys_0, arg_ty); + } + case (none[@ast.expr]) { + args_0 += vec(none[@ast.expr]); + + // FIXME: breaks aliases too? + auto typ = next_ty_var(fcx.ccx); + append[arg](arg_tys_0, rec(mode=ast.val, ty=typ)); + } + } + } + + auto proto_0 = ast.proto_fn; // FIXME: typestate botch + alt (expr_ty(f_0).struct) { + case (ty.ty_fn(?proto, _, _)) { proto_0 = proto; } + case (_) { + log "check_call_or_bind(): fn expr doesn't have fn type"; + fail; + } + } + + auto rt_0 = next_ty_var(fcx.ccx); + auto t_0 = plain_ty(ty.ty_fn(proto_0, 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); + + if (!ty.is_fn_ty(t_1)) { + fcx.ccx.sess.span_err(f_1.span, + "mismatched types: callee has " + + "non-function type: " + + ty_to_str(t_1)); + } + + let vec[arg] arg_tys_1 = ty.ty_fn_args(t_1); + let @ty.t rt_1 = ty.ty_fn_ret(t_1); + + // Unify and write back to the arguments. + auto i = 0u; + let vec[option.t[@ast.expr]] args_1 = vec(); + while (i < _vec.len[option.t[@ast.expr]](args_0)) { + alt (args_0.(i)) { + case (some[@ast.expr](?e_0)) { + auto arg_ty_1 = arg_tys_1.(i); + auto e_1 = demand_expr(fcx, arg_ty_1.ty, e_0); + append[option.t[@ast.expr]](args_1, some[@ast.expr](e_1)); + } + case (none[@ast.expr]) { + append[option.t[@ast.expr]](args_1, none[@ast.expr]); + } + } + + i += 1u; + } + + ret tup(f_1, args_1); + } + alt (expr.node) { case (ast.expr_lit(?lit, _)) { auto ty = check_lit(lit); @@ -1658,62 +1739,40 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { i += 1u; } - let @ty.t t_1 = plain_ty(ty.ty_fn(proto, - residual_args, rt_0)); + let @ty.t t_1 = plain_ty(ty.ty_fn(proto, residual_args, rt_0)); + ret @fold.respan[ast.expr_](expr.span, ast.expr_bind(f_0, args_1, ast.ann_type(t_1))); - } case (ast.expr_call(?f, ?args, _)) { - - // Check the function. - auto f_0 = check_expr(fcx, f); - - // Check the arguments and generate the argument signature. - let vec[@ast.expr] args_0 = vec(); - let vec[arg] arg_tys_0 = vec(); - for (@ast.expr a in args) { - auto a_0 = check_expr(fcx, a); - append[@ast.expr](args_0, a_0); - - // FIXME: this breaks aliases. We need a ty_fn_arg. - append[arg](arg_tys_0, rec(mode=ast.val, ty=expr_ty(a_0))); + let vec[option.t[@ast.expr]] args_opt_0 = vec(); + for (@ast.expr arg in args) { + args_opt_0 += vec(some[@ast.expr](arg)); } - auto rt_0 = next_ty_var(fcx.ccx); - auto t_0 = plain_ty(ty.ty_fn(ty.ty_fn_proto(expr_ty(f_0)), - 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); + // Call the generic checker. + auto result = check_call_or_bind(fcx, f, args_opt_0); - if (!ty.is_fn_ty(t_1)) { - fcx.ccx.sess.span_err(f_1.span, - "mismatched types: callee has " + - "non-function type: " + - ty_to_str(t_1)); - } - - let vec[arg] arg_tys_1 = ty.ty_fn_args(t_1); - let @ty.t rt_1 = ty.ty_fn_ret(t_1); - - // Unify and write back to the arguments. - auto i = 0u; + // Pull out the arguments. let vec[@ast.expr] args_1 = vec(); - while (i < _vec.len[@ast.expr](args_0)) { - auto arg_ty_1 = arg_tys_1.(i); - auto e = demand_expr(fcx, arg_ty_1.ty, args_0.(i)); - append[@ast.expr](args_1, e); + for (option.t[@ast.expr] arg in result._1) { + args_1 += vec(option.get[@ast.expr](arg)); + } - i += 1u; + // Pull the return type out of the type of the function. + auto rt_1 = plain_ty(ty.ty_nil); // FIXME: typestate botch + alt (expr_ty(result._0).struct) { + case (ty.ty_fn(_,_,?rt)) { rt_1 = rt; } + case (_) { + log "LHS of call expr didn't have a function type?!"; + fail; + } } ret @fold.respan[ast.expr_](expr.span, - ast.expr_call(f_1, args_1, + ast.expr_call(result._0, args_1, ast.ann_type(rt_1))); } -- cgit v1.2.3 From b0c7439d777bbb967be7a67fa11096aaf540fe9f Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 18 Feb 2011 18:52:16 -0800 Subject: Implement expr_put. Un-XFAIL foreach-simple.rs; iters w/o env access work. --- src/Makefile | 1 + src/comp/middle/trans.rs | 31 +++++++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index c468ded0..71c9807b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -475,6 +475,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ else-if.rs \ fact.rs \ fn-lval.rs \ + foreach-simple.rs \ fun-call-variants.rs \ fun-indirect-call.rs \ generic-derived-type.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 59d6ad7f..efa3a41d 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3454,8 +3454,35 @@ fn trans_fail(@block_ctxt cx, common.span sp, str fail_str) -> result { } fn trans_put(@block_ctxt cx, &option.t[@ast.expr] e) -> result { - cx.fcx.ccx.sess.unimpl("put expr"); - fail; + auto llcallee = C_nil(); + auto llenv = C_nil(); + + alt (cx.fcx.lliterbody) { + case (some[ValueRef](?lli)) { + auto slot = cx.build.Alloca(val_ty(lli)); + cx.build.Store(lli, slot); + + llcallee = cx.build.GEP(slot, vec(C_int(0), + C_int(abi.fn_field_code))); + llcallee = cx.build.Load(llcallee); + + llenv = cx.build.GEP(slot, vec(C_int(0), + C_int(abi.fn_field_box))); + llenv = cx.build.Load(llenv); + } + } + auto bcx = cx; + auto dummy_retslot = bcx.build.Alloca(T_nil()); + let vec[ValueRef] llargs = vec(dummy_retslot, cx.fcx.lltaskptr, llenv); + alt (e) { + case (none[@ast.expr]) { } + case (some[@ast.expr](?x)) { + auto r = trans_expr(bcx, x); + llargs += r.val; + bcx = r.bcx; + } + } + ret res(bcx, bcx.build.FastCall(llcallee, llargs)); } fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result { -- cgit v1.2.3 From cbe8d222a82c14485cf416c4b85fd5e58363c0e0 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 21 Feb 2011 00:56:09 -0500 Subject: Implement sha-1 in standard library. Closes #228 --- src/lib/sha1.rs | 284 ++++++++++++++++++++++++++++++++++++++++++ src/lib/std.rc | 1 + src/test/run-pass/lib-sha1.rs | 115 +++++++++++++++++ 3 files changed, 400 insertions(+) create mode 100644 src/lib/sha1.rs create mode 100644 src/test/run-pass/lib-sha1.rs diff --git a/src/lib/sha1.rs b/src/lib/sha1.rs new file mode 100644 index 00000000..8be969aa --- /dev/null +++ b/src/lib/sha1.rs @@ -0,0 +1,284 @@ +/* + * A SHA-1 implementation derived from Paul E. Jones's reference + * implementation, which is written for clarity, not speed. At some + * point this will want to be rewritten. + */ + +import std._vec; +import std._str; + +export sha1; +export mk_sha1; + +state type sha1 = state obj { + // Provide message input as bytes + fn input(&vec[u8]); + + // Provide message input as string + fn input_str(&str); + + // Read the digest as a vector of 20 bytes. After + // calling this no further input may provided + // until reset is called + fn result() -> vec[u8]; + + // Reset the sha1 state for reuse. This is called + // automatically during construction + fn reset(); +}; + +// Some unexported constants +const uint digest_buf_len = 5; +const uint msg_block_len = 64; + +// Builds a sha1 object +fn mk_sha1() -> sha1 { + + state type sha1state = rec(vec[mutable u32] h, + mutable u32 len_low, + mutable u32 len_high, + vec[mutable u8] msg_block, + mutable uint msg_block_idx, + mutable bool computed); + + impure fn add_input(&sha1state st, &vec[u8] msg) { + // FIXME: Should be typestate precondition + check (!st.computed); + + for (u8 element in msg) { + st.msg_block.(st.msg_block_idx) = element; + st.msg_block_idx += 1u; + + st.len_low += 8u32; + if (st.len_low == 0u32) { + st.len_high += 1u32; + if (st.len_high == 0u32) { + // FIXME: Need better failure mode + fail; + } + } + + if (st.msg_block_idx == msg_block_len) { + process_msg_block(st); + } + } + } + + impure fn process_msg_block(&sha1state st) { + + // FIXME: Make precondition + check (_vec.len[mutable u32](st.h) == digest_buf_len); + + // Constants + auto k = vec(0x5A827999u32, + 0x6ED9EBA1u32, + 0x8F1BBCDCu32, + 0xCA62C1D6u32); + + let int t; // Loop counter + let vec[mutable u32] w = _vec.init_elt[mutable u32](0u32, 80u); + + // Initialize the first 16 words of the vector w + t = 0; + while (t < 16) { + w.(t) = (st.msg_block.(t * 4) as u32) << 24u32; + w.(t) = w.(t) | ((st.msg_block.(t * 4 + 1) as u32) << 16u32); + w.(t) = w.(t) | ((st.msg_block.(t * 4 + 2) as u32) << 8u32); + w.(t) = w.(t) | (st.msg_block.(t * 4 + 3) as u32); + t += 1; + } + + // Initialize the rest of vector w + while (t < 80) { + auto val = w.(t-3) ^ w.(t-8) ^ w.(t-14) ^ w.(t-16); + w.(t) = circular_shift(1u32, val); + t += 1; + } + + auto a = st.h.(0); + auto b = st.h.(1); + auto c = st.h.(2); + auto d = st.h.(3); + auto e = st.h.(4); + + let u32 temp; + + t = 0; + while (t < 20) { + temp = circular_shift(5u32, a) + + ((b & c) | ((~b) & d)) + e + w.(t) + k.(0); + e = d; + d = c; + c = circular_shift(30u32, b); + b = a; + a = temp; + t += 1; + } + + while (t < 40) { + temp = circular_shift(5u32, a) + + (b ^ c ^ d) + e + w.(t) + k.(1); + e = d; + d = c; + c = circular_shift(30u32, b); + b = a; + a = temp; + t += 1; + } + + while (t < 60) { + temp = circular_shift(5u32, a) + + ((b & c) | (b & d) | (c & d)) + e + w.(t) + k.(2); + e = d; + d = c; + c = circular_shift(30u32, b); + b = a; + a = temp; + t += 1; + } + + while (t < 80) { + temp = circular_shift(5u32, a) + + (b ^ c ^ d) + e + w.(t) + k.(3); + e = d; + d = c; + c = circular_shift(30u32, b); + b = a; + a = temp; + t += 1; + } + + st.h.(0) = st.h.(0) + a; + st.h.(1) = st.h.(1) + b; + st.h.(2) = st.h.(2) + c; + st.h.(3) = st.h.(3) + d; + st.h.(4) = st.h.(4) + e; + + st.msg_block_idx = 0u; + } + + fn circular_shift(u32 bits, u32 word) -> u32 { + // FIXME: This is a workaround for a rustboot + // "unrecognized quads" codegen bug + auto bits_hack = bits; + ret (word << bits_hack) | (word >> (32u32 - bits)); + } + + impure fn mk_result(&sha1state st) -> vec[u8] { + if (!st.computed) { + pad_msg(st); + st.computed = true; + } + + let vec[u8] res = vec(); + for (u32 hpart in st.h) { + res += (hpart >> 24u32) & 0xFFu32 as u8; + res += (hpart >> 16u32) & 0xFFu32 as u8; + res += (hpart >> 8u32) & 0xFFu32 as u8; + res += hpart & 0xFFu32 as u8; + } + ret res; + } + + /* + * According to the standard, the message must be padded to an even + * 512 bits. The first padding bit must be a '1'. The last 64 bits + * represent the length of the original message. All bits in between + * should be 0. This function will pad the message according to those + * rules by filling the message_block array accordingly. It will also + * call ProcessMessageBlock() appropriately. When it returns, it + * can be assumed that the message digest has been computed. + */ + impure fn pad_msg(&sha1state st) { + // FIXME: Should be a precondition + check (_vec.len[mutable u8](st.msg_block) == msg_block_len); + + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second block. + */ + if (st.msg_block_idx > 55u) { + st.msg_block.(st.msg_block_idx) = 0x80u8; + st.msg_block_idx += 1u; + + while (st.msg_block_idx < msg_block_len) { + st.msg_block.(st.msg_block_idx) = 0u8; + st.msg_block_idx += 1u; + } + + process_msg_block(st); + } else { + st.msg_block.(st.msg_block_idx) = 0x80u8; + st.msg_block_idx += 1u; + } + + while (st.msg_block_idx < 56u) { + st.msg_block.(st.msg_block_idx) = 0u8; + st.msg_block_idx += 1u; + } + + // Store the message length as the last 8 octets + st.msg_block.(56) = (st.len_high >> 24u32) & 0xFFu32 as u8; + st.msg_block.(57) = (st.len_high >> 16u32) & 0xFFu32 as u8; + st.msg_block.(58) = (st.len_high >> 8u32) & 0xFFu32 as u8; + st.msg_block.(59) = st.len_high & 0xFFu32 as u8; + st.msg_block.(60) = (st.len_low >> 24u32) & 0xFFu32 as u8; + st.msg_block.(61) = (st.len_low >> 16u32) & 0xFFu32 as u8; + st.msg_block.(62) = (st.len_low >> 8u32) & 0xFFu32 as u8; + st.msg_block.(63) = st.len_low & 0xFFu32 as u8; + + process_msg_block(st); + } + + state obj sha1(sha1state st) { + + fn reset() { + // FIXME: Should be typestate precondition + check (_vec.len[mutable u32](st.h) == digest_buf_len); + + st.len_low = 0u32; + st.len_high = 0u32; + st.msg_block_idx = 0u; + + st.h.(0) = 0x67452301u32; + st.h.(1) = 0xEFCDAB89u32; + st.h.(2) = 0x98BADCFEu32; + st.h.(3) = 0x10325476u32; + st.h.(4) = 0xC3D2E1F0u32; + + st.computed = false; + } + + fn input(&vec[u8] msg) { + add_input(st, msg); + } + + fn input_str(&str msg) { + add_input(st, _str.bytes(msg)); + } + + fn result() -> vec[u8] { + ret mk_result(st); + } + } + + auto st = rec(h = _vec.init_elt[mutable u32](0u32, digest_buf_len), + mutable len_low = 0u32, + mutable len_high = 0u32, + msg_block = _vec.init_elt[mutable u8](0u8, msg_block_len), + mutable msg_block_idx = 0u, + mutable computed = false); + auto sh = sha1(st); + sh.reset(); + ret sh; +} + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: diff --git a/src/lib/std.rc b/src/lib/std.rc index 102aa4d1..3500c4b3 100644 --- a/src/lib/std.rc +++ b/src/lib/std.rc @@ -57,6 +57,7 @@ mod dbg; mod bitv; mod sort; mod path; +mod sha1; // Local Variables: // mode: rust; diff --git a/src/test/run-pass/lib-sha1.rs b/src/test/run-pass/lib-sha1.rs new file mode 100644 index 00000000..57e3cdc8 --- /dev/null +++ b/src/test/run-pass/lib-sha1.rs @@ -0,0 +1,115 @@ +// -*- rust -*- + +use std; + +import std.sha1; +import std._vec; +import std._str; + +fn main() { + + type test = rec(str input, vec[u8] output); + + fn a_million_letter_a() -> str { + auto i = 0; + auto res = ""; + while (i < 100000) { + res += "aaaaaaaaaa"; + i += 1; + } + ret res; + } + + // Test messages from FIPS 180-1 + let vec[test] fips_180_1_tests = + vec( + rec(input = "abc", + output = vec(0xA9u8, 0x99u8, 0x3Eu8, 0x36u8, 0x47u8, + 0x06u8, 0x81u8, 0x6Au8, 0xBAu8, 0x3Eu8, + 0x25u8, 0x71u8, 0x78u8, 0x50u8, 0xC2u8, + 0x6Cu8, 0x9Cu8, 0xD0u8, 0xD8u8, 0x9Du8) + ), + rec(input = "abcdbcdecdefdefgefghfghighij" + + "hijkijkljklmklmnlmnomnopnopq", + output = vec(0x84u8, 0x98u8, 0x3Eu8, 0x44u8, 0x1Cu8, + 0x3Bu8, 0xD2u8, 0x6Eu8, 0xBAu8, 0xAEu8, + 0x4Au8, 0xA1u8, 0xF9u8, 0x51u8, 0x29u8, + 0xE5u8, 0xE5u8, 0x46u8, 0x70u8, 0xF1u8) + ) + // FIXME: This test is disabled because it takes some + // minutes to run under rustboot+valgrind. It may be + // possible to reenable once things are more optimized. + /*, + rec(input = a_million_letter_a(), + output = vec(0x34u8, 0xAAu8, 0x97u8, 0x3Cu8, 0xD4u8, + 0xC4u8, 0xDAu8, 0xA4u8, 0xF6u8, 0x1Eu8, + 0xEBu8, 0x2Bu8, 0xDBu8, 0xADu8, 0x27u8, + 0x31u8, 0x65u8, 0x34u8, 0x01u8, 0x6Fu8) + ) + */ + ); + + // Examples from wikipedia + let vec[test] wikipedia_tests = + vec( + rec(input = "The quick brown fox jumps over the lazy dog", + output = vec(0x2fu8, 0xd4u8, 0xe1u8, 0xc6u8, 0x7au8, + 0x2du8, 0x28u8, 0xfcu8, 0xedu8, 0x84u8, + 0x9eu8, 0xe1u8, 0xbbu8, 0x76u8, 0xe7u8, + 0x39u8, 0x1bu8, 0x93u8, 0xebu8, 0x12u8) + ), + rec(input = "The quick brown fox jumps over the lazy cog", + output = vec(0xdeu8, 0x9fu8, 0x2cu8, 0x7fu8, 0xd2u8, + 0x5eu8, 0x1bu8, 0x3au8, 0xfau8, 0xd3u8, + 0xe8u8, 0x5au8, 0x0bu8, 0xd1u8, 0x7du8, + 0x9bu8, 0x10u8, 0x0du8, 0xb4u8, 0xb3u8) + ) + ); + + auto tests = fips_180_1_tests + wikipedia_tests; + + fn check_vec_eq(vec[u8] v0, vec[u8] v1) { + check (_vec.len[u8](v0) == _vec.len[u8](v1)); + auto len = _vec.len[u8](v0); + auto i = 0u; + while (i < len) { + auto a = v0.(i); + auto b = v1.(i); + check (a == b); + i += 1u; + } + } + + // Test that it works when accepting the message all at once + auto sh = sha1.mk_sha1(); + for (test t in tests) { + sh.input_str(t.input); + auto out = sh.result(); + check_vec_eq(t.output, out); + sh.reset(); + } + + // Test that it works when accepting the message in pieces + for (test t in tests) { + auto len = _str.byte_len(t.input); + auto left = len; + while (left > 0u) { + auto take = (left + 1u) / 2u; + sh.input_str(_str.substr(t.input, len - left, take)); + left = left - take; + } + auto out = sh.result(); + check_vec_eq(t.output, out); + sh.reset(); + } +} + + +// Local Variables: +// mode: rust; +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: -- cgit v1.2.3 From 60f97aa9cc73ee4e0b57abc07dc543c8fa823ee2 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 21 Feb 2011 17:42:23 -0800 Subject: Find main functions buried within modules. Un-XFAIL import.rs. --- src/Makefile | 1 + src/comp/middle/trans.rs | 27 +++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index 71c9807b..872ced98 100644 --- a/src/Makefile +++ b/src/Makefile @@ -492,6 +492,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ int.rs \ i32-sub.rs \ i8-incr.rs \ + import.rs \ import2.rs \ import3.rs \ import4.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index efa3a41d..35fefc10 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4602,6 +4602,30 @@ fn create_crate_constant(@crate_ctxt cx) { llvm.LLVMSetInitializer(cx.crate_ptr, crate_val); } +fn find_main_fn(@crate_ctxt cx) -> ValueRef { + auto e = sep() + "main"; + let ValueRef v = C_nil(); + let uint n = 0u; + for each (tup(str,ValueRef) i in cx.item_names.items()) { + if (_str.ends_with(i._0, e)) { + n += 1u; + v = i._1; + } + } + alt (n) { + case (0u) { + cx.sess.err("main fn not found"); + } + case (1u) { + ret v; + } + case (_) { + cx.sess.err("multiple main fns found"); + } + } + fail; +} + fn trans_main_fn(@crate_ctxt cx, ValueRef llcrate) { auto T_main_args = vec(T_int(), T_int()); auto T_rust_start_args = vec(T_int(), T_int(), T_int(), T_int()); @@ -4621,8 +4645,7 @@ fn trans_main_fn(@crate_ctxt cx, ValueRef llcrate) { auto llargc = llvm.LLVMGetParam(llmain, 0u); auto llargv = llvm.LLVMGetParam(llmain, 1u); - check (cx.item_names.contains_key("_rust" + sep() + "main")); - auto llrust_main = cx.item_names.get("_rust" + sep() + "main"); + auto llrust_main = find_main_fn(cx); // // Emit the moral equivalent of: -- cgit v1.2.3 From aaa6965794b9ff0d942a1367bc7b99f52fd49f99 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 21 Feb 2011 18:55:08 -0800 Subject: Fix typo in rust_task::start. Should be copying 1 fewer initial arg. --- src/rt/rust_task.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 68882b21..3564b9e3 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -174,8 +174,8 @@ rust_task::start(uintptr_t exit_task_glue, src += 1; // spawn-call output slot src += 1; // spawn-call task slot src += 1; // spawn-call closure-or-obj slot - // Memcpy all but the task and output pointers - callsz -= (2 * sizeof(uintptr_t)); + // Memcpy all but the task, output and env pointers + callsz -= (3 * sizeof(uintptr_t)); spp = (uintptr_t*) (((uintptr_t)spp) - callsz); memcpy(spp, src, callsz); -- cgit v1.2.3 From b389611ce772d65ed135d6e52fecb9ca2238e902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Tue, 22 Feb 2011 17:37:11 -0500 Subject: Finish the type of native functions. We now get declare i32 @write(i32, i8*, i32) --- src/comp/middle/trans.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 35fefc10..9da7e009 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -514,7 +514,7 @@ fn type_of_fn(@crate_ctxt cx, fn type_of_native_fn(@crate_ctxt cx, vec[ty.arg] inputs, @ty.t output) -> TypeRef { let vec[TypeRef] atys = type_of_explicit_args(cx, inputs); - ret T_fn(atys, llvm.LLVMVoidType()); + ret T_fn(atys, type_of(cx, output)); } fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { @@ -4305,7 +4305,7 @@ fn decl_native_fn_and_pair(@crate_ctxt cx, auto llpairty = node_type(cx, ann); auto llfty = get_pair_fn_ty(llpairty); - let ValueRef llfn = decl_fastcall_fn(cx.llmod, name, llfty); + let ValueRef llfn = decl_cdecl_fn(cx.llmod, name, llfty); cx.item_ids.insert(id, llfn); } -- cgit v1.2.3 From 01c2761769ab93682afec9101b4896a7253b5251 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 22 Feb 2011 15:28:47 -0800 Subject: Rework typechecking of bind expressions --- src/comp/middle/typeck.rs | 65 +++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 36 deletions(-) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index b259fb4e..1b39cdf5 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1702,47 +1702,40 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } case (ast.expr_bind(?f, ?args, _)) { - auto f_0 = check_expr(fcx, f); - auto t_0 = expr_ty(f_0); - - if (!ty.is_fn_ty(t_0)) { - fcx.ccx.sess.span_err(f_0.span, - "mismatched types: bind callee has " + - "non-function type: " + - ty_to_str(t_0)); - } - - let ast.proto proto = ty.ty_fn_proto(t_0); - let vec[arg] arg_tys_0 = ty.ty_fn_args(t_0); - let @ty.t rt_0 = ty.ty_fn_ret(t_0); - let vec[option.t[@ast.expr]] args_1 = vec(); - - let uint i = 0u; - - let vec[arg] residual_args = vec(); - for (option.t[@ast.expr] a in args) { - alt (a) { - case (none[@ast.expr]) { - append[arg](residual_args, - arg_tys_0.(i)); - append[option.t[@ast.expr]](args_1, - none[@ast.expr]); - } - case (some[@ast.expr](?sa)) { - auto arg_1 = check_expr(fcx, sa); - auto arg_t = expr_ty(arg_1); - demand_expr(fcx, arg_tys_0.(i).ty, arg_1); - append[option.t[@ast.expr]](args_1, - some[@ast.expr](arg_1)); + // Call the generic checker. + auto result = check_call_or_bind(fcx, f, args); + + // Pull the argument and return types out. + auto proto_1 = ast.proto_fn; // FIXME: typestate botch + let vec[ty.arg] arg_tys_1 = vec(); + auto rt_1 = plain_ty(ty.ty_nil); // FIXME: typestate botch + alt (expr_ty(result._0).struct) { + case (ty.ty_fn(?proto, ?arg_tys, ?rt)) { + proto_1 = proto; + rt_1 = rt; + + // For each blank argument, add the type of that argument + // to the resulting function type. + auto i = 0u; + while (i < _vec.len[option.t[@ast.expr]](args)) { + alt (args.(i)) { + case (some[@ast.expr](_)) { /* no-op */ } + case (none[@ast.expr]) { + arg_tys_1 += vec(arg_tys.(i)); + } + } + i += 1u; } } - i += 1u; + case (_) { + log "LHS of bind expr didn't have a function type?!"; + fail; + } } - let @ty.t t_1 = plain_ty(ty.ty_fn(proto, residual_args, rt_0)); - + auto t_1 = plain_ty(ty.ty_fn(proto_1, arg_tys_1, rt_1)); ret @fold.respan[ast.expr_](expr.span, - ast.expr_bind(f_0, args_1, + ast.expr_bind(result._0, result._1, ast.ann_type(t_1))); } -- cgit v1.2.3 From af4d6ae76b05d4edb9d7074b971600a447c9c9a4 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 22 Feb 2011 16:37:01 -0800 Subject: Add ABI tagging to crates, adjust rustc output and runtime stack-frame setup so access to argv works. --- src/boot/be/abi.ml | 34 ++++++++++++++++--------- src/boot/be/x86.ml | 2 ++ src/boot/me/trans.ml | 4 +++ src/comp/back/abi.rs | 3 +++ src/comp/back/x86.rs | 4 +-- src/comp/middle/trans.rs | 13 +++++++--- src/rt/rust.cpp | 8 +++--- src/rt/rust_internal.h | 6 +++++ src/rt/rust_task.cpp | 52 +++++++++++++++++++++++++-------------- src/rt/rust_task.h | 1 + src/rt/rust_upcall.cpp | 11 ++++++--- src/rt/test/rust_test_runtime.cpp | 1 + 12 files changed, 97 insertions(+), 42 deletions(-) diff --git a/src/boot/be/abi.ml b/src/boot/be/abi.ml index 035d1f05..89e308bf 100644 --- a/src/boot/be/abi.ml +++ b/src/boot/be/abi.ml @@ -110,23 +110,33 @@ let indirect_args_elt_closure = 0;; (* Current worst case is by vec grow glue *) let worst_case_glue_call_args = 8;; +(* + * ABI tags used to inform the runtime which sort of frame to set up for new + * spawned functions. FIXME: There is almost certainly a better abstraction to + * use. + *) +let abi_x86_rustboot_cdecl = 1;; +let abi_x86_rustc_fastcall = 2;; + type abi = - { - abi_word_sz: int64; - abi_word_bits: Il.bits; - abi_word_ty: Common.ty_mach; + { + abi_word_sz: int64; + abi_word_bits: Il.bits; + abi_word_ty: Common.ty_mach; + + abi_tag: int; - abi_has_pcrel_data: bool; - abi_has_pcrel_code: bool; + abi_has_pcrel_data: bool; + abi_has_pcrel_code: bool; - abi_n_hardregs: int; - abi_str_of_hardreg: (int -> string); + abi_n_hardregs: int; + abi_str_of_hardreg: (int -> string); - abi_emit_target_specific: (Il.emitter -> Il.quad -> unit); - abi_constrain_vregs: (Il.quad -> (Il.vreg,Bits.t) Hashtbl.t -> unit); + abi_emit_target_specific: (Il.emitter -> Il.quad -> unit); + abi_constrain_vregs: (Il.quad -> (Il.vreg,Bits.t) Hashtbl.t -> unit); - abi_emit_fn_prologue: (Il.emitter - -> Common.size (* framesz *) + abi_emit_fn_prologue: (Il.emitter + -> Common.size (* framesz *) -> Common.size (* callsz *) -> Common.nabi -> Common.fixup (* grow_task *) diff --git a/src/boot/be/x86.ml b/src/boot/be/x86.ml index 30b49ed1..49b660be 100644 --- a/src/boot/be/x86.ml +++ b/src/boot/be/x86.ml @@ -1851,6 +1851,8 @@ let (abi:Abi.abi) = Abi.abi_word_bits = word_bits; Abi.abi_word_ty = word_ty; + Abi.abi_tag = Abi.abi_x86_rustboot_cdecl; + Abi.abi_has_pcrel_data = false; Abi.abi_has_pcrel_code = true; diff --git a/src/boot/me/trans.ml b/src/boot/me/trans.ml index 4f717219..bbf49e83 100644 --- a/src/boot/me/trans.ml +++ b/src/boot/me/trans.ml @@ -2727,6 +2727,7 @@ let trans_visitor [| Il.Cell new_task; exit_task_glue_fptr; + (imm (Int64.of_int abi.Abi.abi_tag)); fptr_operand; callsz |]; @@ -2739,6 +2740,7 @@ let trans_visitor [| Il.Cell new_task; exit_task_glue_fptr; + (imm (Int64.of_int abi.Abi.abi_tag)); fptr_operand; callsz |]; @@ -6183,6 +6185,8 @@ let trans_visitor tab_sz cx.ctxt_required_rust_sym_num; tab_sz cx.ctxt_required_c_sym_num; tab_sz cx.ctxt_required_lib_num; + + Asm.WORD (word_ty_mach, Asm.IMM (Int64.of_int abi.Abi.abi_tag)); |])) in diff --git a/src/comp/back/abi.rs b/src/comp/back/abi.rs index 82a85a6c..f41f6e20 100644 --- a/src/comp/back/abi.rs +++ b/src/comp/back/abi.rs @@ -60,6 +60,9 @@ const int worst_case_glue_call_args = 7; const int n_upcall_glues = 7; +const int abi_x86_rustboot_cdecl = 1; +const int abi_x86_rustc_fastcall = 2; + fn memcpy_glue_name() -> str { ret "rust_memcpy_glue"; } diff --git a/src/comp/back/x86.rs b/src/comp/back/x86.rs index 907cb32e..10227df7 100644 --- a/src/comp/back/x86.rs +++ b/src/comp/back/x86.rs @@ -98,12 +98,12 @@ fn rust_activate_glue() -> vec[str] { * | esi | * | ebx | <-- current task->rust_sp == current esp * - * + * * This is a problem. If we return to "esp <- task->rust_sp" it * will push esp back down by 5 words. This manifests as a rust * stack that grows by 5 words on each yield/reactivate. Not * good. - * + * * So what we do here is just adjust task->rust_sp up 5 words as * well, to mirror the movement in esp we're about to * perform. That way the "esp <- task->rust_sp" we 'ret' to below diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9da7e009..4a672f49 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -345,7 +345,8 @@ fn T_crate(type_names tn) -> TypeRef { T_int(), // size_t main_exit_task_glue_off T_int(), // int n_rust_syms T_int(), // int n_c_syms - T_int() // int n_libs + T_int(), // int n_libs + T_int() // uintptr_t abi_tag )); tn.associate(s, t); ret t; @@ -4545,7 +4546,7 @@ fn trans_exit_task_glue(@crate_ctxt cx) { let vec[ValueRef] V_args = vec(); auto llfn = cx.glues.exit_task_glue; - let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 0u); + let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 3u); auto fcx = @rec(llfn=llfn, lltaskptr=lltaskptr, llenv=C_null(T_opaque_closure_ptr(cx.tn)), @@ -4596,7 +4597,8 @@ fn create_crate_constant(@crate_ctxt cx) { exit_task_glue_off, // size_t main_exit_task_glue_off C_null(T_int()), // int n_rust_syms C_null(T_int()), // int n_c_syms - C_null(T_int()) // int n_libs + C_null(T_int()), // int n_libs + C_int(abi.abi_x86_rustc_fastcall) // uintptr_t abi_tag )); llvm.LLVMSetInitializer(cx.crate_ptr, crate_val); @@ -4810,7 +4812,10 @@ fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns { * this is the signature required to retrieve it. */ exit_task_glue = decl_cdecl_fn(llmod, abi.exit_task_glue_name(), - T_fn(vec(T_taskptr(tn)), + T_fn(vec(T_int(), + T_int(), + T_int(), + T_taskptr(tn)), T_void())), upcall_glues = diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp index 0ea167a4..46fcb22e 100644 --- a/src/rt/rust.cpp +++ b/src/rt/rust.cpp @@ -78,7 +78,7 @@ command_line_args : public dom_owned extern "C" CDECL int rust_start(uintptr_t main_fn, rust_crate const *crate, int argc, - char **argv) { + char **argv) { rust_srv *srv = new rust_srv(); rust_kernel *kernel = new rust_kernel(srv); @@ -87,7 +87,8 @@ rust_start(uintptr_t main_fn, rust_crate const *crate, int argc, rust_dom *dom = handle->referent(); command_line_args *args = new (dom) command_line_args(dom, argc, argv); - dom->log(rust_log::DOM, "startup: %d args", args->argc); + dom->log(rust_log::DOM, "startup: %d args in 0x%" PRIxPTR, + args->argc, (uintptr_t)args->args); for (int i = 0; i < args->argc; i++) { dom->log(rust_log::DOM, "startup: arg[%d] = '%s'", i, args->argv[i]); @@ -99,7 +100,8 @@ rust_start(uintptr_t main_fn, rust_crate const *crate, int argc, uintptr_t main_args[4] = {0, 0, 0, (uintptr_t)args->args}; dom->root_task->start(crate->get_exit_task_glue(), - main_fn, (uintptr_t)&main_args, sizeof(main_args)); + crate->abi_tag, main_fn, + (uintptr_t)&main_args, sizeof(main_args)); int ret = dom->start_main_loop(); delete args; kernel->destroy_domain(dom); diff --git a/src/rt/rust_internal.h b/src/rt/rust_internal.h index 61716703..42b61801 100644 --- a/src/rt/rust_internal.h +++ b/src/rt/rust_internal.h @@ -88,6 +88,10 @@ static size_t const TIME_SLICE_IN_MS = 10; static intptr_t const CONST_REFCOUNT = 0x7badface; +// ABI tags for rust_start, rust_task::start and friends. +static uintptr_t const ABI_X86_RUSTBOOT_CDECL = 1; +static uintptr_t const ABI_X86_RUSTC_FASTCALL = 2; + // This accounts for logging buffers. static size_t const BUF_BYTES = 2048; @@ -241,6 +245,8 @@ public: size_t n_c_syms; size_t n_libs; + uintptr_t abi_tag; + // Crates are immutable, constructed by the compiler. uintptr_t get_image_base() const; diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 3564b9e3..1afbfdd6 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -123,6 +123,7 @@ rust_task::~rust_task() void rust_task::start(uintptr_t exit_task_glue, + uintptr_t spawnee_abi, uintptr_t spawnee_fn, uintptr_t args, size_t callsz) @@ -147,26 +148,29 @@ rust_task::start(uintptr_t exit_task_glue, // The exit_task_glue frame we synthesize above the frame we activate: *spp-- = (uintptr_t) 0; // closure-or-obj *spp-- = (uintptr_t) this; // task - *spp-- = (uintptr_t) 0; // output - *spp-- = (uintptr_t) 0; // retpc + *spp-- = (uintptr_t) 0x0; // output + *spp-- = (uintptr_t) 0x0; // retpc uintptr_t exit_task_frame_base; - for (size_t j = 0; j < n_callee_saves; ++j) { + if (spawnee_abi == ABI_X86_RUSTBOOT_CDECL) { + for (size_t j = 0; j < n_callee_saves; ++j) { - // We want 'frame_base' to point to the old fp in this (exit-task) - // frame, because we're going to inject this frame-pointer into the - // callee-save frame pointer value in the *next* (spawnee) frame. A - // cheap trick, but this means the spawnee frame will restore the - // proper frame pointer of the glue frame as it runs its epilogue. - if (j == callee_save_fp) - exit_task_frame_base = (uintptr_t)spp; + // We want 'frame_base' to point to the old fp in this (exit-task) + // frame, because we're going to inject this frame-pointer into + // the callee-save frame pointer value in the *next* (spawnee) + // frame. A cheap trick, but this means the spawnee frame will + // restore the proper frame pointer of the glue frame as it runs + // its epilogue. + if (j == callee_save_fp) + exit_task_frame_base = (uintptr_t)spp; - *spp-- = 0; - } + *spp-- = 0; + } - *spp-- = (uintptr_t) dom->root_crate; // crate ptr - *spp-- = (uintptr_t) 0; // frame_glue_fns + *spp-- = (uintptr_t) dom->root_crate; // crate ptr + *spp-- = (uintptr_t) 0; // frame_glue_fns + } // Copy args from spawner to spawnee. if (args) { @@ -174,12 +178,16 @@ rust_task::start(uintptr_t exit_task_glue, src += 1; // spawn-call output slot src += 1; // spawn-call task slot src += 1; // spawn-call closure-or-obj slot + + // Undo previous sp-- so we're pointing at the last word pushed. + ++spp; + // Memcpy all but the task, output and env pointers callsz -= (3 * sizeof(uintptr_t)); spp = (uintptr_t*) (((uintptr_t)spp) - callsz); memcpy(spp, src, callsz); - // Move sp down to point to task cell. + // Move sp down to point to last implicit-arg cell (env). spp--; } else { // We're at root, starting up. @@ -188,10 +196,18 @@ rust_task::start(uintptr_t exit_task_glue, // The *implicit* incoming args to the spawnee frame we're // activating: + *spp-- = (uintptr_t) 0x0; // closure-or-obj + + if (spawnee_abi == ABI_X86_RUSTBOOT_CDECL) { + // in CDECL mode we write the task + outptr to the spawnee stack. + *spp-- = (uintptr_t) this; // task + *spp-- = (uintptr_t) 0; // output addr + } else { + // in FASTCALL mode we don't, the outptr will be in ecx and the task + // in edx, and the activate_glue will make sure to set that up. + I(dom, spawnee_abi == ABI_X86_RUSTC_FASTCALL); + } - *spp-- = (uintptr_t) 0; // closure-or-obj - *spp-- = (uintptr_t) this; // task - *spp-- = (uintptr_t) 0; // output addr *spp-- = (uintptr_t) exit_task_glue; // retpc // The context the activate_glue needs to switch stack. diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index 9fbc67ac..5318ab71 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -56,6 +56,7 @@ rust_task : public maybe_proxy, ~rust_task(); void start(uintptr_t exit_task_glue, + uintptr_t spawnee_abi, uintptr_t spawnee_fn, uintptr_t args, size_t callsz); diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 46e53048..1dba1102 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -559,6 +559,7 @@ extern "C" CDECL rust_task * upcall_start_task(rust_task *spawner, rust_task *task, uintptr_t exit_task_glue, + uintptr_t spawnee_abi, uintptr_t spawnee_fn, size_t callsz) { LOG_UPCALL_ENTRY(spawner); @@ -570,7 +571,8 @@ upcall_start_task(rust_task *spawner, ", spawnee 0x%" PRIxPTR ", callsz %" PRIdPTR ")", task->name, task, exit_task_glue, spawnee_fn, callsz); - task->start(exit_task_glue, spawnee_fn, spawner->rust_sp, callsz); + task->start(exit_task_glue, spawnee_abi, spawnee_fn, + spawner->rust_sp, callsz); return task; } @@ -623,6 +625,7 @@ extern "C" CDECL maybe_proxy * upcall_start_thread(rust_task *task, rust_proxy *child_task_proxy, uintptr_t exit_task_glue, + uintptr_t spawnee_abi, uintptr_t spawnee_fn, size_t callsz) { LOG_UPCALL_ENTRY(task); @@ -630,9 +633,11 @@ upcall_start_thread(rust_task *task, rust_handle *child_task_handle = child_task_proxy->handle(); task->log(rust_log::UPCALL | rust_log::MEM | rust_log::TASK, "exit_task_glue: " PTR ", spawnee_fn " PTR - ", callsz %" PRIdPTR ")", exit_task_glue, spawnee_fn, callsz); + ", callsz %" PRIdPTR ")", + exit_task_glue, spawnee_fn, callsz); rust_task *child_task = child_task_handle->referent(); - child_task->start(exit_task_glue, spawnee_fn, task->rust_sp, callsz); + child_task->start(exit_task_glue, spawnee_abi, spawnee_fn, + task->rust_sp, callsz); #if defined(__WIN32__) HANDLE thread; thread = CreateThread(NULL, 0, rust_thread_start, child_task->dom, 0, diff --git a/src/rt/test/rust_test_runtime.cpp b/src/rt/test/rust_test_runtime.cpp index 1cde532e..e0e24156 100644 --- a/src/rt/test/rust_test_runtime.cpp +++ b/src/rt/test/rust_test_runtime.cpp @@ -54,6 +54,7 @@ rust_task_test::worker::run() { kernel->create_domain(crate, "test"); rust_dom *domain = handle->referent(); domain->root_task->start(crate->get_exit_task_glue(), + ABI_X86_RUSTBOOT_CDECL, (uintptr_t)&task_entry, (uintptr_t)NULL, 0); domain->start_main_loop(); kernel->destroy_domain(domain); -- cgit v1.2.3 From d7f7634c955deaf55cf11071d5e92300a059be61 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 22 Feb 2011 18:07:47 -0800 Subject: Drop for-loop temporary at end of scope, fixes memory leak. --- src/comp/middle/trans.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4a672f49..6a19a6e5 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2189,6 +2189,7 @@ fn trans_for(@block_ctxt cx, cx.build.Br(scope_cx.llbb); auto local_res = alloc_local(scope_cx, local); auto bcx = copy_ty(local_res.bcx, INIT, local_res.val, curr, t).bcx; + scope_cx.cleanups += clean(bind drop_slot(_, local_res.val, t)); bcx = trans_block(bcx, body).bcx; bcx.build.Br(next_cx.llbb); ret res(next_cx, C_nil()); -- cgit v1.2.3 From 3a7271a026248c88ebefff6c5b585245a5151eb1 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 22 Feb 2011 18:20:40 -0800 Subject: Un-XFAIL argv.rs and command-line-args.rs. --- src/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Makefile b/src/Makefile index 872ced98..2616ae47 100644 --- a/src/Makefile +++ b/src/Makefile @@ -448,6 +448,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ alt-pattern-lit.rs \ alt-pattern-simple.rs \ alt-tag.rs \ + argv.rs \ arith-0.rs \ arith-1.rs \ arith-2.rs \ @@ -464,6 +465,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ box-in-tup.rs \ cast.rs \ char.rs \ + command-line-args.rs \ complex.rs \ const.rs \ dead-code-one-arm-if.rs \ -- cgit v1.2.3 From b6f1c832e3c883a2ef2f5b47a68db79f33f5fb25 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 22 Feb 2011 18:31:54 -0800 Subject: rustc: Perform explicit type substitution as requested by the programmer --- src/comp/middle/typeck.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 1b39cdf5..8f19e3ad 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -25,6 +25,7 @@ import middle.ty.type_is_scalar; import std._str; import std._uint; import std._vec; +import std.map; import std.map.hashmap; import std.option; import std.option.none; @@ -78,6 +79,65 @@ fn generalize_ty(@crate_ctxt cx, @ty.t t) -> @ty.t { ret ty.fold_ty(generalizer, t); } +// Substitutes the user's explicit types for the parameters in a path +// expression. +fn substitute_ty_params(&@crate_ctxt ccx, + @ty.t typ, + vec[@ast.ty] supplied, + &span sp) -> @ty.t { + state obj ty_substituter(@crate_ctxt ccx, + @mutable uint i, + vec[@ast.ty] supplied, + @hashmap[int,@ty.t] substs) { + fn fold_simple_ty(@ty.t typ) -> @ty.t { + alt (typ.struct) { + case (ty.ty_var(?vid)) { + alt (substs.find(vid)) { + case (some[@ty.t](?resolved_ty)) { + ret resolved_ty; + } + case (none[@ty.t]) { + if (i >= _vec.len[@ast.ty](supplied)) { + // Just leave it as an unresolved parameter + // for now. (We will error out later.) + ret typ; + } + + auto result = ast_ty_to_ty_crate(ccx, + supplied.(*i)); + *i += 1u; + substs.insert(vid, result); + ret result; + } + } + } + case (_) { ret typ; } + } + } + } + + fn hash_int(&int x) -> uint { ret x as uint; } + fn eq_int(&int a, &int b) -> bool { ret a == b; } + auto hasher = hash_int; + auto eqer = eq_int; + auto substs = @map.mk_hashmap[int,@ty.t](hasher, eqer); + + auto subst_count = @mutable 0u; + auto substituter = ty_substituter(ccx, subst_count, supplied, substs); + + auto result = ty.fold_ty(substituter, typ); + + auto supplied_len = _vec.len[@ast.ty](supplied); + if ((*subst_count) != supplied_len) { + ccx.sess.span_err(sp, "expected " + _uint.to_str(*subst_count, 10u) + + " type parameter(s) but found " + + _uint.to_str(supplied_len, 10u) + " parameter(s)"); + fail; + } + + ret result; +} + // 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. @@ -1445,6 +1505,12 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } } + // Substitute type parameters if the user provided some. + if (_vec.len[@ast.ty](pth.node.types) > 0u) { + t = substitute_ty_params(fcx.ccx, t, pth.node.types, + expr.span); + } + ret @fold.respan[ast.expr_](expr.span, ast.expr_path(pth, defopt, ast.ann_type(t))); -- cgit v1.2.3 From c4df39609c9c09c450dd8fe5905a8e6fbeb5f181 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 22 Feb 2011 18:58:07 -0500 Subject: Rename std._io to std.io since 'io' is no longer a keyword --- src/comp/front/lexer.rs | 2 +- src/comp/front/parser.rs | 4 +- src/lib/_io.rs | 183 -------------------------------------------- src/lib/io.rs | 183 ++++++++++++++++++++++++++++++++++++++++++++ src/lib/std.rc | 4 +- src/test/run-pass/lib-io.rs | 6 +- 6 files changed, 191 insertions(+), 191 deletions(-) delete mode 100644 src/lib/_io.rs create mode 100644 src/lib/io.rs diff --git a/src/comp/front/lexer.rs b/src/comp/front/lexer.rs index a45b1113..481fc5dd 100644 --- a/src/comp/front/lexer.rs +++ b/src/comp/front/lexer.rs @@ -1,4 +1,4 @@ -import std._io.stdio_reader; +import std.io.stdio_reader; import std._str; import std.map; import std.map.hashmap; diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 71b06b45..bbac78d3 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1,4 +1,4 @@ -import std._io; +import std.io; import std._vec; import std._str; import std.option; @@ -80,7 +80,7 @@ impure fn new_parser(session.session sess, ret tup(crate, def); } } - auto srdr = _io.new_stdio_reader(path); + auto srdr = io.new_stdio_reader(path); auto rdr = lexer.new_reader(srdr, path); auto npos = rdr.get_curr_pos(); ret stdio_parser(sess, lexer.next_token(rdr), diff --git a/src/lib/_io.rs b/src/lib/_io.rs deleted file mode 100644 index f285f6c8..00000000 --- a/src/lib/_io.rs +++ /dev/null @@ -1,183 +0,0 @@ -import std.os.libc; -import std._str; -import std._vec; - - -type stdio_reader = state obj { - fn getc() -> int; - fn ungetc(int i); -}; - -fn new_stdio_reader(str path) -> stdio_reader { - state obj stdio_FILE_reader(os.libc.FILE f) { - fn getc() -> int { - ret os.libc.fgetc(f); - } - fn ungetc(int i) { - os.libc.ungetc(i, f); - } - drop { - os.libc.fclose(f); - } - } - auto FILE = os.libc.fopen(_str.buf(path), _str.buf("r")); - check (FILE as uint != 0u); - ret stdio_FILE_reader(FILE); -} - - -type buf_reader = state obj { - fn read() -> vec[u8]; -}; - -type buf_writer = state obj { - fn write(vec[u8] v); -}; - -fn default_bufsz() -> uint { - ret 4096u; -} - -fn new_buf() -> vec[u8] { - ret _vec.alloc[u8](default_bufsz()); -} - -fn new_buf_reader(str path) -> buf_reader { - - state obj fd_buf_reader(int fd, mutable vec[u8] buf) { - - fn read() -> vec[u8] { - - // Ensure our buf is singly-referenced. - if (_vec.rustrt.refcount[u8](buf) != 1u) { - buf = new_buf(); - } - - auto len = default_bufsz(); - auto vbuf = _vec.buf[u8](buf); - auto count = os.libc.read(fd, vbuf, len); - - if (count < 0) { - log "error filling buffer"; - log sys.rustrt.last_os_error(); - fail; - } - - _vec.len_set[u8](buf, count as uint); - ret buf; - } - - drop { - os.libc.close(fd); - } - } - - auto fd = os.libc.open(_str.buf(path), - os.libc_constants.O_RDONLY() | - os.libc_constants.O_BINARY(), - 0u); - - if (fd < 0) { - log "error opening file for reading"; - log sys.rustrt.last_os_error(); - fail; - } - ret fd_buf_reader(fd, new_buf()); -} - -/** - * FIXME (issue #150): This should be - * - * type fileflag = tag(append(), create(), truncate()); - * - * but then the tag value ctors are not found from crate-importers of std, so - * we manually simulate the enum below. - */ -type fileflag = uint; -fn append() -> uint { ret 0u; } -fn create() -> uint { ret 1u; } -fn truncate() -> uint { ret 2u; } - -fn new_buf_writer(str path, vec[fileflag] flags) -> buf_writer { - - state obj fd_buf_writer(int fd) { - - fn write(vec[u8] v) { - auto len = _vec.len[u8](v); - auto count = 0u; - auto vbuf; - while (count < len) { - vbuf = _vec.buf_off[u8](v, count); - auto nout = os.libc.write(fd, vbuf, len); - if (nout < 0) { - log "error dumping buffer"; - log sys.rustrt.last_os_error(); - fail; - } - count += nout as uint; - } - } - - drop { - os.libc.close(fd); - } - } - - let int fflags = - os.libc_constants.O_WRONLY() | - os.libc_constants.O_BINARY(); - - for (fileflag f in flags) { - alt (f) { - // FIXME (issue #150): cf comment above defn of fileflag type - //case (append()) { fflags |= os.libc_constants.O_APPEND(); } - //case (create()) { fflags |= os.libc_constants.O_CREAT(); } - //case (truncate()) { fflags |= os.libc_constants.O_TRUNC(); } - case (0u) { fflags |= os.libc_constants.O_APPEND(); } - case (1u) { fflags |= os.libc_constants.O_CREAT(); } - case (2u) { fflags |= os.libc_constants.O_TRUNC(); } - } - } - - auto fd = os.libc.open(_str.buf(path), - fflags, - os.libc_constants.S_IRUSR() | - os.libc_constants.S_IWUSR()); - - if (fd < 0) { - log "error opening file for writing"; - log sys.rustrt.last_os_error(); - fail; - } - ret fd_buf_writer(fd); -} - -type writer = - state obj { - fn write_str(str s); - fn write_int(int n); - fn write_uint(uint n); - }; - -fn file_writer(str path, - vec[fileflag] flags) - -> writer -{ - state obj fw(buf_writer out) { - fn write_str(str s) { out.write(_str.bytes(s)); } - fn write_int(int n) { out.write(_str.bytes(_int.to_str(n, 10u))); } - fn write_uint(uint n) { out.write(_str.bytes(_uint.to_str(n, 10u))); } - } - ret fw(new_buf_writer(path, flags)); -} - -// -// Local Variables: -// mode: rust -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: -// diff --git a/src/lib/io.rs b/src/lib/io.rs new file mode 100644 index 00000000..f285f6c8 --- /dev/null +++ b/src/lib/io.rs @@ -0,0 +1,183 @@ +import std.os.libc; +import std._str; +import std._vec; + + +type stdio_reader = state obj { + fn getc() -> int; + fn ungetc(int i); +}; + +fn new_stdio_reader(str path) -> stdio_reader { + state obj stdio_FILE_reader(os.libc.FILE f) { + fn getc() -> int { + ret os.libc.fgetc(f); + } + fn ungetc(int i) { + os.libc.ungetc(i, f); + } + drop { + os.libc.fclose(f); + } + } + auto FILE = os.libc.fopen(_str.buf(path), _str.buf("r")); + check (FILE as uint != 0u); + ret stdio_FILE_reader(FILE); +} + + +type buf_reader = state obj { + fn read() -> vec[u8]; +}; + +type buf_writer = state obj { + fn write(vec[u8] v); +}; + +fn default_bufsz() -> uint { + ret 4096u; +} + +fn new_buf() -> vec[u8] { + ret _vec.alloc[u8](default_bufsz()); +} + +fn new_buf_reader(str path) -> buf_reader { + + state obj fd_buf_reader(int fd, mutable vec[u8] buf) { + + fn read() -> vec[u8] { + + // Ensure our buf is singly-referenced. + if (_vec.rustrt.refcount[u8](buf) != 1u) { + buf = new_buf(); + } + + auto len = default_bufsz(); + auto vbuf = _vec.buf[u8](buf); + auto count = os.libc.read(fd, vbuf, len); + + if (count < 0) { + log "error filling buffer"; + log sys.rustrt.last_os_error(); + fail; + } + + _vec.len_set[u8](buf, count as uint); + ret buf; + } + + drop { + os.libc.close(fd); + } + } + + auto fd = os.libc.open(_str.buf(path), + os.libc_constants.O_RDONLY() | + os.libc_constants.O_BINARY(), + 0u); + + if (fd < 0) { + log "error opening file for reading"; + log sys.rustrt.last_os_error(); + fail; + } + ret fd_buf_reader(fd, new_buf()); +} + +/** + * FIXME (issue #150): This should be + * + * type fileflag = tag(append(), create(), truncate()); + * + * but then the tag value ctors are not found from crate-importers of std, so + * we manually simulate the enum below. + */ +type fileflag = uint; +fn append() -> uint { ret 0u; } +fn create() -> uint { ret 1u; } +fn truncate() -> uint { ret 2u; } + +fn new_buf_writer(str path, vec[fileflag] flags) -> buf_writer { + + state obj fd_buf_writer(int fd) { + + fn write(vec[u8] v) { + auto len = _vec.len[u8](v); + auto count = 0u; + auto vbuf; + while (count < len) { + vbuf = _vec.buf_off[u8](v, count); + auto nout = os.libc.write(fd, vbuf, len); + if (nout < 0) { + log "error dumping buffer"; + log sys.rustrt.last_os_error(); + fail; + } + count += nout as uint; + } + } + + drop { + os.libc.close(fd); + } + } + + let int fflags = + os.libc_constants.O_WRONLY() | + os.libc_constants.O_BINARY(); + + for (fileflag f in flags) { + alt (f) { + // FIXME (issue #150): cf comment above defn of fileflag type + //case (append()) { fflags |= os.libc_constants.O_APPEND(); } + //case (create()) { fflags |= os.libc_constants.O_CREAT(); } + //case (truncate()) { fflags |= os.libc_constants.O_TRUNC(); } + case (0u) { fflags |= os.libc_constants.O_APPEND(); } + case (1u) { fflags |= os.libc_constants.O_CREAT(); } + case (2u) { fflags |= os.libc_constants.O_TRUNC(); } + } + } + + auto fd = os.libc.open(_str.buf(path), + fflags, + os.libc_constants.S_IRUSR() | + os.libc_constants.S_IWUSR()); + + if (fd < 0) { + log "error opening file for writing"; + log sys.rustrt.last_os_error(); + fail; + } + ret fd_buf_writer(fd); +} + +type writer = + state obj { + fn write_str(str s); + fn write_int(int n); + fn write_uint(uint n); + }; + +fn file_writer(str path, + vec[fileflag] flags) + -> writer +{ + state obj fw(buf_writer out) { + fn write_str(str s) { out.write(_str.bytes(s)); } + fn write_int(int n) { out.write(_str.bytes(_int.to_str(n, 10u))); } + fn write_uint(uint n) { out.write(_str.bytes(_uint.to_str(n, 10u))); } + } + ret fw(new_buf_writer(path, flags)); +} + +// +// Local Variables: +// mode: rust +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: +// diff --git a/src/lib/std.rc b/src/lib/std.rc index 3500c4b3..4ad422a3 100644 --- a/src/lib/std.rc +++ b/src/lib/std.rc @@ -14,7 +14,7 @@ mod _str; // General IO and system-services modules. -mod _io; +mod io; mod sys; mod _task; @@ -25,7 +25,7 @@ mod util; // Authorize various rule-bendings. -auth _io = unsafe; +auth io = unsafe; auth _str = unsafe; auth _vec = unsafe; auth _task = unsafe; diff --git a/src/test/run-pass/lib-io.rs b/src/test/run-pass/lib-io.rs index 66394435..e0665fb6 100644 --- a/src/test/run-pass/lib-io.rs +++ b/src/test/run-pass/lib-io.rs @@ -1,7 +1,7 @@ // -*- rust -*- use std; -import std._io; +import std.io; import std._str; fn test_simple(str tmpfilebase) { @@ -11,11 +11,11 @@ fn test_simple(str tmpfilebase) { log frood; { - let _io.buf_writer out = _io.new_buf_writer(tmpfile, vec(_io.create())); + let io.buf_writer out = io.new_buf_writer(tmpfile, vec(io.create())); out.write(_str.bytes(frood)); } - let _io.buf_reader inp = _io.new_buf_reader(tmpfile); + let io.buf_reader inp = io.new_buf_reader(tmpfile); let str frood2 = _str.from_bytes(inp.read()); log frood2; check (_str.eq(frood, frood2)); -- cgit v1.2.3 From eac75b76486ec54f677b2460f09635380437b125 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 22 Feb 2011 20:23:38 -0500 Subject: Teach rustc about reserved keywords --- src/Makefile | 7 +++++++ src/comp/front/lexer.rs | 17 ++++++++++++++++- src/test/compile-fail/reserved-dec.rs | 5 +++++ src/test/compile-fail/reserved-f128.rs | 5 +++++ src/test/compile-fail/reserved-f16.rs | 5 +++++ src/test/compile-fail/reserved-f80.rs | 5 +++++ src/test/compile-fail/reserved-m128.rs | 5 +++++ src/test/compile-fail/reserved-m32.rs | 5 +++++ src/test/compile-fail/reserved-m64.rs | 5 +++++ 9 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/test/compile-fail/reserved-dec.rs create mode 100644 src/test/compile-fail/reserved-f128.rs create mode 100644 src/test/compile-fail/reserved-f16.rs create mode 100644 src/test/compile-fail/reserved-f80.rs create mode 100644 src/test/compile-fail/reserved-m128.rs create mode 100644 src/test/compile-fail/reserved-m32.rs create mode 100644 src/test/compile-fail/reserved-m64.rs diff --git a/src/Makefile b/src/Makefile index 2616ae47..551a7001 100644 --- a/src/Makefile +++ b/src/Makefile @@ -569,6 +569,13 @@ TEST_XFAILS_RUSTC := $(filter-out \ multiline-comment-line-tracking.rs \ output-type-mismatch.rs \ rec-missing-fields.rs \ + reserved-dec.rs \ + reserved-f128.rs \ + reserved-f16.rs \ + reserved-f80.rs \ + reserved-m128.rs \ + reserved-m32.rs \ + reserved-m64.rs \ tail-non-call.rs \ tail-typeck.rs \ type-shadow.rs \ diff --git a/src/comp/front/lexer.rs b/src/comp/front/lexer.rs index 481fc5dd..99e9217f 100644 --- a/src/comp/front/lexer.rs +++ b/src/comp/front/lexer.rs @@ -90,7 +90,6 @@ fn new_reader(stdio_reader rdr, str filename) -> reader } auto keywords = new_str_hash[token.token](); - auto reserved = new_str_hash[()](); keywords.insert("mod", token.MOD); keywords.insert("use", token.USE); @@ -191,6 +190,16 @@ fn new_reader(stdio_reader rdr, str filename) -> reader keywords.insert("f32", token.MACH(common.ty_f32)); keywords.insert("f64", token.MACH(common.ty_f64)); + auto reserved = new_str_hash[()](); + + reserved.insert("f16", ()); // IEEE 754-2008 'binary16' interchange fmt + reserved.insert("f80", ()); // IEEE 754-1985 'extended' + reserved.insert("f128", ()); // IEEE 754-2008 'binary128' + reserved.insert("m32", ()); // IEEE 754-2008 'decimal32' + reserved.insert("m64", ()); // IEEE 754-2008 'decimal64' + reserved.insert("m128", ()); // IEEE 754-2008 'decimal128' + reserved.insert("dec", ()); // One of m32, m64, m128 + ret reader(rdr, filename, rdr.getc() as char, rdr.getc() as char, 1u, 0u, 1u, 0u, keywords, reserved); } @@ -425,6 +434,12 @@ impure fn next_token(reader rdr) -> token.token { ret kwds.get(accum_str); } + auto rsvd = rdr.get_reserved(); + if (rsvd.contains_key(accum_str)) { + log "reserved keyword"; + fail; + } + ret token.IDENT(accum_str); } diff --git a/src/test/compile-fail/reserved-dec.rs b/src/test/compile-fail/reserved-dec.rs new file mode 100644 index 00000000..d8c204d9 --- /dev/null +++ b/src/test/compile-fail/reserved-dec.rs @@ -0,0 +1,5 @@ +// error-pattern:reserved keyword + +fn main() { + let int dec = 0; +} diff --git a/src/test/compile-fail/reserved-f128.rs b/src/test/compile-fail/reserved-f128.rs new file mode 100644 index 00000000..63d00f70 --- /dev/null +++ b/src/test/compile-fail/reserved-f128.rs @@ -0,0 +1,5 @@ +// error-pattern:reserved keyword + +fn main() { + let int f128 = 0; +} diff --git a/src/test/compile-fail/reserved-f16.rs b/src/test/compile-fail/reserved-f16.rs new file mode 100644 index 00000000..bfb14cd8 --- /dev/null +++ b/src/test/compile-fail/reserved-f16.rs @@ -0,0 +1,5 @@ +// error-pattern:reserved keyword + +fn main() { + let int f16 = 0; +} diff --git a/src/test/compile-fail/reserved-f80.rs b/src/test/compile-fail/reserved-f80.rs new file mode 100644 index 00000000..33e8bd5e --- /dev/null +++ b/src/test/compile-fail/reserved-f80.rs @@ -0,0 +1,5 @@ +// error-pattern:reserved keyword + +fn main() { + let int f80 = 0; +} diff --git a/src/test/compile-fail/reserved-m128.rs b/src/test/compile-fail/reserved-m128.rs new file mode 100644 index 00000000..c4d36bf7 --- /dev/null +++ b/src/test/compile-fail/reserved-m128.rs @@ -0,0 +1,5 @@ +// error-pattern:reserved keyword + +fn main() { + let int m128 = 0; +} diff --git a/src/test/compile-fail/reserved-m32.rs b/src/test/compile-fail/reserved-m32.rs new file mode 100644 index 00000000..bdb3a427 --- /dev/null +++ b/src/test/compile-fail/reserved-m32.rs @@ -0,0 +1,5 @@ +// error-pattern:reserved keyword + +fn main() { + let int m32 = 0; +} diff --git a/src/test/compile-fail/reserved-m64.rs b/src/test/compile-fail/reserved-m64.rs new file mode 100644 index 00000000..034884a6 --- /dev/null +++ b/src/test/compile-fail/reserved-m64.rs @@ -0,0 +1,5 @@ +// error-pattern:reserved keyword + +fn main() { + let int m64 = 0; +} -- cgit v1.2.3 From 3b7e9dc393c7b015bb06a8cc1213c25b8911362f Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 22 Feb 2011 18:50:39 -0500 Subject: Rustify some comments lifted directly from the sha-1 reference implementation --- src/lib/sha1.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/sha1.rs b/src/lib/sha1.rs index 8be969aa..2a6b74d4 100644 --- a/src/lib/sha1.rs +++ b/src/lib/sha1.rs @@ -185,8 +185,8 @@ fn mk_sha1() -> sha1 { * 512 bits. The first padding bit must be a '1'. The last 64 bits * represent the length of the original message. All bits in between * should be 0. This function will pad the message according to those - * rules by filling the message_block array accordingly. It will also - * call ProcessMessageBlock() appropriately. When it returns, it + * rules by filling the msg_block vector accordingly. It will also + * call process_msg_block() appropriately. When it returns, it * can be assumed that the message digest has been computed. */ impure fn pad_msg(&sha1state st) { -- cgit v1.2.3 From 6849abcf7df583f58f390eb55c7b0e84dfb1bd25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Wed, 23 Feb 2011 11:59:07 -0500 Subject: Handle the new ty_native_fn in type check. --- src/comp/middle/ty.rs | 107 +++++++++++++++++++++++++++++++++++++--------- src/comp/middle/typeck.rs | 14 +++--- 2 files changed, 96 insertions(+), 25 deletions(-) diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 68c21140..0f277329 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -346,6 +346,14 @@ fn fold_ty(ty_fold fld, @t ty) -> @t { } ret rewrap(ty, ty_fn(proto, new_args, fold_ty(fld, ret_ty))); } + case (ty_native_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_native_fn(new_args, fold_ty(fld, ret_ty))); + } case (ty_obj(?methods)) { let vec[method] new_methods = vec(); for (method m in methods) { @@ -588,6 +596,7 @@ fn count_ty_params(@t ty) -> uint { fn ty_fn_args(@t fty) -> vec[arg] { alt (fty.struct) { case (ty.ty_fn(_, ?a, _)) { ret a; } + case (ty.ty_native_fn(?a, _)) { ret a; } } } @@ -600,12 +609,14 @@ fn ty_fn_proto(@t fty) -> ast.proto { fn ty_fn_ret(@t fty) -> @t { alt (fty.struct) { case (ty.ty_fn(_, _, ?r)) { ret r; } + case (ty.ty_native_fn(_, ?r)) { ret r; } } } fn is_fn_ty(@t fty) -> bool { alt (fty.struct) { case (ty.ty_fn(_, _, _)) { ret true; } + case (ty.ty_native_fn(_, _)) { ret true; } case (_) { ret false; } } ret false; @@ -826,24 +837,23 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) ret ures_err(terr_mismatch, expected, actual); } - fn unify_fn(@hashmap[int,@ty.t] bindings, - ast.proto e_proto, - ast.proto a_proto, - @ty.t expected, - @ty.t actual, - &unify_handler handler, - vec[arg] expected_inputs, @t expected_output, - vec[arg] actual_inputs, @t actual_output) - -> unify_result { - - if (e_proto != a_proto) { - ret ures_err(terr_mismatch, expected, actual); - } + tag fn_common_res { + fn_common_res_err(unify_result); + fn_common_res_ok(vec[arg], @t); + } + fn unify_fn_common(@hashmap[int,@ty.t] bindings, + @ty.t expected, + @ty.t actual, + &unify_handler handler, + vec[arg] expected_inputs, @t expected_output, + vec[arg] actual_inputs, @t actual_output) + -> fn_common_res { auto expected_len = _vec.len[arg](expected_inputs); auto actual_len = _vec.len[arg](actual_inputs); if (expected_len != actual_len) { - ret ures_err(terr_arg_count, expected, actual); + ret fn_common_res_err(ures_err(terr_arg_count, + expected, actual)); } // TODO: as above, we should have an iter2 iterator. @@ -874,7 +884,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) } case (_) { - ret result; + ret fn_common_res_err(result); } } @@ -882,24 +892,67 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) } // Check the output. - auto result_out; auto result = unify_step(bindings, expected_output, actual_output, handler); alt (result) { case (ures_ok(?rty)) { - result_out = rty; + ret fn_common_res_ok(result_ins, rty); } case (_) { - ret result; + ret fn_common_res_err(result); } } + } - auto t = plain_ty(ty.ty_fn(e_proto, result_ins, result_out)); - ret ures_ok(t); + fn unify_fn(@hashmap[int,@ty.t] bindings, + ast.proto e_proto, + ast.proto a_proto, + @ty.t expected, + @ty.t actual, + &unify_handler handler, + vec[arg] expected_inputs, @t expected_output, + vec[arg] actual_inputs, @t actual_output) + -> unify_result { + if (e_proto != a_proto) { + ret ures_err(terr_mismatch, expected, actual); + } + auto t = unify_fn_common(bindings, expected, actual, + handler, expected_inputs, expected_output, + actual_inputs, actual_output); + alt (t) { + case (fn_common_res_err(?r)) { + ret r; + } + case (fn_common_res_ok(?result_ins, ?result_out)) { + auto t2 = plain_ty(ty.ty_fn(e_proto, result_ins, result_out)); + ret ures_ok(t2); + } + } + } + + fn unify_native_fn(@hashmap[int,@ty.t] bindings, + @ty.t expected, + @ty.t actual, + &unify_handler handler, + vec[arg] expected_inputs, @t expected_output, + vec[arg] actual_inputs, @t actual_output) + -> unify_result { + auto t = unify_fn_common(bindings, expected, actual, + handler, expected_inputs, expected_output, + actual_inputs, actual_output); + alt (t) { + case (fn_common_res_err(?r)) { + ret r; + } + case (fn_common_res_ok(?result_ins, ?result_out)) { + auto t2 = plain_ty(ty.ty_native_fn(result_ins, result_out)); + ret ures_ok(t2); + } + } } fn unify_obj(@hashmap[int,@ty.t] bindings, @@ -1258,6 +1311,20 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) } } + case (ty.ty_native_fn(?expected_inputs, ?expected_output)) { + alt (actual.struct) { + case (ty.ty_native_fn(?actual_inputs, ?actual_output)) { + ret unify_native_fn(bindings, + expected, actual, handler, + expected_inputs, expected_output, + actual_inputs, actual_output); + } + case (_) { + ret ures_err(terr_mismatch, expected, actual); + } + } + } + case (ty.ty_obj(?expected_meths)) { alt (actual.struct) { case (ty.ty_obj(?actual_meths)) { diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 8f19e3ad..0d583c5e 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1336,18 +1336,21 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } } - auto proto_0 = ast.proto_fn; // FIXME: typestate botch + auto rt_0 = next_ty_var(fcx.ccx); + auto t_0 = plain_ty(ty.ty_uint); // FIXME: typestate botch alt (expr_ty(f_0).struct) { - case (ty.ty_fn(?proto, _, _)) { proto_0 = proto; } + case (ty.ty_fn(?proto, _, _)) { + t_0 = plain_ty(ty.ty_fn(proto, arg_tys_0, rt_0)); + } + case (ty.ty_native_fn(_, _)) { + t_0 = plain_ty(ty.ty_native_fn(arg_tys_0, rt_0)); + } case (_) { log "check_call_or_bind(): fn expr doesn't have fn type"; fail; } } - auto rt_0 = next_ty_var(fcx.ccx); - auto t_0 = plain_ty(ty.ty_fn(proto_0, arg_tys_0, rt_0)); - // Unify and write back to the function. auto f_1 = demand_expr(fcx, t_0, f_0); @@ -1824,6 +1827,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto rt_1 = plain_ty(ty.ty_nil); // FIXME: typestate botch alt (expr_ty(result._0).struct) { case (ty.ty_fn(_,_,?rt)) { rt_1 = rt; } + case (ty.ty_native_fn(_,?rt)) { rt_1 = rt; } case (_) { log "LHS of call expr didn't have a function type?!"; fail; -- cgit v1.2.3 From ffcb4613700c968041f891985927b77f70a51c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Wed, 23 Feb 2011 14:06:37 -0500 Subject: Parse the abi in native modules. --- src/comp/front/ast.rs | 6 ++++++ src/comp/front/parser.rs | 44 +++++++++++++++++++++++++++++++++----------- src/comp/middle/fold.rs | 1 + src/test/run-pass/native2.rs | 9 +++++++++ 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 01739d19..30b4d324 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -241,7 +241,13 @@ type _mod = rec(vec[@view_item] view_items, vec[@item] items, mod_index index); +tag native_abi { + native_abi_rust; + native_abi_cdecl; +} + type native_mod = rec(str native_name, + native_abi abi, vec[@native_item] items, native_mod_index index); type native_mod_index = hashmap[ident,@native_item]; diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index bbac78d3..03b24e4e 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1723,7 +1723,8 @@ impure fn parse_native_item(parser p) -> @ast.native_item { } impure fn parse_native_mod_items(parser p, - str native_name) -> ast.native_mod { + str native_name, + ast.native_abi abi) -> ast.native_mod { auto index = new_str_hash[@ast.native_item](); let vec[@ast.native_item] items = vec(); while (p.peek() != token.RBRACE) { @@ -1733,28 +1734,49 @@ impure fn parse_native_mod_items(parser p, // Index the item. ast.index_native_item(index, item); } - ret rec(native_name=native_name, items=items, index=index); + ret rec(native_name=native_name, abi=abi, + items=items, index=index); +} + +fn default_native_name(session.session sess, str id) -> str { + alt (sess.get_targ_cfg().os) { + case (session.os_win32) { + ret id + ".dll"; + } + case (session.os_macos) { + ret "lib" + id + ".dylib"; + } + case (session.os_linux) { + ret "lib" + id + ".so"; + } + } } impure fn parse_item_native_mod(parser p) -> @ast.item { auto lo = p.get_span(); expect(p, token.NATIVE); - auto has_eq; - auto native_name = ""; - if (p.peek() == token.MOD) { - has_eq = true; - } else { - native_name = parse_str_lit(p); - has_eq = false; + auto abi = ast.native_abi_cdecl; + if (p.peek() != token.MOD) { + auto t = parse_str_lit(p); + if (t == "cdecl") { + } else if (t == "rust") { + abi = ast.native_abi_rust; + } else { + p.err("unsupported abi: " + t); + fail; + } } expect(p, token.MOD); auto id = parse_ident(p); - if (has_eq) { + auto native_name; + if (p.peek() == token.EQ) { expect(p, token.EQ); native_name = parse_str_lit(p); + } else { + native_name = default_native_name(p.get_session(), id); } expect(p, token.LBRACE); - auto m = parse_native_mod_items(p, native_name); + auto m = parse_native_mod_items(p, native_name, ast.native_abi_cdecl); auto hi = p.get_span(); expect(p, token.RBRACE); auto item = ast.item_native_mod(id, m, p.next_def_id()); diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index abe94b89..968d4737 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -944,6 +944,7 @@ fn fold_native_mod[ENV](&ENV e, ast_fold[ENV] fld, } ret fld.fold_native_mod(e, rec(native_name=m.native_name, + abi=m.abi, items=items, index=index)); } diff --git a/src/test/run-pass/native2.rs b/src/test/run-pass/native2.rs index 4d2f0ad9..4815345a 100644 --- a/src/test/run-pass/native2.rs +++ b/src/test/run-pass/native2.rs @@ -3,9 +3,18 @@ native "rust" mod rustrt { fn vec_buf[T](vec[T] v, uint offset) -> vbuf; } +native "rust" mod bar = "foo" { +} + +native mod zed { +} + native mod libc = "libc.dylib" { fn write(int fd, rustrt.vbuf buf, uint count) -> int; } +native "cdecl" mod baz { +} + fn main(vec[str] args) { } -- cgit v1.2.3 From 5f6110a4db9639dd8c21f976dc2c3f34ede3e038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Wed, 23 Feb 2011 14:10:02 -0500 Subject: Use the computed abi :-( --- src/comp/front/parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 03b24e4e..eb073e00 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1776,7 +1776,7 @@ impure fn parse_item_native_mod(parser p) -> @ast.item { native_name = default_native_name(p.get_session(), id); } expect(p, token.LBRACE); - auto m = parse_native_mod_items(p, native_name, ast.native_abi_cdecl); + auto m = parse_native_mod_items(p, native_name, abi); auto hi = p.get_span(); expect(p, token.RBRACE); auto item = ast.item_native_mod(id, m, p.next_def_id()); -- cgit v1.2.3 From c6bc5cce4bf2ed84740ec6810505014c7d73b779 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 23 Feb 2011 13:28:46 -0800 Subject: Parse auth clauses, drop them on the floor. Nothing exists to use them yet anyways. --- src/comp/front/parser.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index eb073e00..6d77a204 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -2117,6 +2117,15 @@ impure fn parse_crate_directive(str prefix, parser p, auto lo = p.get_span(); auto hi = lo; alt (p.peek()) { + case (token.AUTH) { + // FIXME: currently dropping auth clauses on the floor, + // as there is no effect-checking pass. + p.bump(); + auto n = parse_path(p, GREEDY); + expect(p, token.EQ); + auto e = parse_effect(p); + expect(p, token.SEMI); + } case (token.CONST) { auto c = parse_item_const(p); ast.index_item(index, c); -- cgit v1.2.3 From 381684043f1ad044c72347d759c1c545c6bccc3d Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 23 Feb 2011 14:37:39 -0800 Subject: Add a type for crate directives, to support intermixing with exprs in crate files. --- src/comp/front/ast.rs | 14 ++++++++++++++ src/comp/util/common.rs | 4 +++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 30b4d324..2c307478 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -5,6 +5,7 @@ import std._vec; import util.common.span; import util.common.spanned; import util.common.ty_mach; +import util.common.filename; type ident = str; @@ -43,6 +44,18 @@ tag def { type crate = spanned[crate_]; type crate_ = rec(_mod module); +tag crate_directive_ { + cdir_expr(@expr); + cdir_src_mod(ident, option.t[filename]); + cdir_dir_mod(ident, option.t[filename], vec[crate_directive]); + cdir_view_item(@view_item); + cdir_meta(@meta_item); + cdir_syntax(path); + cdir_auth(path, effect); +} +type crate_directive = spanned[crate_directive_]; + + type meta_item = spanned[meta_item_]; type meta_item_ = rec(ident name, str value); @@ -161,6 +174,7 @@ tag expr_ { expr_do_while(block, @expr, ann); expr_alt(@expr, vec[arm], ann); expr_block(block, ann); + expr_crate_directive_block(vec[crate_directive_]); expr_assign(@expr /* TODO: @expr|is_lval */, @expr, ann); expr_assign_op(binop, @expr /* TODO: @expr|is_lval */, @expr, ann); expr_field(@expr, ident, ann); diff --git a/src/comp/util/common.rs b/src/comp/util/common.rs index 56f30e07..071acea2 100644 --- a/src/comp/util/common.rs +++ b/src/comp/util/common.rs @@ -2,8 +2,10 @@ import std._uint; import std._int; import front.ast; + +type filename = str; type pos = rec(uint line, uint col); -type span = rec(str filename, pos lo, pos hi); +type span = rec(filename filename, pos lo, pos hi); type spanned[T] = rec(T node, span span); tag ty_mach { -- cgit v1.2.3 From b4d6589e7387a7c7df0841f51f0fa5ef831883d9 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 23 Feb 2011 10:58:43 -0800 Subject: Implement type descriptor binding. Un-XFAIL test/run-pass/generic-bind.rs. --- src/Makefile | 1 + src/comp/middle/trans.rs | 115 +++++++++++++++++++++++++++++++++++++++-------- src/comp/middle/ty.rs | 3 ++ 3 files changed, 100 insertions(+), 19 deletions(-) diff --git a/src/Makefile b/src/Makefile index 551a7001..edbe9e29 100644 --- a/src/Makefile +++ b/src/Makefile @@ -480,6 +480,7 @@ TEST_XFAILS_RUSTC := $(filter-out \ foreach-simple.rs \ fun-call-variants.rs \ fun-indirect-call.rs \ + generic-bind.rs \ generic-derived-type.rs \ generic-fn.rs \ generic-fn-infer.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 6a19a6e5..30f3cdc4 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -373,11 +373,12 @@ fn T_typaram_ptr(type_names tn) -> TypeRef { fn T_closure_ptr(type_names tn, TypeRef lltarget_ty, - TypeRef llbindings_ty) -> TypeRef { + TypeRef llbindings_ty, + uint n_ty_params) -> TypeRef { ret T_ptr(T_box(T_struct(vec(T_ptr(T_tydesc(tn)), lltarget_ty, - llbindings_ty) - // FIXME: add captured typarams. + llbindings_ty, + T_captured_tydescs(tn, n_ty_params)) ))); } @@ -388,7 +389,8 @@ fn T_opaque_closure_ptr(type_names tn) -> TypeRef { } auto t = T_closure_ptr(tn, T_struct(vec(T_ptr(T_nil()), T_ptr(T_nil()))), - T_nil()); + T_nil(), + 0u); tn.associate(s, t); ret t; } @@ -2747,7 +2749,8 @@ fn trans_bind_thunk(@crate_ctxt cx, @ty.t outgoing_fty, vec[option.t[@ast.expr]] args, TypeRef llclosure_ty, - vec[@ty.t] bound_tys) -> ValueRef { + vec[@ty.t] bound_tys, + uint ty_param_count) -> ValueRef { // Construct a thunk-call with signature incoming_fty, and that copies // args forward into a call to outgoing_fty. @@ -2755,9 +2758,6 @@ fn trans_bind_thunk(@crate_ctxt cx, let TypeRef llthunk_ty = get_pair_fn_ty(type_of(cx, incoming_fty)); let ValueRef llthunk = decl_fastcall_fn(cx.llmod, s, llthunk_ty); - // FIXME: handle ty params properly. - let vec[ast.ty_param] ty_params = vec(); - auto fcx = new_fn_ctxt(cx, s, llthunk); auto bcx = new_top_block_ctxt(fcx); @@ -2779,11 +2779,33 @@ fn trans_bind_thunk(@crate_ctxt cx, vec(C_int(0), C_int(abi.fn_field_box))); lltargetclosure = bcx.build.Load(lltargetclosure); - let vec[ValueRef] llargs = vec(fcx.llretptr, + + auto outgoing_ret_ty = ty.ty_fn_ret(outgoing_fty); + auto outgoing_arg_tys = ty.ty_fn_args(outgoing_fty); + + auto llretptr = fcx.llretptr; + if (ty.type_has_dynamic_size(outgoing_ret_ty)) { + llretptr = bcx.build.PointerCast(llretptr, T_typaram_ptr(cx.tn)); + } + + let vec[ValueRef] llargs = vec(llretptr, fcx.lltaskptr, lltargetclosure); - let uint a = 0u; + + // Copy in the type parameters. + let uint i = 0u; + while (i < ty_param_count) { + auto lltyparam_ptr = + bcx.build.GEP(llbody, vec(C_int(0), + C_int(abi.closure_elt_ty_params), + C_int(i as int))); + llargs += vec(bcx.build.Load(lltyparam_ptr)); + i += 1u; + } + + let uint a = 2u + i; // retptr, task ptr, env come first let int b = 0; + let uint outgoing_arg_index = 0u; for (option.t[@ast.expr] arg in args) { alt (arg) { @@ -2800,10 +2822,19 @@ fn trans_bind_thunk(@crate_ctxt cx, // Arg will be provided when the thunk is invoked. case (none[@ast.expr]) { let ValueRef passed_arg = llvm.LLVMGetParam(llthunk, a); + if (ty.type_has_dynamic_size(outgoing_arg_tys. + (outgoing_arg_index).ty)) { + // Cast to a generic typaram pointer in order to make a + // type-compatible call. + passed_arg = bcx.build.PointerCast(passed_arg, + T_typaram_ptr(cx.tn)); + } llargs += passed_arg; a += 1u; } } + + outgoing_arg_index += 0u; } // FIXME: turn this call + ret into a tail call. @@ -2811,6 +2842,7 @@ fn trans_bind_thunk(@crate_ctxt cx, vec(C_int(0), C_int(abi.fn_field_code))); lltargetfn = bcx.build.Load(lltargetfn); + auto r = bcx.build.FastCall(lltargetfn, llargs); bcx.build.RetVoid(); @@ -2835,7 +2867,23 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, } } } - if (_vec.len[@ast.expr](bound) == 0u) { + + // Figure out which tydescs we need to pass, if any. + // FIXME: typestate botch + let @ty.t outgoing_fty = ty.plain_ty(ty.ty_nil); + let vec[ValueRef] lltydescs = vec(); + alt (f_res.generic) { + case (none[generic_info]) { + outgoing_fty = ty.expr_ty(f); + } + case (some[generic_info](?ginfo)) { + outgoing_fty = ginfo.item_type; + lltydescs = ginfo.tydescs; + } + } + auto ty_param_count = _vec.len[ValueRef](lltydescs); + + if (_vec.len[@ast.expr](bound) == 0u && ty_param_count == 0u) { // Trivial 'binding': just return the static pair-ptr. ret f_res.res; } else { @@ -2846,20 +2894,27 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, // Translate the bound expressions. let vec[@ty.t] bound_tys = vec(); let vec[ValueRef] bound_vals = vec(); + auto i = 0u; for (@ast.expr e in bound) { auto arg = trans_expr(bcx, e); bcx = arg.bcx; + append[ValueRef](bound_vals, arg.val); append[@ty.t](bound_tys, ty.expr_ty(e)); + + i += 1u; } + // Get the type of the bound function. + let TypeRef lltarget_ty = type_of(bcx.fcx.ccx, outgoing_fty); + // Synthesize a closure type. let @ty.t bindings_ty = plain_ty(ty.ty_tup(bound_tys)); - let TypeRef lltarget_ty = type_of(bcx.fcx.ccx, ty.expr_ty(f)); let TypeRef llbindings_ty = type_of(bcx.fcx.ccx, bindings_ty); let TypeRef llclosure_ty = T_closure_ptr(cx.fcx.ccx.tn, lltarget_ty, - llbindings_ty); + llbindings_ty, + ty_param_count); // Malloc a box for the body. auto r = trans_malloc_inner(bcx, llclosure_ty); @@ -2888,19 +2943,40 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, bcx.build.GEP(closure, vec(C_int(0), C_int(abi.closure_elt_target))); - bcx.build.Store(bcx.build.Load(f_res.res.val), bound_target); + auto src = bcx.build.Load(f_res.res.val); + bcx.build.Store(src, bound_target); // Copy expr values into boxed bindings. - let int i = 0; + i = 0u; auto bindings = bcx.build.GEP(closure, vec(C_int(0), C_int(abi.closure_elt_bindings))); for (ValueRef v in bound_vals) { auto bound = bcx.build.GEP(bindings, - vec(C_int(0),C_int(i))); + vec(C_int(0), C_int(i as int))); bcx = copy_ty(r.bcx, INIT, bound, v, bound_tys.(i)).bcx; - i += 1; + i += 1u; + } + + // If necessary, copy tydescs describing type parameters into the + // appropriate slot in the closure. + alt (f_res.generic) { + case (none[generic_info]) { /* nothing to do */ } + case (some[generic_info](?ginfo)) { + auto ty_params_slot = + bcx.build.GEP(closure, + vec(C_int(0), + C_int(abi.closure_elt_ty_params))); + auto i = 0; + for (ValueRef td in ginfo.tydescs) { + auto ty_param_slot = bcx.build.GEP(ty_params_slot, + vec(C_int(0), + C_int(i))); + bcx.build.Store(td, ty_param_slot); + i += 1; + } + } } // Make thunk and store thunk-ptr in outer pair's code slot. @@ -2910,8 +2986,9 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, let @ty.t pair_ty = node_ann_type(cx.fcx.ccx, ann); let ValueRef llthunk = - trans_bind_thunk(cx.fcx.ccx, pair_ty, ty.expr_ty(f), - args, llclosure_ty, bound_tys); + trans_bind_thunk(cx.fcx.ccx, pair_ty, outgoing_fty, + args, llclosure_ty, bound_tys, + ty_param_count); bcx.build.Store(llthunk, pair_code); diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 0f277329..5535879e 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -598,12 +598,14 @@ fn ty_fn_args(@t fty) -> vec[arg] { case (ty.ty_fn(_, ?a, _)) { ret a; } case (ty.ty_native_fn(?a, _)) { ret a; } } + fail; } fn ty_fn_proto(@t fty) -> ast.proto { alt (fty.struct) { case (ty.ty_fn(?p, _, _)) { ret p; } } + fail; } fn ty_fn_ret(@t fty) -> @t { @@ -611,6 +613,7 @@ fn ty_fn_ret(@t fty) -> @t { case (ty.ty_fn(_, _, ?r)) { ret r; } case (ty.ty_native_fn(_, ?r)) { ret r; } } + fail; } fn is_fn_ty(@t fty) -> bool { -- cgit v1.2.3 From 144a2a1d339299bc3dff7bc9eebcf1f9bba8656b Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 23 Feb 2011 17:36:33 -0800 Subject: Invert test/run-pass/ for rustc --- src/Makefile | 217 ++++++++++++++++++++++++++++------------------------------- 1 file changed, 104 insertions(+), 113 deletions(-) diff --git a/src/Makefile b/src/Makefile index edbe9e29..390f9173 100644 --- a/src/Makefile +++ b/src/Makefile @@ -438,120 +438,111 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \ test/compile-fail/tail-non-call.rs \ test/compile-fail/writing-through-read-alias.rs -# Same strategy here for the time being: just list the ones that -# work and assume the others don't. Invert this when we're closer -# to actually bootstrapping. - -TEST_XFAILS_RUSTC := $(filter-out \ - $(addprefix test/run-pass/, \ - alt-path.rs \ - alt-pattern-lit.rs \ - alt-pattern-simple.rs \ - alt-tag.rs \ - argv.rs \ - arith-0.rs \ - arith-1.rs \ - arith-2.rs \ - arith-unsigned.rs \ - auto-instantiate.rs \ - autoderef-full-lval.rs \ - bind-exterior.rs \ - bind-interior.rs \ - bind-thunk.rs \ - bind-trivial.rs \ - bitwise.rs \ - bool-not.rs \ - box.rs \ - box-in-tup.rs \ - cast.rs \ - char.rs \ - command-line-args.rs \ - complex.rs \ - const.rs \ - dead-code-one-arm-if.rs \ - deep.rs \ - deref.rs \ - div-mod.rs \ - drop-bind-thunk-args.rs \ - drop-on-ret.rs \ - else-if.rs \ - fact.rs \ - fn-lval.rs \ - foreach-simple.rs \ - fun-call-variants.rs \ - fun-indirect-call.rs \ - generic-bind.rs \ - generic-derived-type.rs \ - generic-fn.rs \ - generic-fn-infer.rs \ - generic-exterior-box.rs \ - generic-drop-glue.rs \ - generic-obj.rs \ - generic-obj-with-derived-type.rs \ - generic-tup.rs \ - generic-type.rs \ - generic-type-synonym.rs \ - hello.rs \ - int.rs \ - i32-sub.rs \ - i8-incr.rs \ - import.rs \ - import2.rs \ - import3.rs \ - import4.rs \ - import5.rs \ - import6.rs \ - import7.rs \ - import8.rs \ - inner-module.rs \ - item-name-overload.rs \ - large-records.rs \ - lazy-init.rs \ - lazy-and-or.rs \ - leak-box-as-tydesc.rs \ - linear-for-loop.rs \ - multiline-comment.rs \ - mutable-vec-drop.rs \ - mutual-recursion-group.rs \ - native2.rs \ - obj-drop.rs \ - obj-recursion.rs \ - obj-with-vec.rs \ - operator-associativity.rs \ - opeq.rs \ - output-slot-variants.rs \ - over-constrained-vregs.rs \ - path.rs \ - readalias.rs \ - rec.rs \ - rec-auto.rs \ - rec-extend.rs \ - rec-tup.rs \ - return-nil.rs \ - simple-obj.rs \ - stateful-obj.rs \ - str-idx.rs \ - tail-call-arg-leak.rs \ - tail-cps.rs \ - tail-direct.rs \ - type-in-nested-module.rs \ - type-param.rs \ - tup.rs \ - u32-decr.rs \ - u8-incr.rs \ - u8-incr-decr.rs \ - uint.rs \ - unit.rs \ - use.rs \ - tag.rs \ - vec.rs \ - vec-drop.rs \ - vec-in-tup.rs \ - vec-late-init.rs \ - while-and-do-while.rs \ - while-flow-graph.rs \ - writealias.rs \ +TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ + acyclic-unwind.rs \ + alt-pattern-drop.rs \ + alt-type-simple.rs \ + append-units.rs \ + autoderef-objfn.rs \ + basic-1.rs \ + basic-2.rs \ + basic.rs \ + bind-obj-ctor.rs \ + box-unbox.rs \ + child-outlives-parent.rs \ + clone-with-exterior.rs \ + comm.rs \ + constrained-type.rs \ + destructor-ordering.rs \ + drop-on-empty-block-exit.rs \ + drop-parametric-closure-with-bound-box.rs \ + export-non-interference.rs \ + exterior.rs \ + foreach-nested-2.rs \ + foreach-nested.rs \ + foreach-put-structured.rs \ + foreach-simple-outer-slot.rs \ + generic-fn-twice.rs \ + generic-iter-frame.rs \ + generic-recursive-tag.rs \ + generic-tag-alt.rs \ + generic-tag-values.rs \ + generic-tag.rs \ + integral-indexing.rs \ + iter-range.rs \ + iter-ret.rs \ + lazychan.rs \ + lib-bitv.rs \ + lib-deque.rs \ + lib-int.rs \ + lib-io.rs \ + lib-map.rs \ + lib-rand.rs \ + lib-sha1.rs \ + lib-sort.rs \ + lib-str.rs \ + lib-task.rs \ + lib-uint.rs \ + lib-vec-str-conversions.rs \ + lib-vec.rs \ + list.rs \ + many.rs \ + mlist-cycle.rs \ + mlist.rs \ + mutable-alias-vec.rs \ + native-opaque-type.rs \ + obj-as.rs \ + obj-dtor.rs \ + obj-return-polytypes.rs \ + pred.rs \ + preempt.rs \ + rt-circular-buffer.rs \ + size-and-align.rs \ + spawn-fn.rs \ + spawn-module-qualified.rs \ + spawn.rs \ + str-append.rs \ + str-concat.rs \ + structured-compare.rs \ + syntax-extension-fmt.rs \ + syntax-extension-shell.rs \ + task-comm-0.rs \ + task-comm-1.rs \ + task-comm-10.rs \ + task-comm-11.rs \ + task-comm-12.rs \ + task-comm-13-thread.rs \ + task-comm-13.rs \ + task-comm-15.rs \ + task-comm-2.rs \ + task-comm-3.rs \ + task-comm-4.rs \ + task-comm-5.rs \ + task-comm-6.rs \ + task-comm-7.rs \ + task-comm-8.rs \ + task-comm-9.rs \ + task-comm.rs \ + task-killjoin.rs \ + task-life-0.rs \ + threads.rs \ + type-sizes.rs \ + use-import-export.rs \ + user.rs \ + utf8.rs \ + vec-alloc-append.rs \ + vec-append.rs \ + vec-concat.rs \ + vec-slice.rs \ + while-prelude-drop.rs \ + while-with-break.rs \ + yield.rs \ + yield2.rs \ + multi.rc \ + native-mod.rc \ + native.rc \ ) \ + $(filter-out \ $(addprefix test/compile-fail/, \ alt-tag-nullary.rs \ alt-tag-unary.rs \ -- cgit v1.2.3 From 4ebd75a54757b06718fc87a72c20389a9e7f29d0 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 24 Feb 2011 00:07:38 -0500 Subject: Restore working rustc run-pass tests --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 390f9173..70b3ca0f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -574,7 +574,7 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ while-type-error.rs \ wrong-ret-type.rs \ ), \ - $(wildcard test/*/*.rs test/*/*.rc)) + $(wildcard test/*fail/*.rs test/*fail/*.rc)) ifdef MINGW_CROSS -- cgit v1.2.3 From 127139aecd5c3a1227ee58c77fc083506125f7cd Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 24 Feb 2011 12:14:05 -0800 Subject: Parse crate directive tree in one pass, then evaluate it in a second. --- src/comp/front/ast.rs | 3 +- src/comp/front/parser.rs | 126 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 96 insertions(+), 33 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 2c307478..088ef4ed 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -46,8 +46,9 @@ type crate_ = rec(_mod module); tag crate_directive_ { cdir_expr(@expr); + cdir_const(@item); cdir_src_mod(ident, option.t[filename]); - cdir_dir_mod(ident, option.t[filename], vec[crate_directive]); + cdir_dir_mod(ident, option.t[filename], vec[@crate_directive]); cdir_view_item(@view_item); cdir_meta(@meta_item); cdir_syntax(path); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 6d77a204..944e1424 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -8,6 +8,7 @@ import std.map.hashmap; import driver.session; import util.common; +import util.common.filename; import util.common.append; import util.common.span; import util.common.new_str_hash; @@ -2110,9 +2111,81 @@ impure fn parse_crate_from_source_file(parser p) -> @ast.crate { // // Each directive imperatively extends its environment with 0 or more items. -impure fn parse_crate_directive(str prefix, parser p, - &mutable vec[@ast.item] items, - hashmap[ast.ident,ast.mod_index_entry] index) +impure fn eval_crate_directives(parser p, + vec[@ast.crate_directive] cdirs, + str prefix) -> ast._mod { + let vec[@ast.item] items = vec(); + auto index = new_str_hash[ast.mod_index_entry](); + auto view_items = parse_view(p, index); + + for (@ast.crate_directive sub_cdir in cdirs) { + eval_crate_directive(p, sub_cdir, prefix, + view_items, items, index); + } + + ret rec(view_items=view_items, items=items, index=index); +} + +impure fn eval_crate_directive(parser p, + @ast.crate_directive cdir, + str prefix, + &mutable vec[@ast.view_item] view_items, + &mutable vec[@ast.item] items, + hashmap[ast.ident,ast.mod_index_entry] index) { + alt (cdir.node) { + case (ast.cdir_expr(?e)) {} + case (ast.cdir_const(?i)) {} + + case (ast.cdir_src_mod(?id, ?file_opt)) { + + auto file_path = id + ".rs"; + alt (file_opt) { + case (some[filename](?f)) { + file_path = f; + } + case (none[filename]) {} + } + + auto full_path = prefix + std.os.path_sep() + file_path; + + auto p0 = new_parser(p.get_session(), 0, full_path); + auto m0 = parse_mod_items(p0, token.EOF); + auto im = ast.item_mod(id, m0, p.next_def_id()); + auto i = @spanned(cdir.span, cdir.span, im); + ast.index_item(index, i); + append[@ast.item](items, i); + } + + case (ast.cdir_dir_mod(?id, ?dir_opt, ?cdirs)) { + + auto path = id; + alt (dir_opt) { + case (some[filename](?d)) { + path = d; + } + case (none[filename]) {} + } + + auto full_path = prefix + std.os.path_sep() + path; + auto m0 = eval_crate_directives(p, cdirs, path); + auto im = ast.item_mod(id, m0, p.next_def_id()); + auto i = @spanned(cdir.span, cdir.span, im); + ast.index_item(index, i); + append[@ast.item](items, i); + } + + case (ast.cdir_view_item(?vi)) { + append[@ast.view_item](view_items, vi); + ast.index_view_item(index, vi); + } + + case (ast.cdir_meta(?mi)) {} + case (ast.cdir_syntax(?pth)) {} + case (ast.cdir_auth(?pth, ?eff)) {} + } +} + +impure fn parse_crate_directive(parser p) -> ast.crate_directive { auto lo = p.get_span(); auto hi = lo; @@ -2124,28 +2197,27 @@ impure fn parse_crate_directive(str prefix, parser p, auto n = parse_path(p, GREEDY); expect(p, token.EQ); auto e = parse_effect(p); + hi = p.get_span(); expect(p, token.SEMI); + ret spanned(lo, hi, ast.cdir_auth(n, e)); } case (token.CONST) { auto c = parse_item_const(p); - ast.index_item(index, c); - append[@ast.item](items, c); + ret spanned(c.span, c.span, ast.cdir_const(c)); } case (token.MOD) { p.bump(); auto id = parse_ident(p); - auto file_path = id; + auto file_opt = none[filename]; alt (p.peek()) { case (token.EQ) { p.bump(); // FIXME: turn this into parse+eval expr - file_path = parse_str_lit(p); + file_opt = some[filename](parse_str_lit(p)); } case (_) {} } - // dir-qualify file path. - auto full_path = prefix + std.os.path_sep() + file_path; alt (p.peek()) { @@ -2154,29 +2226,18 @@ impure fn parse_crate_directive(str prefix, parser p, case (token.SEMI) { hi = p.get_span(); p.bump(); - if (!_str.ends_with(full_path, ".rs")) { - full_path += ".rs"; - } - auto p0 = new_parser(p.get_session(), 0, full_path); - auto m0 = parse_mod_items(p0, token.EOF); - auto im = ast.item_mod(id, m0, p.next_def_id()); - auto i = @spanned(lo, hi, im); - ast.index_item(index, i); - append[@ast.item](items, i); + ret spanned(lo, hi, ast.cdir_src_mod(id, file_opt)); } // mod x = "foo_dir" { ...directives... } case (token.LBRACE) { p.bump(); - auto m0 = parse_crate_directives(full_path, p, - token.RBRACE); + auto cdirs = parse_crate_directives(p, token.RBRACE); hi = p.get_span(); expect(p, token.RBRACE); - auto im = ast.item_mod(id, m0, p.next_def_id()); - auto i = @spanned(lo, hi, im); - ast.index_item(index, i); - append[@ast.item](items, i); + ret spanned(lo, hi, + ast.cdir_dir_mod(id, file_opt, cdirs)); } case (?t) { @@ -2185,27 +2246,28 @@ impure fn parse_crate_directive(str prefix, parser p, } } } + fail; } -impure fn parse_crate_directives(str prefix, parser p, - token.token term) -> ast._mod { - auto index = new_str_hash[ast.mod_index_entry](); - auto view_items = parse_view(p, index); +impure fn parse_crate_directives(parser p, token.token term) + -> vec[@ast.crate_directive] { - let vec[@ast.item] items = vec(); + let vec[@ast.crate_directive] cdirs = vec(); while (p.peek() != term) { - parse_crate_directive(prefix, p, items, index); + auto cdir = @parse_crate_directive(p); + append[@ast.crate_directive](cdirs, cdir); } - ret rec(view_items=view_items, items=items, index=index); + ret cdirs; } impure fn parse_crate_from_crate_file(parser p) -> @ast.crate { auto lo = p.get_span(); auto hi = lo; auto prefix = std.path.dirname(lo.filename); - auto m = parse_crate_directives(prefix, p, token.EOF); + auto cdirs = parse_crate_directives(p, token.EOF); + auto m = eval_crate_directives(p, cdirs, prefix); hi = p.get_span(); expect(p, token.EOF); ret @spanned(lo, hi, rec(module=m)); -- cgit v1.2.3 From 0a65283c5eeae0b98fff7d213dbaad59889e677e Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 23 Feb 2011 18:39:27 -0800 Subject: Cast more aggressively to the callee type when calling generic functions. Add a test-case for this, and XFAIL it in rustboot. --- src/Makefile | 1 + src/comp/middle/trans.rs | 6 +++--- src/test/run-pass/generic-fn-box.rs | 9 +++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 src/test/run-pass/generic-fn-box.rs diff --git a/src/Makefile b/src/Makefile index 70b3ca0f..12b65246 100644 --- a/src/Makefile +++ b/src/Makefile @@ -416,6 +416,7 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \ test/run-pass/obj-as.rs \ test/run-pass/vec-slice.rs \ test/run-pass/fn-lval.rs \ + test/run-pass/generic-fn-box.rs \ test/run-pass/generic-recursive-tag.rs \ test/run-pass/generic-tup.rs \ test/run-pass/iter-ret.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 30f3cdc4..72f1106b 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3132,9 +3132,9 @@ fn trans_args(@block_ctxt cx, bcx = re.bcx; } - if (ty.type_has_dynamic_size(args.(i).ty)) { - val = bcx.build.PointerCast(val, - T_typaram_ptr(cx.fcx.ccx.tn)); + if (ty.count_ty_params(args.(i).ty) > 0u) { + auto lldestty = type_of(cx.fcx.ccx, args.(i).ty); + val = bcx.build.PointerCast(val, lldestty); } llargs += val; diff --git a/src/test/run-pass/generic-fn-box.rs b/src/test/run-pass/generic-fn-box.rs new file mode 100644 index 00000000..e821a784 --- /dev/null +++ b/src/test/run-pass/generic-fn-box.rs @@ -0,0 +1,9 @@ +fn f[T](@T x) -> @T { + ret x; +} + +fn main() { + auto x = f(@3); + log *x; +} + -- cgit v1.2.3 From 5332250d3bddf509994832965f3c5d7b68662ce4 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 24 Feb 2011 13:51:18 -0800 Subject: Revert "Cast more aggressively to the callee type when calling generic functions. Add a test-case for this, and XFAIL it in rustboot." due to test failures This reverts commit 0a65283c5eeae0b98fff7d213dbaad59889e677e. --- src/Makefile | 1 - src/comp/middle/trans.rs | 6 +++--- src/test/run-pass/generic-fn-box.rs | 9 --------- 3 files changed, 3 insertions(+), 13 deletions(-) delete mode 100644 src/test/run-pass/generic-fn-box.rs diff --git a/src/Makefile b/src/Makefile index 12b65246..70b3ca0f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -416,7 +416,6 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \ test/run-pass/obj-as.rs \ test/run-pass/vec-slice.rs \ test/run-pass/fn-lval.rs \ - test/run-pass/generic-fn-box.rs \ test/run-pass/generic-recursive-tag.rs \ test/run-pass/generic-tup.rs \ test/run-pass/iter-ret.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 72f1106b..30f3cdc4 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3132,9 +3132,9 @@ fn trans_args(@block_ctxt cx, bcx = re.bcx; } - if (ty.count_ty_params(args.(i).ty) > 0u) { - auto lldestty = type_of(cx.fcx.ccx, args.(i).ty); - val = bcx.build.PointerCast(val, lldestty); + if (ty.type_has_dynamic_size(args.(i).ty)) { + val = bcx.build.PointerCast(val, + T_typaram_ptr(cx.fcx.ccx.tn)); } llargs += val; diff --git a/src/test/run-pass/generic-fn-box.rs b/src/test/run-pass/generic-fn-box.rs deleted file mode 100644 index e821a784..00000000 --- a/src/test/run-pass/generic-fn-box.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn f[T](@T x) -> @T { - ret x; -} - -fn main() { - auto x = f(@3); - log *x; -} - -- cgit v1.2.3 From dcd65fac199d3caac4b1019304ef5e1b480f31ff Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 24 Feb 2011 13:51:53 -0800 Subject: Cast more aggressively to the callee type when calling generic functions. Add a test-case for this, and XFAIL it in rustboot. --- src/Makefile | 1 + src/comp/middle/trans.rs | 12 +++++++++--- src/test/run-pass/generic-fn-box.rs | 9 +++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 src/test/run-pass/generic-fn-box.rs diff --git a/src/Makefile b/src/Makefile index 70b3ca0f..12b65246 100644 --- a/src/Makefile +++ b/src/Makefile @@ -416,6 +416,7 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \ test/run-pass/obj-as.rs \ test/run-pass/vec-slice.rs \ test/run-pass/fn-lval.rs \ + test/run-pass/generic-fn-box.rs \ test/run-pass/generic-recursive-tag.rs \ test/run-pass/generic-tup.rs \ test/run-pass/iter-ret.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 30f3cdc4..a3a1d83f 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3091,6 +3091,12 @@ fn trans_args(@block_ctxt cx, } // ... then explicit args. + + // First we figure out the caller's view of the types of the arguments. + // This will be needed if this is a generic call, because the callee has + // to cast her view of the arguments to the caller's view. + auto arg_tys = type_of_explicit_args(cx.fcx.ccx, args); + auto i = 0u; for (@ast.expr e in es) { auto mode = args.(i).mode; @@ -3132,9 +3138,9 @@ fn trans_args(@block_ctxt cx, bcx = re.bcx; } - if (ty.type_has_dynamic_size(args.(i).ty)) { - val = bcx.build.PointerCast(val, - T_typaram_ptr(cx.fcx.ccx.tn)); + if (ty.count_ty_params(args.(i).ty) > 0u) { + auto lldestty = arg_tys.(i); + val = bcx.build.PointerCast(val, lldestty); } llargs += val; diff --git a/src/test/run-pass/generic-fn-box.rs b/src/test/run-pass/generic-fn-box.rs new file mode 100644 index 00000000..e821a784 --- /dev/null +++ b/src/test/run-pass/generic-fn-box.rs @@ -0,0 +1,9 @@ +fn f[T](@T x) -> @T { + ret x; +} + +fn main() { + auto x = f(@3); + log *x; +} + -- cgit v1.2.3 From b2a09562a6c0683ca528c866abc1ecc99b4bdcf0 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 24 Feb 2011 15:54:55 -0800 Subject: Factor crate expr evaluator out of parser, expand to simple scalars and ops, if, alt. --- src/comp/front/ast.rs | 8 +- src/comp/front/eval.rs | 443 +++++++++++++++++++++++++++++++++++++++++++++++ src/comp/front/parser.rs | 82 +-------- src/comp/rustc.rc | 2 +- 4 files changed, 453 insertions(+), 82 deletions(-) create mode 100644 src/comp/front/eval.rs diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 088ef4ed..f5c03bd7 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -46,7 +46,10 @@ type crate_ = rec(_mod module); tag crate_directive_ { cdir_expr(@expr); - cdir_const(@item); + // FIXME: cdir_let should be eliminated + // and redirected to the use of const stmt_decls inside + // crate directive blocks. + cdir_let(ident, @expr, vec[@crate_directive]); cdir_src_mod(ident, option.t[filename]); cdir_dir_mod(ident, option.t[filename], vec[@crate_directive]); cdir_view_item(@view_item); @@ -137,6 +140,8 @@ type stmt = spanned[stmt_]; tag stmt_ { stmt_decl(@decl); stmt_expr(@expr); + // These only exist in crate-level blocks. + stmt_crate_directive(@crate_directive); } type local = rec(option.t[@ty] ty, @@ -175,7 +180,6 @@ tag expr_ { expr_do_while(block, @expr, ann); expr_alt(@expr, vec[arm], ann); expr_block(block, ann); - expr_crate_directive_block(vec[crate_directive_]); expr_assign(@expr /* TODO: @expr|is_lval */, @expr, ann); expr_assign_op(binop, @expr /* TODO: @expr|is_lval */, @expr, ann); expr_field(@expr, ident, ann); diff --git a/src/comp/front/eval.rs b/src/comp/front/eval.rs new file mode 100644 index 00000000..7275e557 --- /dev/null +++ b/src/comp/front/eval.rs @@ -0,0 +1,443 @@ +import std._vec; +import std._str; +import std.option; +import std.option.some; +import std.option.none; +import std.map.hashmap; + +import driver.session; +import ast.ident; +import front.parser.parser; +import front.parser.spanned; +import front.parser.new_parser; +import front.parser.parse_mod_items; +import util.common; +import util.common.filename; +import util.common.append; +import util.common.span; +import util.common.new_str_hash; + + +// Simple dynamic-typed value type for eval_expr. +tag val { + val_bool(bool); + val_int(int); + val_str(str); +} + +type env = vec[tup(ident, val)]; + +fn mk_env() -> env { + let env e = vec(); + ret e; +} + +fn val_is_bool(val v) -> bool { + alt (v) { + case (val_bool(_)) { ret true; } + case (_) { } + } + ret false; +} + +fn val_is_int(val v) -> bool { + alt (v) { + case (val_bool(_)) { ret true; } + case (_) { } + } + ret false; +} + +fn val_is_str(val v) -> bool { + alt (v) { + case (val_str(_)) { ret true; } + case (_) { } + } + ret false; +} + +fn val_as_bool(val v) -> bool { + alt (v) { + case (val_bool(?b)) { ret b; } + case (_) { } + } + fail; +} + +fn val_as_int(val v) -> int { + alt (v) { + case (val_int(?i)) { ret i; } + case (_) { } + } + fail; +} + +fn val_as_str(val v) -> str { + alt (v) { + case (val_str(?s)) { ret s; } + case (_) { } + } + fail; +} + +fn lookup(session.session sess, env e, span sp, ident i) -> val { + for (tup(ident, val) pair in e) { + if (_str.eq(i, pair._0)) { + ret pair._1; + } + } + sess.span_err(sp, "unknown variable: " + i); + fail; +} + +fn eval_lit(session.session sess, env e, span sp, @ast.lit lit) -> val { + alt (lit.node) { + case (ast.lit_bool(?b)) { ret val_bool(b); } + case (ast.lit_int(?i)) { ret val_int(i); } + case (ast.lit_str(?s)) { ret val_str(s); } + case (_) { + sess.span_err(sp, "evaluating unsupported literal"); + } + } + fail; +} + +fn eval_expr(session.session sess, env e, @ast.expr x) -> val { + alt (x.node) { + case (ast.expr_path(?pth, _, _)) { + if (_vec.len[ident](pth.node.idents) == 1u && + _vec.len[@ast.ty](pth.node.types) == 0u) { + ret lookup(sess, e, x.span, pth.node.idents.(0)); + } + sess.span_err(x.span, "evaluating structured path-name"); + } + + case (ast.expr_lit(?lit, _)) { + ret eval_lit(sess, e, x.span, lit); + } + + case (ast.expr_unary(?op, ?a, _)) { + auto av = eval_expr(sess, e, a); + alt (op) { + case (ast.not) { + if (val_is_bool(av)) { + ret val_bool(!val_as_bool(av)); + } + sess.span_err(x.span, "bad types in '!' expression"); + } + case (_) { + sess.span_err(x.span, "evaluating unsupported unop"); + } + } + } + + case (ast.expr_binary(?op, ?a, ?b, _)) { + auto av = eval_expr(sess, e, a); + auto bv = eval_expr(sess, e, b); + alt (op) { + case (ast.add) { + if (val_is_int(av) && val_is_int(bv)) { + ret val_int(val_as_int(av) + val_as_int(bv)); + } + if (val_is_str(av) && val_is_str(bv)) { + ret val_str(val_as_str(av) + val_as_str(bv)); + } + sess.span_err(x.span, "bad types in '+' expression"); + } + + case (ast.sub) { + if (val_is_int(av) && val_is_int(bv)) { + ret val_int(val_as_int(av) - val_as_int(bv)); + } + sess.span_err(x.span, "bad types in '-' expression"); + } + + case (ast.mul) { + if (val_is_int(av) && val_is_int(bv)) { + ret val_int(val_as_int(av) * val_as_int(bv)); + } + sess.span_err(x.span, "bad types in '*' expression"); + } + + case (ast.div) { + if (val_is_int(av) && val_is_int(bv)) { + ret val_int(val_as_int(av) / val_as_int(bv)); + } + sess.span_err(x.span, "bad types in '/' expression"); + } + + case (ast.rem) { + if (val_is_int(av) && val_is_int(bv)) { + ret val_int(val_as_int(av) % val_as_int(bv)); + } + sess.span_err(x.span, "bad types in '%' expression"); + } + + case (ast.and) { + if (val_is_bool(av) && val_is_bool(bv)) { + ret val_bool(val_as_bool(av) && val_as_bool(bv)); + } + sess.span_err(x.span, "bad types in '&&' expression"); + } + + case (ast.or) { + if (val_is_bool(av) && val_is_bool(bv)) { + ret val_bool(val_as_bool(av) || val_as_bool(bv)); + } + sess.span_err(x.span, "bad types in '||' expression"); + } + + case (ast.eq) { + ret val_bool(val_eq(sess, x.span, av, bv)); + } + + case (ast.ne) { + ret val_bool(! val_eq(sess, x.span, av, bv)); + } + + case (_) { + sess.span_err(x.span, "evaluating unsupported binop"); + } + } + } + case (_) { + sess.span_err(x.span, "evaluating unsupported expression"); + } + } + fail; +} + +fn val_eq(session.session sess, span sp, val av, val bv) -> bool { + if (val_is_bool(av) && val_is_bool(bv)) { + ret val_as_bool(av) == val_as_bool(bv); + } + if (val_is_int(av) && val_is_int(bv)) { + ret val_as_int(av) == val_as_int(bv); + } + if (val_is_str(av) && val_is_str(bv)) { + ret _str.eq(val_as_str(av), + val_as_str(bv)); + } + sess.span_err(sp, "bad types in comparison"); + fail; +} + +impure fn eval_crate_directives(parser p, + env e, + vec[@ast.crate_directive] cdirs, + str prefix, + &mutable vec[@ast.view_item] view_items, + &mutable vec[@ast.item] items, + hashmap[ast.ident, + ast.mod_index_entry] index) { + + for (@ast.crate_directive sub_cdir in cdirs) { + eval_crate_directive(p, e, sub_cdir, prefix, + view_items, items, index); + } +} + + +impure fn eval_crate_directives_to_mod(parser p, + env e, + vec[@ast.crate_directive] cdirs, + str prefix) -> ast._mod { + let vec[@ast.view_item] view_items = vec(); + let vec[@ast.item] items = vec(); + auto index = new_str_hash[ast.mod_index_entry](); + + eval_crate_directives(p, e, cdirs, prefix, + view_items, items, index); + + ret rec(view_items=view_items, items=items, index=index); +} + + +impure fn eval_crate_directive_block(parser p, + env e, + &ast.block blk, + str prefix, + &mutable vec[@ast.view_item] view_items, + &mutable vec[@ast.item] items, + hashmap[ast.ident, + ast.mod_index_entry] index) { + + for (@ast.stmt s in blk.node.stmts) { + alt (s.node) { + case (ast.stmt_crate_directive(?cdir)) { + eval_crate_directive(p, e, cdir, prefix, + view_items, items, index); + } + case (_) { + auto sess = p.get_session(); + sess.span_err(s.span, + "unsupported stmt in crate-directive block"); + } + } + } +} + +impure fn eval_crate_directive_expr(parser p, + env e, + @ast.expr x, + str prefix, + &mutable vec[@ast.view_item] view_items, + &mutable vec[@ast.item] items, + hashmap[ast.ident, + ast.mod_index_entry] index) { + auto sess = p.get_session(); + + alt (x.node) { + + case (ast.expr_if(?cond, ?thn, ?elifs, ?elopt, _)) { + auto cv = eval_expr(sess, e, cond); + if (!val_is_bool(cv)) { + sess.span_err(x.span, "bad cond type in 'if'"); + } + + if (val_as_bool(cv)) { + ret eval_crate_directive_block(p, e, thn, prefix, + view_items, items, + index); + } + + for (tup(@ast.expr, ast.block) elif in elifs) { + auto cv = eval_expr(sess, e, elif._0); + if (!val_is_bool(cv)) { + sess.span_err(x.span, "bad cond type in 'else if'"); + } + + if (val_as_bool(cv)) { + ret eval_crate_directive_block(p, e, elif._1, prefix, + view_items, items, + index); + } + } + + alt (elopt) { + case (some[ast.block](?els)) { + ret eval_crate_directive_block(p, e, els, prefix, + view_items, items, + index); + } + case (_) { + // Absent-else is ok. + } + } + } + + case (ast.expr_alt(?v, ?arms, _)) { + auto vv = eval_expr(sess, e, v); + for (ast.arm arm in arms) { + alt (arm.pat.node) { + case (ast.pat_lit(?lit, _)) { + auto pv = eval_lit(sess, e, + arm.pat.span, lit); + if (val_eq(sess, arm.pat.span, vv, pv)) { + ret eval_crate_directive_block + (p, e, arm.block, prefix, + view_items, items, index); + } + } + case (ast.pat_wild(_)) { + ret eval_crate_directive_block + (p, e, arm.block, prefix, + view_items, items, index); + } + case (_) { + sess.span_err(arm.pat.span, + "bad pattern type in 'alt'"); + } + } + } + sess.span_err(x.span, "no cases matched in 'alt'"); + } + + case (_) { + sess.span_err(x.span, "unsupported expr type"); + } + } +} + +impure fn eval_crate_directive(parser p, + env e, + @ast.crate_directive cdir, + str prefix, + &mutable vec[@ast.view_item] view_items, + &mutable vec[@ast.item] items, + hashmap[ast.ident, + ast.mod_index_entry] index) { + alt (cdir.node) { + + case (ast.cdir_let(?id, ?x, ?cdirs)) { + auto v = eval_expr(p.get_session(), e, x); + auto e0 = vec(tup(id, v)) + e; + eval_crate_directives(p, e0, cdirs, prefix, + view_items, items, index); + } + + case (ast.cdir_expr(?x)) { + eval_crate_directive_expr(p, e, x, prefix, + view_items, items, index); + } + + case (ast.cdir_src_mod(?id, ?file_opt)) { + + auto file_path = id + ".rs"; + alt (file_opt) { + case (some[filename](?f)) { + file_path = f; + } + case (none[filename]) {} + } + + auto full_path = prefix + std.os.path_sep() + file_path; + + auto p0 = new_parser(p.get_session(), 0, full_path); + auto m0 = parse_mod_items(p0, token.EOF); + auto im = ast.item_mod(id, m0, p.next_def_id()); + auto i = @spanned(cdir.span, cdir.span, im); + ast.index_item(index, i); + append[@ast.item](items, i); + } + + case (ast.cdir_dir_mod(?id, ?dir_opt, ?cdirs)) { + + auto path = id; + alt (dir_opt) { + case (some[filename](?d)) { + path = d; + } + case (none[filename]) {} + } + + auto full_path = prefix + std.os.path_sep() + path; + auto m0 = eval_crate_directives_to_mod(p, e, cdirs, path); + auto im = ast.item_mod(id, m0, p.next_def_id()); + auto i = @spanned(cdir.span, cdir.span, im); + ast.index_item(index, i); + append[@ast.item](items, i); + } + + case (ast.cdir_view_item(?vi)) { + append[@ast.view_item](view_items, vi); + ast.index_view_item(index, vi); + } + + case (ast.cdir_meta(?mi)) {} + case (ast.cdir_syntax(?pth)) {} + case (ast.cdir_auth(?pth, ?eff)) {} + } +} + + +// +// Local Variables: +// mode: rust +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: +// diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 944e1424..3579a3a0 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -2111,80 +2111,6 @@ impure fn parse_crate_from_source_file(parser p) -> @ast.crate { // // Each directive imperatively extends its environment with 0 or more items. -impure fn eval_crate_directives(parser p, - vec[@ast.crate_directive] cdirs, - str prefix) -> ast._mod { - let vec[@ast.item] items = vec(); - auto index = new_str_hash[ast.mod_index_entry](); - auto view_items = parse_view(p, index); - - for (@ast.crate_directive sub_cdir in cdirs) { - eval_crate_directive(p, sub_cdir, prefix, - view_items, items, index); - } - - ret rec(view_items=view_items, items=items, index=index); -} - -impure fn eval_crate_directive(parser p, - @ast.crate_directive cdir, - str prefix, - &mutable vec[@ast.view_item] view_items, - &mutable vec[@ast.item] items, - hashmap[ast.ident,ast.mod_index_entry] index) { - alt (cdir.node) { - case (ast.cdir_expr(?e)) {} - case (ast.cdir_const(?i)) {} - - case (ast.cdir_src_mod(?id, ?file_opt)) { - - auto file_path = id + ".rs"; - alt (file_opt) { - case (some[filename](?f)) { - file_path = f; - } - case (none[filename]) {} - } - - auto full_path = prefix + std.os.path_sep() + file_path; - - auto p0 = new_parser(p.get_session(), 0, full_path); - auto m0 = parse_mod_items(p0, token.EOF); - auto im = ast.item_mod(id, m0, p.next_def_id()); - auto i = @spanned(cdir.span, cdir.span, im); - ast.index_item(index, i); - append[@ast.item](items, i); - } - - case (ast.cdir_dir_mod(?id, ?dir_opt, ?cdirs)) { - - auto path = id; - alt (dir_opt) { - case (some[filename](?d)) { - path = d; - } - case (none[filename]) {} - } - - auto full_path = prefix + std.os.path_sep() + path; - auto m0 = eval_crate_directives(p, cdirs, path); - auto im = ast.item_mod(id, m0, p.next_def_id()); - auto i = @spanned(cdir.span, cdir.span, im); - ast.index_item(index, i); - append[@ast.item](items, i); - } - - case (ast.cdir_view_item(?vi)) { - append[@ast.view_item](view_items, vi); - ast.index_view_item(index, vi); - } - - case (ast.cdir_meta(?mi)) {} - case (ast.cdir_syntax(?pth)) {} - case (ast.cdir_auth(?pth, ?eff)) {} - } -} - impure fn parse_crate_directive(parser p) -> ast.crate_directive { auto lo = p.get_span(); @@ -2201,10 +2127,7 @@ impure fn parse_crate_directive(parser p) -> ast.crate_directive expect(p, token.SEMI); ret spanned(lo, hi, ast.cdir_auth(n, e)); } - case (token.CONST) { - auto c = parse_item_const(p); - ret spanned(c.span, c.span, ast.cdir_const(c)); - } + case (token.MOD) { p.bump(); auto id = parse_ident(p); @@ -2267,7 +2190,8 @@ impure fn parse_crate_from_crate_file(parser p) -> @ast.crate { auto hi = lo; auto prefix = std.path.dirname(lo.filename); auto cdirs = parse_crate_directives(p, token.EOF); - auto m = eval_crate_directives(p, cdirs, prefix); + auto m = eval.eval_crate_directives_to_mod(p, eval.mk_env(), + cdirs, prefix); hi = p.get_span(); expect(p, token.EOF); ret @spanned(lo, hi, rec(module=m)); diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc index b439632c..bc4aaa52 100644 --- a/src/comp/rustc.rc +++ b/src/comp/rustc.rc @@ -8,6 +8,7 @@ mod front { mod lexer; mod parser; mod token; + mod eval; } mod middle { @@ -38,7 +39,6 @@ auth middle.trans.copy_args_to_allocas = impure; auth middle.trans.trans_block = impure; auth lib.llvm = unsafe; - mod lib { alt (target_os) { case ("win32") { -- cgit v1.2.3 From 9acf4b912717831f628ad078f28c597e10d7ec93 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 24 Feb 2011 16:42:04 -0800 Subject: Handle the mutant 'let'-block directive in rustboot, temporarily. --- src/comp/front/parser.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 3579a3a0..4817d960 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -2168,10 +2168,25 @@ impure fn parse_crate_directive(parser p) -> ast.crate_directive } } } + + case (token.LET) { + p.bump(); + expect(p, token.LPAREN); + auto id = parse_ident(p); + expect(p, token.EQ); + auto x = parse_expr(p); + expect(p, token.RPAREN); + expect(p, token.LBRACE); + auto v = parse_crate_directives(p, token.RBRACE); + hi = p.get_span(); + expect(p, token.RBRACE); + ret spanned(lo, hi, ast.cdir_let(id, x, v)); + } } fail; } + impure fn parse_crate_directives(parser p, token.token term) -> vec[@ast.crate_directive] { -- cgit v1.2.3 From dbf53b4c37f9f2a1cda43aa8320ceb4c4460051e Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 24 Feb 2011 17:00:24 -0800 Subject: Connect the crate and source parsers together. --- src/comp/front/parser.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 4817d960..7ae0050e 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -18,6 +18,11 @@ tag restriction { RESTRICT_NO_CALL_EXPRS; } +tag file_type { + CRATE_FILE; + SOURCE_FILE; +} + state type parser = state obj { fn peek() -> token.token; @@ -25,14 +30,17 @@ state type parser = impure fn err(str s); impure fn restrict(restriction r); fn get_restriction() -> restriction; + fn get_file_type() -> file_type; fn get_session() -> session.session; fn get_span() -> common.span; fn next_def_id() -> ast.def_id; }; impure fn new_parser(session.session sess, - ast.crate_num crate, str path) -> parser { + ast.crate_num crate, + str path) -> parser { state obj stdio_parser(session.session sess, + file_type ftype, mutable token.token tok, mutable common.pos lo, mutable common.pos hi, @@ -80,11 +88,20 @@ impure fn new_parser(session.session sess, def += 1; ret tup(crate, def); } + + fn get_file_type() -> file_type { + ret ftype; + } + } + auto ftype = SOURCE_FILE; + if (_str.ends_with(path, ".rc")) { + ftype = CRATE_FILE; + } auto srdr = io.new_stdio_reader(path); auto rdr = lexer.new_reader(srdr, path); auto npos = rdr.get_curr_pos(); - ret stdio_parser(sess, lexer.next_token(rdr), + ret stdio_parser(sess, ftype, lexer.next_token(rdr), npos, npos, 0, UNRESTRICTED, crate, rdr); } @@ -1310,6 +1327,20 @@ impure fn parse_auto(parser p) -> @ast.decl { } impure fn parse_stmt(parser p) -> @ast.stmt { + if (p.get_file_type() == SOURCE_FILE) { + ret parse_source_stmt(p); + } else { + ret parse_crate_stmt(p); + } +} + +impure fn parse_crate_stmt(parser p) -> @ast.stmt { + auto cdir = parse_crate_directive(p); + ret @spanned(cdir.span, cdir.span, + ast.stmt_crate_directive(@cdir)); +} + +impure fn parse_source_stmt(parser p) -> @ast.stmt { auto lo = p.get_span(); alt (p.peek()) { @@ -1485,6 +1516,16 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool { case (ast.expr_check_expr(_)) { ret true; } } } + case (ast.stmt_crate_directive(?cdir)) { + alt (cdir.node) { + case (ast.cdir_src_mod(_, _)) { ret true; } + case (ast.cdir_view_item(_)) { ret true; } + case (ast.cdir_meta(_)) { ret true; } + case (ast.cdir_syntax(_)) { ret true; } + case (ast.cdir_auth(_, _)) { ret true; } + case (_) { ret false; } + } + } } } @@ -2182,6 +2223,21 @@ impure fn parse_crate_directive(parser p) -> ast.crate_directive expect(p, token.RBRACE); ret spanned(lo, hi, ast.cdir_let(id, x, v)); } + + case (token.USE) { + auto vi = parse_use_or_import(p); + ret spanned(lo, vi.span, ast.cdir_view_item(vi)); + } + + case (token.IMPORT) { + auto vi = parse_use_or_import(p); + ret spanned(lo, vi.span, ast.cdir_view_item(vi)); + } + + case (_) { + auto x = parse_expr(p); + ret spanned(lo, x.span, ast.cdir_expr(x)); + } } fail; } -- cgit v1.2.3 From 88f0463c2bd6e7fd2af461afc5e83bd3417e3bc5 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 24 Feb 2011 17:17:39 -0800 Subject: Support the awful alt-else form in rustboot's cexp grammar, at least transiently. Remove in the future. --- src/comp/front/parser.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 7ae0050e..67b9cc80 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1170,6 +1170,23 @@ impure fn parse_alt_expr(parser p) -> @ast.expr { auto block = parse_block(p); arms += vec(rec(pat=pat, block=block, index=index)); } + + // FIXME: this is a vestigial form left over from + // rustboot, we're keeping it here for source-compat + // for the time being but it should be flushed out + // once we've bootstrapped. When we see 'else {' here, + // we pretend we saw 'case (_) {'. It has the same + // meaning, and only exists due to the cexp/pexp split + // in rustboot, which we're not maintaining. + + case (token.ELSE) { + p.bump(); + auto hi = p.get_span(); + auto pat = @spanned(lo, hi, ast.pat_wild(ast.ann_none)); + auto index = index_arm(pat); + auto block = parse_block(p); + arms += vec(rec(pat=pat, block=block, index=index)); + } case (token.RBRACE) { /* empty */ } case (?tok) { p.err("expected 'case' or '}' when parsing 'alt' statement " + -- cgit v1.2.3 From 19b2850388f634b500e612d8f24bbcb8c0fa2f3c Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 24 Feb 2011 19:24:12 -0800 Subject: rustc: Perform type parameter substitutions when emitting glue for generic tags. Un-XFAIL generic-tag.rs. --- src/Makefile | 1 - src/comp/middle/trans.rs | 21 +++++++++++++-------- src/comp/middle/ty.rs | 43 ++++++++++++++++++++++++++++++++++++++++++- src/comp/middle/typeck.rs | 23 +---------------------- 4 files changed, 56 insertions(+), 32 deletions(-) diff --git a/src/Makefile b/src/Makefile index 12b65246..1f5901ba 100644 --- a/src/Makefile +++ b/src/Makefile @@ -468,7 +468,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ generic-recursive-tag.rs \ generic-tag-alt.rs \ generic-tag-values.rs \ - generic-tag.rs \ integral-indexing.rs \ iter-range.rs \ iter-ret.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index a3a1d83f..467aaa0d 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1,3 +1,4 @@ +import std._int; import std._str; import std._uint; import std._vec; @@ -61,7 +62,8 @@ type glue_fns = rec(ValueRef activate_glue, tag arity { nullary; n_ary; } type tag_info = rec(type_handle th, mutable vec[tup(ast.def_id,arity)] variants, - mutable uint size); + mutable uint size, + vec[ast.ty_param] ty_params); state type crate_ctxt = rec(session.session sess, ModuleRef llmod, @@ -1498,9 +1500,7 @@ fn iter_structural_ty(@block_ctxt cx, i += 1; } } - case (ty.ty_tag(?tid, _)) { - // TODO: type params! - + case (ty.ty_tag(?tid, ?tps)) { 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); @@ -1559,11 +1559,15 @@ fn iter_structural_ty(@block_ctxt cx, auto llfldp = variant_cx.build.GEP(llvarp, v); + auto ty_subst = ty.substitute_ty_params( + info.ty_params, tps, a.ty); + auto llfld = load_scalar_or_boxed(variant_cx, - llfldp, a.ty); + llfldp, + ty_subst); - auto res = f(variant_cx, llfld, a.ty); + auto res = f(variant_cx, llfld, ty_subst); variant_cx = res.bcx; j += 1u; } @@ -4433,13 +4437,14 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { cx.items.insert(mid, i); } - case (ast.item_tag(_, ?variants, _, ?tag_id)) { + case (ast.item_tag(_, ?variants, ?tps, ?tag_id)) { auto vi = new_def_hash[uint](); auto navi = new_def_hash[uint](); let vec[tup(ast.def_id,arity)] variant_info = vec(); cx.tags.insert(tag_id, @rec(th=mk_type_handle(), mutable variants=variant_info, - mutable size=0u)); + mutable size=0u, + ty_params=tps)); cx.items.insert(tag_id, i); } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 5535879e..02a7ffc2 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -1450,7 +1450,7 @@ fn type_err_to_str(&ty.type_err err) -> str { } } -// Type parameter resolution, used in translation +// Type parameter resolution, used in translation and typechecking fn resolve_ty_params(ty_params_and_ty ty_params_and_polyty, @t monoty) -> vec[@t] { @@ -1492,6 +1492,47 @@ fn resolve_ty_params(ty_params_and_ty ty_params_and_polyty, ret result_tys; } +// Performs type parameter replacement using the supplied mapping from +// parameter IDs to types. +fn replace_type_params(@t typ, hashmap[ast.def_id,@t] param_map) -> @t { + state obj param_replacer(hashmap[ast.def_id,@t] param_map) { + fn fold_simple_ty(@t typ) -> @t { + alt (typ.struct) { + case (ty_param(?param_def)) { + if (param_map.contains_key(param_def)) { + ret param_map.get(param_def); + } else { + ret typ; + } + } + case (_) { + ret typ; + } + } + } + } + auto replacer = param_replacer(param_map); + ret fold_ty(replacer, typ); +} + +// Substitutes the type parameters specified by @ty_params with the +// corresponding types in @bound in the given type. The two vectors must have +// the same length. +fn substitute_ty_params(vec[ast.ty_param] ty_params, vec[@t] bound, @t ty) + -> @t { + auto ty_param_len = _vec.len[ast.ty_param](ty_params); + check (ty_param_len == _vec.len[@t](bound)); + + auto bindings = common.new_def_hash[@t](); + auto i = 0u; + while (i < ty_param_len) { + bindings.insert(ty_params.(i).id, bound.(i)); + i += 1u; + } + + ret replace_type_params(ty, bindings); +} + // Local Variables: // mode: rust // fill-column: 78; diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 0d583c5e..40fd0f15 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -147,27 +147,6 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t { ret rec(mode=arg.mode, ty=ast_ty_to_ty(getter, arg.ty)); } - fn replace_type_params(@ty.t t, ty_table param_map) -> @ty.t { - state obj param_replacer(ty_table param_map) { - fn fold_simple_ty(@ty.t t) -> @ty.t { - alt (t.struct) { - case (ty.ty_param(?param_def)) { - if (param_map.contains_key(param_def)) { - ret param_map.get(param_def); - } else { - ret t; - } - } - case (_) { - ret t; - } - } - } - } - auto replacer = param_replacer(param_map); - ret ty.fold_ty(replacer, t); - } - fn instantiate(ty_getter getter, ast.def_id id, vec[@ast.ty] args) -> @ty.t { // TODO: maybe record cname chains so we can do @@ -183,7 +162,7 @@ fn ast_ty_to_ty(ty_getter getter, &@ast.ty ast_ty) -> @ty.t { auto param = params.(i); param_map.insert(param.id, ast_ty_to_ty(getter, arg)); } - ret replace_type_params(ty_and_params.ty, param_map); + ret ty.replace_type_params(ty_and_params.ty, param_map); } auto mut = ast.imm; -- cgit v1.2.3 From 3d04fa029e7773bca591502c2890944fae1cefdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Fri, 25 Feb 2011 11:59:00 -0500 Subject: Disable test that is failing on valgrind. --- src/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 1f5901ba..e189c8d0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -439,7 +439,8 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \ test/compile-fail/tail-non-call.rs \ test/compile-fail/writing-through-read-alias.rs -TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ +TEST_XFAILS_RUSTC := $(CONST_TAG_XFAILS) \ + $(addprefix test/run-pass/, \ acyclic-unwind.rs \ alt-pattern-drop.rs \ alt-type-simple.rs \ -- cgit v1.2.3 From f8f6f078c505dd0f20526e3ad86c360605fce109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Fri, 25 Feb 2011 12:08:21 -0500 Subject: There are no native iterators (or at least they are not going to be supported soon.). --- src/comp/front/ast.rs | 2 +- src/comp/front/parser.rs | 31 ++++++++++++++++--------------- src/comp/middle/fold.rs | 17 +++++++++-------- src/comp/middle/trans.rs | 2 +- src/comp/middle/typeck.rs | 19 +++++++++++-------- 5 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index f5c03bd7..9b995f9a 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -235,10 +235,10 @@ tag ty_ { type arg = rec(mode mode, @ty ty, ident ident, def_id id); type fn_decl = rec(effect effect, - proto proto, vec[arg] inputs, @ty output); type _fn = rec(fn_decl decl, + proto proto, block body); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 67b9cc80..7bd34fdf 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1617,8 +1617,7 @@ impure fn parse_ty_params(parser p) -> vec[ast.ty_param] { ret ty_params; } -impure fn parse_fn_decl(parser p, ast.proto proto, - ast.effect eff) -> ast.fn_decl { +impure fn parse_fn_decl(parser p, ast.effect eff) -> ast.fn_decl { auto pf = parse_arg; let util.common.spanned[vec[ast.arg]] inputs = // FIXME: passing parse_arg as an lval doesn't work at the @@ -1636,32 +1635,32 @@ impure fn parse_fn_decl(parser p, ast.proto proto, } else { output = @spanned(inputs.span, inputs.span, ast.ty_nil); } - ret rec(effect=eff, proto=proto, - inputs=inputs.node, output=output); + ret rec(effect=eff, inputs=inputs.node, output=output); } impure fn parse_fn(parser p, ast.effect eff, ast.proto proto) -> ast._fn { - auto decl = parse_fn_decl(p, proto, eff); + auto decl = parse_fn_decl(p, eff); auto body = parse_block(p); ret rec(decl = decl, + proto = proto, body = body); } impure fn parse_fn_header(parser p) - -> tup(span, ast.proto, ast.ident, vec[ast.ty_param]) { - auto lo = p.get_span(); - auto proto = parse_proto(p); + -> tup(ast.ident, vec[ast.ty_param]) { auto id = parse_ident(p); auto ty_params = parse_ty_params(p); - ret tup(lo, proto, id, ty_params); + ret tup(id, ty_params); } impure fn parse_item_fn_or_iter(parser p, ast.effect eff) -> @ast.item { + auto lo = p.get_span(); + auto proto = parse_proto(p); auto t = parse_fn_header(p); - auto f = parse_fn(p, eff, t._1); - auto item = ast.item_fn(t._2, f, t._3, + auto f = parse_fn(p, eff, proto); + auto item = ast.item_fn(t._0, f, t._1, p.next_def_id(), ast.ann_none); - ret @spanned(t._0, f.body.span, item); + ret @spanned(lo, f.body.span, item); } @@ -1760,13 +1759,15 @@ impure fn parse_item_native_type(parser p) -> @ast.native_item { } impure fn parse_item_native_fn(parser p, ast.effect eff) -> @ast.native_item { + auto lo = p.get_span(); + expect(p, token.FN); auto t = parse_fn_header(p); - auto decl = parse_fn_decl(p, t._1, eff); + auto decl = parse_fn_decl(p, eff); auto hi = p.get_span(); expect(p, token.SEMI); - auto item = ast.native_item_fn(t._2, decl, t._3, p.next_def_id(), + auto item = ast.native_item_fn(t._0, decl, t._1, p.next_def_id(), ast.ann_none); - ret @spanned(t._0, hi, item); + ret @spanned(lo, hi, item); } impure fn parse_native_item(parser p) -> @ast.native_item { diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 968d4737..65bbe602 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -253,10 +253,11 @@ type ast_fold[ENV] = &ast.block_) -> block) fold_block, (fn(&ENV e, &fn_decl decl, + ast.proto proto, &block body) -> ast._fn) fold_fn, (fn(&ENV e, ast.effect effect, - ast.proto proto, vec[arg] inputs, + vec[arg] inputs, @ty output) -> ast.fn_decl) fold_fn_decl, (fn(&ENV e, &ast._mod m) -> ast._mod) fold_mod, @@ -757,7 +758,7 @@ fn fold_fn_decl[ENV](&ENV env, ast_fold[ENV] fld, inputs += fold_arg(env, fld, a); } auto output = fold_ty[ENV](env, fld, decl.output); - ret fld.fold_fn_decl(env, decl.effect, decl.proto, inputs, output); + ret fld.fold_fn_decl(env, decl.effect, inputs, output); } fn fold_fn[ENV](&ENV env, ast_fold[ENV] fld, &ast._fn f) -> ast._fn { @@ -765,7 +766,7 @@ fn fold_fn[ENV](&ENV env, ast_fold[ENV] fld, &ast._fn f) -> ast._fn { auto body = fold_block[ENV](env, fld, f.body); - ret fld.fold_fn(env, decl, body); + ret fld.fold_fn(env, decl, f.proto, body); } @@ -1306,16 +1307,16 @@ fn identity_fold_block[ENV](&ENV e, &span sp, &ast.block_ blk) -> block { fn identity_fold_fn_decl[ENV](&ENV e, ast.effect effect, - ast.proto proto, vec[arg] inputs, @ty output) -> ast.fn_decl { - ret rec(effect=effect, proto=proto, inputs=inputs, output=output); + ret rec(effect=effect, inputs=inputs, output=output); } fn identity_fold_fn[ENV](&ENV e, &fn_decl decl, + ast.proto proto, &block body) -> ast._fn { - ret rec(decl=decl, body=body); + ret rec(decl=decl, proto=proto, body=body); } fn identity_fold_mod[ENV](&ENV e, &ast._mod m) -> ast._mod { @@ -1475,8 +1476,8 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { bind identity_fold_view_item_import[ENV](_,_,_,_,_,_), fold_block = bind identity_fold_block[ENV](_,_,_), - fold_fn = bind identity_fold_fn[ENV](_,_,_), - fold_fn_decl = bind identity_fold_fn_decl[ENV](_,_,_,_,_), + fold_fn = bind identity_fold_fn[ENV](_,_,_,_), + fold_fn_decl = bind identity_fold_fn_decl[ENV](_,_,_,_), fold_mod = bind identity_fold_mod[ENV](_,_), fold_native_mod = bind identity_fold_native_mod[ENV](_,_), fold_crate = bind identity_fold_crate[ENV](_,_,_), diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 467aaa0d..33693835 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4019,7 +4019,7 @@ fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid, cx.item_names.insert(cx.path, llfndecl); auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); - create_llargs_for_fn_args(fcx, f.decl.proto, + create_llargs_for_fn_args(fcx, f.proto, ty_self, ret_ty_of_fn(ann), f.decl.inputs, ty_params); auto bcx = new_top_block_ctxt(fcx); diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 40fd0f15..db28735e 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -332,10 +332,11 @@ fn ty_of_fn_decl(@ty_item_table id_to_ty_item, fn(&@ast.ty ast_ty) -> @ty.t convert, fn(&ast.arg a) -> arg ty_of_arg, &ast.fn_decl decl, + ast.proto proto, ast.def_id def_id) -> @ty.t { auto input_tys = _vec.map[ast.arg,arg](ty_of_arg, decl.inputs); auto output_ty = convert(decl.output); - auto t_fn = plain_ty(ty.ty_fn(decl.proto, input_tys, output_ty)); + auto t_fn = plain_ty(ty.ty_fn(proto, input_tys, output_ty)); item_to_ty.insert(def_id, t_fn); ret t_fn; } @@ -394,7 +395,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) auto f = bind ty_of_arg(id_to_ty_item, item_to_ty, _); auto inputs = _vec.map[ast.arg,arg](f, m.node.meth.decl.inputs); auto output = convert(m.node.meth.decl.output); - ret rec(proto=m.node.meth.decl.proto, ident=m.node.ident, + ret rec(proto=m.node.meth.proto, ident=m.node.ident, inputs=inputs, output=output); } @@ -446,7 +447,7 @@ fn collect_item_types(session.session sess, @ast.crate crate) case (ast.item_fn(?ident, ?fn_info, _, ?def_id, _)) { auto f = bind ty_of_arg(id_to_ty_item, item_to_ty, _); ret ty_of_fn_decl(id_to_ty_item, item_to_ty, convert, f, - fn_info.decl, def_id); + fn_info.decl, fn_info.proto, def_id); } case (ast.item_obj(?ident, ?obj_info, _, ?def_id, _)) { @@ -2155,7 +2156,8 @@ fn check_const(&@crate_ctxt ccx, &span sp, ast.ident ident, @ast.ty t, ret @fold.respan[ast.item_](sp, item); } -fn check_fn(&@crate_ctxt ccx, &ast.fn_decl decl, &ast.block body) -> ast._fn { +fn check_fn(&@crate_ctxt ccx, &ast.fn_decl decl, ast.proto proto, + &ast.block body) -> ast._fn { auto local_ty_table = @common.new_def_hash[@ty.t](); // FIXME: duplicate work: the item annotation already has the arg types @@ -2182,8 +2184,9 @@ fn check_fn(&@crate_ctxt ccx, &ast.fn_decl decl, &ast.block body) -> ast._fn { auto block_t = check_block(fcx, body); auto block_wb = writeback(fcx, block_t); - auto fn_t = rec(decl=decl, - body=block_wb); + auto fn_t = rec(decl=decl, + proto=proto, + body=block_wb); ret fn_t; } @@ -2202,7 +2205,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.decl.output); - auto fn_sty = ty.ty_fn(f.decl.proto, inputs, output_ty); + auto fn_sty = ty.ty_fn(f.proto, 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); @@ -2234,7 +2237,7 @@ fn check_crate(session.session sess, @ast.crate crate) -> @ast.crate { auto fld = fold.new_identity_fold[@crate_ctxt](); fld = @rec(update_env_for_item = bind update_obj_fields(_, _), - fold_fn = bind check_fn(_,_,_), + fold_fn = bind check_fn(_,_,_,_), fold_item_fn = bind check_item_fn(_,_,_,_,_,_,_) with *fld); ret fold.fold_crate[@crate_ctxt](ccx, fld, result._0); -- cgit v1.2.3 From 081c3aa76dd0805767e0233c0cc6ccf313cf44ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Fri, 25 Feb 2011 15:58:08 -0500 Subject: Pass the abi of native functions all the way to codegen. --- src/comp/front/parser.rs | 4 ++-- src/comp/middle/trans.rs | 7 ++++--- src/comp/middle/ty.rs | 31 ++++++++++++++++++++----------- src/comp/middle/typeck.rs | 41 +++++++++++++++++++++++++---------------- 4 files changed, 51 insertions(+), 32 deletions(-) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 7bd34fdf..32bcf6ef 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1818,8 +1818,8 @@ impure fn parse_item_native_mod(parser p) -> @ast.item { auto abi = ast.native_abi_cdecl; if (p.peek() != token.MOD) { auto t = parse_str_lit(p); - if (t == "cdecl") { - } else if (t == "rust") { + if (_str.eq(t, "cdecl")) { + } else if (_str.eq(t, "rust")) { abi = ast.native_abi_rust; } else { p.err("unsupported abi: " + t); diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 33693835..d175432d 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -516,7 +516,8 @@ fn type_of_fn(@crate_ctxt cx, ret type_of_fn_full(cx, proto, none[TypeRef], inputs, output); } -fn type_of_native_fn(@crate_ctxt cx, vec[ty.arg] inputs, +fn type_of_native_fn(@crate_ctxt cx, ast.native_abi abi, + vec[ty.arg] inputs, @ty.t output) -> TypeRef { let vec[TypeRef] atys = type_of_explicit_args(cx, inputs); ret T_fn(atys, type_of(cx, output)); @@ -571,8 +572,8 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { case (ty.ty_fn(?proto, ?args, ?out)) { ret T_fn_pair(cx.tn, type_of_fn(cx, proto, args, out)); } - case (ty.ty_native_fn(?args, ?out)) { - ret T_fn_pair(cx.tn, type_of_native_fn(cx, args, out)); + case (ty.ty_native_fn(?abi, ?args, ?out)) { + ret T_fn_pair(cx.tn, type_of_native_fn(cx, abi, args, out)); } case (ty.ty_obj(?meths)) { auto th = mk_type_handle(); diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 02a7ffc2..f19c2997 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -41,7 +41,7 @@ tag sty { ty_tup(vec[@t]); ty_rec(vec[field]); ty_fn(ast.proto, vec[arg], @t); // TODO: effect - ty_native_fn(vec[arg], @t); // TODO: effect + ty_native_fn(ast.native_abi, 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 @@ -261,7 +261,7 @@ fn ty_to_str(&@t typ) -> str { s = fn_to_str(proto, none[ast.ident], inputs, output); } - case (ty_native_fn(?inputs, ?output)) { + case (ty_native_fn(_, ?inputs, ?output)) { s = fn_to_str(ast.proto_fn, none[ast.ident], inputs, output); } @@ -346,13 +346,13 @@ fn fold_ty(ty_fold fld, @t ty) -> @t { } ret rewrap(ty, ty_fn(proto, new_args, fold_ty(fld, ret_ty))); } - case (ty_native_fn(?args, ?ret_ty)) { + case (ty_native_fn(?abi, ?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_native_fn(new_args, fold_ty(fld, ret_ty))); + ret rewrap(ty, ty_native_fn(abi, new_args, fold_ty(fld, ret_ty))); } case (ty_obj(?methods)) { let vec[method] new_methods = vec(); @@ -596,7 +596,7 @@ fn count_ty_params(@t ty) -> uint { fn ty_fn_args(@t fty) -> vec[arg] { alt (fty.struct) { case (ty.ty_fn(_, ?a, _)) { ret a; } - case (ty.ty_native_fn(?a, _)) { ret a; } + case (ty.ty_native_fn(_, ?a, _)) { ret a; } } fail; } @@ -611,7 +611,7 @@ fn ty_fn_proto(@t fty) -> ast.proto { fn ty_fn_ret(@t fty) -> @t { alt (fty.struct) { case (ty.ty_fn(_, _, ?r)) { ret r; } - case (ty.ty_native_fn(_, ?r)) { ret r; } + case (ty.ty_native_fn(_, _, ?r)) { ret r; } } fail; } @@ -619,7 +619,7 @@ fn ty_fn_ret(@t fty) -> @t { fn is_fn_ty(@t fty) -> bool { alt (fty.struct) { case (ty.ty_fn(_, _, _)) { ret true; } - case (ty.ty_native_fn(_, _)) { ret true; } + case (ty.ty_native_fn(_, _, _)) { ret true; } case (_) { ret false; } } ret false; @@ -938,12 +938,18 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) } fn unify_native_fn(@hashmap[int,@ty.t] bindings, + ast.native_abi e_abi, + ast.native_abi a_abi, @ty.t expected, @ty.t actual, &unify_handler handler, vec[arg] expected_inputs, @t expected_output, vec[arg] actual_inputs, @t actual_output) -> unify_result { + if (e_abi != a_abi) { + ret ures_err(terr_mismatch, expected, actual); + } + auto t = unify_fn_common(bindings, expected, actual, handler, expected_inputs, expected_output, actual_inputs, actual_output); @@ -952,7 +958,8 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) ret r; } case (fn_common_res_ok(?result_ins, ?result_out)) { - auto t2 = plain_ty(ty.ty_native_fn(result_ins, result_out)); + auto t2 = plain_ty(ty.ty_native_fn(e_abi, result_ins, + result_out)); ret ures_ok(t2); } } @@ -1314,10 +1321,12 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) } } - case (ty.ty_native_fn(?expected_inputs, ?expected_output)) { + case (ty.ty_native_fn(?e_abi, ?expected_inputs, + ?expected_output)) { alt (actual.struct) { - case (ty.ty_native_fn(?actual_inputs, ?actual_output)) { - ret unify_native_fn(bindings, + case (ty.ty_native_fn(?a_abi, ?actual_inputs, + ?actual_output)) { + ret unify_native_fn(bindings, e_abi, a_abi, expected, actual, handler, expected_inputs, expected_output, actual_inputs, actual_output); diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index db28735e..ce1c59ec 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -35,7 +35,7 @@ type ty_table = hashmap[ast.def_id, @ty.t]; tag any_item { any_item_rust(@ast.item); - any_item_native(@ast.native_item); + any_item_native(@ast.native_item, ast.native_abi); } type ty_item_table = hashmap[ast.def_id,any_item]; @@ -272,7 +272,7 @@ fn ast_ty_to_ty_crate(@crate_ctxt ccx, &@ast.ty ast_ty) -> @ty.t { ty = actual_type(ty, item); params = ty_params_of_item(item); } - case (any_item_native(?native_item)) { + case (any_item_native(?native_item, _)) { params = ty_params_of_native_item(native_item); } } @@ -346,10 +346,11 @@ fn ty_of_native_fn_decl(@ty_item_table id_to_ty_item, fn(&@ast.ty ast_ty) -> @ty.t convert, fn(&ast.arg a) -> arg ty_of_arg, &ast.fn_decl decl, + ast.native_abi abi, ast.def_id def_id) -> @ty.t { auto input_tys = _vec.map[ast.arg,arg](ty_of_arg, decl.inputs); auto output_ty = convert(decl.output); - auto t_fn = plain_ty(ty.ty_native_fn(input_tys, output_ty)); + auto t_fn = plain_ty(ty.ty_native_fn(abi, input_tys, output_ty)); item_to_ty.insert(def_id, t_fn); ret t_fn; } @@ -370,9 +371,9 @@ fn collect_item_types(session.session sess, @ast.crate crate) ty = actual_type(ty, item); params = ty_params_of_item(item); } - case (any_item_native(?native_item)) { + case (any_item_native(?native_item, ?abi)) { ty = ty_of_native_item(id_to_ty_item, item_to_ty, - native_item); + native_item, abi); params = ty_params_of_native_item(native_item); } } @@ -490,14 +491,15 @@ fn collect_item_types(session.session sess, @ast.crate crate) fn ty_of_native_item(@ty_item_table id_to_ty_item, @ty_table item_to_ty, - @ast.native_item it) -> @ty.t { + @ast.native_item it, + ast.native_abi abi) -> @ty.t { alt (it.node) { case (ast.native_item_fn(?ident, ?fn_decl, ?params, ?def_id, _)) { auto get = bind getter(id_to_ty_item, item_to_ty, _); auto convert = bind ast_ty_to_ty(get, _); auto f = bind ty_of_arg(id_to_ty_item, item_to_ty, _); ret ty_of_native_fn_decl(id_to_ty_item, item_to_ty, convert, - f, fn_decl, def_id); + f, fn_decl, abi, def_id); } case (ast.native_item_ty(_, ?def_id)) { if (item_to_ty.contains_key(def_id)) { @@ -578,7 +580,10 @@ fn collect_item_types(session.session sess, @ast.crate crate) -> @ty_item_table { alt (i.node) { case (ast.native_item_ty(_, ?def_id)) { - id_to_ty_item.insert(def_id, any_item_native(i)); + // The abi of types is not used. + id_to_ty_item.insert(def_id, + any_item_native(i, + ast.native_abi_cdecl)); } case (_) { } @@ -598,18 +603,22 @@ fn collect_item_types(session.session sess, @ast.crate crate) type env = rec(session.session sess, @ty_item_table id_to_ty_item, - @ty_table item_to_ty); + @ty_table item_to_ty, + ast.native_abi abi); let @env e = @rec(sess=sess, id_to_ty_item=id_to_ty_item, - item_to_ty=item_to_ty); + item_to_ty=item_to_ty, + abi=ast.native_abi_cdecl); fn convert(&@env e, @ast.item i) -> @env { + auto abi = e.abi; alt (i.node) { case (ast.item_mod(_, _, _)) { // ignore item_mod, it has no type. } - case (ast.item_native_mod(_, _, _)) { + case (ast.item_native_mod(_, ?native_mod, _)) { // ignore item_native_mod, it has no type. + abi = native_mod.abi; } case (_) { // This call populates the ty_table with the converted type of @@ -617,11 +626,11 @@ fn collect_item_types(session.session sess, @ast.crate crate) ty_of_item(e.id_to_ty_item, e.item_to_ty, i); } } - ret e; + ret @rec(abi=abi with *e); } fn convert_native(&@env e, @ast.native_item i) -> @env { - ty_of_native_item(e.id_to_ty_item, e.item_to_ty, i); + ty_of_native_item(e.id_to_ty_item, e.item_to_ty, i, e.abi); ret e; } @@ -1322,8 +1331,8 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { case (ty.ty_fn(?proto, _, _)) { t_0 = plain_ty(ty.ty_fn(proto, arg_tys_0, rt_0)); } - case (ty.ty_native_fn(_, _)) { - t_0 = plain_ty(ty.ty_native_fn(arg_tys_0, rt_0)); + case (ty.ty_native_fn(?abi, _, _)) { + t_0 = plain_ty(ty.ty_native_fn(abi, arg_tys_0, rt_0)); } case (_) { log "check_call_or_bind(): fn expr doesn't have fn type"; @@ -1807,7 +1816,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto rt_1 = plain_ty(ty.ty_nil); // FIXME: typestate botch alt (expr_ty(result._0).struct) { case (ty.ty_fn(_,_,?rt)) { rt_1 = rt; } - case (ty.ty_native_fn(_,?rt)) { rt_1 = rt; } + case (ty.ty_native_fn(_, _, ?rt)) { rt_1 = rt; } case (_) { log "LHS of call expr didn't have a function type?!"; fail; -- cgit v1.2.3 From 7a1d01effcfa5763bc62aefba40f67ad2130d28d Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 25 Feb 2011 12:37:03 -0800 Subject: rustc: Push type parameters down through alt tag patterns; add a test --- src/comp/middle/typeck.rs | 55 ++++++++++++++++++++++++++++---- src/test/run-pass/generic-tag-box-alt.rs | 19 +++++++++++ 2 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 src/test/run-pass/generic-tag-box-alt.rs diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index ce1c59ec..a69d169d 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -919,9 +919,42 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { // acquire here with the type parameters provided to us by // "expected". + // Grab the values for the type parameters of the tag from the + // expected type. + let vec[@ty.t] typaram_bindings = vec(); // FIXME: typestate botch + alt (expected.struct) { + case (ty.ty_tag(_, ?tps)) { typaram_bindings = tps; } + case (_) { + log "tag pattern didn't have tag type?!"; + fail; + } + } + + // Get the item corresponding to the tag and its type. auto vdef = option.get[ast.variant_def](vdef_opt); auto variant_ty = fcx.ccx.item_types.get(vdef._1); + // FIXME: typestate botch + let option.t[@ast.item] item_opt = none[@ast.item]; + alt (fcx.ccx.item_items.get(vdef._0)) { + case (any_item_rust(?it)) { item_opt = some[@ast.item](it); } + case (_) { + log "tag item isn't a Rust item?!"; + fail; + } + } + let @ast.item item = option.get[@ast.item](item_opt); + + // Get the IDs of the type parameters from that item. + let vec[ast.ty_param] ty_params = vec(); // FIXME: typestate botch + alt (item.node) { + case (ast.item_tag(_, _, ?tps, _)) { ty_params = tps; } + case (_) { + log "tag's corresponding item isn't a tag?!"; + fail; + } + } + auto subpats_len = _vec.len[@ast.pat](subpats); alt (variant_ty.struct) { case (ty.ty_tag(_, _)) { @@ -930,10 +963,14 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { p_1 = ast.pat_tag(id, subpats, vdef_opt, ast.ann_type(t)); } case (ty.ty_fn(_, ?args, ?tag_ty)) { + // N-ary tag variant. let vec[@ast.pat] new_subpats = vec(); auto i = 0u; for (arg a in args) { - auto new_subpat = demand_pat(fcx, a.ty, subpats.(i)); + auto arg_ty = ty.substitute_ty_params(ty_params, + typaram_bindings, a.ty); + auto new_subpat = demand_pat(fcx, arg_ty, + subpats.(i)); new_subpats += vec(new_subpat); i += 1u; } @@ -1260,14 +1297,13 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat { new_subpats += vec(check_pat(fcx, subpat)); } - auto ann = ast.ann_type(tag_ty); + auto tag_ty_g = generalize_ty(fcx.ccx, tag_ty); + auto ann = ast.ann_type(tag_ty_g); new_pat = ast.pat_tag(p, new_subpats, vdef_opt, ann); } // Nullary variants have tag types. - case (ty.ty_tag(?tid, _)) { - // TODO: ty params - + case (ty.ty_tag(?tid, ?tps)) { auto subpats_len = _vec.len[@ast.pat](subpats); if (subpats_len > 0u) { // TODO: pluralize properly @@ -1281,7 +1317,14 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat { fail; // TODO: recover } - let vec[@ty.t] tys = vec(); // FIXME + // Add the appropriate number of type variables. + let vec[@ty.t] tys = vec(); + auto i = 0u; + while (i < _vec.len[@ty.t](tps)) { + tys += vec(next_ty_var(fcx.ccx)); + i += 1u; + } + 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-box-alt.rs b/src/test/run-pass/generic-tag-box-alt.rs new file mode 100644 index 00000000..2727885a --- /dev/null +++ b/src/test/run-pass/generic-tag-box-alt.rs @@ -0,0 +1,19 @@ +tag foo[T] { + arm(@T); +} + +fn altfoo[T](foo[T] f) { + auto hit = false; + alt (f) { + case (arm[T](?x)) { + log "in arm"; + hit = true; + } + } + check (hit); +} + +fn main() { + altfoo[int](arm[int](@10)); +} + -- cgit v1.2.3 From 69464aae62aef5a65fcf5bb79ab18f8967f32206 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 25 Feb 2011 13:44:37 -0800 Subject: rustc: Remove FIXME obsoleted by the previous commit --- src/comp/middle/typeck.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index a69d169d..472bd8d3 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -913,11 +913,6 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { // of the variant, which is either a tag type in the case of // nullary variants or a function type in the case of n-ary // variants. - // - // TODO: When we have type-parametric tags, this will get a little - // trickier. Basically, we have to instantiate the variant type we - // acquire here with the type parameters provided to us by - // "expected". // Grab the values for the type parameters of the tag from the // expected type. -- cgit v1.2.3 From dabccadd3202513ab0bcb424e2c62c90ab23062d Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 25 Feb 2011 15:00:05 -0800 Subject: Update manual to define identifiers using UAX 31 XID_Start / XID_Continue. --- doc/rust.texi | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/doc/rust.texi b/doc/rust.texi index adf84a12..740d45c6 100644 --- a/doc/rust.texi +++ b/doc/rust.texi @@ -592,10 +592,12 @@ or interrupted by ignored characters. Most tokens in Rust follow rules similar to the C family. -Most tokens (including identifiers, whitespace, keywords, operators and -structural symbols) are drawn from the ASCII-compatible range of -Unicode. String and character literals, however, may include the full range of -Unicode characters. +Most tokens (including whitespace, keywords, operators and structural symbols) +are drawn from the ASCII-compatible range of Unicode. Identifiers are drawn +from Unicode characters specified by the @code{XID_start} and +@code{XID_continue} rules given by UAX #31@footnote{Unicode Standard Annex +#31: Unicode Identifier and Pattern Syntax}. String and character literals may +include the full range of Unicode characters. @emph{TODO: formalize this section much more}. @@ -638,18 +640,22 @@ token or a syntactic extension token. Multi-line comments may be nested. @c * Ref.Lex.Ident:: Identifier tokens. @cindex Identifier token -Identifiers follow the pattern of C identifiers: they begin with a -@emph{letter} or @emph{underscore}, and continue with any combination of -@emph{letters}, @emph{decimal digits} and underscores, and must not be equal -to any keyword or reserved token. @xref{Ref.Lex.Key}. @xref{Ref.Lex.Res}. +Identifiers follow the rules given by Unicode Standard Annex #31, in the form +closed under NFKC normalization, @emph{excluding} those tokens that are +otherwise defined as keywords or reserved +tokens. @xref{Ref.Lex.Key}. @xref{Ref.Lex.Res}. -A @emph{letter} is a Unicode character in the ranges U+0061-U+007A and -U+0041-U+005A (@code{'a'}-@code{'z'} and @code{'A'}-@code{'Z'}). +That is: an identifier starts with any character having derived property +@code{XID_Start} and continues with zero or more characters having derived +property @code{XID_Continue}; and such an identifier is NFKC-normalized during +lexing, such that all subsequent comparison of identifiers is performed on the +NFKC-normalized forms. -An @dfn{underscore} is the character U+005F ('_'). +@emph{TODO: define relationship between Unicode and Rust versions}. -A @dfn{decimal digit} is a character in the range U+0030-U+0039 -(@code{'0'}-@code{'9'}). +@footnote{This identifier syntax is a superset of the identifier syntaxes of C +and Java, and is modeled on Python PEP #3131, which formed the definition of +identifiers in Python 3.0 and later.} @node Ref.Lex.Key @subsection Ref.Lex.Key -- cgit v1.2.3 From 7a6ac1c00041fc8043e240c8fb7255251fea63f4 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 25 Feb 2011 15:00:30 -0800 Subject: Fix typo in crate directive evaluator. --- src/comp/front/eval.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/comp/front/eval.rs b/src/comp/front/eval.rs index 7275e557..ab8d5d32 100644 --- a/src/comp/front/eval.rs +++ b/src/comp/front/eval.rs @@ -412,7 +412,7 @@ impure fn eval_crate_directive(parser p, } auto full_path = prefix + std.os.path_sep() + path; - auto m0 = eval_crate_directives_to_mod(p, e, cdirs, path); + auto m0 = eval_crate_directives_to_mod(p, e, cdirs, full_path); auto im = ast.item_mod(id, m0, p.next_def_id()); auto i = @spanned(cdir.span, cdir.span, im); ast.index_item(index, i); -- cgit v1.2.3 From 6c24d0403b2e8fefecc5eea11933d493a01f1daf Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 25 Feb 2011 15:49:08 -0800 Subject: Revert "rustc: Push type parameters down through alt tag patterns; add a test" due to valgrind failures This reverts commit 7a1d01effcfa5763bc62aefba40f67ad2130d28d. --- src/comp/middle/typeck.rs | 60 ++++++-------------------------- src/test/run-pass/generic-tag-box-alt.rs | 19 ---------- 2 files changed, 11 insertions(+), 68 deletions(-) delete mode 100644 src/test/run-pass/generic-tag-box-alt.rs diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 472bd8d3..ce1c59ec 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -913,43 +913,15 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { // of the variant, which is either a tag type in the case of // nullary variants or a function type in the case of n-ary // variants. + // + // TODO: When we have type-parametric tags, this will get a little + // trickier. Basically, we have to instantiate the variant type we + // acquire here with the type parameters provided to us by + // "expected". - // Grab the values for the type parameters of the tag from the - // expected type. - let vec[@ty.t] typaram_bindings = vec(); // FIXME: typestate botch - alt (expected.struct) { - case (ty.ty_tag(_, ?tps)) { typaram_bindings = tps; } - case (_) { - log "tag pattern didn't have tag type?!"; - fail; - } - } - - // Get the item corresponding to the tag and its type. auto vdef = option.get[ast.variant_def](vdef_opt); auto variant_ty = fcx.ccx.item_types.get(vdef._1); - // FIXME: typestate botch - let option.t[@ast.item] item_opt = none[@ast.item]; - alt (fcx.ccx.item_items.get(vdef._0)) { - case (any_item_rust(?it)) { item_opt = some[@ast.item](it); } - case (_) { - log "tag item isn't a Rust item?!"; - fail; - } - } - let @ast.item item = option.get[@ast.item](item_opt); - - // Get the IDs of the type parameters from that item. - let vec[ast.ty_param] ty_params = vec(); // FIXME: typestate botch - alt (item.node) { - case (ast.item_tag(_, _, ?tps, _)) { ty_params = tps; } - case (_) { - log "tag's corresponding item isn't a tag?!"; - fail; - } - } - auto subpats_len = _vec.len[@ast.pat](subpats); alt (variant_ty.struct) { case (ty.ty_tag(_, _)) { @@ -958,14 +930,10 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat { p_1 = ast.pat_tag(id, subpats, vdef_opt, ast.ann_type(t)); } case (ty.ty_fn(_, ?args, ?tag_ty)) { - // N-ary tag variant. let vec[@ast.pat] new_subpats = vec(); auto i = 0u; for (arg a in args) { - auto arg_ty = ty.substitute_ty_params(ty_params, - typaram_bindings, a.ty); - auto new_subpat = demand_pat(fcx, arg_ty, - subpats.(i)); + auto new_subpat = demand_pat(fcx, a.ty, subpats.(i)); new_subpats += vec(new_subpat); i += 1u; } @@ -1292,13 +1260,14 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat { new_subpats += vec(check_pat(fcx, subpat)); } - auto tag_ty_g = generalize_ty(fcx.ccx, tag_ty); - auto ann = ast.ann_type(tag_ty_g); + auto ann = ast.ann_type(tag_ty); new_pat = ast.pat_tag(p, new_subpats, vdef_opt, ann); } // Nullary variants have tag types. - case (ty.ty_tag(?tid, ?tps)) { + case (ty.ty_tag(?tid, _)) { + // TODO: ty params + auto subpats_len = _vec.len[@ast.pat](subpats); if (subpats_len > 0u) { // TODO: pluralize properly @@ -1312,14 +1281,7 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat { fail; // TODO: recover } - // Add the appropriate number of type variables. - let vec[@ty.t] tys = vec(); - auto i = 0u; - while (i < _vec.len[@ty.t](tps)) { - tys += vec(next_ty_var(fcx.ccx)); - i += 1u; - } - + 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-box-alt.rs b/src/test/run-pass/generic-tag-box-alt.rs deleted file mode 100644 index 2727885a..00000000 --- a/src/test/run-pass/generic-tag-box-alt.rs +++ /dev/null @@ -1,19 +0,0 @@ -tag foo[T] { - arm(@T); -} - -fn altfoo[T](foo[T] f) { - auto hit = false; - alt (f) { - case (arm[T](?x)) { - log "in arm"; - hit = true; - } - } - check (hit); -} - -fn main() { - altfoo[int](arm[int](@10)); -} - -- cgit v1.2.3 From 2cd7fbbdf1edf84d962c62e9990acc0906998413 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 25 Feb 2011 16:24:19 -0800 Subject: rustc: Move all of the logic in type_of() to type_of_inner() --- src/comp/middle/trans.rs | 78 +++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index d175432d..29ff9d6e 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -419,10 +419,7 @@ fn T_opaque_obj_ptr(type_names tn) -> 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(ty.ty_to_str(t)), llty); - ret llty; + ret type_of_inner(cx, t); } fn type_of_explicit_args(@crate_ctxt cx, @@ -433,7 +430,7 @@ fn type_of_explicit_args(@crate_ctxt cx, check (arg.mode == ast.alias); atys += T_typaram_ptr(cx.tn); } else { - let TypeRef t = type_of(cx, arg.ty); + let TypeRef t = type_of_inner(cx, arg.ty); alt (arg.mode) { case (ast.alias) { t = T_ptr(t); @@ -464,7 +461,7 @@ fn type_of_fn_full(@crate_ctxt cx, if (ty.type_has_dynamic_size(output)) { atys += T_typaram_ptr(cx.tn); } else { - atys += T_ptr(type_of(cx, output)); + atys += T_ptr(type_of_inner(cx, output)); } // Arg 1: Task pointer. @@ -520,60 +517,62 @@ fn type_of_native_fn(@crate_ctxt cx, ast.native_abi abi, vec[ty.arg] inputs, @ty.t output) -> TypeRef { let vec[TypeRef] atys = type_of_explicit_args(cx, inputs); - ret T_fn(atys, type_of(cx, output)); + ret T_fn(atys, type_of_inner(cx, output)); } fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { + let TypeRef llty = 0 as TypeRef; + alt (t.struct) { - case (ty.ty_native) { ret T_ptr(T_i8()); } - 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_native) { llty = T_ptr(T_i8()); } + case (ty.ty_nil) { llty = T_nil(); } + case (ty.ty_bool) { llty = T_bool(); } + case (ty.ty_int) { llty = T_int(); } + case (ty.ty_uint) { llty = T_int(); } case (ty.ty_machine(?tm)) { alt (tm) { - case (common.ty_i8) { ret T_i8(); } - case (common.ty_u8) { ret T_i8(); } - case (common.ty_i16) { ret T_i16(); } - case (common.ty_u16) { ret T_i16(); } - case (common.ty_i32) { ret T_i32(); } - case (common.ty_u32) { ret T_i32(); } - case (common.ty_i64) { ret T_i64(); } - case (common.ty_u64) { ret T_i64(); } - case (common.ty_f32) { ret T_f32(); } - case (common.ty_f64) { ret T_f64(); } + case (common.ty_i8) { llty = T_i8(); } + case (common.ty_u8) { llty = T_i8(); } + case (common.ty_i16) { llty = T_i16(); } + case (common.ty_u16) { llty = T_i16(); } + case (common.ty_i32) { llty = T_i32(); } + case (common.ty_u32) { llty = T_i32(); } + case (common.ty_i64) { llty = T_i64(); } + case (common.ty_u64) { llty = T_i64(); } + case (common.ty_f32) { llty = T_f32(); } + case (common.ty_f64) { llty = T_f64(); } } } - case (ty.ty_char) { ret T_char(); } - case (ty.ty_str) { ret T_ptr(T_str()); } + case (ty.ty_char) { llty = T_char(); } + case (ty.ty_str) { llty = T_ptr(T_str()); } case (ty.ty_tag(?tag_id, _)) { - ret llvm.LLVMResolveTypeHandle(cx.tags.get(tag_id).th.llth); + llty = llvm.LLVMResolveTypeHandle(cx.tags.get(tag_id).th.llth); } case (ty.ty_box(?t)) { - ret T_ptr(T_box(type_of(cx, t))); + llty = T_ptr(T_box(type_of_inner(cx, t))); } case (ty.ty_vec(?t)) { - ret T_ptr(T_vec(type_of(cx, t))); + llty = T_ptr(T_vec(type_of_inner(cx, t))); } case (ty.ty_tup(?elts)) { let vec[TypeRef] tys = vec(); for (@ty.t elt in elts) { - tys += type_of(cx, elt); + tys += type_of_inner(cx, elt); } - ret T_struct(tys); + llty = T_struct(tys); } case (ty.ty_rec(?fields)) { let vec[TypeRef] tys = vec(); for (ty.field f in fields) { - tys += type_of(cx, f.ty); + tys += type_of_inner(cx, f.ty); } - ret T_struct(tys); + llty = T_struct(tys); } case (ty.ty_fn(?proto, ?args, ?out)) { - ret T_fn_pair(cx.tn, type_of_fn(cx, proto, args, out)); + llty = T_fn_pair(cx.tn, type_of_fn(cx, proto, args, out)); } case (ty.ty_native_fn(?abi, ?args, ?out)) { - ret T_fn_pair(cx.tn, type_of_native_fn(cx, abi, args, out)); + llty = T_fn_pair(cx.tn, type_of_native_fn(cx, abi, args, out)); } case (ty.ty_obj(?meths)) { auto th = mk_type_handle(); @@ -594,22 +593,25 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { auto abs_pair = llvm.LLVMResolveTypeHandle(th.llth); llvm.LLVMRefineType(abs_pair, pair); abs_pair = llvm.LLVMResolveTypeHandle(th.llth); - ret abs_pair; + llty = abs_pair; } case (ty.ty_var(_)) { log "ty_var in trans.type_of"; fail; } case (ty.ty_param(_)) { - ret T_typaram_ptr(cx.tn); + llty = T_typaram_ptr(cx.tn); } - case (ty.ty_type) { ret T_ptr(T_tydesc(cx.tn)); } + case (ty.ty_type) { llty = T_ptr(T_tydesc(cx.tn)); } } - fail; + + check (llty as int != 0); + llvm.LLVMAddTypeName(cx.llmod, _str.buf(ty.ty_to_str(t)), llty); + ret llty; } fn type_of_arg(@crate_ctxt cx, &ty.arg arg) -> TypeRef { - auto ty = type_of(cx, arg.ty); + auto ty = type_of_inner(cx, arg.ty); if (arg.mode == ast.alias) { ty = T_ptr(ty); } -- cgit v1.2.3 From b5081a6a825f23b45920cf72896076039f30386d Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 25 Feb 2011 16:45:43 -0800 Subject: Add a tag_variant_count() function to trans that doesn't go through the soon-to-be-deprecated tag info table --- src/comp/middle/trans.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 29ff9d6e..cfe07caa 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1442,6 +1442,8 @@ fn decr_refcnt_and_if_zero(@block_ctxt cx, ret res(next_cx, phi); } +// Tag information + fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef { let vec[TypeRef] lltys = vec(); alt (ty.ann_to_type(v.ann).struct) { @@ -1455,6 +1457,17 @@ fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef { ret T_struct(lltys); } +// Returns the number of variants in a tag. +fn tag_variant_count(@crate_ctxt cx, ast.def_id id) -> uint { + check (cx.items.contains_key(id)); + alt (cx.items.get(id).node) { + case (ast.item_tag(_, ?variants, _, _)) { + ret _vec.len[ast.variant](variants); + } + } + fail; // not reached +} + type val_and_ty_fn = fn(@block_ctxt cx, ValueRef v, @ty.t t) -> result; // Iterates through the elements of a structural type. @@ -1506,7 +1519,7 @@ fn iter_structural_ty(@block_ctxt cx, case (ty.ty_tag(?tid, ?tps)) { 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); + auto n_variants = tag_variant_count(cx.fcx.ccx, tid); // Look up the tag in the typechecked AST. check (cx.fcx.ccx.items.contains_key(tid)); -- cgit v1.2.3 From 9c928fcf8c584659274bdb9095e47f2fa963d05c Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 25 Feb 2011 17:14:48 -0800 Subject: rustc: Make iter_structural_ty() not use the "variants" field in the tag info --- src/comp/middle/trans.rs | 104 +++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 62 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index cfe07caa..a56421ba 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1457,13 +1457,11 @@ fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef { ret T_struct(lltys); } -// Returns the number of variants in a tag. -fn tag_variant_count(@crate_ctxt cx, ast.def_id id) -> uint { +// Returns the variants in a tag. +fn tag_variants(@crate_ctxt cx, ast.def_id id) -> vec[ast.variant] { check (cx.items.contains_key(id)); alt (cx.items.get(id).node) { - case (ast.item_tag(_, ?variants, _, _)) { - ret _vec.len[ast.variant](variants); - } + case (ast.item_tag(_, ?variants, _, _)) { ret variants; } } fail; // not reached } @@ -1519,21 +1517,9 @@ fn iter_structural_ty(@block_ctxt cx, case (ty.ty_tag(?tid, ?tps)) { check (cx.fcx.ccx.tags.contains_key(tid)); auto info = cx.fcx.ccx.tags.get(tid); - auto n_variants = tag_variant_count(cx.fcx.ccx, tid); - - // Look up the tag in the typechecked AST. - check (cx.fcx.ccx.items.contains_key(tid)); - auto tag_item = cx.fcx.ccx.items.get(tid); - let vec[ast.variant] variants = vec(); // FIXME: typestate bug - alt (tag_item.node) { - case (ast.item_tag(_, ?vs, _, _)) { - variants = vs; - } - case (_) { - log "trans: ty_tag doesn't actually refer to a tag"; - fail; - } - } + + auto variants = tag_variants(cx.fcx.ccx, tid); + auto n_variants = _vec.len[ast.variant](variants); auto lldiscrim_ptr = cx.build.GEP(v, vec(C_int(0), C_int(0))); auto llunion_ptr = cx.build.GEP(v, vec(C_int(0), C_int(1))); @@ -1548,55 +1534,49 @@ fn iter_structural_ty(@block_ctxt cx, auto next_cx = new_sub_block_ctxt(cx, "tag-iter-next"); auto i = 0u; - for (tup(ast.def_id,arity) variant in info.variants) { + for (ast.variant variant in variants) { auto variant_cx = new_sub_block_ctxt(cx, "tag-iter-variant-" + _uint.to_str(i, 10u)); llvm.LLVMAddCase(llswitch, C_int(i as int), variant_cx.llbb); - alt (variant._1) { - case (n_ary) { - let vec[ValueRef] vals = vec(C_int(0), C_int(1), - C_int(i as int)); - auto llvar = variant_cx.build.GEP(v, vals); - auto llvarty = type_of_variant(cx.fcx.ccx, - variants.(i)); - - auto fn_ty = ty.ann_to_type(variants.(i).ann); - alt (fn_ty.struct) { - case (ty.ty_fn(_, ?args, _)) { - auto llvarp = variant_cx.build. - TruncOrBitCast(llunion_ptr, - T_ptr(llvarty)); - - auto j = 0u; - for (ty.arg a in args) { - auto v = vec(C_int(0), - C_int(j as int)); - auto llfldp = - variant_cx.build.GEP(llvarp, v); - - auto ty_subst = ty.substitute_ty_params( - info.ty_params, tps, a.ty); - - auto llfld = - load_scalar_or_boxed(variant_cx, - llfldp, - ty_subst); - - auto res = f(variant_cx, llfld, ty_subst); - variant_cx = res.bcx; - j += 1u; - } + if (_vec.len[ast.variant_arg](variant.args) > 0u) { + // N-ary variant. + let vec[ValueRef] vals = vec(C_int(0), C_int(1), + C_int(i as int)); + auto llvar = variant_cx.build.GEP(v, vals); + auto llvarty = type_of_variant(cx.fcx.ccx, variants.(i)); + + auto fn_ty = ty.ann_to_type(variants.(i).ann); + alt (fn_ty.struct) { + case (ty.ty_fn(_, ?args, _)) { + auto llvarp = variant_cx.build. + TruncOrBitCast(llunion_ptr, T_ptr(llvarty)); + + auto j = 0u; + for (ty.arg a in args) { + auto v = vec(C_int(0), C_int(j as int)); + auto llfldp = variant_cx.build.GEP(llvarp, v); + + auto ty_subst = ty.substitute_ty_params( + info.ty_params, tps, a.ty); + + auto llfld = + load_scalar_or_boxed(variant_cx, + llfldp, + ty_subst); + + auto res = f(variant_cx, llfld, ty_subst); + variant_cx = res.bcx; + j += 1u; } - case (_) { fail; } } - - variant_cx.build.Br(next_cx.llbb); - } - case (nullary) { - // Nothing to do. - variant_cx.build.Br(next_cx.llbb); + case (_) { fail; } } + + variant_cx.build.Br(next_cx.llbb); + } else { + // Nullary variant; nothing to do. + variant_cx.build.Br(next_cx.llbb); } i += 1u; -- cgit v1.2.3 From 699eb69cc85f663d62200ee64ec9f2a606fcf440 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 25 Feb 2011 18:16:50 -0800 Subject: rustc: Eliminate the "variants" field from the tag info --- src/comp/middle/trans.rs | 59 ++++++++++++++++++------------------------------ 1 file changed, 22 insertions(+), 37 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index a56421ba..3f9c770e 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -61,7 +61,6 @@ type glue_fns = rec(ValueRef activate_glue, tag arity { nullary; n_ary; } type tag_info = rec(type_handle th, - mutable vec[tup(ast.def_id,arity)] variants, mutable uint size, vec[ast.ty_param] ty_params); @@ -2384,11 +2383,12 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, auto vdef = option.get[ast.variant_def](vdef_opt); auto variant_id = vdef._1; - auto tinfo = cx.fcx.ccx.tags.get(vdef._0); auto variant_tag = 0; + + auto variants = tag_variants(cx.fcx.ccx, vdef._0); auto i = 0; - for (tup(ast.def_id,arity) vinfo in tinfo.variants) { - auto this_variant_id = vinfo._0; + for (ast.variant v in variants) { + auto this_variant_id = v.id; if (variant_id._0 == this_variant_id._0 && variant_id._1 == this_variant_id._1) { variant_tag = i; @@ -4436,9 +4436,7 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { case (ast.item_tag(_, ?variants, ?tps, ?tag_id)) { auto vi = new_def_hash[uint](); auto navi = new_def_hash[uint](); - let vec[tup(ast.def_id,arity)] variant_info = vec(); cx.tags.insert(tag_id, @rec(th=mk_type_handle(), - mutable variants=variant_info, mutable size=0u, ty_params=tps)); cx.items.insert(tag_id, i); @@ -4502,10 +4500,8 @@ fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { auto max_size = 0u; auto info = cx.tags.get(tag_id); - let vec[tup(ast.def_id,arity)] variant_info = vec(); for (ast.variant variant in variants) { - auto arity_info; if (_vec.len[ast.variant_arg](variant.args) > 0u) { auto llvariantty = type_of_variant(cx, variant); auto align = @@ -4516,16 +4512,9 @@ fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { llvariantty) as uint; if (max_align < align) { max_align = align; } if (max_size < size) { max_size = size; } - - arity_info = n_ary; - } else { - arity_info = nullary; } - - variant_info += vec(tup(variant.id, arity_info)); } - info.variants = variant_info; info.size = max_size; // FIXME: alignment is wrong here, manually insert padding I @@ -4566,28 +4555,24 @@ fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt { auto union_ty = elts.(1); auto i = 0u; - while (i < _vec.len[tup(ast.def_id,arity)](info.variants)) { - auto variant_info = info.variants.(i); - alt (variant_info._1) { - case (nullary) { - // Nullary tags become constants. - auto union_val = C_zero_byte_arr(info.size as uint); - auto val = C_struct(vec(C_int(i as int), union_val)); - - // FIXME: better name - auto gvar = llvm.LLVMAddGlobal(cx.llmod, val_ty(val), - _str.buf("tag")); - llvm.LLVMSetInitializer(gvar, val); - llvm.LLVMSetGlobalConstant(gvar, True); - llvm.LLVMSetLinkage(gvar, - lib.llvm.LLVMPrivateLinkage - as llvm.Linkage); - cx.item_ids.insert(variant_info._0, gvar); - } - case (n_ary) { - // N-ary tags are treated as functions and generated - // later. - } + auto n_variants = _vec.len[ast.variant](variants); + while (i < n_variants) { + auto variant = variants.(i); + if (_vec.len[ast.variant_arg](variant.args) == 0u) { + // Nullary tags become constants. (N-ary tags are treated + // as functions and generated later.) + + auto union_val = C_zero_byte_arr(info.size as uint); + auto val = C_struct(vec(C_int(i as int), union_val)); + + // FIXME: better name + auto gvar = llvm.LLVMAddGlobal(cx.llmod, val_ty(val), + _str.buf("tag")); + llvm.LLVMSetInitializer(gvar, val); + llvm.LLVMSetGlobalConstant(gvar, True); + llvm.LLVMSetLinkage(gvar, lib.llvm.LLVMPrivateLinkage + as llvm.Linkage); + cx.item_ids.insert(variant.id, gvar); } i += 1u; -- cgit v1.2.3 From e37db13b02557b887de295a63b4b96021042ccde Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 25 Feb 2011 18:24:58 -0800 Subject: rustc: Eliminate the "ty_params" field from the tag info --- src/comp/middle/trans.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 3f9c770e..b70568b4 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -60,9 +60,7 @@ type glue_fns = rec(ValueRef activate_glue, ValueRef bzero_glue); tag arity { nullary; n_ary; } -type tag_info = rec(type_handle th, - mutable uint size, - vec[ast.ty_param] ty_params); +type tag_info = rec(type_handle th, mutable uint size); state type crate_ctxt = rec(session.session sess, ModuleRef llmod, @@ -1456,6 +1454,15 @@ fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef { ret T_struct(lltys); } +// Returns the type parameters of a tag. +fn tag_ty_params(@crate_ctxt cx, ast.def_id id) -> vec[ast.ty_param] { + check (cx.items.contains_key(id)); + alt (cx.items.get(id).node) { + case (ast.item_tag(_, _, ?tps, _)) { ret tps; } + } + fail; // not reached +} + // Returns the variants in a tag. fn tag_variants(@crate_ctxt cx, ast.def_id id) -> vec[ast.variant] { check (cx.items.contains_key(id)); @@ -1551,13 +1558,15 @@ fn iter_structural_ty(@block_ctxt cx, auto llvarp = variant_cx.build. TruncOrBitCast(llunion_ptr, T_ptr(llvarty)); + auto ty_params = tag_ty_params(cx.fcx.ccx, tid); + auto j = 0u; for (ty.arg a in args) { auto v = vec(C_int(0), C_int(j as int)); auto llfldp = variant_cx.build.GEP(llvarp, v); auto ty_subst = ty.substitute_ty_params( - info.ty_params, tps, a.ty); + ty_params, tps, a.ty); auto llfld = load_scalar_or_boxed(variant_cx, @@ -4437,8 +4446,7 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { auto vi = new_def_hash[uint](); auto navi = new_def_hash[uint](); cx.tags.insert(tag_id, @rec(th=mk_type_handle(), - mutable size=0u, - ty_params=tps)); + mutable size=0u)); cx.items.insert(tag_id, i); } -- cgit v1.2.3 From 0120571e90a68befb03892c63c470d0923d425c4 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 25 Feb 2011 19:42:26 -0800 Subject: rustc: Make the tag info table keyed by both tag ID and type parameter. Also fix a bug that was causing all tags to compare equal. --- src/comp/middle/trans.rs | 33 +++++++++++++++++++++------------ src/comp/middle/ty.rs | 5 +++-- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index b70568b4..fb916f00 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -74,7 +74,7 @@ state type crate_ctxt = rec(session.session sess, hashmap[ast.def_id, @ast.item] items, hashmap[ast.def_id, @ast.native_item] native_items, - hashmap[ast.def_id, @tag_info] tags, + hashmap[@ty.t, @tag_info] tags, hashmap[ast.def_id, ValueRef] fn_pairs, hashmap[ast.def_id, ValueRef] consts, hashmap[ast.def_id,()] obj_methods, @@ -543,7 +543,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { case (ty.ty_char) { llty = T_char(); } case (ty.ty_str) { llty = T_ptr(T_str()); } case (ty.ty_tag(?tag_id, _)) { - llty = llvm.LLVMResolveTypeHandle(cx.tags.get(tag_id).th.llth); + llty = llvm.LLVMResolveTypeHandle(cx.tags.get(t).th.llth); } case (ty.ty_box(?t)) { llty = T_ptr(T_box(type_of_inner(cx, t))); @@ -1472,6 +1472,14 @@ fn tag_variants(@crate_ctxt cx, ast.def_id id) -> vec[ast.variant] { fail; // not reached } +// Returns a new plain tag type of the given ID with no type parameters. Don't +// use this function in new code; it's a hack to keep things working for now. +fn mk_plain_tag(ast.def_id tid) -> @ty.t { + let vec[@ty.t] tps = vec(); + ret ty.plain_ty(ty.ty_tag(tid, tps)); +} + + type val_and_ty_fn = fn(@block_ctxt cx, ValueRef v, @ty.t t) -> result; // Iterates through the elements of a structural type. @@ -1521,8 +1529,7 @@ fn iter_structural_ty(@block_ctxt cx, } } case (ty.ty_tag(?tid, ?tps)) { - check (cx.fcx.ccx.tags.contains_key(tid)); - auto info = cx.fcx.ccx.tags.get(tid); + auto info = cx.fcx.ccx.tags.get(mk_plain_tag(tid)); auto variants = tag_variants(cx.fcx.ccx, tid); auto n_variants = _vec.len[ast.variant](variants); @@ -2591,7 +2598,6 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, ret lval_generic_fn(cx, ty.item_ty(fn_item), did, ann); } case (ast.def_variant(?tid, ?vid)) { - check (cx.fcx.ccx.tags.contains_key(tid)); if (cx.fcx.ccx.fn_pairs.contains_key(vid)) { check (cx.fcx.ccx.items.contains_key(tid)); auto tag_item = cx.fcx.ccx.items.get(tid); @@ -4247,7 +4253,9 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, auto arg_tys = arg_tys_of_fn(variant.ann); copy_args_to_allocas(bcx, none[TypeRef], fn_args, arg_tys); - auto info = cx.tags.get(tag_id); + // FIXME: This is wrong for generic tags. We should be dynamically + // computing "size" below based on the tydescs passed in. + auto info = cx.tags.get(mk_plain_tag(tag_id)); auto lltagty = T_struct(vec(T_int(), T_array(T_i8(), info.size))); @@ -4445,8 +4453,8 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { case (ast.item_tag(_, ?variants, ?tps, ?tag_id)) { auto vi = new_def_hash[uint](); auto navi = new_def_hash[uint](); - cx.tags.insert(tag_id, @rec(th=mk_type_handle(), - mutable size=0u)); + cx.tags.insert(mk_plain_tag(tag_id), @rec(th=mk_type_handle(), + mutable size=0u)); cx.items.insert(tag_id, i); } @@ -4507,7 +4515,7 @@ fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { auto max_align = 0u; auto max_size = 0u; - auto info = cx.tags.get(tag_id); + auto info = cx.tags.get(mk_plain_tag(tag_id)); for (ast.variant variant in variants) { if (_vec.len[ast.variant_arg](variant.args) > 0u) { @@ -4528,7 +4536,7 @@ fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { // FIXME: alignment is wrong here, manually insert padding I // guess :( auto tag_ty = T_struct(vec(T_int(), T_array(T_i8(), max_size))); - auto th = cx.tags.get(tag_id).th.llth; + auto th = info.th.llth; llvm.LLVMRefineType(llvm.LLVMResolveTypeHandle(th), tag_ty); } case (_) { @@ -4554,7 +4562,7 @@ fn resolve_tag_types(@crate_ctxt cx, @ast.crate crate) { fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt { alt (it.node) { case (ast.item_tag(_, ?variants, _, ?tag_id)) { - auto info = cx.tags.get(tag_id); + auto info = cx.tags.get(mk_plain_tag(tag_id)); auto tag_ty = llvm.LLVMResolveTypeHandle(info.th.llth); check (llvm.LLVMCountStructElementTypes(tag_ty) == 2u); @@ -4924,6 +4932,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, auto glues = make_glues(llmod, tn); auto hasher = ty.hash_ty; auto eqer = ty.eq_ty; + auto tags = map.mk_hashmap[@ty.t,@tag_info](hasher, eqer); auto tydescs = map.mk_hashmap[@ty.t,ValueRef](hasher, eqer); let vec[ast.ty_param] obj_typarams = vec(); let vec[ast.obj_field] obj_fields = vec(); @@ -4939,7 +4948,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, item_ids = new_def_hash[ValueRef](), items = new_def_hash[@ast.item](), native_items = new_def_hash[@ast.native_item](), - tags = new_def_hash[@tag_info](), + tags = tags, fn_pairs = new_def_hash[ValueRef](), consts = new_def_hash[ValueRef](), obj_methods = new_def_hash[()](), diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index f19c2997..25ef8709 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -247,9 +247,10 @@ fn ty_to_str(&@t typ) -> str { s = "rec(" + _str.connect(strs, ",") + ")"; } - case (ty_tag(_, ?tps)) { + case (ty_tag(?id, ?tps)) { // The user should never see this if the cname is set properly! - s = ""; + s = ""; if (_vec.len[@t](tps) > 0u) { auto f = ty_to_str; auto strs = _vec.map[@t,str](f, tps); -- cgit v1.2.3 From 4ac4d03f0cac829650f7a297162d070de53c6455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Mon, 28 Feb 2011 10:37:49 -0500 Subject: Update the function declarations with rust abi. A cdecl fn write(int fd, rustrt.vbuf buf, uint count) -> int; compiles to declare i32 @write(i32, i8*, i32) and a rust fn vec_buf[T](vec[T] v, uint offset) -> vbuf; compiles to declare i8* @vec_buf(%task*, %tydesc*, %"vec[]", i32) which I think is the correct declaration for both :-) --- src/comp/middle/trans.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index fb916f00..3564b1b3 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -513,7 +513,18 @@ fn type_of_fn(@crate_ctxt cx, fn type_of_native_fn(@crate_ctxt cx, ast.native_abi abi, vec[ty.arg] inputs, @ty.t output) -> TypeRef { - let vec[TypeRef] atys = type_of_explicit_args(cx, inputs); + let vec[TypeRef] atys = vec(); + if (abi == ast.native_abi_rust) { + atys += T_taskptr(cx.tn); + auto t = ty.ty_native_fn(abi, inputs, output); + auto ty_param_count = ty.count_ty_params(plain_ty(t)); + auto i = 0u; + while (i < ty_param_count) { + atys += T_ptr(T_tydesc(cx.tn)); + i += 1u; + } + } + atys += type_of_explicit_args(cx, inputs); ret T_fn(atys, type_of_inner(cx, output)); } -- cgit v1.2.3 From a172f5aef5f7d26fba9dbf94a1ade60d6d62ba74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Mon, 28 Feb 2011 17:33:46 -0500 Subject: Declare wrappers to the native functions and use those to create the fn/closure pairs. Disable native2.rs for now as we are not yet defining the wrappers and it fails to link. --- src/Makefile | 1 + src/comp/middle/trans.rs | 32 ++++++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/Makefile b/src/Makefile index e189c8d0..6659297e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -491,6 +491,7 @@ TEST_XFAILS_RUSTC := $(CONST_TAG_XFAILS) \ mlist-cycle.rs \ mlist.rs \ mutable-alias-vec.rs \ + native2.rs \ native-opaque-type.rs \ obj-as.rs \ obj-dtor.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 3564b1b3..189c742c 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4395,6 +4395,12 @@ fn decl_fn_and_pair(@crate_ctxt cx, // Declare the global constant pair that points to it. let str ps = cx.names.next("_rust_" + kind + "_pair") + sep() + name; + + register_fn_pair(cx, ps, llpairty, llfn, id); +} + +fn register_fn_pair(@crate_ctxt cx, str ps, TypeRef llpairty, ValueRef llfn, + ast.def_id id) { let ValueRef gvar = llvm.LLVMAddGlobal(cx.llmod, llpairty, _str.buf(ps)); auto pair = C_struct(vec(llfn, @@ -4410,16 +4416,34 @@ fn decl_fn_and_pair(@crate_ctxt cx, cx.fn_pairs.insert(id, gvar); } +fn native_fn_wrapper_type(@crate_ctxt cx, &ast.ann ann) -> TypeRef { + auto x = node_ann_type(cx, ann); + alt (x.struct) { + case (ty.ty_native_fn(?abi, ?args, ?out)) { + ret type_of_fn(cx, ast.proto_fn, args, out); + } + } + fail; +} + fn decl_native_fn_and_pair(@crate_ctxt cx, str name, &ast.ann ann, ast.def_id id) { + // Declare the wrapper. + auto wrapper_type = native_fn_wrapper_type(cx, ann); + let str s = cx.names.next("_rust_wrapper") + sep() + name; + let ValueRef wrapper_fn = decl_fastcall_fn(cx.llmod, s, wrapper_type); - auto llpairty = node_type(cx, ann); - auto llfty = get_pair_fn_ty(llpairty); + // Declare the global constant pair that points to it. + auto wrapper_pair_type = T_fn_pair(cx.tn, wrapper_type); + let str ps = cx.names.next("_rust_wrapper_pair") + sep() + name; - let ValueRef llfn = decl_cdecl_fn(cx.llmod, name, llfty); - cx.item_ids.insert(id, llfn); + register_fn_pair(cx, ps, wrapper_pair_type, wrapper_fn, id); + + // Declare the function itself. + auto llfty = get_pair_fn_ty(node_type(cx, ann)); + decl_cdecl_fn(cx.llmod, name, llfty); } fn collect_native_item(&@crate_ctxt cx, @ast.native_item i) -> @crate_ctxt { -- cgit v1.2.3 From 86309ed3ea896473641c9cdeadf16b02931b8ac8 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 28 Feb 2011 16:08:05 -0800 Subject: rustc: Write tag variant discriminants into the crate as integer constants --- src/comp/middle/trans.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 189c742c..b2ef0f16 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4609,12 +4609,26 @@ fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt { auto n_variants = _vec.len[ast.variant](variants); while (i < n_variants) { auto variant = variants.(i); + + auto discrim_val = C_int(i as int); + + // FIXME: better name. + auto discrim_gvar = llvm.LLVMAddGlobal(cx.llmod, T_int(), + _str.buf("tag_discrim")); + + // FIXME: Eventually we do want to export these, but we need + // to figure out what name they get first! + llvm.LLVMSetInitializer(discrim_gvar, discrim_val); + llvm.LLVMSetGlobalConstant(discrim_gvar, True); + llvm.LLVMSetLinkage(discrim_gvar, lib.llvm.LLVMPrivateLinkage + as llvm.Linkage); + if (_vec.len[ast.variant_arg](variant.args) == 0u) { // Nullary tags become constants. (N-ary tags are treated // as functions and generated later.) auto union_val = C_zero_byte_arr(info.size as uint); - auto val = C_struct(vec(C_int(i as int), union_val)); + auto val = C_struct(vec(discrim_val, union_val)); // FIXME: better name auto gvar = llvm.LLVMAddGlobal(cx.llmod, val_ty(val), -- cgit v1.2.3 From 1291cc2df90c36eee8642048e1bf1b69a690781f Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 28 Feb 2011 16:36:08 -0800 Subject: Groundwork for structural comparison. Still lacking the actual loop that does it. --- src/comp/lib/llvm.rs | 23 ++++++++- src/comp/middle/trans.rs | 121 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 118 insertions(+), 26 deletions(-) diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs index 751507d6..f75bdbe1 100644 --- a/src/comp/lib/llvm.rs +++ b/src/comp/lib/llvm.rs @@ -76,6 +76,25 @@ const uint LLVMIntSLT = 40u; const uint LLVMIntSLE = 41u; +// Consts for the LLVM RealPredicate type, pre-case to uint. +// FIXME: as above. + +const uint LLVMRealOEQ = 1u; +const uint LLVMRealOGT = 2u; +const uint LLVMRealOGE = 3u; +const uint LLVMRealOLT = 4u; +const uint LLVMRealOLE = 5u; +const uint LLVMRealONE = 6u; + +const uint LLVMRealORD = 7u; +const uint LLVMRealUNO = 8u; +const uint LLVMRealUEQ = 9u; +const uint LLVMRealUGT = 10u; +const uint LLVMRealUGE = 11u; +const uint LLVMRealULT = 12u; +const uint LLVMRealULE = 13u; +const uint LLVMRealUNE = 14u; + native mod llvm = llvm_lib { type ModuleRef; @@ -657,7 +676,7 @@ native mod llvm = llvm_lib { fn LLVMBuildICmp(BuilderRef B, uint Op, ValueRef LHS, ValueRef RHS, sbuf Name) -> ValueRef; - fn LLVMBuildFCmp(BuilderRef B, RealPredicate Op, + fn LLVMBuildFCmp(BuilderRef B, uint Op, ValueRef LHS, ValueRef RHS, sbuf Name) -> ValueRef; @@ -1034,7 +1053,7 @@ obj builder(BuilderRef B) { ret llvm.LLVMBuildICmp(B, Op, LHS, RHS, _str.buf("")); } - fn FCmp(RealPredicate Op, ValueRef LHS, ValueRef RHS) -> ValueRef { + fn FCmp(uint Op, ValueRef LHS, ValueRef RHS) -> ValueRef { ret llvm.LLVMBuildFCmp(B, Op, LHS, RHS, _str.buf("")); } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index b2ef0f16..4a45beea 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1958,10 +1958,66 @@ fn trans_unary(@block_ctxt cx, ast.unop op, fail; } -// FIXME: implement proper structural comparison. +fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t t, + ValueRef lhs, ValueRef rhs) -> result { + + if (ty.type_is_scalar(t)) { + ret res(cx, trans_scalar_compare(cx, op, t, lhs, rhs)); + + } else if (ty.type_is_structural(t)) { + auto scx = new_sub_block_ctxt(cx, "structural compare body"); + auto next = new_sub_block_ctxt(cx, "structural compare completion"); + cx.build.Br(scx.llbb); + + // Start with the assumptioin that our predicate holds. + auto flag = scx.build.Alloca(T_i1()); + scx.build.Store(C_integral(1, T_i1()), flag); + + // Attempt to prove otherwise by inverting the sense of the comparison + // on each inner element and bailing if any succeed. + + // FIXME: finish this. + + auto v = scx.build.Load(flag); + scx.build.Br(next.llbb); + ret res(next, v); + + } else { + // FIXME: compare vec, str, box? + cx.fcx.ccx.sess.unimpl("type in trans_compare"); + ret res(cx, C_bool(false)); + } +} + +fn trans_scalar_compare(@block_ctxt cx, ast.binop op, @ty.t t, + ValueRef lhs, ValueRef rhs) -> ValueRef { + if (ty.type_is_fp(t)) { + ret trans_fp_compare(cx, op, t, lhs, rhs); + } else { + ret trans_integral_compare(cx, op, t, lhs, rhs); + } +} + +fn trans_fp_compare(@block_ctxt cx, ast.binop op, @ty.t fptype, + ValueRef lhs, ValueRef rhs) -> ValueRef { -fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t intype, - ValueRef lhs, ValueRef rhs) -> ValueRef { + auto cmp = lib.llvm.LLVMIntEQ; + alt (op) { + // FIXME: possibly use the unordered-or-< predicates here, + // for now we're only going with ordered-and-< style (no NaNs). + case (ast.eq) { cmp = lib.llvm.LLVMRealOEQ; } + case (ast.ne) { cmp = lib.llvm.LLVMRealONE; } + case (ast.lt) { cmp = lib.llvm.LLVMRealOLT; } + case (ast.gt) { cmp = lib.llvm.LLVMRealOGT; } + case (ast.le) { cmp = lib.llvm.LLVMRealOLE; } + case (ast.ge) { cmp = lib.llvm.LLVMRealOGE; } + } + + ret cx.build.FCmp(cmp, lhs, rhs); +} + +fn trans_integral_compare(@block_ctxt cx, ast.binop op, @ty.t intype, + ValueRef lhs, ValueRef rhs) -> ValueRef { auto cmp = lib.llvm.LLVMIntEQ; alt (op) { case (ast.eq) { cmp = lib.llvm.LLVMIntEQ; } @@ -2000,34 +2056,34 @@ fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t intype, } fn trans_eager_binop(@block_ctxt cx, ast.binop op, @ty.t intype, - ValueRef lhs, ValueRef rhs) -> ValueRef { + ValueRef lhs, ValueRef rhs) -> result { alt (op) { - case (ast.add) { ret cx.build.Add(lhs, rhs); } - case (ast.sub) { ret cx.build.Sub(lhs, rhs); } + case (ast.add) { ret res(cx, cx.build.Add(lhs, rhs)); } + case (ast.sub) { ret res(cx, cx.build.Sub(lhs, rhs)); } - case (ast.mul) { ret cx.build.Mul(lhs, rhs); } + case (ast.mul) { ret res(cx, cx.build.Mul(lhs, rhs)); } case (ast.div) { if (ty.type_is_signed(intype)) { - ret cx.build.SDiv(lhs, rhs); + ret res(cx, cx.build.SDiv(lhs, rhs)); } else { - ret cx.build.UDiv(lhs, rhs); + ret res(cx, cx.build.UDiv(lhs, rhs)); } } case (ast.rem) { if (ty.type_is_signed(intype)) { - ret cx.build.SRem(lhs, rhs); + ret res(cx, cx.build.SRem(lhs, rhs)); } else { - ret cx.build.URem(lhs, rhs); + ret res(cx, cx.build.URem(lhs, rhs)); } } - case (ast.bitor) { ret cx.build.Or(lhs, rhs); } - case (ast.bitand) { ret cx.build.And(lhs, rhs); } - case (ast.bitxor) { ret cx.build.Xor(lhs, rhs); } - case (ast.lsl) { ret cx.build.Shl(lhs, rhs); } - case (ast.lsr) { ret cx.build.LShr(lhs, rhs); } - case (ast.asr) { ret cx.build.AShr(lhs, rhs); } + case (ast.bitor) { ret res(cx, cx.build.Or(lhs, rhs)); } + case (ast.bitand) { ret res(cx, cx.build.And(lhs, rhs)); } + case (ast.bitxor) { ret res(cx, cx.build.Xor(lhs, rhs)); } + case (ast.lsl) { ret res(cx, cx.build.Shl(lhs, rhs)); } + case (ast.lsr) { ret res(cx, cx.build.LShr(lhs, rhs)); } + case (ast.asr) { ret res(cx, cx.build.AShr(lhs, rhs)); } case (_) { ret trans_compare(cx, op, intype, lhs, rhs); } @@ -2055,6 +2111,21 @@ fn autoderef(@block_ctxt cx, ValueRef v, @ty.t t) -> result { } } +fn autoderefed_ty(@ty.t t) -> @ty.t { + let @ty.t t1 = t; + + while (true) { + alt (t1.struct) { + case (ty.ty_box(?inner)) { + t1 = inner; + } + case (_) { + ret t1; + } + } + } +} + fn trans_binary(@block_ctxt cx, ast.binop op, @ast.expr a, @ast.expr b) -> result { @@ -2109,8 +2180,9 @@ fn trans_binary(@block_ctxt cx, ast.binop op, auto rhs = trans_expr(lhs.bcx, b); auto rhty = ty.expr_ty(b); rhs = autoderef(rhs.bcx, rhs.val, rhty); - ret res(rhs.bcx, trans_eager_binop(rhs.bcx, op, lhty, - lhs.val, rhs.val)); + ret trans_eager_binop(rhs.bcx, op, + autoderefed_ty(lhty), + lhs.val, rhs.val); } } fail; @@ -2399,8 +2471,8 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, auto lltype = ty.ann_to_type(ann); auto lleq = trans_compare(cx, ast.eq, lltype, llval, lllit); - auto matched_cx = new_sub_block_ctxt(cx, "matched_cx"); - cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb); + auto matched_cx = new_sub_block_ctxt(lleq.bcx, "matched_cx"); + lleq.bcx.build.CondBr(lleq.val, matched_cx.llbb, next_cx.llbb); ret res(matched_cx, llval); } @@ -2656,8 +2728,9 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, fn trans_field(@block_ctxt cx, &ast.span sp, @ast.expr base, &ast.ident field, &ast.ann ann) -> lval_result { auto r = trans_expr(cx, base); - r = autoderef(r.bcx, r.val, ty.expr_ty(base)); auto t = ty.expr_ty(base); + r = autoderef(r.bcx, r.val, t); + t = autoderefed_ty(t); alt (t.struct) { case (ty.ty_tup(?fields)) { let uint ix = ty.field_num(cx.fcx.ccx.sess, sp, field); @@ -3439,8 +3512,8 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { auto v = trans_eager_binop(rhs_res.bcx, op, t, lhs_val, rhs_res.val); // FIXME: calculate copy init-ness in typestate. - ret copy_ty(rhs_res.bcx, DROP_EXISTING, - lhs_res.res.val, v, t); + ret copy_ty(v.bcx, DROP_EXISTING, + lhs_res.res.val, v.val, t); } case (ast.expr_bind(?f, ?args, ?ann)) { -- cgit v1.2.3 From d08f3a1c702c337c494bbc03d8bed9664ac1dddf Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 28 Feb 2011 17:49:26 -0800 Subject: More complete sketch of structural compare. Still not quite working. --- src/comp/middle/trans.rs | 153 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 115 insertions(+), 38 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4a45beea..8dc4efb7 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1493,27 +1493,50 @@ fn mk_plain_tag(ast.def_id tid) -> @ty.t { type val_and_ty_fn = fn(@block_ctxt cx, ValueRef v, @ty.t t) -> result; +type val_pair_and_ty_fn = + fn(@block_ctxt cx, ValueRef av, ValueRef bv, @ty.t t) -> result; + // Iterates through the elements of a structural type. fn iter_structural_ty(@block_ctxt cx, ValueRef v, @ty.t t, val_and_ty_fn f) -> result { + fn adaptor_fn(val_and_ty_fn f, + @block_ctxt cx, + ValueRef av, + ValueRef bv, + @ty.t t) -> result { + ret f(cx, av, t); + } + be iter_structural_ty_full(cx, v, v, t, + bind adaptor_fn(f, _, _, _, _)); +} + + +fn iter_structural_ty_full(@block_ctxt cx, + ValueRef av, + ValueRef bv, + @ty.t t, + val_pair_and_ty_fn f) + -> result { let result r = res(cx, C_nil()); fn iter_boxpp(@block_ctxt cx, - ValueRef box_cell, - val_and_ty_fn f) -> result { - auto box_ptr = cx.build.Load(box_cell); + ValueRef box_a_cell, + ValueRef box_b_cell, + val_pair_and_ty_fn f) -> result { + auto box_a_ptr = cx.build.Load(box_a_cell); + auto box_b_ptr = cx.build.Load(box_b_cell); auto tnil = plain_ty(ty.ty_nil); auto tbox = 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"); - auto null_test = cx.build.IsNull(box_ptr); + auto null_test = cx.build.IsNull(box_a_ptr); cx.build.CondBr(null_test, next_cx.llbb, inner_cx.llbb); - auto r = f(inner_cx, box_ptr, tbox); + auto r = f(inner_cx, box_a_ptr, box_b_ptr, tbox); r.bcx.build.Br(next_cx.llbb); ret res(next_cx, r.val); } @@ -1522,9 +1545,11 @@ fn iter_structural_ty(@block_ctxt cx, case (ty.ty_tup(?args)) { let int i = 0; for (@ty.t arg in args) { - auto elt = r.bcx.build.GEP(v, vec(C_int(0), C_int(i))); + auto elt_a = r.bcx.build.GEP(av, vec(C_int(0), C_int(i))); + auto elt_b = r.bcx.build.GEP(bv, vec(C_int(0), C_int(i))); r = f(r.bcx, - load_scalar_or_boxed(r.bcx, elt, arg), + load_scalar_or_boxed(r.bcx, elt_a, arg), + load_scalar_or_boxed(r.bcx, elt_b, arg), arg); i += 1; } @@ -1532,9 +1557,11 @@ fn iter_structural_ty(@block_ctxt cx, case (ty.ty_rec(?fields)) { let int i = 0; for (ty.field fld in fields) { - auto llfld = r.bcx.build.GEP(v, vec(C_int(0), C_int(i))); + auto llfld_a = r.bcx.build.GEP(av, vec(C_int(0), C_int(i))); + auto llfld_b = r.bcx.build.GEP(bv, vec(C_int(0), C_int(i))); r = f(r.bcx, - load_scalar_or_boxed(r.bcx, llfld, fld.ty), + load_scalar_or_boxed(r.bcx, llfld_a, fld.ty), + load_scalar_or_boxed(r.bcx, llfld_b, fld.ty), fld.ty); i += 1; } @@ -1545,53 +1572,69 @@ fn iter_structural_ty(@block_ctxt cx, auto variants = tag_variants(cx.fcx.ccx, tid); auto n_variants = _vec.len[ast.variant](variants); - auto lldiscrim_ptr = cx.build.GEP(v, vec(C_int(0), C_int(0))); - auto llunion_ptr = cx.build.GEP(v, vec(C_int(0), C_int(1))); - auto lldiscrim = cx.build.Load(lldiscrim_ptr); + auto lldiscrim_a_ptr = cx.build.GEP(av, vec(C_int(0), C_int(0))); + auto llunion_a_ptr = cx.build.GEP(av, vec(C_int(0), C_int(1))); + auto lldiscrim_a = cx.build.Load(lldiscrim_a_ptr); + + auto lldiscrim_b_ptr = cx.build.GEP(bv, vec(C_int(0), C_int(0))); + auto llunion_b_ptr = cx.build.GEP(bv, vec(C_int(0), C_int(1))); + auto lldiscrim_b = cx.build.Load(lldiscrim_b_ptr); auto unr_cx = new_sub_block_ctxt(cx, "tag-iter-unr"); unr_cx.build.Unreachable(); - auto llswitch = cx.build.Switch(lldiscrim, unr_cx.llbb, - n_variants); + auto llswitch = cx.build.Switch(lldiscrim_a, unr_cx.llbb, + n_variants); auto next_cx = new_sub_block_ctxt(cx, "tag-iter-next"); auto i = 0u; for (ast.variant variant in variants) { - auto variant_cx = new_sub_block_ctxt(cx, "tag-iter-variant-" + + auto variant_cx = new_sub_block_ctxt(cx, + "tag-iter-variant-" + _uint.to_str(i, 10u)); llvm.LLVMAddCase(llswitch, C_int(i as int), variant_cx.llbb); if (_vec.len[ast.variant_arg](variant.args) > 0u) { // N-ary variant. - let vec[ValueRef] vals = vec(C_int(0), C_int(1), - C_int(i as int)); - auto llvar = variant_cx.build.GEP(v, vals); auto llvarty = type_of_variant(cx.fcx.ccx, variants.(i)); auto fn_ty = ty.ann_to_type(variants.(i).ann); alt (fn_ty.struct) { case (ty.ty_fn(_, ?args, _)) { - auto llvarp = variant_cx.build. - TruncOrBitCast(llunion_ptr, T_ptr(llvarty)); + auto llvarp_a = variant_cx.build. + TruncOrBitCast(llunion_a_ptr, T_ptr(llvarty)); + + auto llvarp_b = variant_cx.build. + TruncOrBitCast(llunion_b_ptr, T_ptr(llvarty)); auto ty_params = tag_ty_params(cx.fcx.ccx, tid); auto j = 0u; for (ty.arg a in args) { auto v = vec(C_int(0), C_int(j as int)); - auto llfldp = variant_cx.build.GEP(llvarp, v); + + auto llfldp_a = + variant_cx.build.GEP(llvarp_a, v); + + auto llfldp_b = + variant_cx.build.GEP(llvarp_b, v); auto ty_subst = ty.substitute_ty_params( ty_params, tps, a.ty); - auto llfld = + auto llfld_a = load_scalar_or_boxed(variant_cx, - llfldp, + llfldp_a, ty_subst); - auto res = f(variant_cx, llfld, ty_subst); + auto llfld_b = + load_scalar_or_boxed(variant_cx, + llfldp_b, + ty_subst); + + auto res = f(variant_cx, + llfld_a, llfld_b, ty_subst); variant_cx = res.bcx; j += 1u; } @@ -1611,21 +1654,29 @@ fn iter_structural_ty(@block_ctxt cx, ret res(next_cx, C_nil()); } case (ty.ty_fn(_,_,_)) { - auto box_cell = - cx.build.GEP(v, + auto box_cell_a = + cx.build.GEP(av, + vec(C_int(0), + C_int(abi.fn_field_box))); + auto box_cell_b = + cx.build.GEP(bv, vec(C_int(0), C_int(abi.fn_field_box))); - ret iter_boxpp(cx, box_cell, f); + ret iter_boxpp(cx, box_cell_a, box_cell_b, f); } case (ty.ty_obj(_)) { - auto box_cell = - cx.build.GEP(v, + auto box_cell_a = + cx.build.GEP(av, + vec(C_int(0), + C_int(abi.obj_field_box))); + auto box_cell_b = + cx.build.GEP(bv, vec(C_int(0), C_int(abi.obj_field_box))); - ret iter_boxpp(cx, box_cell, f); + ret iter_boxpp(cx, box_cell_a, box_cell_b, f); } case (_) { - cx.fcx.ccx.sess.unimpl("type in iter_structural_ty"); + cx.fcx.ccx.sess.unimpl("type in iter_structural_ty_full"); } } ret r; @@ -1965,21 +2016,47 @@ fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t t, ret res(cx, trans_scalar_compare(cx, op, t, lhs, rhs)); } else if (ty.type_is_structural(t)) { - auto scx = new_sub_block_ctxt(cx, "structural compare body"); - auto next = new_sub_block_ctxt(cx, "structural compare completion"); + auto scx = new_sub_block_ctxt(cx, "structural compare start"); + auto next = new_sub_block_ctxt(cx, "structural compare end"); cx.build.Br(scx.llbb); // Start with the assumptioin that our predicate holds. auto flag = scx.build.Alloca(T_i1()); scx.build.Store(C_integral(1, T_i1()), flag); - // Attempt to prove otherwise by inverting the sense of the comparison - // on each inner element and bailing if any succeed. + // Attempt to prove otherwise by assuming true, comparing each element + // and writing 0 + early-exiting if any comparisons fail. + + fn inner(@block_ctxt next_cx, + ValueRef flag, + ast.binop op, + @block_ctxt cx, + ValueRef av, + ValueRef bv, + @ty.t t) -> result { + // Compare av op bv + auto cnt_cx = new_sub_block_ctxt(cx, "continue comparison"); + auto stop_cx = new_sub_block_ctxt(cx, "stop comparison"); + + auto r = trans_compare(cx, op, t, av, bv); + + // if true, then carry on, else write 0 to flag, branch to 'next'. + r.bcx.build.CondBr(r.val, cnt_cx.llbb, stop_cx.llbb); + stop_cx.build.Store(C_integral(0, T_i1()), flag); + stop_cx.build.Br(next_cx.llbb); + + ret res(cnt_cx, C_nil()); + } + + // FIXME: this is wrong for tag types; need to confirm discriminants + // are equal before blindly walking over elements. - // FIXME: finish this. + auto r = iter_structural_ty_full(scx, lhs, rhs, t, + bind inner(next, flag, op, + _, _, _, _)); - auto v = scx.build.Load(flag); - scx.build.Br(next.llbb); + r.bcx.build.Br(next.llbb); + auto v = next.build.Load(flag); ret res(next, v); } else { -- cgit v1.2.3 From 687d328d7cf3fdec84ab4f07f86262dc5001738a Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 28 Feb 2011 18:26:14 -0800 Subject: rustc: Trivial cleanup: Remove unused "arity" tag --- src/comp/middle/trans.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 8dc4efb7..de3f99ba 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -59,7 +59,6 @@ type glue_fns = rec(ValueRef activate_glue, ValueRef memcpy_glue, ValueRef bzero_glue); -tag arity { nullary; n_ary; } type tag_info = rec(type_handle th, mutable uint size); state type crate_ctxt = rec(session.session sess, -- cgit v1.2.3 From 8d8b3d985a02153a349e72bd9840231b43c51864 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 28 Feb 2011 19:07:26 -0800 Subject: rustc: Mark tags that have subtypes with dynamic size as dynamic --- src/comp/middle/ty.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 25ef8709..8b9ef6d1 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -471,6 +471,13 @@ fn type_has_dynamic_size(@t ty) -> bool { i += 1u; } } + case (ty_tag(_, ?subtys)) { + auto i = 0u; + while (i < _vec.len[@t](subtys)) { + if (type_has_dynamic_size(subtys.(i))) { ret true; } + i += 1u; + } + } case (ty_param(_)) { ret true; } case (_) { /* fall through */ } } -- cgit v1.2.3 From f239ecb5f2e46cb4c938b6bd481ec75fe137e414 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 1 Mar 2011 12:41:41 -0800 Subject: rustc: Switch from storing nullary tags as constants to storing their discriminants --- src/comp/middle/trans.rs | 53 ++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index de3f99ba..61da7f53 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -59,7 +59,11 @@ type glue_fns = rec(ValueRef activate_glue, ValueRef memcpy_glue, ValueRef bzero_glue); -type tag_info = rec(type_handle th, mutable uint size); +type tag_info = rec( + type_handle th, + mutable uint size, + mutable @hashmap[ast.def_id,ValueRef] lldiscrims +); state type crate_ctxt = rec(session.session sess, ModuleRef llmod, @@ -2774,9 +2778,23 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, } ret lval_generic_fn(cx, tup(params, fty), vid, ann); } else { - // Nullary variants are just scalar constants. - check (cx.fcx.ccx.item_ids.contains_key(vid)); - ret lval_val(cx, cx.fcx.ccx.item_ids.get(vid)); + // Nullary variant. + auto tag_ty = node_ann_type(cx.fcx.ccx, ann); + auto info = cx.fcx.ccx.tags.get(tag_ty); + check (info.lldiscrims.contains_key(vid)); + auto lldiscrim_gv = info.lldiscrims.get(vid); + auto lldiscrim = cx.build.Load(lldiscrim_gv); + + auto alloc_result = alloc_ty(cx, tag_ty); + auto lltagblob = alloc_result.val; + auto lltagptr = alloc_result.bcx.build.PointerCast( + lltagblob, T_ptr(type_of(cx.fcx.ccx, tag_ty))); + + auto lldiscrimptr = alloc_result.bcx.build.GEP( + lltagptr, vec(C_int(0), C_int(0))); + alloc_result.bcx.build.Store(lldiscrim, lldiscrimptr); + + ret lval_val(alloc_result.bcx, lltagptr); } } case (ast.def_const(?did)) { @@ -4637,8 +4655,14 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { case (ast.item_tag(_, ?variants, ?tps, ?tag_id)) { auto vi = new_def_hash[uint](); auto navi = new_def_hash[uint](); - cx.tags.insert(mk_plain_tag(tag_id), @rec(th=mk_type_handle(), - mutable size=0u)); + + auto info = @rec( + th=mk_type_handle(), + mutable size=0u, + mutable lldiscrims=@new_def_hash[ValueRef]() + ); + + cx.tags.insert(mk_plain_tag(tag_id), info); cx.items.insert(tag_id, i); } @@ -4772,22 +4796,7 @@ fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt { llvm.LLVMSetLinkage(discrim_gvar, lib.llvm.LLVMPrivateLinkage as llvm.Linkage); - if (_vec.len[ast.variant_arg](variant.args) == 0u) { - // Nullary tags become constants. (N-ary tags are treated - // as functions and generated later.) - - auto union_val = C_zero_byte_arr(info.size as uint); - auto val = C_struct(vec(discrim_val, union_val)); - - // FIXME: better name - auto gvar = llvm.LLVMAddGlobal(cx.llmod, val_ty(val), - _str.buf("tag")); - llvm.LLVMSetInitializer(gvar, val); - llvm.LLVMSetGlobalConstant(gvar, True); - llvm.LLVMSetLinkage(gvar, lib.llvm.LLVMPrivateLinkage - as llvm.Linkage); - cx.item_ids.insert(variant.id, gvar); - } + info.lldiscrims.insert(variant.id, discrim_gvar); i += 1u; } -- cgit v1.2.3 From 7f2398e557d4b75cbf83dc88b6740e83a8d20910 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 1 Mar 2011 13:00:50 -0800 Subject: Implement structured compare for rec, tup, tag. Un-XFAIL structured-compare.rs. --- src/Makefile | 1 - src/comp/middle/trans.rs | 76 +++++++++++++++++++++++++++++++++++------------- 2 files changed, 55 insertions(+), 22 deletions(-) diff --git a/src/Makefile b/src/Makefile index 6659297e..2be8be48 100644 --- a/src/Makefile +++ b/src/Makefile @@ -505,7 +505,6 @@ TEST_XFAILS_RUSTC := $(CONST_TAG_XFAILS) \ spawn.rs \ str-append.rs \ str-concat.rs \ - structured-compare.rs \ syntax-extension-fmt.rs \ syntax-extension-shell.rs \ task-comm-0.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 61da7f53..9a650da5 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1583,24 +1583,30 @@ fn iter_structural_ty_full(@block_ctxt cx, auto llunion_b_ptr = cx.build.GEP(bv, vec(C_int(0), C_int(1))); auto lldiscrim_b = cx.build.Load(lldiscrim_b_ptr); - auto unr_cx = new_sub_block_ctxt(cx, "tag-iter-unr"); + // NB: we must hit the discriminant first so that structural + // comparison know not to proceed when the discriminants differ. + auto bcx = cx; + bcx = f(bcx, lldiscrim_a, lldiscrim_b, + plain_ty(ty.ty_int)).bcx; + + auto unr_cx = new_sub_block_ctxt(bcx, "tag-iter-unr"); unr_cx.build.Unreachable(); - auto llswitch = cx.build.Switch(lldiscrim_a, unr_cx.llbb, + auto llswitch = bcx.build.Switch(lldiscrim_a, unr_cx.llbb, n_variants); - auto next_cx = new_sub_block_ctxt(cx, "tag-iter-next"); + auto next_cx = new_sub_block_ctxt(bcx, "tag-iter-next"); auto i = 0u; for (ast.variant variant in variants) { - auto variant_cx = new_sub_block_ctxt(cx, + auto variant_cx = new_sub_block_ctxt(bcx, "tag-iter-variant-" + _uint.to_str(i, 10u)); llvm.LLVMAddCase(llswitch, C_int(i as int), variant_cx.llbb); if (_vec.len[ast.variant_arg](variant.args) > 0u) { // N-ary variant. - auto llvarty = type_of_variant(cx.fcx.ccx, variants.(i)); + auto llvarty = type_of_variant(bcx.fcx.ccx, variants.(i)); auto fn_ty = ty.ann_to_type(variants.(i).ann); alt (fn_ty.struct) { @@ -1611,7 +1617,7 @@ fn iter_structural_ty_full(@block_ctxt cx, auto llvarp_b = variant_cx.build. TruncOrBitCast(llunion_b_ptr, T_ptr(llvarty)); - auto ty_params = tag_ty_params(cx.fcx.ccx, tid); + auto ty_params = tag_ty_params(bcx.fcx.ccx, tid); auto j = 0u; for (ty.arg a in args) { @@ -2023,37 +2029,65 @@ fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t t, auto next = new_sub_block_ctxt(cx, "structural compare end"); cx.build.Br(scx.llbb); - // Start with the assumptioin that our predicate holds. + /* + * We're doing lexicographic comparison here. We start with the + * assumption that the two input elements are equal. Depending on + * operator, this means that the result is either true or false; + * equality produces 'true' for ==, <= and >=. It produces 'false' for + * !=, < and >. + * + * We then move one element at a time through the structure checking + * for pairwise element equality. If we have equality, our assumption + * about overall sequence equality is not modified, so we have to move + * to the next element. + * + * If we do not have pairwise element equality, we have reached an + * element that 'decides' the lexicographic comparison. So we exit the + * loop with a flag that indicates the true/false sense of that + * decision, by testing the element again with the operator we're + * interested in. + * + * When we're lucky, LLVM should be able to fold some of these two + * tests together (as they're applied to the same operands and in some + * cases are sometimes redundant). But we don't bother trying to + * optimize combinations like that, at this level. + */ + auto flag = scx.build.Alloca(T_i1()); - scx.build.Store(C_integral(1, T_i1()), flag); - // Attempt to prove otherwise by assuming true, comparing each element - // and writing 0 + early-exiting if any comparisons fail. + alt (op) { + // ==, <= and >= default to true if they find == all the way. + case (ast.eq) { scx.build.Store(C_integral(1, T_i1()), flag); } + case (ast.le) { scx.build.Store(C_integral(1, T_i1()), flag); } + case (ast.ge) { scx.build.Store(C_integral(1, T_i1()), flag); } + case (_) { + // ==, <= and >= default to false if they find == all the way. + scx.build.Store(C_integral(0, T_i1()), flag); + } + } - fn inner(@block_ctxt next_cx, + fn inner(@block_ctxt last_cx, ValueRef flag, ast.binop op, @block_ctxt cx, ValueRef av, ValueRef bv, @ty.t t) -> result { - // Compare av op bv + auto cnt_cx = new_sub_block_ctxt(cx, "continue comparison"); auto stop_cx = new_sub_block_ctxt(cx, "stop comparison"); - auto r = trans_compare(cx, op, t, av, bv); - - // if true, then carry on, else write 0 to flag, branch to 'next'. - r.bcx.build.CondBr(r.val, cnt_cx.llbb, stop_cx.llbb); - stop_cx.build.Store(C_integral(0, T_i1()), flag); - stop_cx.build.Br(next_cx.llbb); + // First 'eq' comparison: if so, continue to next elts. + auto eq_r = trans_compare(cx, ast.eq, t, av, bv); + eq_r.bcx.build.CondBr(eq_r.val, cnt_cx.llbb, stop_cx.llbb); + // Second 'op' comparison: find out how this elt-pair decides. + auto stop_r = trans_compare(stop_cx, op, t, av, bv); + stop_r.bcx.build.Store(stop_r.val, flag); + stop_r.bcx.build.Br(last_cx.llbb); ret res(cnt_cx, C_nil()); } - // FIXME: this is wrong for tag types; need to confirm discriminants - // are equal before blindly walking over elements. - auto r = iter_structural_ty_full(scx, lhs, rhs, t, bind inner(next, flag, op, _, _, _, _)); -- cgit v1.2.3 From 0761c5f4626153eba8478c66f93ba27e021f4dc2 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 1 Mar 2011 15:13:50 -0800 Subject: Fix typo in comment. --- src/comp/driver/rustc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index 004c9d4c..278b6873 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -38,7 +38,7 @@ fn warn_wrong_compiler() { log "This is the rust 'self-hosted' compiler."; log "The one written in rust."; log "It is currently incomplete."; - log "You may want rustboot insteaad, the compiler next door."; + log "You may want rustboot instead, the compiler next door."; } fn usage(session.session sess, str argv0) { -- cgit v1.2.3 From 348c77c31b7dcd5be85438dfcf4292f7e0951dd6 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 1 Mar 2011 15:57:55 -0800 Subject: Populate default compilation environment as in rustboot. --- src/comp/driver/rustc.rs | 38 ++++++++++++++++++++++++++++++++++---- src/comp/front/eval.rs | 2 +- src/comp/front/parser.rs | 11 +++++++++-- 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index 278b6873..69e61aa0 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -2,6 +2,7 @@ import front.parser; import front.token; +import front.eval; import middle.trans; import middle.resolve; import middle.typeck; @@ -13,6 +14,30 @@ import std.option.none; import std._str; import std._vec; +fn default_environment(session.session sess, + str argv0, + str input) -> eval.env { + + auto libc = "libc.so"; + alt (sess.get_targ_cfg().os) { + case (session.os_win32) { libc = "msvcrt.dll"; } + case (session.os_macos) { libc = "libc.dylib"; } + case (session.os_linux) { libc = "libc.so.6"; } + } + + ret + vec( + // Target bindings. + tup("target_os", eval.val_str(std.os.target_os())), + tup("target_arch", eval.val_str("x86")), + tup("target_libc", eval.val_str(libc)), + + // Build bindings. + tup("build_compiler", eval.val_str(argv0)), + tup("build_input", eval.val_str(input)) + ); +} + impure fn parse_input(session.session sess, parser.parser p, str input) -> @front.ast.crate { @@ -25,9 +50,11 @@ impure fn parse_input(session.session sess, fail; } -impure fn compile_input(session.session sess, str input, str output, +impure fn compile_input(session.session sess, + eval.env env, + str input, str output, bool shared) { - auto p = parser.new_parser(sess, 0, input); + auto p = parser.new_parser(sess, env, 0, input); auto crate = parse_input(sess, p, input); crate = resolve.resolve_crate(sess, crate); crate = typeck.check_crate(sess, crate); @@ -131,16 +158,19 @@ impure fn main(vec[str] args) { sess.err("no input filename"); } case (some[str](?ifile)) { + + auto env = default_environment(sess, args.(0), ifile); + alt (output_file) { case (none[str]) { let vec[str] parts = _str.split(ifile, '.' as u8); parts = _vec.pop[str](parts); parts += ".bc"; auto ofile = _str.concat(parts); - compile_input(sess, ifile, ofile, shared); + compile_input(sess, env, ifile, ofile, shared); } case (some[str](?ofile)) { - compile_input(sess, ifile, ofile, shared); + compile_input(sess, env, ifile, ofile, shared); } } } diff --git a/src/comp/front/eval.rs b/src/comp/front/eval.rs index ab8d5d32..cae72b1e 100644 --- a/src/comp/front/eval.rs +++ b/src/comp/front/eval.rs @@ -393,7 +393,7 @@ impure fn eval_crate_directive(parser p, auto full_path = prefix + std.os.path_sep() + file_path; - auto p0 = new_parser(p.get_session(), 0, full_path); + auto p0 = new_parser(p.get_session(), e, 0, full_path); auto m0 = parse_mod_items(p0, token.EOF); auto im = ast.item_mod(id, m0, p.next_def_id()); auto i = @spanned(cdir.span, cdir.span, im); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 32bcf6ef..4ffa6f92 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -31,15 +31,18 @@ state type parser = impure fn restrict(restriction r); fn get_restriction() -> restriction; fn get_file_type() -> file_type; + fn get_env() -> eval.env; fn get_session() -> session.session; fn get_span() -> common.span; fn next_def_id() -> ast.def_id; }; impure fn new_parser(session.session sess, + eval.env env, ast.crate_num crate, str path) -> parser { state obj stdio_parser(session.session sess, + eval.env env, file_type ftype, mutable token.token tok, mutable common.pos lo, @@ -93,6 +96,10 @@ impure fn new_parser(session.session sess, ret ftype; } + fn get_env() -> eval.env { + ret env; + } + } auto ftype = SOURCE_FILE; if (_str.ends_with(path, ".rc")) { @@ -101,7 +108,7 @@ impure fn new_parser(session.session sess, auto srdr = io.new_stdio_reader(path); auto rdr = lexer.new_reader(srdr, path); auto npos = rdr.get_curr_pos(); - ret stdio_parser(sess, ftype, lexer.next_token(rdr), + ret stdio_parser(sess, env, ftype, lexer.next_token(rdr), npos, npos, 0, UNRESTRICTED, crate, rdr); } @@ -2279,7 +2286,7 @@ impure fn parse_crate_from_crate_file(parser p) -> @ast.crate { auto hi = lo; auto prefix = std.path.dirname(lo.filename); auto cdirs = parse_crate_directives(p, token.EOF); - auto m = eval.eval_crate_directives_to_mod(p, eval.mk_env(), + auto m = eval.eval_crate_directives_to_mod(p, p.get_env(), cdirs, prefix); hi = p.get_span(); expect(p, token.EOF); -- cgit v1.2.3 From bdbaf0c7897366f17e36797e5c9fc7ef12fa9fce Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 1 Mar 2011 16:01:33 -0800 Subject: rustc: Factor out the align-elements logic in dynamic_size_of() --- src/comp/middle/trans.rs | 63 ++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9a650da5..7bdca92a 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -851,50 +851,45 @@ fn align_of(@block_ctxt cx, @ty.t t) -> result { } fn dynamic_size_of(@block_ctxt cx, @ty.t t) -> result { + fn align_elements(@block_ctxt cx, vec[@ty.t] elts) -> result { + // + // C padding rules: + // + // + // - Pad after each element so that next element is aligned. + // - Pad after final structure member so that whole structure + // is aligned to max alignment of interior. + // + auto off = C_int(0); + auto max_align = C_int(1); + auto bcx = cx; + for (@ty.t e in elts) { + auto elt_align = align_of(bcx, e); + bcx = elt_align.bcx; + auto elt_size = size_of(bcx, e); + bcx = elt_size.bcx; + auto aligned_off = align_to(bcx, off, elt_align.val); + off = cx.build.Add(aligned_off, elt_size.val); + max_align = umax(bcx, max_align, elt_align.val); + } + off = align_to(bcx, off, max_align); + ret res(bcx, off); + } + alt (t.struct) { case (ty.ty_param(?p)) { auto szptr = field_of_tydesc(cx, t, abi.tydesc_field_size); ret res(szptr.bcx, szptr.bcx.build.Load(szptr.val)); } case (ty.ty_tup(?elts)) { - // - // C padding rules: - // - // - // - Pad after each element so that next element is aligned. - // - Pad after final structure member so that whole structure - // is aligned to max alignment of interior. - // - auto off = C_int(0); - auto max_align = C_int(1); - auto bcx = cx; - for (@ty.t e in elts) { - auto elt_align = align_of(bcx, e); - bcx = elt_align.bcx; - auto elt_size = size_of(bcx, e); - bcx = elt_size.bcx; - auto aligned_off = align_to(bcx, off, elt_align.val); - off = cx.build.Add(aligned_off, elt_size.val); - max_align = umax(bcx, max_align, elt_align.val); - } - off = align_to(bcx, off, max_align); - ret res(bcx, off); + ret align_elements(cx, elts); } case (ty.ty_rec(?flds)) { - auto off = C_int(0); - auto max_align = C_int(1); - auto bcx = cx; + let vec[@ty.t] tys = vec(); for (ty.field f in flds) { - auto elt_align = align_of(bcx, f.ty); - bcx = elt_align.bcx; - auto elt_size = size_of(bcx, f.ty); - bcx = elt_size.bcx; - auto aligned_off = align_to(bcx, off, elt_align.val); - off = cx.build.Add(aligned_off, elt_size.val); - max_align = umax(bcx, max_align, elt_align.val); + tys += vec(f.ty); } - off = align_to(bcx, off, max_align); - ret res(bcx, off); + ret align_elements(cx, tys); } } } -- cgit v1.2.3 From 71f853b3fdaede022ac9b680ff2a3767379faacd Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 1 Mar 2011 16:37:17 -0800 Subject: rustc: Add logic for generic tags to dynamic_size_of(). --- src/comp/middle/trans.rs | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 7bdca92a..ed61fdd7 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -891,6 +891,26 @@ fn dynamic_size_of(@block_ctxt cx, @ty.t t) -> result { } ret align_elements(cx, tys); } + case (ty.ty_tag(?tid, ?tps)) { + auto bcx = cx; + + // Compute max(variant sizes). + let ValueRef max_size = bcx.build.Alloca(T_int()); + bcx.build.Store(C_int(0), max_size); + + auto variants = tag_variants(bcx.fcx.ccx, tid); + for (ast.variant variant in variants) { + let vec[@ty.t] tys = variant_types(bcx.fcx.ccx, variant); + auto rslt = align_elements(bcx, tys); + bcx = rslt.bcx; + + auto this_size = rslt.val; + auto old_max_size = bcx.build.Load(max_size); + bcx.build.Store(umax(bcx, this_size, old_max_size), max_size); + } + + ret res(bcx, bcx.build.Load(max_size)); + } } } @@ -1450,16 +1470,25 @@ fn decr_refcnt_and_if_zero(@block_ctxt cx, // Tag information -fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef { - let vec[TypeRef] lltys = vec(); +fn variant_types(@crate_ctxt cx, &ast.variant v) -> vec[@ty.t] { + let vec[@ty.t] tys = vec(); 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)); + tys += vec(arg.ty); } } case (_) { fail; } } + ret tys; +} + +fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef { + let vec[TypeRef] lltys = vec(); + auto tys = variant_types(cx, v); + for (@ty.t typ in tys) { + lltys += vec(type_of(cx, typ)); + } ret T_struct(lltys); } -- cgit v1.2.3 From 9d59d33515d889f6e65f50226ba83d91a36bba0e Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 1 Mar 2011 16:49:05 -0800 Subject: rustc: Add in the size of the discriminant to generic_size_of() for tags --- src/comp/middle/trans.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index ed61fdd7..0aaf582d 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -909,7 +909,9 @@ fn dynamic_size_of(@block_ctxt cx, @ty.t t) -> result { bcx.build.Store(umax(bcx, this_size, old_max_size), max_size); } - ret res(bcx, bcx.build.Load(max_size)); + auto max_size_val = bcx.build.Load(max_size); + auto total_size = bcx.build.Add(max_size_val, llsize_of(T_int())); + ret res(bcx, total_size); } } } -- cgit v1.2.3 From 7cae0c8c4d15546cbccacb6a937759903df608d7 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 1 Mar 2011 16:14:30 -0800 Subject: Implement the gross rustboot hack for contextual parser access to the compilation environment. --- src/comp/front/parser.rs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 4ffa6f92..696140b1 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -147,9 +147,23 @@ impure fn parse_ident(parser p) -> ast.ident { } -impure fn parse_str_lit(parser p) -> ast.ident { +/* FIXME: gross hack copied from rustboot to make certain configuration-based + * decisions work at build-time. We should probably change it to use a + * lexical sytnax-extension or something similar. For now we just imitate + * rustboot. + */ +impure fn parse_str_lit_or_env_ident(parser p) -> ast.ident { alt (p.peek()) { case (token.LIT_STR(?s)) { p.bump(); ret s; } + case (token.IDENT(?i)) { + auto v = eval.lookup(p.get_session(), p.get_env(), + p.get_span(), i); + if (!eval.val_is_str(v)) { + p.err("expecting string-valued variable"); + } + p.bump(); + ret eval.val_as_str(v); + } case (_) { p.err("expecting string literal"); fail; @@ -1824,7 +1838,7 @@ impure fn parse_item_native_mod(parser p) -> @ast.item { expect(p, token.NATIVE); auto abi = ast.native_abi_cdecl; if (p.peek() != token.MOD) { - auto t = parse_str_lit(p); + auto t = parse_str_lit_or_env_ident(p); if (_str.eq(t, "cdecl")) { } else if (_str.eq(t, "rust")) { abi = ast.native_abi_rust; @@ -1838,7 +1852,7 @@ impure fn parse_item_native_mod(parser p) -> @ast.item { auto native_name; if (p.peek() == token.EQ) { expect(p, token.EQ); - native_name = parse_str_lit(p); + native_name = parse_str_lit_or_env_ident(p); } else { native_name = default_native_name(p.get_session(), id); } @@ -2202,7 +2216,7 @@ impure fn parse_crate_directive(parser p) -> ast.crate_directive case (token.EQ) { p.bump(); // FIXME: turn this into parse+eval expr - file_opt = some[filename](parse_str_lit(p)); + file_opt = some[filename](parse_str_lit_or_env_ident(p)); } case (_) {} } -- cgit v1.2.3 From 9869aebf7d21e5076e16193f2fad9c7f9446fdc6 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 1 Mar 2011 16:58:13 -0800 Subject: rustc: Remove the static "size" field from the tag info --- src/comp/middle/trans.rs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 0aaf582d..e961acb4 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -61,7 +61,6 @@ type glue_fns = rec(ValueRef activate_glue, type tag_info = rec( type_handle th, - mutable uint size, mutable @hashmap[ast.def_id,ValueRef] lldiscrims ); @@ -4491,15 +4490,6 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, auto arg_tys = arg_tys_of_fn(variant.ann); copy_args_to_allocas(bcx, none[TypeRef], fn_args, arg_tys); - // FIXME: This is wrong for generic tags. We should be dynamically - // computing "size" below based on the tydescs passed in. - auto info = cx.tags.get(mk_plain_tag(tag_id)); - - auto lltagty = T_struct(vec(T_int(), T_array(T_i8(), info.size))); - - // FIXME: better name. - llvm.LLVMAddTypeName(cx.llmod, _str.buf("tag"), lltagty); - auto lldiscrimptr = bcx.build.GEP(fcx.llretptr, vec(C_int(0), C_int(0))); bcx.build.Store(C_int(index), lldiscrimptr); @@ -4718,7 +4708,6 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { auto info = @rec( th=mk_type_handle(), - mutable size=0u, mutable lldiscrims=@new_def_hash[ValueRef]() ); @@ -4780,6 +4769,9 @@ fn collect_tag_ctors(@crate_ctxt cx, @ast.crate crate) { fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { alt (i.node) { case (ast.item_tag(_, ?variants, _, ?tag_id)) { + // FIXME: This is all wrong. Now sizes and alignments are computed + // dynamically instead of up front. + auto max_align = 0u; auto max_size = 0u; @@ -4799,8 +4791,6 @@ fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { } } - info.size = max_size; - // FIXME: alignment is wrong here, manually insert padding I // guess :( auto tag_ty = T_struct(vec(T_int(), T_array(T_i8(), max_size))); -- cgit v1.2.3 From 64ab5eaaf09de6a75392554c13784c492ed19465 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 1 Mar 2011 17:32:16 -0800 Subject: Parse (and ignore) dtors on objs. --- src/comp/front/ast.rs | 3 ++- src/comp/front/parser.rs | 30 +++++++++++++++++++++--------- src/comp/middle/fold.rs | 19 ++++++++++++++----- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 9b995f9a..4ed513a3 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -247,7 +247,8 @@ type method = spanned[method_]; type obj_field = rec(@ty ty, ident ident, def_id id, ann ann); type _obj = rec(vec[obj_field] fields, - vec[@method] methods); + vec[@method] methods, + option.t[block] dtor); tag mod_index_entry { mie_view_item(@view_item); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 696140b1..f747c084 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1715,21 +1715,33 @@ impure fn parse_item_obj(parser p, ast.layer lyr) -> @ast.item { some(token.COMMA), pf, p); - auto pm = parse_method; - let util.common.spanned[vec[@ast.method]] meths = - parse_seq[@ast.method] - (token.LBRACE, - token.RBRACE, - none[token.token], - pm, p); + let vec[@ast.method] meths = vec(); + let option.t[ast.block] dtor = none[ast.block]; + + expect(p, token.LBRACE); + while (p.peek() != token.RBRACE) { + alt (p.peek()) { + case (token.DROP) { + p.bump(); + dtor = some[ast.block](parse_block(p)); + } + case (_) { + append[@ast.method](meths, + parse_method(p)); + } + } + } + auto hi = p.get_span(); + expect(p, token.RBRACE); let ast._obj ob = rec(fields=fields.node, - methods=meths.node); + methods=meths, + dtor=dtor); auto item = ast.item_obj(ident, ob, ty_params, p.next_def_id(), ast.ann_none); - ret @spanned(lo, meths.span, item); + ret @spanned(lo, hi, item); } impure fn parse_mod_items(parser p, token.token term) -> ast._mod { diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 65bbe602..09783070 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -269,7 +269,8 @@ type ast_fold[ENV] = (fn(&ENV e, vec[ast.obj_field] fields, - vec[@ast.method] methods) -> ast._obj) fold_obj, + vec[@ast.method] methods, + option.t[block] dtor) -> ast._obj) fold_obj, // Env updates. (fn(&ENV e, @ast.crate c) -> ENV) update_env_for_crate, @@ -791,6 +792,13 @@ fn fold_obj[ENV](&ENV env, ast_fold[ENV] fld, &ast._obj ob) -> ast._obj { for (ast.obj_field f in ob.fields) { fields += fold_obj_field(env, fld, f); } + let option.t[block] dtor = none[block]; + alt (ob.dtor) { + case (none[block]) { } + case (some[block](?b)) { + dtor = some[block](fold_block[ENV](env, fld, b)); + } + } let vec[ast.ty_param] tp = vec(); for (@ast.method m in ob.methods) { // Fake-up an ast.item for this method. @@ -805,7 +813,7 @@ fn fold_obj[ENV](&ENV env, ast_fold[ENV] fld, &ast._obj ob) -> ast._obj { let ENV _env = fld.update_env_for_item(env, i); append[@ast.method](meths, fold_method(_env, fld, m)); } - ret fld.fold_obj(env, fields, meths); + ret fld.fold_obj(env, fields, meths, dtor); } fn fold_view_item[ENV](&ENV env, ast_fold[ENV] fld, @view_item vi) @@ -1334,8 +1342,9 @@ fn identity_fold_crate[ENV](&ENV e, &span sp, &ast._mod m) -> @ast.crate { fn identity_fold_obj[ENV](&ENV e, vec[ast.obj_field] fields, - vec[@ast.method] methods) -> ast._obj { - ret rec(fields=fields, methods=methods); + vec[@ast.method] methods, + option.t[block] dtor) -> ast._obj { + ret rec(fields=fields, methods=methods, dtor=dtor); } @@ -1481,7 +1490,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_mod = bind identity_fold_mod[ENV](_,_), fold_native_mod = bind identity_fold_native_mod[ENV](_,_), fold_crate = bind identity_fold_crate[ENV](_,_,_), - fold_obj = bind identity_fold_obj[ENV](_,_,_), + fold_obj = bind identity_fold_obj[ENV](_,_,_,_), update_env_for_crate = bind identity_update_env_for_crate[ENV](_,_), update_env_for_item = bind identity_update_env_for_item[ENV](_,_), -- cgit v1.2.3 From 727970c2309d6451f501f248f8100c72649ccece Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 24 Feb 2011 01:02:23 -0500 Subject: Remove reference to deceased rustboot LLVM backend --- src/README | 1 - 1 file changed, 1 deletion(-) diff --git a/src/README b/src/README index 3618ee18..05d701bd 100644 --- a/src/README +++ b/src/README @@ -8,7 +8,6 @@ boot/fe - Front end (lexer, parser, AST) boot/me - Middle end (resolve, check, layout, trans) boot/be - Back end (IL, RA, insns, asm, objfiles) boot/util - Ubiquitous helpers -boot/llvm - LLVM-based alternative back end boot/driver - Compiler driver comp/ The self-hosted compiler ("rustc": incomplete) -- cgit v1.2.3 From e2d36e00ce2b58272b52a5c1f999b0bcb61d066b Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 24 Feb 2011 18:39:57 -0500 Subject: Remove parens from nullary tag constructors in docs --- doc/rust.texi | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/rust.texi b/doc/rust.texi index 740d45c6..48a639dd 100644 --- a/doc/rust.texi +++ b/doc/rust.texi @@ -1990,22 +1990,22 @@ module system). An example of a @code{tag} item and its use: @example tag animal @{ - dog(); - cat(); + dog; + cat; @} -let animal a = dog(); -a = cat(); +let animal a = dog; +a = cat; @end example An example of a @emph{recursive} @code{tag} item and its use: @example tag list[T] @{ - nil(); + nil; cons(T, @@list[T]); @} -let list[int] a = cons(7, cons(13, nil())); +let list[int] a = cons(7, cons(13, nil)); @end example @@ -3401,9 +3401,9 @@ control enters the block. An example of a pattern @code{alt} statement: @example -type list[X] = tag(nil(), cons(X, @@list[X])); +type list[X] = tag(nil, cons(X, @@list[X])); -let list[int] x = cons(10, cons(11, nil())); +let list[int] x = cons(10, cons(11, nil)); alt (x) @{ case (cons(a, cons(b, _))) @{ -- cgit v1.2.3 From 9528c34774ff27b112c9e66afff6e10fa7021635 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 23 Feb 2011 23:48:01 -0500 Subject: Begin implementing #fmt in rustc --- src/comp/front/ast.rs | 13 ++++- src/comp/front/extfmt.rs | 84 +++++++++++++++++++++++++++++++ src/comp/front/parser.rs | 35 ++++++++++++- src/comp/rustc.rc | 1 + src/test/run-pass/syntax-extension-fmt.rs | 12 ++++- 5 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 src/comp/front/extfmt.rs diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 4ed513a3..18add3bd 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -185,7 +185,7 @@ tag expr_ { expr_field(@expr, ident, ann); expr_index(@expr, @expr, ann); expr_path(path, option.t[def], ann); - expr_ext(path, vec[@expr], option.t[@expr], ann); + expr_ext(path, vec[@expr], option.t[@expr], option.t[@expr], ann); expr_fail; expr_ret(option.t[@expr]); expr_put(option.t[@expr]); @@ -363,6 +363,17 @@ fn is_call_expr(@expr e) -> bool { } } +fn is_ext_expr(@expr e) -> bool { + alt (e.node) { + case (expr_ext(_, _, _, _, _)) { + ret true; + } + case (_) { + ret false; + } + } +} + // // Local Variables: // mode: rust diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs new file mode 100644 index 00000000..cb70805a --- /dev/null +++ b/src/comp/front/extfmt.rs @@ -0,0 +1,84 @@ +/* The 'fmt' extension is modeled on the posix printf system. + * + * A posix conversion ostensibly looks like this: + * + * %[parameter][flags][width][.precision][length]type + * + * Given the different numeric type bestiary we have, we omit the 'length' + * parameter and support slightly different conversions for 'type': + * + * %[parameter][flags][width][.precision]type + * + * we also only support translating-to-rust a tiny subset of the possible + * combinations at the moment. + */ + +use std; + +import std.option; + +tag signedness { + signed; + unsigned; +} + +tag caseness { + case_upper; + case_lower; +} + +tag ty { + ty_bool; + ty_str; + ty_char; + ty_int(signedness); + ty_bits; + ty_hex(caseness); + // FIXME: More types +} + +tag flag { + flag_left_justify; + flag_left_zero_pad; + flag_left_space_pad; + flag_plus_if_positive; + flag_alternate; +} + +tag count { + count_is(int); + count_is_param(int); + count_is_next_param; + count_implied; +} + +// A formatted conversion from an expression to a string +tag conv { + conv_param(option.t[int]); + conv_flags(vec[flag]); + conv_width(count); + conv_precision(count); + conv_ty(ty); +} + +// A fragment of the output sequence +tag piece { + piece_string(str); + piece_conv(str); +} + +fn expand_syntax_ext(vec[@ast.expr] args, + option.t[@ast.expr] body) -> @ast.expr { + fail; +} + +// +// Local Variables: +// mode: rust +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: +// diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index f747c084..8f6db17d 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -656,7 +656,10 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr { some(token.COMMA), pf, p); hi = es.span; - ex = ast.expr_ext(pth, es.node, none[@ast.expr], ast.ann_none); + ex = ast.expr_ext(pth, es.node, none[@ast.expr], + none[@ast.expr], ast.ann_none); + // FIXME: Here is probably not the right place for this + ex = expand_syntax_ext(p, @spanned(lo, hi, ex)).node; } case (token.FAIL) { @@ -736,6 +739,36 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr { ret @spanned(lo, hi, ex); } +/* + * FIXME: This is a crude approximation of the syntax-extension system, + * for purposes of prototyping and/or hard-wiring any extensions we + * wish to use while bootstrapping. The eventual aim is to permit + * loading rust crates to process extensions, but this will likely + * require a rust-based frontend, or an ocaml-FFI-based connection to + * rust crates. At the moment we have neither. + */ + +impure fn expand_syntax_ext(parser p, @ast.expr ext) -> @ast.expr { + check (ast.is_ext_expr(ext)); + alt (ext.node) { + case (ast.expr_ext(?path, ?args, ?body, _, ?ann)) { + check (_vec.len[ast.ident](path.node.idents) > 0u); + auto extname = path.node.idents.(0); + if (_str.eq(extname, "fmt")) { + auto expanded = extfmt.expand_syntax_ext(args, body); + check (ast.is_ext_expr(expanded)); + auto newexpr = ast.expr_ext(path, args, body, + some[@ast.expr](expanded), ann); + + ret @spanned(ext.span, ext.span, newexpr); + } else { + p.err("unknown syntax extension"); + } + } + } + fail; +} + impure fn extend_expr_by_ident(parser p, span lo, span hi, @ast.expr e, ast.ident i) -> @ast.expr { auto e_ = e.node; diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc index bc4aaa52..16d24e9b 100644 --- a/src/comp/rustc.rc +++ b/src/comp/rustc.rc @@ -5,6 +5,7 @@ use std; mod front { mod ast; + mod extfmt; mod lexer; mod parser; mod token; diff --git a/src/test/run-pass/syntax-extension-fmt.rs b/src/test/run-pass/syntax-extension-fmt.rs index 65e7647e..66fe4fd7 100644 --- a/src/test/run-pass/syntax-extension-fmt.rs +++ b/src/test/run-pass/syntax-extension-fmt.rs @@ -1,5 +1,13 @@ use std; +import std._str; + +fn test(str actual, str expected) { + log actual; + log expected; + check (_str.eq(actual, expected)); +} + fn main() { - auto s = #fmt("hello %d friends and %s things", 10, "formatted"); - log s; + test(#fmt("hello %d friends and %s things", 10, "formatted"), + "hello 10 friends and formatted things"); } -- cgit v1.2.3 From 1c60399257cde71fc265eb10cae1f398a0ac2516 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 24 Feb 2011 23:22:36 -0500 Subject: Begin work on #fmt parsing --- src/comp/front/extfmt.rs | 100 +++++++++++++++++++++++++++++- src/comp/front/parser.rs | 1 - src/test/run-pass/syntax-extension-fmt.rs | 6 +- 3 files changed, 101 insertions(+), 6 deletions(-) diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index cb70805a..7018ef14 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -13,8 +13,10 @@ * combinations at the moment. */ -use std; +import front.parser; +import std._str; +import std._vec; import std.option; tag signedness { @@ -64,14 +66,108 @@ tag conv { // A fragment of the output sequence tag piece { piece_string(str); - piece_conv(str); + piece_conv(conv); +} + +fn bad_fmt_call() { + log "malformed #fmt call"; + fail; } fn expand_syntax_ext(vec[@ast.expr] args, option.t[@ast.expr] body) -> @ast.expr { + + if (_vec.len[@ast.expr](args) == 0u) { + bad_fmt_call(); + } + + auto fmt = expr_to_str(args.(0)); + log fmt; + auto pieces = parse_fmt_string(fmt); + ret pieces_to_expr(pieces, args); +} + +fn expr_to_str(@ast.expr expr) -> str { + alt (expr.node) { + case (ast.expr_lit(?l, _)) { + alt (l.node) { + case (ast.lit_str(?s)) { + ret s; + } + } + } + } + bad_fmt_call(); fail; } +fn parse_fmt_string(str s) -> vec[piece] { + let vec[piece] pieces = vec(); + // FIXME: Should be counting codepoints instead of bytes + auto lim = _str.byte_len(s); + auto buf = ""; + + // TODO: This is super ugly + fn flush_buf(str buf, vec[piece] pieces) -> str { + log "flushing"; + if (_str.byte_len(buf) > 0u) { + auto piece = piece_string(buf); + pieces += piece; + } + log "buf:"; + log buf; + log "pieces:"; + for (piece p in pieces) { + alt (p) { + case (piece_string(?s)) { + log s; + } + case (piece_conv(_)) { + log "conv"; + } + } + } + ret ""; + } + + auto i = 0u; + while (i < lim) { + log "step:"; + log i; + auto curr = _str.substr(s, i, 1u); + if (_str.eq(curr, "%")) { + i += 1u; + if (i >= lim) { + log "unterminated conversion at end of string"; + fail; + } + auto curr2 = _str.substr(s, i, 1u); + if (_str.eq(curr2, "%")) { + i += 1u; + } else { + buf = flush_buf(buf, pieces); + } + } else { + buf += curr; + log "buf:"; + log buf; + i += 1u; + } + } + + ret pieces; +} + +fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { + auto lo = args.(0).span; + auto hi = args.(0).span; + auto strlit = ast.lit_str("TODO"); + auto spstrlit = @parser.spanned[ast.lit_](lo, hi, strlit); + auto expr = ast.expr_lit(spstrlit, ast.ann_none); + auto spexpr = @parser.spanned[ast.expr_](lo, hi, expr); + ret spexpr; +} + // // Local Variables: // mode: rust diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 8f6db17d..e5f68033 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -756,7 +756,6 @@ impure fn expand_syntax_ext(parser p, @ast.expr ext) -> @ast.expr { auto extname = path.node.idents.(0); if (_str.eq(extname, "fmt")) { auto expanded = extfmt.expand_syntax_ext(args, body); - check (ast.is_ext_expr(expanded)); auto newexpr = ast.expr_ext(path, args, body, some[@ast.expr](expanded), ann); diff --git a/src/test/run-pass/syntax-extension-fmt.rs b/src/test/run-pass/syntax-extension-fmt.rs index 66fe4fd7..a0f51c27 100644 --- a/src/test/run-pass/syntax-extension-fmt.rs +++ b/src/test/run-pass/syntax-extension-fmt.rs @@ -1,10 +1,10 @@ -use std; -import std._str; +//use std; +//import std._str; fn test(str actual, str expected) { log actual; log expected; - check (_str.eq(actual, expected)); + //check (_str.eq(actual, expected)); } fn main() { -- cgit v1.2.3 From f1500e5872d03e3ec3b140060641136a2ff5a15a Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 26 Feb 2011 20:51:02 -0500 Subject: Add fold, typecheck and trans for expr_ext --- src/comp/middle/fold.rs | 24 ++++++++++++++++++++++++ src/comp/middle/trans.rs | 8 ++++++++ src/comp/middle/ty.rs | 1 + src/comp/middle/typeck.rs | 14 ++++++++++++++ src/test/run-pass/syntax-extension-fmt.rs | 5 +++-- 5 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 09783070..d533082c 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -154,6 +154,12 @@ type ast_fold[ENV] = &option.t[def] d, ann a) -> @expr) fold_expr_path, + (fn(&ENV e, &span sp, + &path p, vec[@expr] args, + option.t[@expr] body, + option.t[@expr] expanded, + ann a) -> @expr) fold_expr_ext, + (fn(&ENV e, &span sp) -> @expr) fold_expr_fail, (fn(&ENV e, &span sp, @@ -644,6 +650,15 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr { ret fld.fold_expr_path(env_, e.span, p_, r, t); } + case (ast.expr_ext(?p, ?args, ?body, ?expanded, ?t)) { + // Only fold the expanded expression, not the + // expressions involved in syntax extension + auto exp = option.get[@expr](expanded); + auto exp_ = fold_expr(env_, fld, exp); + ret fld.fold_expr_ext(env_, e.span, p, args, body, + some[@ast.expr](exp_), t); + } + case (ast.expr_fail) { ret fld.fold_expr_fail(env_, e.span); } @@ -1166,6 +1181,14 @@ fn identity_fold_expr_path[ENV](&ENV env, &span sp, ret @respan(sp, ast.expr_path(p, d, a)); } +fn identity_fold_expr_ext[ENV](&ENV env, &span sp, + &path p, vec[@expr] args, + option.t[@expr] body, + option.t[@expr] expanded, + ann a) -> @expr { + ret @respan(sp, ast.expr_ext(p, args, body, expanded, a)); +} + fn identity_fold_expr_fail[ENV](&ENV env, &span sp) -> @expr { ret @respan(sp, ast.expr_fail); } @@ -1447,6 +1470,7 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] { fold_expr_field = bind identity_fold_expr_field[ENV](_,_,_,_,_), fold_expr_index = bind identity_fold_expr_index[ENV](_,_,_,_,_), fold_expr_path = bind identity_fold_expr_path[ENV](_,_,_,_,_), + fold_expr_ext = bind identity_fold_expr_ext[ENV](_,_,_,_,_,_,_), fold_expr_fail = bind identity_fold_expr_fail[ENV](_,_), fold_expr_ret = bind identity_fold_expr_ret[ENV](_,_,_), fold_expr_put = bind identity_fold_expr_put[ENV](_,_,_), diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index e961acb4..f8c3fd61 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1957,6 +1957,8 @@ fn trans_lit(@crate_ctxt cx, &ast.lit lit, &ast.ann ann) -> ValueRef { ret C_nil(); } case (ast.lit_str(?s)) { + log "translating literal:"; + log s; ret C_str(cx, s); } } @@ -3599,6 +3601,7 @@ fn trans_rec(@block_ctxt cx, vec[ast.field] fields, fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { alt (e.node) { case (ast.expr_lit(?lit, ?ann)) { + log "translating literal"; ret res(cx, trans_lit(cx.fcx.ccx, *lit, ann)); } @@ -3693,6 +3696,11 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { ret trans_rec(cx, args, base, ann); } + case (ast.expr_ext(_, _, _, ?expanded, _)) { + log "translating extension"; + ret trans_expr(cx, option.get[@ast.expr](expanded)); + } + case (ast.expr_fail) { ret trans_fail(cx, e.span, "explicit failure"); } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 8b9ef6d1..478f54d1 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -749,6 +749,7 @@ fn expr_ty(@ast.expr expr) -> @t { case (ast.expr_field(_, _, ?ann)) { ret ann_to_type(ann); } case (ast.expr_index(_, _, ?ann)) { ret ann_to_type(ann); } case (ast.expr_path(_, _, ?ann)) { ret ann_to_type(ann); } + case (ast.expr_ext(_, _, _, _, ?ann)) { ret ann_to_type(ann); } case (ast.expr_fail) { ret plain_ty(ty_nil); } case (ast.expr_log(_)) { ret plain_ty(ty_nil); } diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index ce1c59ec..5cccc4d7 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1156,6 +1156,11 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, ann_to_type(ann), adk); e_1 = ast.expr_path(pth, d, ast.ann_type(t)); } + case (ast.expr_ext(?p, ?args, ?body, ?expanded, ?ann)) { + auto t = demand_full(fcx, e.span, expected, + ann_to_type(ann), adk); + e_1 = ast.expr_ext(p, args, body, expanded, ast.ann_type(t)); + } case (ast.expr_fail) { e_1 = e.node; } case (ast.expr_log(_)) { e_1 = e.node; } case (ast.expr_ret(_)) { e_1 = e.node; } @@ -1508,6 +1513,15 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { ast.ann_type(t))); } + case (ast.expr_ext(?p, ?args, ?body, ?expanded, _)) { + auto exp_ = check_expr(fcx, option.get[@ast.expr](expanded)); + auto t = expr_ty(exp_); + ret @fold.respan[ast.expr_](expr.span, + ast.expr_ext(p, args, body, + some[@ast.expr](exp_), + ast.ann_type(t))); + } + case (ast.expr_fail) { ret expr; } diff --git a/src/test/run-pass/syntax-extension-fmt.rs b/src/test/run-pass/syntax-extension-fmt.rs index a0f51c27..0d1d7082 100644 --- a/src/test/run-pass/syntax-extension-fmt.rs +++ b/src/test/run-pass/syntax-extension-fmt.rs @@ -8,6 +8,7 @@ fn test(str actual, str expected) { } fn main() { - test(#fmt("hello %d friends and %s things", 10, "formatted"), - "hello 10 friends and formatted things"); + /*test(#fmt("hello %d friends and %s things", 10, "formatted"), + "hello 10 friends and formatted things");*/ + log #fmt("test"); } -- cgit v1.2.3 From fe5de6bfffee3c277f540517b5766547f34e81c7 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 27 Feb 2011 14:30:44 -0500 Subject: Parse parameter types for fmt extension --- src/comp/front/extfmt.rs | 148 ++++++++++++++++++++++++------ src/comp/middle/trans.rs | 4 - src/rt/memory_region.cpp | 2 +- src/test/run-pass/syntax-extension-fmt.rs | 11 +-- 4 files changed, 126 insertions(+), 39 deletions(-) diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index 7018ef14..998bfa4d 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -18,6 +18,8 @@ import front.parser; import std._str; import std._vec; import std.option; +import std.option.none; +import std.option.some; tag signedness { signed; @@ -55,13 +57,11 @@ tag count { } // A formatted conversion from an expression to a string -tag conv { - conv_param(option.t[int]); - conv_flags(vec[flag]); - conv_width(count); - conv_precision(count); - conv_ty(ty); -} +type conv = rec(option.t[int] param, + vec[flag] flags, + count width, + count precision, + ty typ); // A fragment of the output sequence tag piece { @@ -84,6 +84,18 @@ fn expand_syntax_ext(vec[@ast.expr] args, auto fmt = expr_to_str(args.(0)); log fmt; auto pieces = parse_fmt_string(fmt); + log "printing all pieces"; + for (piece p in pieces) { + alt (p) { + case (piece_string(?s)) { + log s; + } + case (piece_conv(_)) { + log "conv"; + } + } + } + log "done printing all pieces"; ret pieces_to_expr(pieces, args); } @@ -107,33 +119,16 @@ fn parse_fmt_string(str s) -> vec[piece] { auto lim = _str.byte_len(s); auto buf = ""; - // TODO: This is super ugly - fn flush_buf(str buf, vec[piece] pieces) -> str { - log "flushing"; + fn flush_buf(str buf, &vec[piece] pieces) -> str { if (_str.byte_len(buf) > 0u) { auto piece = piece_string(buf); pieces += piece; } - log "buf:"; - log buf; - log "pieces:"; - for (piece p in pieces) { - alt (p) { - case (piece_string(?s)) { - log s; - } - case (piece_conv(_)) { - log "conv"; - } - } - } ret ""; } auto i = 0u; while (i < lim) { - log "step:"; - log i; auto curr = _str.substr(s, i, 1u); if (_str.eq(curr, "%")) { i += 1u; @@ -146,18 +141,115 @@ fn parse_fmt_string(str s) -> vec[piece] { i += 1u; } else { buf = flush_buf(buf, pieces); + auto res = parse_conversion(s, i, lim); + pieces += res._0; + i = res._1; } } else { buf += curr; - log "buf:"; - log buf; i += 1u; } } - + buf = flush_buf(buf, pieces); ret pieces; } +fn peek_num(str s, uint i, uint lim) -> option.t[tup(int, int)] { + if (i >= lim) { + ret none[tup(int, int)]; + } else { + ret none[tup(int, int)]; + /*if ('0' <= c && c <= '9') { + log c; + fail; + } else { + ret option.none[tup(int, int)]; + } + */ + } +} + +fn parse_conversion(str s, uint i, uint lim) -> tup(piece, uint) { + auto parm = parse_parameter(s, i, lim); + auto flags = parse_flags(s, parm._1, lim); + auto width = parse_width(s, flags._1, lim); + auto prec = parse_precision(s, width._1, lim); + auto ty = parse_type(s, prec._1, lim); + ret tup(piece_conv(rec(param = parm._0, + flags = flags._0, + width = width._0, + precision = prec._0, + typ = ty._0)), + ty._1); +} + +fn parse_parameter(str s, uint i, uint lim) -> tup(option.t[int], uint) { + if (i >= lim) { + ret tup(none[int], i); + } + + auto num = peek_num(s, i, lim); + alt (num) { + case (none[tup(int, int)]) { + ret tup(none[int], i); + } + case (some[tup(int, int)](?t)) { + fail; + } + } +} + +fn parse_flags(str s, uint i, uint lim) -> tup(vec[flag], uint) { + let vec[flag] flags = vec(); + ret tup(flags, i); +} + +fn parse_width(str s, uint i, uint lim) -> tup(count, uint) { + ret tup(count_implied, i); +} + +fn parse_precision(str s, uint i, uint lim) -> tup(count, uint) { + ret tup(count_implied, i); +} + +fn parse_type(str s, uint i, uint lim) -> tup(ty, uint) { + if (i >= lim) { + log "missing type in conversion"; + fail; + } + + auto t; + auto tstr = _str.substr(s, i, 1u); + if (_str.eq(tstr, "b")) { + t = ty_bool; + } else if (_str.eq(tstr, "s")) { + t = ty_str; + } else if (_str.eq(tstr, "c")) { + t = ty_char; + } else if (_str.eq(tstr, "d") + || _str.eq(tstr, "i")) { + // TODO: Do we really want two signed types here? + // How important is it to be printf compatible? + t = ty_int(signed); + } else if (_str.eq(tstr, "u")) { + t = ty_int(unsigned); + } else if (_str.eq(tstr, "x")) { + t = ty_hex(case_lower); + } else if (_str.eq(tstr, "X")) { + t = ty_hex(case_upper); + } else if (_str.eq(tstr, "t")) { + t = ty_bits; + } else { + // FIXME: This is a hack to avoid 'unsatisfied precondition + // constraint' on uninitialized variable t below + t = ty_bool; + log "unknown type in conversion"; + fail; + } + + ret tup(t, i + 1u); +} + fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { auto lo = args.(0).span; auto hi = args.(0).span; diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index f8c3fd61..9fee3dab 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1957,8 +1957,6 @@ fn trans_lit(@crate_ctxt cx, &ast.lit lit, &ast.ann ann) -> ValueRef { ret C_nil(); } case (ast.lit_str(?s)) { - log "translating literal:"; - log s; ret C_str(cx, s); } } @@ -3601,7 +3599,6 @@ fn trans_rec(@block_ctxt cx, vec[ast.field] fields, fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { alt (e.node) { case (ast.expr_lit(?lit, ?ann)) { - log "translating literal"; ret res(cx, trans_lit(cx.fcx.ccx, *lit, ann)); } @@ -3697,7 +3694,6 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { } case (ast.expr_ext(_, _, _, ?expanded, _)) { - log "translating extension"; ret trans_expr(cx, option.get[@ast.expr](expanded)); } diff --git a/src/rt/memory_region.cpp b/src/rt/memory_region.cpp index 7ede3761..fb19620f 100644 --- a/src/rt/memory_region.cpp +++ b/src/rt/memory_region.cpp @@ -1,7 +1,7 @@ #include "rust_internal.h" #include "memory_region.h" -// #define TRACK_ALLOCATIONS +#define TRACK_ALLOCATIONS memory_region::memory_region(rust_srv *srv, bool synchronized) : _srv(srv), _parent(NULL), _live_allocations(0), diff --git a/src/test/run-pass/syntax-extension-fmt.rs b/src/test/run-pass/syntax-extension-fmt.rs index 0d1d7082..b7076c81 100644 --- a/src/test/run-pass/syntax-extension-fmt.rs +++ b/src/test/run-pass/syntax-extension-fmt.rs @@ -1,14 +1,13 @@ -//use std; -//import std._str; +use std; +import std._str; fn test(str actual, str expected) { log actual; log expected; - //check (_str.eq(actual, expected)); + check (_str.eq(actual, expected)); } fn main() { - /*test(#fmt("hello %d friends and %s things", 10, "formatted"), - "hello 10 friends and formatted things");*/ - log #fmt("test"); + test(#fmt("hello %d friends and %s things", 10, "formatted"), + "hello 10 friends and formatted things"); } -- cgit v1.2.3 From 5e06ec977f4446a7b19a09dd3a3781bcf26f8442 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 27 Feb 2011 15:29:31 -0500 Subject: Rewrite expand_syntax_ext to avoid a mysterious memory leak --- src/comp/front/parser.rs | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index e5f68033..7a7a863c 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -656,10 +656,8 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr { some(token.COMMA), pf, p); hi = es.span; - ex = ast.expr_ext(pth, es.node, none[@ast.expr], - none[@ast.expr], ast.ann_none); - // FIXME: Here is probably not the right place for this - ex = expand_syntax_ext(p, @spanned(lo, hi, ex)).node; + ex = expand_syntax_ext(p, es.span, pth, es.node, + none[@ast.expr]); } case (token.FAIL) { @@ -748,24 +746,23 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr { * rust crates. At the moment we have neither. */ -impure fn expand_syntax_ext(parser p, @ast.expr ext) -> @ast.expr { - check (ast.is_ext_expr(ext)); - alt (ext.node) { - case (ast.expr_ext(?path, ?args, ?body, _, ?ann)) { - check (_vec.len[ast.ident](path.node.idents) > 0u); - auto extname = path.node.idents.(0); - if (_str.eq(extname, "fmt")) { - auto expanded = extfmt.expand_syntax_ext(args, body); - auto newexpr = ast.expr_ext(path, args, body, - some[@ast.expr](expanded), ann); - - ret @spanned(ext.span, ext.span, newexpr); - } else { - p.err("unknown syntax extension"); - } - } +impure fn expand_syntax_ext(parser p, ast.span sp, + &ast.path path, vec[@ast.expr] args, + option.t[@ast.expr] body) -> ast.expr_ { + + check (_vec.len[ast.ident](path.node.idents) > 0u); + auto extname = path.node.idents.(0); + if (_str.eq(extname, "fmt")) { + auto expanded = extfmt.expand_syntax_ext(args, body); + auto newexpr = ast.expr_ext(path, args, body, + some[@ast.expr](expanded), + ast.ann_none); + + ret newexpr; + } else { + p.err("unknown syntax extension"); + fail; } - fail; } impure fn extend_expr_by_ident(parser p, span lo, span hi, -- cgit v1.2.3 From 1badf9316a174615e9e5c60e6cfd12e4f071d623 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 27 Feb 2011 18:22:54 -0500 Subject: Begin an AST pretty-printer --- src/comp/front/pretty.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ src/comp/rustc.rc | 1 + 2 files changed, 52 insertions(+) create mode 100644 src/comp/front/pretty.rs diff --git a/src/comp/front/pretty.rs b/src/comp/front/pretty.rs new file mode 100644 index 00000000..8e5414ee --- /dev/null +++ b/src/comp/front/pretty.rs @@ -0,0 +1,51 @@ +use std; + +fn unknown() -> str { + ret ""; +} + +fn print_expr(@ast.expr expr) -> str { + alt (expr.node) { + case (ast.expr_lit(?lit, _)) { + ret print_expr_lit(lit); + } + case (ast.expr_binary(?op, ?lhs, ?rhs, _)) { + ret print_expr_binary(op, lhs, rhs); + } + case (_) { + ret unknown(); + } + } +} + +fn print_expr_lit(@ast.lit lit) -> str { + alt (lit.node) { + case (ast.lit_str(?s)) { + ret "\"" + s + "\""; + } + case (_) { + ret unknown(); + } + } +} + +fn print_expr_binary(ast.binop op, @ast.expr lhs, @ast.expr rhs) -> str { + alt (op) { + case (ast.add) { + auto l = print_expr(lhs); + auto r = print_expr(rhs); + ret l + " + " + r; + } + } +} + +// +// Local Variables: +// mode: rust +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: +// diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc index 16d24e9b..43a04117 100644 --- a/src/comp/rustc.rc +++ b/src/comp/rustc.rc @@ -8,6 +8,7 @@ mod front { mod extfmt; mod lexer; mod parser; + mod pretty; mod token; mod eval; } -- cgit v1.2.3 From f9144d5972aef3e7078b272703bf275691991297 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 27 Feb 2011 18:23:16 -0500 Subject: Start generating AST nodes for #fmt --- src/comp/front/extfmt.rs | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index 998bfa4d..38c2ea8c 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -13,7 +13,7 @@ * combinations at the moment. */ -import front.parser; +import util.common; import std._str; import std._vec; @@ -251,13 +251,39 @@ fn parse_type(str s, uint i, uint lim) -> tup(ty, uint) { } fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { - auto lo = args.(0).span; - auto hi = args.(0).span; - auto strlit = ast.lit_str("TODO"); - auto spstrlit = @parser.spanned[ast.lit_](lo, hi, strlit); - auto expr = ast.expr_lit(spstrlit, ast.ann_none); - auto spexpr = @parser.spanned[ast.expr_](lo, hi, expr); - ret spexpr; + + fn make_new_str(common.span sp, str s) -> @ast.expr { + auto strlit = ast.lit_str(s); + auto spstrlit = @parser.spanned[ast.lit_](sp, sp, strlit); + auto expr = ast.expr_lit(spstrlit, ast.ann_none); + ret @parser.spanned[ast.expr_](sp, sp, expr); + } + + fn make_add_expr(common.span sp, + @ast.expr lhs, @ast.expr rhs) -> @ast.expr { + auto binexpr = ast.expr_binary(ast.add, lhs, rhs, ast.ann_none); + ret @parser.spanned[ast.expr_](sp, sp, binexpr); + } + + auto sp = args.(0).span; + auto n = 0; + auto tmp_expr = make_new_str(sp, "whatever"); + + for (piece p in pieces) { + alt (p) { + case (piece_string(?s)) { + auto s_expr = make_new_str(sp, s); + tmp_expr = make_add_expr(sp, tmp_expr, s_expr); + } + case (piece_conv(?conv)) { + } + } + } + + // TODO: Remove this print and return the real expanded AST + log "dumping expanded ast:"; + log pretty.print_expr(tmp_expr); + ret make_new_str(sp, "TODO"); } // -- cgit v1.2.3 From 61edf544a2d16b43d0c4ba1c7537d6a8475f681c Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 27 Feb 2011 19:44:57 -0500 Subject: Implement #fmt conversion for int and uint --- src/comp/front/extfmt.rs | 115 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 107 insertions(+), 8 deletions(-) diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index 38c2ea8c..bd5bab5b 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -21,6 +21,8 @@ import std.option; import std.option.none; import std.option.some; +export expand_syntax_ext; + tag signedness { signed; unsigned; @@ -61,7 +63,7 @@ type conv = rec(option.t[int] param, vec[flag] flags, count width, count precision, - ty typ); + ty ty); // A fragment of the output sequence tag piece { @@ -74,6 +76,7 @@ fn bad_fmt_call() { fail; } +// TODO: Need to thread parser through here to handle errors correctly fn expand_syntax_ext(vec[@ast.expr] args, option.t[@ast.expr] body) -> @ast.expr { @@ -96,6 +99,8 @@ fn expand_syntax_ext(vec[@ast.expr] args, } } log "done printing all pieces"; + auto args_len = _vec.len[@ast.expr](args); + auto fmt_args = _vec.slice[@ast.expr](args, 1u, args_len - 1u); ret pieces_to_expr(pieces, args); } @@ -179,7 +184,7 @@ fn parse_conversion(str s, uint i, uint lim) -> tup(piece, uint) { flags = flags._0, width = width._0, precision = prec._0, - typ = ty._0)), + ty = ty._0)), ty._1); } @@ -252,22 +257,107 @@ fn parse_type(str s, uint i, uint lim) -> tup(ty, uint) { fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { - fn make_new_str(common.span sp, str s) -> @ast.expr { - auto strlit = ast.lit_str(s); - auto spstrlit = @parser.spanned[ast.lit_](sp, sp, strlit); - auto expr = ast.expr_lit(spstrlit, ast.ann_none); + fn make_new_lit(common.span sp, ast.lit_ lit) -> @ast.expr { + auto sp_lit = @parser.spanned[ast.lit_](sp, sp, lit); + auto expr = ast.expr_lit(sp_lit, ast.ann_none); ret @parser.spanned[ast.expr_](sp, sp, expr); } + fn make_new_str(common.span sp, str s) -> @ast.expr { + auto lit = ast.lit_str(s); + ret make_new_lit(sp, lit); + } + + fn make_new_uint(common.span sp, uint u) -> @ast.expr { + auto lit = ast.lit_uint(u); + ret make_new_lit(sp, lit); + } + fn make_add_expr(common.span sp, @ast.expr lhs, @ast.expr rhs) -> @ast.expr { auto binexpr = ast.expr_binary(ast.add, lhs, rhs, ast.ann_none); ret @parser.spanned[ast.expr_](sp, sp, binexpr); } + fn make_call(common.span sp, vec[ast.ident] fn_path, + vec[@ast.expr] args) -> @ast.expr { + let vec[ast.ident] path_idents = fn_path; + let vec[@ast.ty] path_types = vec(); + auto path = rec(idents = path_idents, types = path_types); + auto sp_path = parser.spanned[ast.path_](sp, sp, path); + auto pathexpr = ast.expr_path(sp_path, none[ast.def], ast.ann_none); + auto sp_pathexpr = @parser.spanned[ast.expr_](sp, sp, pathexpr); + auto callexpr = ast.expr_call(sp_pathexpr, args, ast.ann_none); + auto sp_callexpr = @parser.spanned[ast.expr_](sp, sp, callexpr); + ret sp_callexpr; + } + + fn make_new_conv(conv cnv, @ast.expr arg) -> @ast.expr { + + auto unsupported = "conversion not supported in #fmt string"; + + alt (cnv.param) { + case (option.none[int]) { + } + case (_) { + log unsupported; + fail; + } + } + + if (_vec.len[flag](cnv.flags) != 0u) { + log unsupported; + fail; + } + + alt (cnv.width) { + case (count_implied) { + } + case (_) { + log unsupported; + fail; + } + } + + alt (cnv.precision) { + case (count_implied) { + } + case (_) { + log unsupported; + fail; + } + } + + alt (cnv.ty) { + case (ty_str) { + ret arg; + } + case (ty_int(?sign)) { + alt (sign) { + case (signed) { + let vec[str] path = vec("std", "_int", "to_str"); + auto radix_expr = make_new_uint(arg.span, 10u); + let vec[@ast.expr] args = vec(arg, radix_expr); + ret make_call(arg.span, path, args); + } + case (unsigned) { + let vec[str] path = vec("std", "_uint", "to_str"); + auto radix_expr = make_new_uint(arg.span, 10u); + let vec[@ast.expr] args = vec(arg, radix_expr); + ret make_call(arg.span, path, args); + } + } + } + case (_) { + log unsupported; + fail; + } + } + } + auto sp = args.(0).span; - auto n = 0; - auto tmp_expr = make_new_str(sp, "whatever"); + auto n = 0u; + auto tmp_expr = make_new_str(sp, ""); for (piece p in pieces) { alt (p) { @@ -276,6 +366,15 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { tmp_expr = make_add_expr(sp, tmp_expr, s_expr); } case (piece_conv(?conv)) { + if (n >= _vec.len[@ast.expr](args)) { + log "too many conversions in #fmt string"; + fail; + } + + n += 1u; + auto arg_expr = args.(n); + auto c_expr = make_new_conv(conv, arg_expr); + tmp_expr = make_add_expr(sp, tmp_expr, c_expr); } } } -- cgit v1.2.3 From 41a043303a53550590b2a8f10b3e57b79a92ecaa Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 27 Feb 2011 22:17:59 -0500 Subject: Remove debug logging from extfmt --- src/comp/front/extfmt.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index bd5bab5b..938704b9 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -85,20 +85,7 @@ fn expand_syntax_ext(vec[@ast.expr] args, } auto fmt = expr_to_str(args.(0)); - log fmt; auto pieces = parse_fmt_string(fmt); - log "printing all pieces"; - for (piece p in pieces) { - alt (p) { - case (piece_string(?s)) { - log s; - } - case (piece_conv(_)) { - log "conv"; - } - } - } - log "done printing all pieces"; auto args_len = _vec.len[@ast.expr](args); auto fmt_args = _vec.slice[@ast.expr](args, 1u, args_len - 1u); ret pieces_to_expr(pieces, args); -- cgit v1.2.3 From 7350b7ff238c886018ecd3924298fa63895dd2f8 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 27 Feb 2011 22:18:27 -0500 Subject: Add more #fmt tests --- src/test/run-pass/syntax-extension-fmt.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/run-pass/syntax-extension-fmt.rs b/src/test/run-pass/syntax-extension-fmt.rs index b7076c81..ebb09f96 100644 --- a/src/test/run-pass/syntax-extension-fmt.rs +++ b/src/test/run-pass/syntax-extension-fmt.rs @@ -10,4 +10,7 @@ fn test(str actual, str expected) { fn main() { test(#fmt("hello %d friends and %s things", 10, "formatted"), "hello 10 friends and formatted things"); + test(#fmt("d: %d", 1), "d: 1"); + test(#fmt("i: %i", 2), "i: 2"); + test(#fmt("s: %s", "test"), "s: test"); } -- cgit v1.2.3 From 7cef1b3a0f645a3cc420a4ae9583b1fd5463e833 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 27 Feb 2011 22:19:03 -0500 Subject: Add pretty printing for expr_call, expr_path, and more literals --- src/comp/front/pretty.rs | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/comp/front/pretty.rs b/src/comp/front/pretty.rs index 8e5414ee..267763e3 100644 --- a/src/comp/front/pretty.rs +++ b/src/comp/front/pretty.rs @@ -1,4 +1,9 @@ -use std; +import std._int; +import std._str; +import std._uint; +import std._vec; + +export print_expr; fn unknown() -> str { ret ""; @@ -7,22 +12,34 @@ fn unknown() -> str { fn print_expr(@ast.expr expr) -> str { alt (expr.node) { case (ast.expr_lit(?lit, _)) { - ret print_expr_lit(lit); + ret print_lit(lit); } case (ast.expr_binary(?op, ?lhs, ?rhs, _)) { ret print_expr_binary(op, lhs, rhs); } + case (ast.expr_call(?path, ?args, _)) { + ret print_expr_call(path, args); + } + case (ast.expr_path(?path, _, _)) { + ret print_path(path); + } case (_) { ret unknown(); } } } -fn print_expr_lit(@ast.lit lit) -> str { +fn print_lit(@ast.lit lit) -> str { alt (lit.node) { case (ast.lit_str(?s)) { ret "\"" + s + "\""; } + case (ast.lit_int(?i)) { + ret _int.to_str(i, 10u); + } + case (ast.lit_uint(?u)) { + ret _uint.to_str(u, 10u); + } case (_) { ret unknown(); } @@ -39,6 +56,23 @@ fn print_expr_binary(ast.binop op, @ast.expr lhs, @ast.expr rhs) -> str { } } +fn print_expr_call(@ast.expr path_expr, vec[@ast.expr] args) -> str { + auto s = print_expr(path_expr); + + s += "("; + fn print_expr_ref(&@ast.expr e) -> str { ret print_expr(e); } + auto mapfn = print_expr_ref; + auto argstrs = _vec.map[@ast.expr, str](mapfn, args); + s += _str.connect(argstrs, ", "); + s += ")"; + + ret s; +} + +fn print_path(ast.path path) -> str { + ret _str.connect(path.node.idents, "."); +} + // // Local Variables: // mode: rust -- cgit v1.2.3 From c1e6f5328c3f46884ed7a7e29c780e307b02100a Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 27 Feb 2011 22:35:27 -0500 Subject: Make the expanded expression in expr_ext not optional --- src/comp/front/ast.rs | 2 +- src/comp/front/parser.rs | 2 +- src/comp/middle/fold.rs | 9 ++++----- src/comp/middle/trans.rs | 2 +- src/comp/middle/typeck.rs | 5 ++--- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 18add3bd..694a709d 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -185,7 +185,7 @@ tag expr_ { expr_field(@expr, ident, ann); expr_index(@expr, @expr, ann); expr_path(path, option.t[def], ann); - expr_ext(path, vec[@expr], option.t[@expr], option.t[@expr], ann); + expr_ext(path, vec[@expr], option.t[@expr], @expr, ann); expr_fail; expr_ret(option.t[@expr]); expr_put(option.t[@expr]); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 7a7a863c..5fe16536 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -755,7 +755,7 @@ impure fn expand_syntax_ext(parser p, ast.span sp, if (_str.eq(extname, "fmt")) { auto expanded = extfmt.expand_syntax_ext(args, body); auto newexpr = ast.expr_ext(path, args, body, - some[@ast.expr](expanded), + expanded, ast.ann_none); ret newexpr; diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index d533082c..c7041b26 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -157,7 +157,7 @@ type ast_fold[ENV] = (fn(&ENV e, &span sp, &path p, vec[@expr] args, option.t[@expr] body, - option.t[@expr] expanded, + @expr expanded, ann a) -> @expr) fold_expr_ext, (fn(&ENV e, &span sp) -> @expr) fold_expr_fail, @@ -653,10 +653,9 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr { case (ast.expr_ext(?p, ?args, ?body, ?expanded, ?t)) { // Only fold the expanded expression, not the // expressions involved in syntax extension - auto exp = option.get[@expr](expanded); - auto exp_ = fold_expr(env_, fld, exp); + auto exp = fold_expr(env_, fld, expanded); ret fld.fold_expr_ext(env_, e.span, p, args, body, - some[@ast.expr](exp_), t); + exp, t); } case (ast.expr_fail) { @@ -1184,7 +1183,7 @@ fn identity_fold_expr_path[ENV](&ENV env, &span sp, fn identity_fold_expr_ext[ENV](&ENV env, &span sp, &path p, vec[@expr] args, option.t[@expr] body, - option.t[@expr] expanded, + @expr expanded, ann a) -> @expr { ret @respan(sp, ast.expr_ext(p, args, body, expanded, a)); } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9fee3dab..2594590a 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3694,7 +3694,7 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { } case (ast.expr_ext(_, _, _, ?expanded, _)) { - ret trans_expr(cx, option.get[@ast.expr](expanded)); + ret trans_expr(cx, expanded); } case (ast.expr_fail) { diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 5cccc4d7..f8f7fc72 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1514,11 +1514,10 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } case (ast.expr_ext(?p, ?args, ?body, ?expanded, _)) { - auto exp_ = check_expr(fcx, option.get[@ast.expr](expanded)); + auto exp_ = check_expr(fcx, expanded); auto t = expr_ty(exp_); ret @fold.respan[ast.expr_](expr.span, - ast.expr_ext(p, args, body, - some[@ast.expr](exp_), + ast.expr_ext(p, args, body, exp_, ast.ann_type(t))); } -- cgit v1.2.3 From dbd90996ee1fd8eb996ac85f44fe17f0f3d834ca Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 1 Mar 2011 19:50:27 -0500 Subject: Remove unused is_ext_expr --- src/comp/front/ast.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 694a709d..46f57168 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -363,17 +363,6 @@ fn is_call_expr(@expr e) -> bool { } } -fn is_ext_expr(@expr e) -> bool { - alt (e.node) { - case (expr_ext(_, _, _, _, _)) { - ret true; - } - case (_) { - ret false; - } - } -} - // // Local Variables: // mode: rust -- cgit v1.2.3 From 77a0dc06a7cead4a1d38cdb68f1465cbeccf48c1 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 1 Mar 2011 19:51:21 -0500 Subject: Whitespace cleanup --- src/comp/front/extfmt.rs | 10 +++++----- src/comp/front/parser.rs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index 938704b9..dfeb79de 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -1,14 +1,14 @@ /* The 'fmt' extension is modeled on the posix printf system. - * + * * A posix conversion ostensibly looks like this: - * + * * %[parameter][flags][width][.precision][length]type - * + * * Given the different numeric type bestiary we have, we omit the 'length' * parameter and support slightly different conversions for 'type': - * + * * %[parameter][flags][width][.precision]type - * + * * we also only support translating-to-rust a tiny subset of the possible * combinations at the moment. */ diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 5fe16536..50545a2f 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -737,7 +737,7 @@ impure fn parse_bottom_expr(parser p) -> @ast.expr { ret @spanned(lo, hi, ex); } -/* +/* * FIXME: This is a crude approximation of the syntax-extension system, * for purposes of prototyping and/or hard-wiring any extensions we * wish to use while bootstrapping. The eventual aim is to permit -- cgit v1.2.3 From 4bc9052e135c25c79d4fa8556c44876e620ba1f7 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 1 Mar 2011 21:03:44 -0500 Subject: Add debug logging for #fmt conv. Implement peek_num fn --- src/comp/front/extfmt.rs | 144 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 123 insertions(+), 21 deletions(-) diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index dfeb79de..5ca50c05 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -71,17 +71,13 @@ tag piece { piece_conv(conv); } -fn bad_fmt_call() { - log "malformed #fmt call"; - fail; -} - // TODO: Need to thread parser through here to handle errors correctly fn expand_syntax_ext(vec[@ast.expr] args, option.t[@ast.expr] body) -> @ast.expr { if (_vec.len[@ast.expr](args) == 0u) { - bad_fmt_call(); + log "malformed #fmt call"; + fail; } auto fmt = expr_to_str(args.(0)); @@ -101,7 +97,7 @@ fn expr_to_str(@ast.expr expr) -> str { } } } - bad_fmt_call(); + log "malformed #fmt call"; fail; } @@ -146,19 +142,29 @@ fn parse_fmt_string(str s) -> vec[piece] { ret pieces; } -fn peek_num(str s, uint i, uint lim) -> option.t[tup(int, int)] { +fn peek_num(str s, uint i, uint lim) -> option.t[tup(uint, uint)] { if (i >= lim) { - ret none[tup(int, int)]; - } else { - ret none[tup(int, int)]; - /*if ('0' <= c && c <= '9') { - log c; - fail; - } else { - ret option.none[tup(int, int)]; + ret none[tup(uint, uint)]; + } + + // FIXME: Presumably s.(i) will return char eventually + auto c = s.(i); + if (!('0' as u8 <= c && c <= '9' as u8)) { + ret option.none[tup(uint, uint)]; + } + + auto n = (c - ('0' as u8)) as uint; + alt (peek_num(s, i + 1u, lim)) { + case (none[tup(uint, uint)]) { + ret some[tup(uint, uint)](tup(n, i + 1u)); + } + case (some[tup(uint, uint)](?next)) { + auto m = next._0; + auto j = next._1; + ret some[tup(uint, uint)](tup(n * 10u + m, j)); } - */ } + } fn parse_conversion(str s, uint i, uint lim) -> tup(piece, uint) { @@ -182,10 +188,10 @@ fn parse_parameter(str s, uint i, uint lim) -> tup(option.t[int], uint) { auto num = peek_num(s, i, lim); alt (num) { - case (none[tup(int, int)]) { + case (none[tup(uint, uint)]) { ret tup(none[int], i); } - case (some[tup(int, int)](?t)) { + case (some[tup(uint, uint)](?t)) { fail; } } @@ -342,6 +348,98 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { } } + fn log_conv(conv c) { + alt (c.param) { + case (some[int](?p)) { + log "param: " + std._int.to_str(p, 10u); + } + case (_) { + log "param: none"; + } + } + for (flag f in c.flags) { + alt (f) { + case (flag_left_justify) { + log "flag: left justify"; + } + case (flag_left_zero_pad) { + log "flag: left zero pad"; + } + case (flag_left_space_pad) { + log "flag: left space pad"; + } + case (flag_plus_if_positive) { + log "flag: plus if positive"; + } + case (flag_alternate) { + log "flag: alternate"; + } + } + } + alt (c.width) { + case (count_is(?i)) { + log "width: count is " + std._int.to_str(i, 10u); + } + case (count_is_param(?i)) { + log "width: count is param " + std._int.to_str(i, 10u); + } + case (count_is_next_param) { + log "width: count is next param"; + } + case (count_implied) { + log "width: count is implied"; + } + } + alt (c.precision) { + case (count_is(?i)) { + log "prec: count is " + std._int.to_str(i, 10u); + } + case (count_is_param(?i)) { + log "prec: count is param " + std._int.to_str(i, 10u); + } + case (count_is_next_param) { + log "prec: count is next param"; + } + case (count_implied) { + log "prec: count is implied"; + } + } + alt (c.ty) { + case (ty_bool) { + log "type: bool"; + } + case (ty_str) { + log "type: str"; + } + case (ty_char) { + log "type: char"; + } + case (ty_int(?s)) { + alt (s) { + case (signed) { + log "type: signed"; + } + case (unsigned) { + log "type: unsigned"; + } + } + } + case (ty_bits) { + log "type: bits"; + } + case (ty_hex(?cs)) { + alt (cs) { + case (case_upper) { + log "type: uhex"; + } + case (case_lower) { + log "type: lhex"; + } + } + } + } + } + auto sp = args.(0).span; auto n = 0u; auto tmp_expr = make_new_str(sp, ""); @@ -358,6 +456,10 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { fail; } + // TODO: Remove debug logging + log "Building conversion:"; + log_conv(conv); + n += 1u; auto arg_expr = args.(n); auto c_expr = make_new_conv(conv, arg_expr); @@ -366,10 +468,10 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { } } - // TODO: Remove this print and return the real expanded AST + // TODO: Remove this debug logging log "dumping expanded ast:"; log pretty.print_expr(tmp_expr); - ret make_new_str(sp, "TODO"); + ret tmp_expr; } // -- cgit v1.2.3 From 012c2d18d04f27ad52322a1a7673a14817c7d291 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 1 Mar 2011 22:43:19 -0500 Subject: Finish #fmt string parsing. Completely untested. --- src/comp/front/extfmt.rs | 96 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 89 insertions(+), 7 deletions(-) diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index 5ca50c05..3f1e5c30 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -81,6 +81,10 @@ fn expand_syntax_ext(vec[@ast.expr] args, } auto fmt = expr_to_str(args.(0)); + + log "Format string:"; + log fmt; + auto pieces = parse_fmt_string(fmt); auto args_len = _vec.len[@ast.expr](args); auto fmt_args = _vec.slice[@ast.expr](args, 1u, args_len - 1u); @@ -170,7 +174,7 @@ fn peek_num(str s, uint i, uint lim) -> option.t[tup(uint, uint)] { fn parse_conversion(str s, uint i, uint lim) -> tup(piece, uint) { auto parm = parse_parameter(s, i, lim); auto flags = parse_flags(s, parm._1, lim); - auto width = parse_width(s, flags._1, lim); + auto width = parse_count(s, flags._1, lim); auto prec = parse_precision(s, width._1, lim); auto ty = parse_type(s, prec._1, lim); ret tup(piece_conv(rec(param = parm._0, @@ -192,22 +196,100 @@ fn parse_parameter(str s, uint i, uint lim) -> tup(option.t[int], uint) { ret tup(none[int], i); } case (some[tup(uint, uint)](?t)) { - fail; + auto n = t._0; + auto j = t._1; + if (j < lim && s.(j) == '$' as u8) { + ret tup(some[int](n as int), j + 1u); + } + else { + ret tup(none[int], i); + } } } } fn parse_flags(str s, uint i, uint lim) -> tup(vec[flag], uint) { - let vec[flag] flags = vec(); - ret tup(flags, i); + let vec[flag] noflags = vec(); + + if (i >= lim) { + ret tup(noflags, i); + } + + fn more_(flag f, str s, uint i, uint lim) -> tup(vec[flag], uint) { + auto next = parse_flags(s, i + 1u, lim); + auto rest = next._0; + auto j = next._1; + let vec[flag] curr = vec(f); + ret tup(curr + rest, j); + } + + auto more = bind more_(_, s, i, lim); + + auto f = s.(i); + if (f == ('-' as u8)) { + ret more(flag_left_justify); + } else if (f == ('0' as u8)) { + ret more(flag_left_zero_pad); + } else if (f == (' ' as u8)) { + ret more(flag_left_space_pad); + } else if (f == ('+' as u8)) { + ret more(flag_plus_if_positive); + } else if (f == ('#' as u8)) { + ret more(flag_alternate); + } else { + ret tup(noflags, i); + } } -fn parse_width(str s, uint i, uint lim) -> tup(count, uint) { - ret tup(count_implied, i); +fn parse_count(str s, uint i, uint lim) -> tup(count, uint) { + if (i >= lim) { + ret tup(count_implied, i); + } + + // FIXME: These inner functions are just to avoid a rustboot + // "Unsatisfied precondition constraint" bug with alts nested in ifs + fn parse_star_count(str s, uint i, uint lim) -> tup(count, uint) { + auto param = parse_parameter(s, i + 1u, lim); + auto j = param._1; + alt (param._0) { + case (none[int]) { + ret tup(count_is_next_param, j); + } + case (some[int](?n)) { + ret tup(count_is_param(n), j); + } + } + } + + fn parse_count_(str s, uint i, uint lim) -> tup(count, uint) { + auto num = peek_num(s, i, lim); + alt (num) { + case (none[tup(uint, uint)]) { + ret tup(count_implied, i); + } + case (some[tup(uint, uint)](?num)) { + ret tup(count_is(num._0 as int), num._1); + } + } + } + + if (s.(i) == ('*' as u8)) { + ret parse_star_count(s, i, lim); + } else { + ret parse_count_(s, i, lim); + } } fn parse_precision(str s, uint i, uint lim) -> tup(count, uint) { - ret tup(count_implied, i); + if (i >= lim) { + ret tup(count_implied, i); + } + + if (s.(i) == '.' as u8) { + ret parse_count(s, i + 1u, lim); + } else { + ret tup(count_implied, i); + } } fn parse_type(str s, uint i, uint lim) -> tup(ty, uint) { -- cgit v1.2.3 From d33110ebfcf7f2a5796d3a4c4f969efbf13e7548 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Mar 2011 13:43:33 -0800 Subject: Comment-out TRACK_ALLOCATIONS again. Leave a note about it. --- src/rt/memory_region.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/rt/memory_region.cpp b/src/rt/memory_region.cpp index fb19620f..48220290 100644 --- a/src/rt/memory_region.cpp +++ b/src/rt/memory_region.cpp @@ -1,7 +1,10 @@ #include "rust_internal.h" #include "memory_region.h" -#define TRACK_ALLOCATIONS +// NB: please do not commit code with this uncommented. It's +// hugely expensive and should only be used as a last resort. +// +// #define TRACK_ALLOCATIONS memory_region::memory_region(rust_srv *srv, bool synchronized) : _srv(srv), _parent(NULL), _live_allocations(0), -- cgit v1.2.3 From 9e4943c9229e15fa11069eeb2b20060994f9ac0f Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Mar 2011 13:50:42 -0800 Subject: Parse, add to AST, and otherwise ignore 'export' view items. Need to add support to resolve. --- src/comp/front/ast.rs | 6 ++++++ src/comp/front/parser.rs | 39 ++++++++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 46f57168..474dc4aa 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -279,6 +279,7 @@ type view_item = spanned[view_item_]; tag view_item_ { view_item_use(ident, vec[@meta_item], def_id); view_item_import(ident, vec[ident], def_id, option.t[def]); + view_item_export(ident); } type item = spanned[item_]; @@ -306,6 +307,11 @@ fn index_view_item(mod_index index, @view_item it) { case(ast.view_item_import(?def_ident,_,_,_)) { index.insert(def_ident, ast.mie_view_item(it)); } + case(ast.view_item_export(_)) { + // NB: don't index these, they might collide with + // the import or use that they're exporting. Have + // to do linear search for exports. + } } } diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 50545a2f..1be4226c 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -2187,7 +2187,16 @@ impure fn parse_import(parser p) -> @ast.view_item { fail; } -impure fn parse_use_or_import(parser p) -> @ast.view_item { +impure fn parse_export(parser p) -> @ast.view_item { + auto lo = p.get_span(); + expect(p, token.EXPORT); + auto id = parse_ident(p); + auto hi = p.get_span(); + expect(p, token.SEMI); + ret @spanned(lo, hi, ast.view_item_export(id)); +} + +impure fn parse_view_item(parser p) -> @ast.view_item { alt (p.peek()) { case (token.USE) { ret parse_use(p); @@ -2195,23 +2204,26 @@ impure fn parse_use_or_import(parser p) -> @ast.view_item { case (token.IMPORT) { ret parse_import(p); } + case (token.EXPORT) { + ret parse_export(p); + } } } -fn is_use_or_import(token.token t) -> bool { - if (t == token.USE) { - ret true; - } - if (t == token.IMPORT) { - ret true; +fn is_view_item(token.token t) -> bool { + alt (t) { + case (token.USE) { ret true; } + case (token.IMPORT) { ret true; } + case (token.EXPORT) { ret true; } + case (_) {} } ret false; } impure fn parse_view(parser p, ast.mod_index index) -> vec[@ast.view_item] { let vec[@ast.view_item] items = vec(); - while (is_use_or_import(p.peek())) { - auto item = parse_use_or_import(p); + while (is_view_item(p.peek())) { + auto item = parse_view_item(p); items += vec(item); ast.index_view_item(index, item); @@ -2305,12 +2317,17 @@ impure fn parse_crate_directive(parser p) -> ast.crate_directive } case (token.USE) { - auto vi = parse_use_or_import(p); + auto vi = parse_view_item(p); ret spanned(lo, vi.span, ast.cdir_view_item(vi)); } case (token.IMPORT) { - auto vi = parse_use_or_import(p); + auto vi = parse_view_item(p); + ret spanned(lo, vi.span, ast.cdir_view_item(vi)); + } + + case (token.EXPORT) { + auto vi = parse_view_item(p); ret spanned(lo, vi.span, ast.cdir_view_item(vi)); } -- cgit v1.2.3 From fc722b17c92a91853f75c31e05b9a50d45fbe5e9 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Mar 2011 13:53:08 -0800 Subject: Comment-out some logging chatter in extfmt. --- src/comp/front/extfmt.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index 3f1e5c30..48f05df7 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -82,8 +82,8 @@ fn expand_syntax_ext(vec[@ast.expr] args, auto fmt = expr_to_str(args.(0)); - log "Format string:"; - log fmt; + // log "Format string:"; + // log fmt; auto pieces = parse_fmt_string(fmt); auto args_len = _vec.len[@ast.expr](args); @@ -539,8 +539,8 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { } // TODO: Remove debug logging - log "Building conversion:"; - log_conv(conv); + // log "Building conversion:"; + // log_conv(conv); n += 1u; auto arg_expr = args.(n); @@ -551,8 +551,8 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { } // TODO: Remove this debug logging - log "dumping expanded ast:"; - log pretty.print_expr(tmp_expr); + // log "dumping expanded ast:"; + // log pretty.print_expr(tmp_expr); ret tmp_expr; } -- cgit v1.2.3 From c19e4e1c2987383ef686ca831f8115a1179ecb40 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 2 Mar 2011 16:13:33 -0800 Subject: rustc: Don't have type_of_arg() rely on the particular lie told by type_of() --- src/comp/middle/trans.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2594590a..45f59841 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -621,11 +621,22 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { } fn type_of_arg(@crate_ctxt cx, &ty.arg arg) -> TypeRef { - auto ty = type_of_inner(cx, arg.ty); + alt (arg.ty.struct) { + case (ty.ty_param(_)) { + if (arg.mode == ast.alias) { + ret T_typaram_ptr(cx.tn); + } + } + case (_) { + // fall through + } + } + + auto typ = type_of_inner(cx, arg.ty); if (arg.mode == ast.alias) { - ty = T_ptr(ty); + typ = T_ptr(typ); } - ret ty; + ret typ; } // Name sanitation. LLVM will happily accept identifiers with weird names, but -- cgit v1.2.3 From 21e42ad88a388d2178770fe2ee046c4f30148da9 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 2 Mar 2011 16:23:14 -0800 Subject: rustc: For derived tydescs, explicitly store 0 for size and align when the type in question has a dynamic size --- src/comp/middle/trans.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 45f59841..2258ee18 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1201,7 +1201,19 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { auto dg = make_drop_glue; auto drop_glue = make_generic_glue(cx, t, "drop", dg, typaram_defs); - auto llty = type_of(cx, t); + auto llsize; + auto llalign; + if (!ty.type_has_dynamic_size(t)) { + auto llty = type_of(cx, t); + llsize = llsize_of(llty); + llalign = llalign_of(llty); + } else { + // These will be overwritten as the derived tydesc is generated, so + // we create placeholder values. + llsize = C_int(0); + llalign = C_int(0); + } + auto glue_fn_ty = T_ptr(T_glue_fn(cx.tn)); // FIXME: this adjustment has to do with the ridiculous encoding of @@ -1218,8 +1230,8 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { auto gvar = llvm.LLVMAddGlobal(cx.llmod, T_tydesc(cx.tn), _str.buf(name)); auto tydesc = C_struct(vec(C_null(T_ptr(T_ptr(T_tydesc(cx.tn)))), - llsize_of(llty), - llalign_of(llty), + llsize, + llalign, off(gvar, take_glue), // take_glue_off off(gvar, drop_glue), // drop_glue_off C_null(glue_fn_ty), // free_glue_off -- cgit v1.2.3 From 5ebb91f24d84391f6c821c54fb8c497964eac6c3 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 2 Mar 2011 16:31:20 -0800 Subject: rustc: Teach iter_structural_ty about dynamically-sized tuples and records --- src/comp/middle/trans.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2258ee18..f58fe188 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1596,8 +1596,10 @@ fn iter_structural_ty_full(@block_ctxt cx, case (ty.ty_tup(?args)) { let int i = 0; for (@ty.t arg in args) { - auto elt_a = r.bcx.build.GEP(av, vec(C_int(0), C_int(i))); - auto elt_b = r.bcx.build.GEP(bv, vec(C_int(0), C_int(i))); + r = GEP_tup_like(r.bcx, t, av, vec(0, i)); + auto elt_a = r.val; + r = GEP_tup_like(r.bcx, t, bv, vec(0, i)); + auto elt_b = r.val; r = f(r.bcx, load_scalar_or_boxed(r.bcx, elt_a, arg), load_scalar_or_boxed(r.bcx, elt_b, arg), @@ -1608,8 +1610,10 @@ fn iter_structural_ty_full(@block_ctxt cx, case (ty.ty_rec(?fields)) { let int i = 0; for (ty.field fld in fields) { - auto llfld_a = r.bcx.build.GEP(av, vec(C_int(0), C_int(i))); - auto llfld_b = r.bcx.build.GEP(bv, vec(C_int(0), C_int(i))); + r = GEP_tup_like(r.bcx, t, av, vec(0, i)); + auto llfld_a = r.val; + r = GEP_tup_like(r.bcx, t, bv, vec(0, i)); + auto llfld_b = r.val; r = f(r.bcx, load_scalar_or_boxed(r.bcx, llfld_a, fld.ty), load_scalar_or_boxed(r.bcx, llfld_b, fld.ty), -- cgit v1.2.3 From dddeba19d33a1aa2e7681ae84424dbe4d7b510b7 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Mar 2011 16:42:09 -0800 Subject: Sketch out some more pieces of vec-append. --- src/comp/back/abi.rs | 4 ++ src/comp/middle/trans.rs | 132 ++++++++++++++++++++++++++++++++++++++++++----- src/comp/middle/ty.rs | 10 ++++ 3 files changed, 133 insertions(+), 13 deletions(-) diff --git a/src/comp/back/abi.rs b/src/comp/back/abi.rs index f41f6e20..89d6b487 100644 --- a/src/comp/back/abi.rs +++ b/src/comp/back/abi.rs @@ -71,6 +71,10 @@ fn bzero_glue_name() -> str { ret "rust_bzero_glue"; } +fn vec_grow_glue_name() -> str { + ret "rust_vec_grow_glue"; +} + fn upcall_glue_name(int n) -> str { ret "rust_upcall_" + util.common.istr(n); } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index f58fe188..2cd26664 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -57,7 +57,8 @@ type glue_fns = rec(ValueRef activate_glue, vec[ValueRef] upcall_glues, ValueRef no_op_type_glue, ValueRef memcpy_glue, - ValueRef bzero_glue); + ValueRef bzero_glue, + ValueRef vec_grow_glue); type tag_info = rec( type_handle th, @@ -809,7 +810,7 @@ fn trans_upcall(@block_ctxt cx, str name, vec[ValueRef] args) -> result { } fn trans_non_gc_free(@block_ctxt cx, ValueRef v) -> result { - ret trans_upcall(cx, "upcall_free", vec(cx.build.PtrToInt(v, T_int()), + ret trans_upcall(cx, "upcall_free", vec(vp2i(cx, v), C_int(0))); } @@ -1065,7 +1066,7 @@ fn trans_malloc_inner(@block_ctxt cx, TypeRef llptr_ty) -> result { auto tydesc = C_int(0); auto sz = llsize_of(llbody_ty); auto sub = trans_upcall(cx, "upcall_malloc", vec(sz, tydesc)); - sub.val = sub.bcx.build.IntToPtr(sub.val, llptr_ty); + sub.val = vi2p(sub.bcx, sub.val, llptr_ty); ret sub; } @@ -1181,10 +1182,10 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { sz.val, align.val, C_int((1u + n_params) as int), - bcx.build.PtrToInt(tydescs, T_int()))); + vp2i(bcx, tydescs))); - ret res(v.bcx, v.bcx.build.IntToPtr(v.val, - T_ptr(T_tydesc(cx.fcx.ccx.tn)))); + ret res(v.bcx, vi2p(v.bcx, v.val, + T_ptr(T_tydesc(cx.fcx.ccx.tn)))); } // Otherwise, generate a tydesc if necessary, and return it. @@ -1829,9 +1830,9 @@ fn call_tydesc_glue_full(@block_ctxt cx, ValueRef v, // glue-pointer-constants in the tydesc records: They are tydesc-relative // displacements. This is purely for compatibility with rustboot and // should go when it is discarded. - llfn = cx.build.IntToPtr(cx.build.Add(cx.build.PtrToInt(llfn, T_int()), - cx.build.PtrToInt(tydesc, T_int())), - val_ty(llfn)); + llfn = vi2p(cx, cx.build.Add(vp2i(cx, llfn), + vp2i(cx, tydesc)), + val_ty(llfn)); cx.build.FastCall(llfn, vec(C_null(T_ptr(T_nil())), cx.fcx.lltaskptr, @@ -2221,11 +2222,30 @@ fn trans_integral_compare(@block_ctxt cx, ast.binop op, @ty.t intype, ret cx.build.ICmp(cmp, lhs, rhs); } +fn trans_sequence_append(@block_ctxt cx, @ty.t t, + ValueRef lhs, ValueRef rhs) -> result { + cx.fcx.ccx.sess.unimpl("sequence append"); + fail; +} + +fn trans_sequence_add(@block_ctxt cx, @ty.t t, + ValueRef lhs, ValueRef rhs) -> result { + auto r = alloc_ty(cx, t); + r = copy_ty(r.bcx, INIT, r.val, lhs, t); + ret trans_sequence_append(r.bcx, t, lhs, rhs); +} + + fn trans_eager_binop(@block_ctxt cx, ast.binop op, @ty.t intype, ValueRef lhs, ValueRef rhs) -> result { alt (op) { - case (ast.add) { ret res(cx, cx.build.Add(lhs, rhs)); } + case (ast.add) { + if (ty.type_is_sequence(intype)) { + ret trans_sequence_add(cx, intype, lhs, rhs); + } + ret res(cx, cx.build.Add(lhs, rhs)); + } case (ast.sub) { ret res(cx, cx.build.Sub(lhs, rhs)); } case (ast.mul) { ret res(cx, cx.build.Mul(lhs, rhs)); } @@ -3539,7 +3559,7 @@ fn trans_vec(@block_ctxt cx, vec[@ast.expr] args, bcx = sub.bcx; auto llty = type_of(bcx.fcx.ccx, t); - auto vec_val = bcx.build.IntToPtr(sub.val, llty); + auto vec_val = vi2p(bcx, sub.val, llty); find_scope_cx(bcx).cleanups += clean(bind drop_ty(_, vec_val, t)); auto body = bcx.build.GEP(vec_val, vec(C_int(0), @@ -3782,7 +3802,7 @@ fn trans_log(@block_ctxt cx, @ast.expr e) -> result { auto e_ty = ty.expr_ty(e); alt (e_ty.struct) { case (ty.ty_str) { - auto v = sub.bcx.build.PtrToInt(sub.val, T_int()); + auto v = vp2i(sub.bcx, sub.val); ret trans_upcall(sub.bcx, "upcall_log_str", vec(v)); @@ -4907,6 +4927,16 @@ fn trans_constants(@crate_ctxt cx, @ast.crate crate) { fold.fold_crate[@crate_ctxt](cx, fld, crate); } + +fn vp2i(@block_ctxt cx, ValueRef v) -> ValueRef { + ret cx.build.PtrToInt(v, T_int()); +} + + +fn vi2p(@block_ctxt cx, ValueRef v, TypeRef t) -> ValueRef { + ret cx.build.IntToPtr(v, t); +} + fn p2i(ValueRef v) -> ValueRef { ret llvm.LLVMConstPtrToInt(v, T_int()); } @@ -5172,6 +5202,80 @@ fn make_bzero_glue(ModuleRef llmod) -> ValueRef { ret fun; } +fn make_vec_grow_glue(ModuleRef llmod, type_names tn) -> ValueRef { + /* + * Args to vec_grow_glue: + * + * 0. (Implicit) task ptr + * + * 1. Pointer to the tydesc of the vec, so that we can tell if it's gc + * mem, and have a tydesc to pass to malloc if we're allocating anew. + * + * 2. Pointer to the tydesc of the vec's stored element type, so that + * elements can be copied to a newly alloc'ed vec if one must be + * created. + * + * 3. Alias to vec that needs to grow (i.e. ptr to ptr to rust_vec). + * + * 4. Number of bytes of growth requested + * + */ + + auto ty = T_fn(vec(T_taskptr(tn), + T_ptr(T_tydesc(tn)), + T_ptr(T_tydesc(tn)), + T_ptr(T_ptr(T_vec(T_int()))), // a lie. + T_int()), T_void()); + + auto llfn = decl_fastcall_fn(llmod, abi.vec_grow_glue_name(), ty); + ret llfn; +} + +fn trans_vec_grow_glue(@crate_ctxt cx) { + + auto llfn = cx.glues.vec_grow_glue; + + let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 0u); + let ValueRef llvec_tydesc = llvm.LLVMGetParam(llfn, 1u); + let ValueRef llelt_tydesc = llvm.LLVMGetParam(llfn, 2u); + let ValueRef llvec_ptr = llvm.LLVMGetParam(llfn, 3u); + let ValueRef llnbytes = llvm.LLVMGetParam(llfn, 4u); + + auto fcx = @rec(llfn=llfn, + lltaskptr=lltaskptr, + llenv=C_null(T_ptr(T_nil())), + llretptr=C_null(T_ptr(T_nil())), + mutable llself=none[ValueRef], + mutable lliterbody=none[ValueRef], + llargs=new_def_hash[ValueRef](), + llobjfields=new_def_hash[ValueRef](), + lllocals=new_def_hash[ValueRef](), + lltydescs=new_def_hash[ValueRef](), + ccx=cx); + + auto bcx = new_top_block_ctxt(fcx); + + auto llneed_copy_ptr = bcx.build.Alloca(T_int()); + + auto llnew_vec_res = + trans_upcall(bcx, "upcall_vec_grow", + vec(vp2i(bcx, bcx.build.Load(llvec_ptr)), + llnbytes, + vp2i(bcx, llneed_copy_ptr), + vp2i(bcx, llvec_tydesc))); + + bcx = llnew_vec_res.bcx; + auto llnew_vec = vi2p(bcx, + llnew_vec_res.val, + T_ptr(T_vec(T_int())) // a lie. + ); + + // FIXME: complete this. + + bcx.build.RetVoid(); +} + + fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns { ret @rec(activate_glue = decl_glue(llmod, tn, abi.activate_glue_name()), yield_glue = decl_glue(llmod, tn, abi.yield_glue_name()), @@ -5197,7 +5301,8 @@ fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns { abi.n_upcall_glues as uint), no_op_type_glue = make_no_op_type_glue(llmod, tn), memcpy_glue = make_memcpy_glue(llmod), - bzero_glue = make_bzero_glue(llmod)); + bzero_glue = make_bzero_glue(llmod), + vec_grow_glue = make_vec_grow_glue(llmod, tn)); } fn trans_crate(session.session sess, @ast.crate crate, str output, @@ -5256,6 +5361,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, trans_mod(cx, crate.node.module); trans_exit_task_glue(cx); + trans_vec_grow_glue(cx); create_crate_constant(cx); if (!shared) { trans_main_fn(cx, cx.crate_ptr); diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 478f54d1..771136da 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -395,6 +395,7 @@ fn type_is_nil(@t ty) -> bool { fail; } + fn type_is_structural(@t ty) -> bool { alt (ty.struct) { case (ty_tup(_)) { ret true; } @@ -407,6 +408,15 @@ fn type_is_structural(@t ty) -> bool { fail; } +fn type_is_sequence(@t ty) -> bool { + alt (ty.struct) { + case (ty_str) { ret true; } + case (ty_vec(_)) { ret true; } + case (_) { ret false; } + } + fail; +} + fn type_is_tup_like(@t ty) -> bool { alt (ty.struct) { case (ty_box(_)) { ret true; } -- cgit v1.2.3 From ec5c5a750d2b9ed7b32902f216a1ae28604c4acb Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 2 Mar 2011 17:24:22 -0800 Subject: rustc: Rework the API for trans_malloc() to be generic-aware and so that clients don't need to call trans_malloc_inner() --- src/comp/middle/trans.rs | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2cd26664..8b0747d5 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1060,22 +1060,26 @@ fn GEP_tup_like(@block_ctxt cx, @ty.t t, } -fn trans_malloc_inner(@block_ctxt cx, TypeRef llptr_ty) -> result { - auto llbody_ty = lib.llvm.llvm.LLVMGetElementType(llptr_ty); +fn trans_raw_malloc(@block_ctxt cx, TypeRef llptr_ty, ValueRef llsize) + -> result { // FIXME: need a table to collect tydesc globals. auto tydesc = C_int(0); - auto sz = llsize_of(llbody_ty); - auto sub = trans_upcall(cx, "upcall_malloc", vec(sz, tydesc)); - sub.val = vi2p(sub.bcx, sub.val, llptr_ty); - ret sub; + auto rslt = trans_upcall(cx, "upcall_malloc", vec(llsize, tydesc)); + rslt = res(rslt.bcx, vi2p(cx, rslt.val, llptr_ty)); + ret rslt; +} + +fn trans_malloc_without_cleanup(@block_ctxt cx, @ty.t t) -> result { + auto llty = type_of(cx.fcx.ccx, t); + auto rslt = size_of(cx, t); + ret trans_raw_malloc(rslt.bcx, llty, rslt.val); } fn trans_malloc(@block_ctxt cx, @ty.t t) -> result { auto scope_cx = find_scope_cx(cx); - auto llptr_ty = type_of(cx.fcx.ccx, t); - auto sub = trans_malloc_inner(cx, llptr_ty); - scope_cx.cleanups += clean(bind drop_ty(_, sub.val, t)); - ret sub; + auto rslt = trans_malloc_without_cleanup(cx, t); + scope_cx.cleanups += clean(bind drop_ty(_, rslt.val, t)); + ret rslt; } @@ -3216,7 +3220,9 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, ty_param_count); // Malloc a box for the body. - auto r = trans_malloc_inner(bcx, llclosure_ty); + // FIXME: this isn't generic-safe + auto r = trans_raw_malloc(bcx, llclosure_ty, + llsize_of(llvm.LLVMGetElementType(llclosure_ty))); auto box = r.val; bcx = r.bcx; auto rc = bcx.build.GEP(box, @@ -4453,7 +4459,8 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, let TypeRef llboxed_body_ty = type_of(cx, boxed_body_ty); // Malloc a box for the body. - auto box = trans_malloc_inner(bcx, llboxed_body_ty); + auto box = trans_raw_malloc(bcx, llboxed_body_ty, + llsize_of(llvm.LLVMGetElementType(llboxed_body_ty))); bcx = box.bcx; auto rc = GEP_tup_like(bcx, boxed_body_ty, box.val, vec(0, abi.box_rc_field_refcnt)); -- cgit v1.2.3 From 792af12a3ca706ec4f0fcc6af006371c7f96abe0 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 2 Mar 2011 18:06:53 -0800 Subject: rustc: Remove unused call to type_of() in trans_tup() --- src/comp/middle/trans.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 8b0747d5..4708ffc5 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3520,7 +3520,6 @@ fn trans_tup(@block_ctxt cx, vec[ast.elt] elts, &ast.ann ann) -> result { auto bcx = cx; auto t = node_ann_type(bcx.fcx.ccx, ann); - auto llty = type_of(bcx.fcx.ccx, t); auto tup_res = alloc_ty(bcx, t); auto tup_val = tup_res.val; bcx = tup_res.bcx; -- cgit v1.2.3 From 675f762621a0e2bb7d746e82bcafa05650786b94 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 2 Mar 2011 18:23:38 -0800 Subject: rustc: Have make_generic_glue pass an opaque type instead of an incorrect type in the case of dynamically sized types --- src/comp/middle/trans.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4708ffc5..3d4f44ea 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1267,7 +1267,9 @@ fn make_generic_glue(@crate_ctxt cx, @ty.t t, str name, auto re; if (!ty.type_is_scalar(t)) { auto llty; - if (ty.type_is_structural(t)) { + if (ty.type_has_dynamic_size(t)) { + llty = T_ptr(T_i8()); + } else if (ty.type_is_structural(t)) { llty = T_ptr(type_of(cx, t)); } else { llty = type_of(cx, t); -- cgit v1.2.3 From 7ab58db4d02443fdfd68e135224a79fe3a212bda Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 2 Mar 2011 18:36:03 -0800 Subject: rustc: Use llsize_of rather than size_of in trans_malloc_without_cleanup(). Should put out burning tinderbox... --- src/comp/middle/trans.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 3d4f44ea..4d1bfde7 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1071,8 +1071,8 @@ fn trans_raw_malloc(@block_ctxt cx, TypeRef llptr_ty, ValueRef llsize) fn trans_malloc_without_cleanup(@block_ctxt cx, @ty.t t) -> result { auto llty = type_of(cx.fcx.ccx, t); - auto rslt = size_of(cx, t); - ret trans_raw_malloc(rslt.bcx, llty, rslt.val); + auto llsize = llsize_of(llvm.LLVMGetElementType(llty)); + ret trans_raw_malloc(cx, llty, llsize); } fn trans_malloc(@block_ctxt cx, @ty.t t) -> result { -- cgit v1.2.3 From 5876da00cfb78a849211804c820547fadef935f8 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 2 Mar 2011 19:08:04 -0500 Subject: Remove some erroneous FIXMEs from #fmt parser --- src/comp/front/extfmt.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index 48f05df7..7201a17c 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -107,7 +107,6 @@ fn expr_to_str(@ast.expr expr) -> str { fn parse_fmt_string(str s) -> vec[piece] { let vec[piece] pieces = vec(); - // FIXME: Should be counting codepoints instead of bytes auto lim = _str.byte_len(s); auto buf = ""; @@ -151,7 +150,6 @@ fn peek_num(str s, uint i, uint lim) -> option.t[tup(uint, uint)] { ret none[tup(uint, uint)]; } - // FIXME: Presumably s.(i) will return char eventually auto c = s.(i); if (!('0' as u8 <= c && c <= '9' as u8)) { ret option.none[tup(uint, uint)]; -- cgit v1.2.3 From fae6870d05683e372dd13ec9849dab0b55a66fb8 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 3 Mar 2011 11:49:35 -0800 Subject: rustc: Make populate_fn_ctxt_from_llself() generic-aware --- src/comp/middle/trans.rs | 92 ++++++++++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 38 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4d1bfde7..f47aed2d 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -401,20 +401,19 @@ fn T_captured_tydescs(type_names tn, uint n) -> TypeRef { ret T_struct(_vec.init_elt[TypeRef](T_ptr(T_tydesc(tn)), n)); } -fn T_obj(type_names tn, uint n_captured_tydescs, - TypeRef llfields_ty) -> TypeRef { - ret T_struct(vec(T_ptr(T_tydesc(tn)), - T_captured_tydescs(tn, n_captured_tydescs), - llfields_ty)); -} +fn T_obj_ptr(type_names tn, uint n_captured_tydescs) -> TypeRef { + // This function is not publicly exposed because it returns an incomplete + // type. The dynamically-sized fields follow the captured tydescs. + fn T_obj(type_names tn, uint n_captured_tydescs) -> TypeRef { + ret T_struct(vec(T_ptr(T_tydesc(tn)), + T_captured_tydescs(tn, n_captured_tydescs))); + } -fn T_obj_ptr(type_names tn, uint n_captured_tydescs, - TypeRef llfields_ty) -> TypeRef { - ret T_ptr(T_box(T_obj(tn, n_captured_tydescs, llfields_ty))); + ret T_ptr(T_box(T_obj(tn, n_captured_tydescs))); } fn T_opaque_obj_ptr(type_names tn) -> TypeRef { - ret T_obj_ptr(tn, 0u, T_nil()); + ret T_obj_ptr(tn, 0u); } @@ -4265,56 +4264,73 @@ fn ret_ty_of_fn(ast.ann ann) -> @ty.t { ret ret_ty_of_fn_ty(ty.ann_to_type(ann)); } -fn populate_fn_ctxt_from_llself(@block_ctxt cx, ValueRef llself) { +fn populate_fn_ctxt_from_llself(@block_ctxt cx, ValueRef llself) -> result { + auto bcx = cx; - let vec[TypeRef] llfield_tys = vec(); + let vec[@ty.t] field_tys = vec(); - for (ast.obj_field f in cx.fcx.ccx.obj_fields) { - llfield_tys += node_type(cx.fcx.ccx, f.ann); + for (ast.obj_field f in bcx.fcx.ccx.obj_fields) { + field_tys += vec(node_ann_type(bcx.fcx.ccx, f.ann)); } - auto n_typarams = _vec.len[ast.ty_param](cx.fcx.ccx.obj_typarams); - let TypeRef llobj_box_ty = T_obj_ptr(cx.fcx.ccx.tn, n_typarams, - T_struct(llfield_tys)); + // Synthesize a tuple type for the fields so that GEP_tup_like() can work + // its magic. + auto fields_tup_ty = ty.plain_ty(ty.ty_tup(field_tys)); + + auto n_typarams = _vec.len[ast.ty_param](bcx.fcx.ccx.obj_typarams); + let TypeRef llobj_box_ty = T_obj_ptr(bcx.fcx.ccx.tn, n_typarams); auto box_cell = - cx.build.GEP(llself, - vec(C_int(0), - C_int(abi.obj_field_box))); + bcx.build.GEP(llself, + vec(C_int(0), + C_int(abi.obj_field_box))); - auto box_ptr = cx.build.Load(box_cell); + auto box_ptr = bcx.build.Load(box_cell); - box_ptr = cx.build.PointerCast(box_ptr, llobj_box_ty); + box_ptr = bcx.build.PointerCast(box_ptr, llobj_box_ty); - auto obj_typarams = cx.build.GEP(box_ptr, + auto obj_typarams = bcx.build.GEP(box_ptr, vec(C_int(0), C_int(abi.box_rc_field_body), C_int(abi.obj_body_elt_typarams))); - auto obj_fields = cx.build.GEP(box_ptr, - vec(C_int(0), - C_int(abi.box_rc_field_body), - C_int(abi.obj_body_elt_fields))); + // The object fields immediately follow the type parameters, so we skip + // over them to get the pointer. + auto obj_fields = bcx.build.Add(vp2i(bcx, obj_typarams), + llsize_of(llvm.LLVMGetElementType(val_ty(obj_typarams)))); + + // If we can (i.e. the type is statically sized), then cast the resulting + // fields pointer to the appropriate LLVM type. If not, just leave it as + // i8 *. + if (!ty.type_has_dynamic_size(fields_tup_ty)) { + auto llfields_ty = type_of(bcx.fcx.ccx, fields_tup_ty); + obj_fields = vi2p(bcx, obj_fields, T_ptr(llfields_ty)); + } else { + obj_fields = vi2p(bcx, obj_fields, T_ptr(T_i8())); + } + let int i = 0; - for (ast.ty_param p in cx.fcx.ccx.obj_typarams) { - let ValueRef lltyparam = cx.build.GEP(obj_typarams, - vec(C_int(0), - C_int(i))); - lltyparam = cx.build.Load(lltyparam); - cx.fcx.lltydescs.insert(p.id, lltyparam); + for (ast.ty_param p in bcx.fcx.ccx.obj_typarams) { + let ValueRef lltyparam = bcx.build.GEP(obj_typarams, + vec(C_int(0), + C_int(i))); + lltyparam = bcx.build.Load(lltyparam); + bcx.fcx.lltydescs.insert(p.id, lltyparam); i += 1; } i = 0; - for (ast.obj_field f in cx.fcx.ccx.obj_fields) { - let ValueRef llfield = cx.build.GEP(obj_fields, - vec(C_int(0), - C_int(i))); + for (ast.obj_field f in bcx.fcx.ccx.obj_fields) { + auto rslt = GEP_tup_like(bcx, fields_tup_ty, obj_fields, vec(0, i)); + bcx = rslt.bcx; + auto llfield = rslt.val; cx.fcx.llobjfields.insert(f.id, llfield); i += 1; } + + ret res(bcx, C_nil()); } fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid, @@ -4335,7 +4351,7 @@ fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid, alt (fcx.llself) { case (some[ValueRef](?llself)) { - populate_fn_ctxt_from_llself(bcx, llself); + bcx = populate_fn_ctxt_from_llself(bcx, llself).bcx; } case (_) { } -- cgit v1.2.3 From da8058ff836a4e9a30e36ef96449dfef576b13e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Thu, 3 Mar 2011 16:43:47 -0500 Subject: Handle native types in calls. --- src/comp/middle/trans.rs | 5 +++-- src/comp/middle/ty.rs | 10 ++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index f47aed2d..7e463ae9 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1445,6 +1445,7 @@ fn make_drop_glue(@block_ctxt cx, ValueRef v, @ty.t t) -> result { bind drop_ty(_, _, _)); } else if (ty.type_is_scalar(t) || + ty.type_is_native(t) || ty.type_is_nil(t)) { ret res(cx, C_nil()); } @@ -1927,7 +1928,7 @@ fn copy_ty(@block_ctxt cx, ValueRef dst, ValueRef src, @ty.t t) -> result { - if (ty.type_is_scalar(t)) { + if (ty.type_is_scalar(t) || ty.type_is_native(t)) { ret res(cx, cx.build.Store(src, dst)); } else if (ty.type_is_nil(t)) { @@ -3795,7 +3796,7 @@ fn trans_expr(@block_ctxt cx, @ast.expr e) -> result { fn load_scalar_or_boxed(@block_ctxt cx, ValueRef v, @ty.t t) -> ValueRef { - if (ty.type_is_scalar(t) || ty.type_is_boxed(t)) { + if (ty.type_is_scalar(t) || ty.type_is_boxed(t) || ty.type_is_native(t)) { ret cx.build.Load(v); } else { ret v; diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 771136da..c85892f2 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -465,6 +465,16 @@ fn type_is_scalar(@t ty) -> bool { fail; } +// FIXME: should we just return true for native types in +// type_is_scalar? +fn type_is_native(@t ty) -> bool { + alt (ty.struct) { + case (ty_native) { ret true; } + case (_) { ret false; } + } + fail; +} + fn type_has_dynamic_size(@t ty) -> bool { alt (ty.struct) { case (ty_tup(?ts)) { -- cgit v1.2.3 From 5dba7a77d2c7396989262da3de5ea055bed151bc Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 3 Mar 2011 14:02:29 -0800 Subject: rustc: Don't call type_of() in GEP_tup_like() if there are any type parameters in the result --- src/comp/middle/trans.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 7e463ae9..9587b008 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1049,13 +1049,13 @@ fn GEP_tup_like(@block_ctxt cx, @ty.t t, bcx = sz.bcx; auto raw = bcx.build.PointerCast(base, T_ptr(T_i8())); auto bumped = bcx.build.GEP(raw, vec(sz.val)); - alt (s.target.struct) { - case (ty.ty_param(_)) { ret res(bcx, bumped); } - case (_) { - auto ty = T_ptr(type_of(bcx.fcx.ccx, s.target)); - ret res(bcx, bcx.build.PointerCast(bumped, ty)); - } + + if (ty.type_has_dynamic_size(s.target)) { + ret res(bcx, bumped); } + + auto typ = T_ptr(type_of(bcx.fcx.ccx, s.target)); + ret res(bcx, bcx.build.PointerCast(bumped, typ)); } -- cgit v1.2.3 From 2a241ece3a8fdaa536946b29eeab4524da164903 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 3 Mar 2011 14:10:36 -0800 Subject: rustc: Disallow calling type_of() on dynamically-sized types --- src/comp/middle/trans.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9587b008..65f5b135 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -417,7 +417,17 @@ fn T_opaque_obj_ptr(type_names tn) -> TypeRef { } +// This function now fails if called on a type with dynamic size (as its +// return value was always meaningless in that case anyhow). Beware! +// +// TODO: Enforce via a predicate. fn type_of(@crate_ctxt cx, @ty.t t) -> TypeRef { + if (ty.type_has_dynamic_size(t)) { + log "type_of() called on a type with dynamic size: " + + ty.ty_to_str(t); + fail; + } + ret type_of_inner(cx, t); } -- cgit v1.2.3 From 7f74d4d4f2e0635d644be6e2259973b5cf559a2e Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 3 Mar 2011 14:31:25 -0800 Subject: Turn on Valgrind for Mac --- src/Makefile | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/Makefile b/src/Makefile index 2be8be48..37726b6e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -43,13 +43,6 @@ ifeq ($(CFG_OSTYPE), FreeBSD) endif CFG_NATIVE := 1 CFG_UNIXY := 1 - CFG_VALGRIND := $(shell which valgrind) - ifdef CFG_VALGRIND - CFG_VALGRIND += --leak-check=full \ - --error-exitcode=1 \ - --quiet --vex-iropt-level=0 \ - --suppressions=etc/x86.supp - endif endif ifeq ($(CFG_OSTYPE), Linux) @@ -63,13 +56,6 @@ ifeq ($(CFG_OSTYPE), Linux) endif CFG_NATIVE := 1 CFG_UNIXY := 1 - CFG_VALGRIND := $(shell which valgrind) - ifdef CFG_VALGRIND - CFG_VALGRIND += --leak-check=full \ - --error-exitcode=1 \ - --quiet --vex-iropt-level=0 \ - --suppressions=etc/x86.supp - endif endif ifeq ($(CFG_OSTYPE), Darwin) @@ -137,6 +123,13 @@ ifdef CFG_UNIXY CFG_GCC_LINK_FLAGS += -m32 endif endif + CFG_VALGRIND := $(shell which valgrind) + ifdef CFG_VALGRIND + CFG_VALGRIND += --leak-check=full \ + --error-exitcode=1 \ + --quiet --vex-iropt-level=0 \ + --suppressions=etc/x86.supp + endif endif ifdef CFG_GCC -- cgit v1.2.3 From 5c7db0cde15adfda5b43112ee86d4bfe3bd9ee82 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 3 Mar 2011 15:19:26 -0800 Subject: Rewrite rustboot's flow-graph wiring passes to be less awful. Add test for nested control-flow constructs. --- src/Makefile | 1 + src/boot/me/typestate.ml | 352 +++++++++-------------------- src/test/run-pass/typestate-cfg-nesting.rs | 26 +++ 3 files changed, 131 insertions(+), 248 deletions(-) create mode 100644 src/test/run-pass/typestate-cfg-nesting.rs diff --git a/src/Makefile b/src/Makefile index 37726b6e..49cc0456 100644 --- a/src/Makefile +++ b/src/Makefile @@ -521,6 +521,7 @@ TEST_XFAILS_RUSTC := $(CONST_TAG_XFAILS) \ task-life-0.rs \ threads.rs \ type-sizes.rs \ + typestate-cfg-nesting.rs \ use-import-export.rs \ user.rs \ utf8.rs \ diff --git a/src/boot/me/typestate.ml b/src/boot/me/typestate.ml index ea0204f3..1c9c90ea 100644 --- a/src/boot/me/typestate.ml +++ b/src/boot/me/typestate.ml @@ -24,7 +24,6 @@ type typestate_tables = ts_prestates: (node_id,Bits.t) Hashtbl.t; ts_poststates: (node_id,Bits.t) Hashtbl.t; ts_graph: node_graph; - ts_siblings: sibling_map; ts_stmts: Ast.stmt Stack.t; ts_maxid: int ref; } @@ -38,7 +37,6 @@ let new_tables _ = ts_poststates = Hashtbl.create 0; ts_prestates = Hashtbl.create 0; ts_graph = Hashtbl.create 0; - ts_siblings = Hashtbl.create 0; ts_stmts = Stack.create (); ts_maxid = ref 0 } ;; @@ -790,279 +788,143 @@ let show_node cx graph s i = s (int_of_node i) (lset_fmt (Hashtbl.find graph i))) ;; -let graph_sequence_building_visitor - (cx:ctxt) - (tables_stack:typestate_tables Stack.t) - (inner:Walk.visitor) - : Walk.visitor = +let add_flow_edges (graph:node_graph) (n:node_id) (dsts:node_id list) : unit = + if Hashtbl.mem graph n + then + let existing = Hashtbl.find graph n in + Hashtbl.replace graph n (lset_union existing dsts) + else + Hashtbl.add graph n dsts +;; - let tables _ = Stack.top tables_stack in +let rec build_flow_graph_for_stmt + (graph:node_graph) + (predecessors:node_id list) + (s:Ast.stmt) + : node_id list = - (* Flow each stmt to its sequence-successor. *) - let visit_stmts stmts = - let ts = tables () in - let graph = ts.ts_graph in - let sibs = ts.ts_siblings in - let len = Array.length stmts in - for i = 0 to len - 2 - do - let stmt = stmts.(i) in - let next = stmts.(i+1) in - log cx "sequential stmt edge %d -> %d" - (int_of_node stmt.id) (int_of_node next.id); - htab_put graph stmt.id [next.id]; - htab_put sibs stmt.id next.id; - done; - (* Flow last node to nowhere. *) - if len > 0 - then htab_put graph stmts.(len-1).id [] + let connect ps qs = + List.iter + (fun pred -> add_flow_edges graph pred qs) + ps in - let visit_stmt_pre s = - (* Sequence the prelude nodes on special stmts. *) - begin - match s.node with - Ast.STMT_while sw -> - let (stmts, _) = sw.Ast.while_lval in - visit_stmts stmts - | _ -> () - end; - inner.Walk.visit_stmt_pre s + let seq ps (ss:Ast.stmt array) = + build_flow_graph_for_stmts graph ps ss in - let visit_block_pre b = - visit_stmts b.node; - inner.Walk.visit_block_pre b + let blk ps b = + connect ps [b.id]; + seq [b.id] b.node in - { inner with - Walk.visit_stmt_pre = visit_stmt_pre; - Walk.visit_block_pre = visit_block_pre } -;; - -let add_flow_edges (graph:node_graph) (n:node_id) (dsts:node_id list) : unit = - let existing = Hashtbl.find graph n in - Hashtbl.replace graph n (lset_union existing dsts) -;; + let first ss = + if Array.length ss = 0 + then [] + else [ss.(0).id] + in -let remove_flow_edges - (graph:node_graph) - (n:node_id) - (dsts:node_id list) - : unit = - let existing = Hashtbl.find graph n in - Hashtbl.replace graph n (lset_diff existing dsts) -;; + connect [s.id] []; + let outs = + match s.node with + | Ast.STMT_while sw -> + let (pre_loop_stmts, _) = sw.Ast.while_lval in + let body = sw.Ast.while_body in + let preloop_end = seq [s.id] pre_loop_stmts in + connect predecessors [s.id]; + connect (blk preloop_end body) (first pre_loop_stmts); + preloop_end + + | Ast.STMT_for sf -> + let body_end = blk [s.id] sf.Ast.for_body in + connect predecessors [s.id]; + connect body_end (first sf.Ast.for_body.node); + body_end + + | Ast.STMT_for_each sfe -> + let head_end = blk [s.id] sfe.Ast.for_each_head in + let body_end = blk head_end sfe.Ast.for_each_body in + connect predecessors [s.id]; + connect body_end (first sfe.Ast.for_each_head.node); + body_end + + | Ast.STMT_if sif -> + connect predecessors [s.id]; + (blk [s.id] sif.Ast.if_then) @ + (match sif.Ast.if_else with + None -> [s.id] + | Some els -> blk [s.id] els) + + | Ast.STMT_alt_tag sat -> + connect predecessors [s.id]; + Array.fold_left + (fun ends {node=(_, b); id=_} -> (blk [s.id] b) @ ends) + [] sat.Ast.alt_tag_arms + + | Ast.STMT_block b -> + blk predecessors b + + | _ -> + connect predecessors [s.id]; + [s.id] + in + connect outs []; + outs -let last_id (nodes:('a identified) array) : node_id = - let len = Array.length nodes in - nodes.(len-1).id +and build_flow_graph_for_stmts + (graph:node_graph) + (predecessors:node_id list) + (ss:Ast.stmt array) + : node_id list = + Array.fold_left (build_flow_graph_for_stmt graph) predecessors ss ;; -let last_id_or_block_id (block:Ast.block) : node_id = - let len = Array.length block.node in - if len = 0 - then block.id - else last_id block.node -;; -let graph_general_block_structure_building_visitor +let graph_building_visitor (cx:ctxt) (tables_stack:typestate_tables Stack.t) (inner:Walk.visitor) : Walk.visitor = let tables _ = Stack.top tables_stack in + let graph _ = (tables()).ts_graph in + let blk b = + add_flow_edges (graph()) b.id []; + ignore (build_flow_graph_for_stmts (graph()) [b.id] b.node) + in - let visit_stmt_pre s = - let ts = tables () in - let stmts = ts.ts_stmts in - Stack.push s stmts; - inner.Walk.visit_stmt_pre s + let visit_mod_item_pre n p i = + begin + match i.node.Ast.decl_item with + Ast.MOD_ITEM_fn fn -> blk fn.Ast.fn_body + | _ -> () + end; + inner.Walk.visit_mod_item_pre n p i in - let visit_stmt_post s = - let ts = tables () in - let stmts = ts.ts_stmts in - inner.Walk.visit_stmt_post s; - ignore (Stack.pop stmts) + let visit_obj_fn_pre obj ident fn = + blk fn.node.Ast.fn_body; + inner.Walk.visit_obj_fn_pre obj ident fn in - let show_node = - fun n id -> show_node cx (tables()).ts_graph n id + let visit_obj_drop_pre obj b = + blk b; + inner.Walk.visit_obj_drop_pre obj b in let visit_block_pre b = - begin - let ts = tables () in - let graph = ts.ts_graph in - let sibs = ts.ts_siblings in - let stmts = ts.ts_stmts in - let len = Array.length b.node in - let _ = htab_put graph b.id - (if len > 0 then [b.node.(0).id] else []) - in - - (* - * If block has len, - * then flow block to block.node.(0) and block.node.(len-1) to dsts - * else flow block to dsts - * - * so AST: - * - * block#n{ stmt#0 ... stmt#k }; - * stmt#j; - * - * turns into graph: - * - * block#n -> stmt#0 -> ... -> stmt#k -> stmt#j - * - *) - if Stack.is_empty stmts - then () - else - let s = Stack.top stmts in - add_flow_edges graph s.id [b.id]; - match htab_search sibs s.id with - None -> () - | Some sib_id -> - if len > 0 - then - add_flow_edges graph (last_id b.node) [sib_id] - else - add_flow_edges graph b.id [sib_id] - end; - show_node "block" b.id; + if Hashtbl.mem cx.ctxt_block_is_loop_body b.id + then blk b; inner.Walk.visit_block_pre b in { inner with - Walk.visit_stmt_pre = visit_stmt_pre; - Walk.visit_stmt_post = visit_stmt_post; + Walk.visit_mod_item_pre = visit_mod_item_pre; + Walk.visit_obj_fn_pre = visit_obj_fn_pre; + Walk.visit_obj_drop_pre = visit_obj_drop_pre; Walk.visit_block_pre = visit_block_pre } -;; - - -let graph_special_block_structure_building_visitor - (cx:ctxt) - (tables_stack:typestate_tables Stack.t) - (inner:Walk.visitor) - : Walk.visitor = - let tables _ = Stack.top tables_stack in - - let visit_stmt_pre s = - begin - match s.node with - - Ast.STMT_if sif -> - let ts = tables () in - let graph = ts.ts_graph in - let cond_id = s.id in - let succ = Hashtbl.find graph cond_id in - let then_id = sif.Ast.if_then.id in - let then_end_id = last_id_or_block_id sif.Ast.if_then in - let show_node = show_node cx graph in - let succ = List.filter (fun x -> not (x = then_id)) succ in - show_node "initial cond" cond_id; - show_node "initial then" then_id; - show_node "initial then_end" then_end_id; - begin - match sif.Ast.if_else with - None -> - Hashtbl.replace graph cond_id (then_id :: succ); - (* Kill residual messed-up block wiring.*) - remove_flow_edges graph then_end_id [then_id]; - show_node "cond" cond_id; - show_node "then" then_id; - show_node "then_end" then_end_id; - - | Some e -> - let else_id = e.id in - let succ = - List.filter (fun x -> not (x = else_id)) succ - in - let else_end_id = last_id_or_block_id e in - show_node "initial else" else_id; - show_node "initial else_end" else_end_id; - Hashtbl.replace graph cond_id [then_id; else_id]; - Hashtbl.replace graph then_end_id succ; - Hashtbl.replace graph else_end_id succ; - - (* Kill residual messed-up block wiring.*) - remove_flow_edges graph then_end_id [then_id]; - remove_flow_edges graph else_id [then_id]; - remove_flow_edges graph else_end_id [then_id]; - show_node "cond" cond_id; - show_node "then" then_id; - show_node "then_end" then_end_id; - show_node "else" else_id; - show_node "else_end" else_end_id; - end; - - | Ast.STMT_while sw -> - (* There are a bunch of rewirings to do on 'while' nodes. *) - - begin - let ts = tables () in - let graph = ts.ts_graph in - let dsts = Hashtbl.find graph s.id in - let body = sw.Ast.while_body in - let succ_stmts = - List.filter (fun x -> not (x = body.id)) dsts - in - - let (pre_loop_stmts, _) = sw.Ast.while_lval in - let loop_head_id = - (* Splice loop prelude into flow graph, save loop-head - * node. - *) - let slen = Array.length pre_loop_stmts in - if slen > 0 - then - begin - let pre_loop_begin = pre_loop_stmts.(0).id in - let pre_loop_end = last_id pre_loop_stmts in - remove_flow_edges graph s.id [body.id]; - add_flow_edges graph s.id [pre_loop_begin]; - add_flow_edges graph pre_loop_end [body.id]; - pre_loop_end - end - else - body.id - in - - (* Always flow s into the loop prelude; prelude may end - * loop. - *) - remove_flow_edges graph s.id succ_stmts; - add_flow_edges graph loop_head_id succ_stmts; - - (* Flow loop-end to loop-head. *) - let loop_end = last_id_or_block_id body in - add_flow_edges graph loop_end [loop_head_id] - end - - | Ast.STMT_alt_tag at -> - let ts = tables () in - let graph = ts.ts_graph in - let dsts = Hashtbl.find graph s.id in - let arm_blocks = - let arm_block_id { node = (_, block); id = _ } = block.id in - Array.to_list (Array.map arm_block_id at.Ast.alt_tag_arms) - in - let succ_stmts = - List.filter (fun x -> not (List.mem x arm_blocks)) dsts - in - remove_flow_edges graph s.id succ_stmts - - | _ -> () - end; - inner.Walk.visit_stmt_post s - in - { inner with - Walk.visit_stmt_pre = visit_stmt_pre } ;; let find_roots @@ -1631,13 +1493,7 @@ let process_crate (condition_assigning_visitor cx tables_stack scopes Walk.empty_visitor))); (table_managed - (graph_sequence_building_visitor cx tables_stack - Walk.empty_visitor)); - (table_managed - (graph_general_block_structure_building_visitor cx tables_stack - Walk.empty_visitor)); - (table_managed - (graph_special_block_structure_building_visitor cx tables_stack + (graph_building_visitor cx tables_stack Walk.empty_visitor)); |] in diff --git a/src/test/run-pass/typestate-cfg-nesting.rs b/src/test/run-pass/typestate-cfg-nesting.rs new file mode 100644 index 00000000..8f050646 --- /dev/null +++ b/src/test/run-pass/typestate-cfg-nesting.rs @@ -0,0 +1,26 @@ + +fn f() { + + auto x = 10; + auto y = 11; + if (true) { + alt (x) { + case (_) { + y = x; + } + } + } else { + } +} + +fn main() { + + auto x = 10; + auto y = 11; + if (true) { + while (false) { + y = x; + } + } else { + } +} -- cgit v1.2.3 From f44fea8b6d77c24785fc351c5ca334df47b804b3 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 3 Mar 2011 15:52:54 -0800 Subject: rustc: Teach trans_tag_variant() about generic tags --- src/comp/middle/trans.rs | 46 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 65f5b135..e85bcbbc 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -397,6 +397,16 @@ fn T_opaque_closure_ptr(type_names tn) -> TypeRef { ret t; } +fn T_opaque_tag_ptr(type_names tn) -> TypeRef { + auto s = "*tag"; + if (tn.name_has_type(s)) { + ret tn.get_type(s); + } + auto t = T_ptr(T_struct(vec(T_int(), T_i8()))); + tn.associate(s, t); + ret t; +} + fn T_captured_tydescs(type_names tn, uint n) -> TypeRef { ret T_struct(_vec.init_elt[TypeRef](T_ptr(T_tydesc(tn)), n)); } @@ -4576,27 +4586,41 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, auto arg_tys = arg_tys_of_fn(variant.ann); copy_args_to_allocas(bcx, none[TypeRef], fn_args, arg_tys); - auto lldiscrimptr = bcx.build.GEP(fcx.llretptr, + // Now synthesize a tuple type for the arguments, so that GEP_tup_like() + // will know what the data part of the variant looks like. + let vec[@ty.t] true_arg_tys = vec(); + for (ty.arg a in arg_tys) { + true_arg_tys += vec(a.ty); + } + auto tup_ty = ty.plain_ty(ty.ty_tup(true_arg_tys)); + + // Cast the tag to a type we can GEP into. + auto lltagptr = bcx.build.PointerCast(fcx.llretptr, + T_opaque_tag_ptr(fcx.ccx.tn)); + + auto lldiscrimptr = bcx.build.GEP(lltagptr, vec(C_int(0), C_int(0))); bcx.build.Store(C_int(index), lldiscrimptr); - auto llblobptr = bcx.build.GEP(fcx.llretptr, + auto llblobptr = bcx.build.GEP(lltagptr, vec(C_int(0), C_int(1))); - // First, generate the union type. - let vec[TypeRef] llargtys = vec(); - for (ty.arg arg in arg_tys) { - llargtys += vec(type_of(cx, arg.ty)); + // Cast the blob pointer to the appropriate type, if we need to (i.e. if + // the blob pointer isn't dynamically sized). + let ValueRef llunionptr; + if (!ty.type_has_dynamic_size(tup_ty)) { + auto llty = type_of(cx, tup_ty); + llunionptr = bcx.build.TruncOrBitCast(llblobptr, T_ptr(llty)); + } else { + llunionptr = llblobptr; } - auto llunionty = T_struct(llargtys); - auto llunionptr = bcx.build.TruncOrBitCast(llblobptr, T_ptr(llunionty)); - i = 0u; for (ast.variant_arg va in variant.args) { auto llargval = bcx.build.Load(fcx.llargs.get(va.id)); - auto lldestptr = bcx.build.GEP(llunionptr, - vec(C_int(0), C_int(i as int))); + auto rslt = GEP_tup_like(bcx, tup_ty, llunionptr, vec(0, i as int)); + bcx = rslt.bcx; + auto lldestptr = rslt.val; bcx.build.Store(llargval, lldestptr); i += 1u; -- cgit v1.2.3 From 39b05632057a9d9e71cbf7b486c26f70c84f0c14 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 3 Mar 2011 16:18:43 -0800 Subject: rustc: Remove dead code that used to generate tag constants from trans_constant() --- src/comp/middle/trans.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index e85bcbbc..5f163d10 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4932,12 +4932,6 @@ fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt { case (ast.item_tag(_, ?variants, _, ?tag_id)) { auto info = cx.tags.get(mk_plain_tag(tag_id)); - auto tag_ty = llvm.LLVMResolveTypeHandle(info.th.llth); - check (llvm.LLVMCountStructElementTypes(tag_ty) == 2u); - auto elts = vec(0 as TypeRef, 0 as TypeRef); - llvm.LLVMGetStructElementTypes(tag_ty, _vec.buf[TypeRef](elts)); - auto union_ty = elts.(1); - auto i = 0u; auto n_variants = _vec.len[ast.variant](variants); while (i < n_variants) { -- cgit v1.2.3 From f6682280f3e3e8923c283df8277964b6cbf8d8b8 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 3 Mar 2011 16:54:15 -0800 Subject: rustc: Add support for folding over tag types --- src/comp/middle/trans.rs | 2 ++ src/comp/middle/ty.rs | 10 +++++++++- src/comp/middle/typeck.rs | 4 ++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 5f163d10..98433305 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1144,6 +1144,8 @@ fn linearize_ty_params(@block_ctxt cx, @ty.t t) } ret t; } + + fn fold_tag_ty(@ty.t t) -> @ty.t { ret t; } } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index c85892f2..a44cdb4d 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -294,6 +294,7 @@ fn ty_to_str(&@t typ) -> str { type ty_fold = state obj { fn fold_simple_ty(@t ty) -> @t; + fn fold_tag_ty(@t ty) -> @t; }; fn fold_ty(ty_fold fld, @t ty) -> @t { @@ -322,7 +323,8 @@ fn fold_ty(ty_fold fld, @t ty) -> @t { for (@t subty in subtys) { new_subtys += vec(fold_ty(fld, subty)); } - ret rewrap(ty, ty_tag(tid, new_subtys)); + auto typ = rewrap(ty, ty_tag(tid, new_subtys)); + ret fld.fold_tag_ty(typ); } case (ty_tup(?subtys)) { let vec[@t] new_subtys = vec(); @@ -611,6 +613,8 @@ fn count_ty_params(@t ty) -> uint { } ret ty; } + + fn fold_tag_ty(@t ty) -> @t { ret ty; } } let vec[ast.def_id] param_ids_inner = vec(); @@ -1429,6 +1433,8 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) } } } + + fn fold_tag_ty(@t typ) -> @t { ret typ; } } ret ty.fold_ty(folder(bindings), typ); @@ -1548,6 +1554,8 @@ fn replace_type_params(@t typ, hashmap[ast.def_id,@t] param_map) -> @t { } } } + + fn fold_tag_ty(@t typ) -> @t { ret typ; } } auto replacer = param_replacer(param_map); ret fold_ty(replacer, typ); diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index f8f7fc72..918cc4f1 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -73,6 +73,8 @@ fn generalize_ty(@crate_ctxt cx, @ty.t t) -> @ty.t { } ret t; } + + fn fold_tag_ty(@ty.t t) -> @ty.t { ret t; } } auto generalizer = ty_generalizer(cx, @common.new_def_hash[@ty.t]()); @@ -114,6 +116,8 @@ fn substitute_ty_params(&@crate_ctxt ccx, case (_) { ret typ; } } } + + fn fold_tag_ty(@ty.t typ) -> @ty.t { ret typ; } } fn hash_int(&int x) -> uint { ret x as uint; } -- cgit v1.2.3 From 04a0a6fbef0cc7c3c89fbbbeff68ab2c999d9592 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 3 Mar 2011 17:09:20 -0800 Subject: Revert "rustc: Add support for folding over tag types" as it's unnecessary. Oops. --- src/comp/middle/trans.rs | 2 -- src/comp/middle/ty.rs | 10 +--------- src/comp/middle/typeck.rs | 4 ---- 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 98433305..5f163d10 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1144,8 +1144,6 @@ fn linearize_ty_params(@block_ctxt cx, @ty.t t) } ret t; } - - fn fold_tag_ty(@ty.t t) -> @ty.t { ret t; } } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index a44cdb4d..c85892f2 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -294,7 +294,6 @@ fn ty_to_str(&@t typ) -> str { type ty_fold = state obj { fn fold_simple_ty(@t ty) -> @t; - fn fold_tag_ty(@t ty) -> @t; }; fn fold_ty(ty_fold fld, @t ty) -> @t { @@ -323,8 +322,7 @@ fn fold_ty(ty_fold fld, @t ty) -> @t { for (@t subty in subtys) { new_subtys += vec(fold_ty(fld, subty)); } - auto typ = rewrap(ty, ty_tag(tid, new_subtys)); - ret fld.fold_tag_ty(typ); + ret rewrap(ty, ty_tag(tid, new_subtys)); } case (ty_tup(?subtys)) { let vec[@t] new_subtys = vec(); @@ -613,8 +611,6 @@ fn count_ty_params(@t ty) -> uint { } ret ty; } - - fn fold_tag_ty(@t ty) -> @t { ret ty; } } let vec[ast.def_id] param_ids_inner = vec(); @@ -1433,8 +1429,6 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) } } } - - fn fold_tag_ty(@t typ) -> @t { ret typ; } } ret ty.fold_ty(folder(bindings), typ); @@ -1554,8 +1548,6 @@ fn replace_type_params(@t typ, hashmap[ast.def_id,@t] param_map) -> @t { } } } - - fn fold_tag_ty(@t typ) -> @t { ret typ; } } auto replacer = param_replacer(param_map); ret fold_ty(replacer, typ); diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 918cc4f1..f8f7fc72 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -73,8 +73,6 @@ fn generalize_ty(@crate_ctxt cx, @ty.t t) -> @ty.t { } ret t; } - - fn fold_tag_ty(@ty.t t) -> @ty.t { ret t; } } auto generalizer = ty_generalizer(cx, @common.new_def_hash[@ty.t]()); @@ -116,8 +114,6 @@ fn substitute_ty_params(&@crate_ctxt ccx, case (_) { ret typ; } } } - - fn fold_tag_ty(@ty.t typ) -> @ty.t { ret typ; } } fn hash_int(&int x) -> uint { ret x as uint; } -- cgit v1.2.3 From b4a85c7b583b75eade31d698ad9862f5f98e8857 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 3 Mar 2011 17:27:35 -0800 Subject: Factor out and generalize sequence pointer walking, for use in vec-grow. --- src/comp/middle/trans.rs | 110 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 80 insertions(+), 30 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 5f163d10..2af5359a 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1770,6 +1770,81 @@ fn iter_structural_ty_full(@block_ctxt cx, ret r; } +// Iterates through a pair of sequences, until the src* hits the src_lim*. +fn iter_sequence_pair_inner(@block_ctxt cx, + ValueRef dst, // elt* + ValueRef src, // elt* + ValueRef src_lim, // elt* + @ty.t elt_ty, + val_pair_and_ty_fn f) -> result { + + auto bcx = cx; + + auto llunit_ty = type_of(cx.fcx.ccx, elt_ty); + auto unit_sz = size_of(bcx, elt_ty); + bcx = unit_sz.bcx; + + let ValueRef src_int = vp2i(bcx, src); + let ValueRef src_lim_int = vp2i(bcx, src_lim); + let ValueRef dst_int = vp2i(bcx, dst); + + auto cond_cx = new_scope_block_ctxt(cx, "sequence-iter cond"); + auto body_cx = new_scope_block_ctxt(cx, "sequence-iter body"); + auto next_cx = new_sub_block_ctxt(cx, "next"); + + bcx.build.Br(cond_cx.llbb); + + let ValueRef src_curr = cond_cx.build.Phi(T_int(), + vec(src_int), vec(bcx.llbb)); + let ValueRef dst_curr = cond_cx.build.Phi(T_int(), + vec(dst_int), vec(bcx.llbb)); + + auto end_test = cond_cx.build.ICmp(lib.llvm.LLVMIntNE, + src_curr, src_lim_int); + + cond_cx.build.CondBr(end_test, body_cx.llbb, next_cx.llbb); + + auto src_curr_ptr = vi2p(body_cx, src_curr, T_ptr(llunit_ty)); + auto dst_curr_ptr = vi2p(body_cx, dst_curr, T_ptr(llunit_ty)); + + auto body_res = f(body_cx, + dst_curr_ptr, + load_scalar_or_boxed(body_cx, src_curr_ptr, elt_ty), + elt_ty); + body_cx = body_res.bcx; + + auto src_next = body_cx.build.Add(src_curr, unit_sz.val); + auto dst_next = body_cx.build.Add(dst_curr, unit_sz.val); + body_cx.build.Br(cond_cx.llbb); + + cond_cx.build.AddIncomingToPhi(src_curr, vec(src_next), + vec(body_cx.llbb)); + + cond_cx.build.AddIncomingToPhi(dst_curr, vec(dst_next), + vec(body_cx.llbb)); + + ret res(next_cx, C_nil()); +} + + +fn iter_sequence_inner(@block_ctxt cx, + ValueRef src, // elt* + ValueRef src_lim, // elt* + @ty.t elt_ty, + val_and_ty_fn f) -> result { + fn adaptor_fn(val_and_ty_fn f, + @block_ctxt cx, + ValueRef av, + ValueRef bv, + @ty.t t) -> result { + ret f(cx, bv, t); + } + + be iter_sequence_pair_inner(cx, src, src, src_lim, elt_ty, + bind adaptor_fn(f, _, _, _, _)); +} + + // Iterates through the elements of a vec or str. fn iter_sequence(@block_ctxt cx, ValueRef v, @@ -1789,43 +1864,18 @@ fn iter_sequence(@block_ctxt cx, auto llunit_ty = type_of(cx.fcx.ccx, elt_ty); auto bcx = cx; - auto unit_sz = size_of(bcx, elt_ty); - bcx = unit_sz.bcx; auto len = bcx.build.Load(lenptr); if (trailing_null) { + auto unit_sz = size_of(bcx, elt_ty); + bcx = unit_sz.bcx; len = bcx.build.Sub(len, unit_sz.val); } - auto cond_cx = new_scope_block_ctxt(cx, "sequence-iter cond"); - auto body_cx = new_scope_block_ctxt(cx, "sequence-iter body"); - auto next_cx = new_sub_block_ctxt(cx, "next"); - - bcx.build.Br(cond_cx.llbb); - - auto ix = cond_cx.build.Phi(T_int(), vec(C_int(0)), vec(cx.llbb)); - auto scaled_ix = cond_cx.build.Phi(T_int(), - vec(C_int(0)), vec(cx.llbb)); - - auto end_test = cond_cx.build.ICmp(lib.llvm.LLVMIntNE, - scaled_ix, len); - cond_cx.build.CondBr(end_test, body_cx.llbb, next_cx.llbb); + auto p1 = vi2p(bcx, bcx.build.Add(vp2i(bcx, p0), len), + T_ptr(llunit_ty)); - auto elt = body_cx.build.GEP(p0, vec(C_int(0), ix)); - auto body_res = f(body_cx, - load_scalar_or_boxed(body_cx, elt, elt_ty), - elt_ty); - auto next_ix = body_res.bcx.build.Add(ix, C_int(1)); - auto next_scaled_ix = body_res.bcx.build.Add(scaled_ix, unit_sz.val); - - cond_cx.build.AddIncomingToPhi(ix, vec(next_ix), - vec(body_res.bcx.llbb)); - - cond_cx.build.AddIncomingToPhi(scaled_ix, vec(next_scaled_ix), - vec(body_res.bcx.llbb)); - - body_res.bcx.build.Br(cond_cx.llbb); - ret res(next_cx, C_nil()); + ret iter_sequence_inner(cx, p0, p1, elt_ty, f); } alt (t.struct) { -- cgit v1.2.3 From 629eba1d066ba4295baf4bfed41cae240c527af5 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 3 Mar 2011 17:57:36 -0800 Subject: rustc: Make tag discriminants per-tag-ID, not per-tag-ID-and-subtypes --- src/comp/middle/trans.rs | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2af5359a..5bee0e11 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -60,10 +60,7 @@ type glue_fns = rec(ValueRef activate_glue, ValueRef bzero_glue, ValueRef vec_grow_glue); -type tag_info = rec( - type_handle th, - mutable @hashmap[ast.def_id,ValueRef] lldiscrims -); +type tag_info = rec(type_handle th); state type crate_ctxt = rec(session.session sess, ModuleRef llmod, @@ -78,6 +75,7 @@ state type crate_ctxt = rec(session.session sess, hashmap[ast.def_id, @ast.native_item] native_items, hashmap[@ty.t, @tag_info] tags, + hashmap[ast.def_id, ValueRef] discrims, hashmap[ast.def_id, ValueRef] fn_pairs, hashmap[ast.def_id, ValueRef] consts, hashmap[ast.def_id,()] obj_methods, @@ -2962,9 +2960,7 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt, } else { // Nullary variant. auto tag_ty = node_ann_type(cx.fcx.ccx, ann); - auto info = cx.fcx.ccx.tags.get(tag_ty); - check (info.lldiscrims.contains_key(vid)); - auto lldiscrim_gv = info.lldiscrims.get(vid); + auto lldiscrim_gv = cx.fcx.ccx.discrims.get(vid); auto lldiscrim = cx.build.Load(lldiscrim_gv); auto alloc_result = alloc_ty(cx, tag_ty); @@ -4866,10 +4862,7 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { auto vi = new_def_hash[uint](); auto navi = new_def_hash[uint](); - auto info = @rec( - th=mk_type_handle(), - mutable lldiscrims=@new_def_hash[ValueRef]() - ); + auto info = @rec(th=mk_type_handle()); cx.tags.insert(mk_plain_tag(tag_id), info); cx.items.insert(tag_id, i); @@ -4980,8 +4973,6 @@ fn resolve_tag_types(@crate_ctxt cx, @ast.crate crate) { fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt { alt (it.node) { case (ast.item_tag(_, ?variants, _, ?tag_id)) { - auto info = cx.tags.get(mk_plain_tag(tag_id)); - auto i = 0u; auto n_variants = _vec.len[ast.variant](variants); while (i < n_variants) { @@ -5000,7 +4991,7 @@ fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt { llvm.LLVMSetLinkage(discrim_gvar, lib.llvm.LLVMPrivateLinkage as llvm.Linkage); - info.lldiscrims.insert(variant.id, discrim_gvar); + cx.discrims.insert(variant.id, discrim_gvar); i += 1u; } @@ -5445,6 +5436,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, items = new_def_hash[@ast.item](), native_items = new_def_hash[@ast.native_item](), tags = tags, + discrims = new_def_hash[ValueRef](), fn_pairs = new_def_hash[ValueRef](), consts = new_def_hash[ValueRef](), obj_methods = new_def_hash[()](), -- cgit v1.2.3 From 652cb484758a72811e16a574805ce60827daa153 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Thu, 3 Mar 2011 18:18:51 -0800 Subject: Assortment of additional work on vec-append. Not done yet. --- src/comp/back/abi.rs | 4 +-- src/comp/middle/trans.rs | 86 ++++++++++++++++++++++++++++++++++-------------- src/comp/middle/ty.rs | 9 +++++ 3 files changed, 73 insertions(+), 26 deletions(-) diff --git a/src/comp/back/abi.rs b/src/comp/back/abi.rs index 89d6b487..dd058590 100644 --- a/src/comp/back/abi.rs +++ b/src/comp/back/abi.rs @@ -71,8 +71,8 @@ fn bzero_glue_name() -> str { ret "rust_bzero_glue"; } -fn vec_grow_glue_name() -> str { - ret "rust_vec_grow_glue"; +fn vec_append_glue_name() -> str { + ret "rust_vec_append_glue"; } fn upcall_glue_name(int n) -> str { diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 5bee0e11..038e0baf 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -58,7 +58,7 @@ type glue_fns = rec(ValueRef activate_glue, ValueRef no_op_type_glue, ValueRef memcpy_glue, ValueRef bzero_glue, - ValueRef vec_grow_glue); + ValueRef vec_append_glue); type tag_info = rec(type_handle th); @@ -2296,17 +2296,39 @@ fn trans_integral_compare(@block_ctxt cx, ast.binop op, @ty.t intype, ret cx.build.ICmp(cmp, lhs, rhs); } -fn trans_sequence_append(@block_ctxt cx, @ty.t t, - ValueRef lhs, ValueRef rhs) -> result { - cx.fcx.ccx.sess.unimpl("sequence append"); - fail; +fn trans_vec_append(@block_ctxt cx, @ty.t t, + ValueRef lhs, ValueRef rhs) -> result { + + auto elt_ty = ty.sequence_element_type(t); + + auto skip_null = C_bool(false); + alt (t.struct) { + case (ty.ty_str) { skip_null = C_bool(true); } + case (_) { } + } + + auto bcx = cx; + + auto llvec_tydesc = get_tydesc(bcx, t); + bcx = llvec_tydesc.bcx; + + auto llelt_tydesc = get_tydesc(bcx, elt_ty); + bcx = llelt_tydesc.bcx; + + ret res(cx, cx.build.FastCall(cx.fcx.ccx.glues.memcpy_glue, + vec(cx.fcx.lltaskptr, + llvec_tydesc.val, + llelt_tydesc.val, + lhs, + load_scalar_or_boxed(cx, rhs, t), + skip_null))); } -fn trans_sequence_add(@block_ctxt cx, @ty.t t, - ValueRef lhs, ValueRef rhs) -> result { +fn trans_vec_add(@block_ctxt cx, @ty.t t, + ValueRef lhs, ValueRef rhs) -> result { auto r = alloc_ty(cx, t); r = copy_ty(r.bcx, INIT, r.val, lhs, t); - ret trans_sequence_append(r.bcx, t, lhs, rhs); + ret trans_vec_append(r.bcx, t, lhs, rhs); } @@ -2316,7 +2338,7 @@ fn trans_eager_binop(@block_ctxt cx, ast.binop op, @ty.t intype, alt (op) { case (ast.add) { if (ty.type_is_sequence(intype)) { - ret trans_sequence_add(cx, intype, lhs, rhs); + ret trans_vec_add(cx, intype, lhs, rhs); } ret res(cx, cx.build.Add(lhs, rhs)); } @@ -5296,9 +5318,9 @@ fn make_bzero_glue(ModuleRef llmod) -> ValueRef { ret fun; } -fn make_vec_grow_glue(ModuleRef llmod, type_names tn) -> ValueRef { +fn make_vec_append_glue(ModuleRef llmod, type_names tn) -> ValueRef { /* - * Args to vec_grow_glue: + * Args to vec_append_glue: * * 0. (Implicit) task ptr * @@ -5309,9 +5331,11 @@ fn make_vec_grow_glue(ModuleRef llmod, type_names tn) -> ValueRef { * elements can be copied to a newly alloc'ed vec if one must be * created. * - * 3. Alias to vec that needs to grow (i.e. ptr to ptr to rust_vec). + * 3. Dst vec alias (i.e. ptr to ptr to rust_vec, we will mutate it). + * + * 4. Src vec (i.e. ptr to rust_vec). * - * 4. Number of bytes of growth requested + * 5. Flag indicating whether to skip trailing null on dst. * */ @@ -5319,21 +5343,23 @@ fn make_vec_grow_glue(ModuleRef llmod, type_names tn) -> ValueRef { T_ptr(T_tydesc(tn)), T_ptr(T_tydesc(tn)), T_ptr(T_ptr(T_vec(T_int()))), // a lie. - T_int()), T_void()); + T_ptr(T_vec(T_int())), // a lie. + T_bool()), T_void()); - auto llfn = decl_fastcall_fn(llmod, abi.vec_grow_glue_name(), ty); + auto llfn = decl_fastcall_fn(llmod, abi.vec_append_glue_name(), ty); ret llfn; } -fn trans_vec_grow_glue(@crate_ctxt cx) { +fn trans_vec_append_glue(@crate_ctxt cx) { - auto llfn = cx.glues.vec_grow_glue; + auto llfn = cx.glues.vec_append_glue; let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 0u); let ValueRef llvec_tydesc = llvm.LLVMGetParam(llfn, 1u); let ValueRef llelt_tydesc = llvm.LLVMGetParam(llfn, 2u); - let ValueRef llvec_ptr = llvm.LLVMGetParam(llfn, 3u); - let ValueRef llnbytes = llvm.LLVMGetParam(llfn, 4u); + let ValueRef lldst_vec_ptr = llvm.LLVMGetParam(llfn, 3u); + let ValueRef llsrc_vec = llvm.LLVMGetParam(llfn, 4u); + let ValueRef llskipnull = llvm.LLVMGetParam(llfn, 5u); auto fcx = @rec(llfn=llfn, lltaskptr=lltaskptr, @@ -5349,12 +5375,23 @@ fn trans_vec_grow_glue(@crate_ctxt cx) { auto bcx = new_top_block_ctxt(fcx); - auto llneed_copy_ptr = bcx.build.Alloca(T_int()); + // First the dst vec needs to grow to accommodate the src vec. + // To do this we have to figure out how many bytes to add. + auto n_bytes = + bcx.build.Load(bcx.build.GEP(llsrc_vec, + vec(C_int(0), + C_int(abi.vec_elt_fill)))); + n_bytes = bcx.build.Select(llskipnull, + bcx.build.Sub(n_bytes, C_int(1)), + n_bytes); + + + auto llneed_copy_ptr = bcx.build.Alloca(T_int()); auto llnew_vec_res = trans_upcall(bcx, "upcall_vec_grow", - vec(vp2i(bcx, bcx.build.Load(llvec_ptr)), - llnbytes, + vec(vp2i(bcx, bcx.build.Load(lldst_vec_ptr)), + n_bytes, vp2i(bcx, llneed_copy_ptr), vp2i(bcx, llvec_tydesc))); @@ -5364,6 +5401,7 @@ fn trans_vec_grow_glue(@crate_ctxt cx) { T_ptr(T_vec(T_int())) // a lie. ); + // FIXME: complete this. bcx.build.RetVoid(); @@ -5396,7 +5434,7 @@ fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns { no_op_type_glue = make_no_op_type_glue(llmod, tn), memcpy_glue = make_memcpy_glue(llmod), bzero_glue = make_bzero_glue(llmod), - vec_grow_glue = make_vec_grow_glue(llmod, tn)); + vec_append_glue = make_vec_append_glue(llmod, tn)); } fn trans_crate(session.session sess, @ast.crate crate, str output, @@ -5456,7 +5494,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, trans_mod(cx, crate.node.module); trans_exit_task_glue(cx); - trans_vec_grow_glue(cx); + trans_vec_append_glue(cx); create_crate_constant(cx); if (!shared) { trans_main_fn(cx, cx.crate_ptr); diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index c85892f2..2fc3160c 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -417,6 +417,15 @@ fn type_is_sequence(@t ty) -> bool { fail; } +fn sequence_element_type(@t ty) -> @t { + alt (ty.struct) { + case (ty_str) { ret plain_ty(ty_machine(common.ty_u8)); } + case (ty_vec(?e)) { ret e; } + } + fail; +} + + fn type_is_tup_like(@t ty) -> bool { alt (ty.struct) { case (ty_box(_)) { ret true; } -- cgit v1.2.3 From 02dff96b52cac4900fd35235623c8a2dd98ca08f Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 4 Mar 2011 11:28:40 -0800 Subject: Parse meta directives in crates. --- src/comp/front/ast.rs | 2 +- src/comp/front/parser.rs | 35 +++++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index 474dc4aa..e9dee7ec 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -53,7 +53,7 @@ tag crate_directive_ { cdir_src_mod(ident, option.t[filename]); cdir_dir_mod(ident, option.t[filename], vec[@crate_directive]); cdir_view_item(@view_item); - cdir_meta(@meta_item); + cdir_meta(vec[@meta_item]); cdir_syntax(path); cdir_auth(path, effect); } diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 1be4226c..f80c3bd5 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1564,14 +1564,14 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool { case (ast.expr_if(_,_,_,_,_)) { ret false; } case (ast.expr_for(_,_,_,_)) { ret false; } case (ast.expr_for_each(_,_,_,_)) - { ret false; } + { ret false; } case (ast.expr_while(_,_,_)) { ret false; } case (ast.expr_do_while(_,_,_)) { ret false; } case (ast.expr_alt(_,_,_)) { ret false; } case (ast.expr_block(_,_)) { ret false; } case (ast.expr_assign(_,_,_)) { ret true; } case (ast.expr_assign_op(_,_,_,_)) - { ret true; } + { ret true; } case (ast.expr_field(_,_,_)) { ret true; } case (ast.expr_index(_,_,_)) { ret true; } case (ast.expr_path(_,_,_)) { ret true; } @@ -1583,16 +1583,8 @@ fn stmt_ends_with_semi(@ast.stmt stmt) -> bool { case (ast.expr_check_expr(_)) { ret true; } } } - case (ast.stmt_crate_directive(?cdir)) { - alt (cdir.node) { - case (ast.cdir_src_mod(_, _)) { ret true; } - case (ast.cdir_view_item(_)) { ret true; } - case (ast.cdir_meta(_)) { ret true; } - case (ast.cdir_syntax(_)) { ret true; } - case (ast.cdir_auth(_, _)) { ret true; } - case (_) { ret false; } - } - } + // We should not be calling this on a cdir. + case (ast.stmt_crate_directive(?cdir)) { fail; } } } @@ -1636,8 +1628,13 @@ impure fn parse_block(parser p) -> ast.block { case (none[@ast.expr]) { // Not an expression statement. stmts += vec(stmt); - if (stmt_ends_with_semi(stmt)) { - expect(p, token.SEMI); + // FIXME: crazy differentiation between conditions + // used in branches and binary expressions in rustboot + // means we cannot use && here. I know, right? + if (p.get_file_type() == SOURCE_FILE) { + if (stmt_ends_with_semi(stmt)) { + expect(p, token.SEMI); + } } } } @@ -2261,6 +2258,16 @@ impure fn parse_crate_directive(parser p) -> ast.crate_directive ret spanned(lo, hi, ast.cdir_auth(n, e)); } + case (token.META) { + // FIXME: currently dropping meta clauses on the floor, + // as there is no crate metadata system + p.bump(); + auto mis = parse_meta(p); + hi = p.get_span(); + expect(p, token.SEMI); + ret spanned(lo, hi, ast.cdir_meta(mis)); + } + case (token.MOD) { p.bump(); auto id = parse_ident(p); -- cgit v1.2.3 From 2ff67ed94e9835f7ee01088aa479a1ca5796bee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Fri, 4 Mar 2011 14:53:52 -0500 Subject: Remove unused argument. --- src/comp/middle/trans.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 038e0baf..d2fa0acc 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1278,7 +1278,7 @@ fn make_generic_glue(@crate_ctxt cx, @ty.t t, str name, fn_name = sanitize(fn_name); auto llfn = decl_fastcall_fn(cx.llmod, fn_name, llfnty); - auto fcx = new_fn_ctxt(cx, fn_name, llfn); + auto fcx = new_fn_ctxt(cx, llfn); auto bcx = new_top_block_ctxt(fcx); auto re; @@ -2656,7 +2656,7 @@ fn trans_for_each(@block_ctxt cx, // FIXME: handle ty params properly. let vec[ast.ty_param] ty_params = vec(); - auto fcx = new_fn_ctxt(cx.fcx.ccx, s, lliterbody); + auto fcx = new_fn_ctxt(cx.fcx.ccx, lliterbody); auto bcx = new_top_block_ctxt(fcx); // FIXME: populate lllocals from llenv here. @@ -3151,7 +3151,7 @@ fn trans_bind_thunk(@crate_ctxt cx, let TypeRef llthunk_ty = get_pair_fn_ty(type_of(cx, incoming_fty)); let ValueRef llthunk = decl_fastcall_fn(cx.llmod, s, llthunk_ty); - auto fcx = new_fn_ctxt(cx, s, llthunk); + auto fcx = new_fn_ctxt(cx, llthunk); auto bcx = new_top_block_ctxt(fcx); auto llclosure = bcx.build.PointerCast(fcx.llenv, llclosure_ty); @@ -4213,7 +4213,6 @@ fn trans_block(@block_ctxt cx, &ast.block b) -> result { // - trans_args fn new_fn_ctxt(@crate_ctxt cx, - str name, ValueRef llfndecl) -> @fn_ctxt { let ValueRef llretptr = llvm.LLVMGetParam(llfndecl, 0u); @@ -4429,7 +4428,7 @@ fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid, auto llfndecl = cx.item_ids.get(fid); cx.item_names.insert(cx.path, llfndecl); - auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); + auto fcx = new_fn_ctxt(cx, llfndecl); create_llargs_for_fn_args(fcx, f.proto, ty_self, ret_ty_of_fn(ann), f.decl.inputs, ty_params); @@ -4514,7 +4513,7 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, id=f.id)); } - auto fcx = new_fn_ctxt(cx, cx.path, llctor_decl); + auto fcx = new_fn_ctxt(cx, llctor_decl); create_llargs_for_fn_args(fcx, ast.proto_fn, none[TypeRef], ret_ty_of_fn(ann), fn_args, ty_params); @@ -4644,7 +4643,7 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, check (cx.item_ids.contains_key(variant.id)); let ValueRef llfndecl = cx.item_ids.get(variant.id); - auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); + auto fcx = new_fn_ctxt(cx, llfndecl); create_llargs_for_fn_args(fcx, ast.proto_fn, none[TypeRef], ret_ty_of_fn(variant.ann), fn_args, ty_params); -- cgit v1.2.3 From 95c0cefd32bc1af5e91857511187760010aaffc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Fri, 4 Mar 2011 15:29:33 -0500 Subject: Build empty wrappers. This lets us compile hello world, but so far it just returns 0. --- src/Makefile | 1 - src/comp/middle/trans.rs | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 49cc0456..2ec0f9d1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -484,7 +484,6 @@ TEST_XFAILS_RUSTC := $(CONST_TAG_XFAILS) \ mlist-cycle.rs \ mlist.rs \ mutable-alias-vec.rs \ - native2.rs \ native-opaque-type.rs \ obj-as.rs \ obj-dtor.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index d2fa0acc..2f45691a 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4829,6 +4829,11 @@ fn decl_native_fn_and_pair(@crate_ctxt cx, let str s = cx.names.next("_rust_wrapper") + sep() + name; let ValueRef wrapper_fn = decl_fastcall_fn(cx.llmod, s, wrapper_type); + // Build the wrapper. + auto fcx = new_fn_ctxt(cx, wrapper_fn); + auto bcx = new_top_block_ctxt(fcx); + bcx.build.RetVoid(); + // Declare the global constant pair that points to it. auto wrapper_pair_type = T_fn_pair(cx.tn, wrapper_type); let str ps = cx.names.next("_rust_wrapper_pair") + sep() + name; -- cgit v1.2.3 From 596face2745ccc11a959a530807ea3e36e9d1354 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 4 Mar 2011 14:15:19 -0800 Subject: Parse (and generally ignore) constraints and constrained types. --- src/comp/front/ast.rs | 9 +++++++ src/comp/front/parser.rs | 68 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index e9dee7ec..a8bf4b00 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -231,8 +231,17 @@ tag ty_ { ty_path(path, option.t[def]); ty_mutable(@ty); ty_type; + ty_constr(@ty, vec[@constr]); } +tag constr_arg_ { + carg_base; + carg_ident(ident); +} +type constr_arg = spanned[constr_arg_]; +type constr_ = rec(path path, vec[@constr_arg] args); +type constr = spanned[constr_]; + type arg = rec(mode mode, @ty ty, ident ident, def_id id); type fn_decl = rec(effect effect, vec[arg] inputs, diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index f80c3bd5..934764e6 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -199,6 +199,10 @@ impure fn parse_ty_fn(ast.proto proto, parser p, auto inputs = parse_seq[rec(ast.mode mode, @ast.ty ty)](token.LPAREN, token.RPAREN, some(token.COMMA), f, p); + // FIXME: dropping constrs on the floor at the moment. + // pick them up when they're used by typestate pass. + parse_constrs(p); + let @ast.ty output; if (p.peek() == token.RARROW) { p.bump(); @@ -254,6 +258,62 @@ impure fn parse_ty_field(parser p) -> ast.ty_field { ret rec(ident=id, ty=ty); } +impure fn parse_constr_arg(parser p) -> @ast.constr_arg { + auto lo = p.get_span(); + auto carg = ast.carg_base; + if (p.peek() == token.BINOP(token.STAR)) { + p.bump(); + } else { + carg = ast.carg_ident(parse_ident(p)); + } + ret @spanned(lo, lo, carg); +} + +impure fn parse_ty_constr(parser p) -> @ast.constr { + auto lo = p.get_span(); + auto path = parse_path(p, GREEDY); + auto pf = parse_constr_arg; + auto args = parse_seq[@ast.constr_arg](token.LPAREN, + token.RPAREN, + some(token.COMMA), pf, p); + auto hi = args.span; + ret @spanned(lo, hi, rec(path=path, args=args.node)); +} + +impure fn parse_constrs(parser p) -> common.spanned[vec[@ast.constr]] { + auto lo = p.get_span(); + auto hi = lo; + let vec[@ast.constr] constrs = vec(); + if (p.peek() == token.COLON) { + p.bump(); + let bool more = true; + while (more) { + alt (p.peek()) { + case (token.IDENT(_)) { + auto constr = parse_ty_constr(p); + hi = constr.span; + append[@ast.constr](constrs, constr); + if (p.peek() == token.COMMA) { + p.bump(); + more = false; + } + } + case (_) { more = false; } + } + } + } + ret spanned(lo, hi, constrs); +} + +impure fn parse_ty_constrs(@ast.ty t, parser p) -> @ast.ty { + if (p.peek() == token.COLON) { + auto constrs = parse_constrs(p); + ret @spanned(t.span, constrs.span, + ast.ty_constr(t, constrs.node)); + } + ret t; +} + impure fn parse_ty(parser p) -> @ast.ty { auto lo = p.get_span(); auto hi = lo; @@ -368,7 +428,8 @@ impure fn parse_ty(parser p) -> @ast.ty { fail; } } - ret @spanned(lo, hi, t); + + ret parse_ty_constrs(@spanned(lo, hi, t), p); } impure fn parse_arg(parser p) -> ast.arg { @@ -1676,6 +1737,11 @@ impure fn parse_fn_decl(parser p, ast.effect eff) -> ast.fn_decl { pf, p); let @ast.ty output; + + // FIXME: dropping constrs on the floor at the moment. + // pick them up when they're used by typestate pass. + parse_constrs(p); + if (p.peek() == token.RARROW) { p.bump(); output = parse_ty(p); -- cgit v1.2.3 From 76ec67063e3b310aca4d4164577d167862d1bf73 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 4 Mar 2011 15:08:33 -0800 Subject: rustc: Don't use recursive types for tags; remove tag_info; introduce GEP_tag() --- src/comp/middle/trans.rs | 262 ++++++++++++++++++++++++++++------------------- 1 file changed, 154 insertions(+), 108 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2f45691a..66539ab2 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -60,8 +60,6 @@ type glue_fns = rec(ValueRef activate_glue, ValueRef bzero_glue, ValueRef vec_append_glue); -type tag_info = rec(type_handle th); - state type crate_ctxt = rec(session.session sess, ModuleRef llmod, target_data td, @@ -74,7 +72,8 @@ state type crate_ctxt = rec(session.session sess, hashmap[ast.def_id, @ast.item] items, hashmap[ast.def_id, @ast.native_item] native_items, - hashmap[@ty.t, @tag_info] tags, + // TODO: hashmap[tup(tag_id,subtys), @tag_info] + hashmap[@ty.t, uint] tag_sizes, hashmap[ast.def_id, ValueRef] discrims, hashmap[ast.def_id, ValueRef] fn_pairs, hashmap[ast.def_id, ValueRef] consts, @@ -395,16 +394,30 @@ fn T_opaque_closure_ptr(type_names tn) -> TypeRef { ret t; } -fn T_opaque_tag_ptr(type_names tn) -> TypeRef { - auto s = "*tag"; +fn T_tag(type_names tn, uint size) -> TypeRef { + auto s = "tag_" + _uint.to_str(size, 10u); + if (tn.name_has_type(s)) { + ret tn.get_type(s); + } + auto t = T_struct(vec(T_int(), T_array(T_i8(), size))); + tn.associate(s, t); + ret t; +} + +fn T_opaque_tag(type_names tn) -> TypeRef { + auto s = "tag"; if (tn.name_has_type(s)) { ret tn.get_type(s); } - auto t = T_ptr(T_struct(vec(T_int(), T_i8()))); + auto t = T_struct(vec(T_int(), T_i8())); tn.associate(s, t); ret t; } +fn T_opaque_tag_ptr(type_names tn) -> TypeRef { + ret T_ptr(T_opaque_tag(tn)); +} + fn T_captured_tydescs(type_names tn, uint n) -> TypeRef { ret T_struct(_vec.init_elt[TypeRef](T_ptr(T_tydesc(tn)), n)); } @@ -436,7 +449,7 @@ fn type_of(@crate_ctxt cx, @ty.t t) -> TypeRef { fail; } - ret type_of_inner(cx, t); + ret type_of_inner(cx, t, false); } fn type_of_explicit_args(@crate_ctxt cx, @@ -447,12 +460,14 @@ fn type_of_explicit_args(@crate_ctxt cx, check (arg.mode == ast.alias); atys += T_typaram_ptr(cx.tn); } else { - let TypeRef t = type_of_inner(cx, arg.ty); + let TypeRef t; alt (arg.mode) { case (ast.alias) { - t = T_ptr(t); + t = T_ptr(type_of_inner(cx, arg.ty, true)); + } + case (_) { + t = type_of_inner(cx, arg.ty, false); } - case (_) { /* fall through */ } } atys += t; } @@ -478,7 +493,7 @@ fn type_of_fn_full(@crate_ctxt cx, if (ty.type_has_dynamic_size(output)) { atys += T_typaram_ptr(cx.tn); } else { - atys += T_ptr(type_of_inner(cx, output)); + atys += T_ptr(type_of_inner(cx, output, false)); } // Arg 1: Task pointer. @@ -545,10 +560,10 @@ fn type_of_native_fn(@crate_ctxt cx, ast.native_abi abi, } } atys += type_of_explicit_args(cx, inputs); - ret T_fn(atys, type_of_inner(cx, output)); + ret T_fn(atys, type_of_inner(cx, output, false)); } -fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { +fn type_of_inner(@crate_ctxt cx, @ty.t t, bool boxed) -> TypeRef { let TypeRef llty = 0 as TypeRef; alt (t.struct) { @@ -573,26 +588,31 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef { } case (ty.ty_char) { llty = T_char(); } case (ty.ty_str) { llty = T_ptr(T_str()); } - case (ty.ty_tag(?tag_id, _)) { - llty = llvm.LLVMResolveTypeHandle(cx.tags.get(t).th.llth); + case (ty.ty_tag(_, _)) { + if (boxed) { + llty = T_opaque_tag(cx.tn); + } else { + auto size = static_size_of_tag(cx, t); + llty = T_tag(cx.tn, size); + } } case (ty.ty_box(?t)) { - llty = T_ptr(T_box(type_of_inner(cx, t))); + llty = T_ptr(T_box(type_of_inner(cx, t, true))); } case (ty.ty_vec(?t)) { - llty = T_ptr(T_vec(type_of_inner(cx, t))); + llty = T_ptr(T_vec(type_of_inner(cx, t, true))); } case (ty.ty_tup(?elts)) { let vec[TypeRef] tys = vec(); for (@ty.t elt in elts) { - tys += type_of_inner(cx, elt); + tys += type_of_inner(cx, elt, boxed); } llty = T_struct(tys); } case (ty.ty_rec(?fields)) { let vec[TypeRef] tys = vec(); for (ty.field f in fields) { - tys += type_of_inner(cx, f.ty); + tys += type_of_inner(cx, f.ty, boxed); } llty = T_struct(tys); } @@ -650,9 +670,11 @@ fn type_of_arg(@crate_ctxt cx, &ty.arg arg) -> TypeRef { } } - auto typ = type_of_inner(cx, arg.ty); + auto typ; if (arg.mode == ast.alias) { - typ = T_ptr(typ); + typ = T_ptr(type_of_inner(cx, arg.ty, true)); + } else { + typ = type_of_inner(cx, arg.ty, false); } ret typ; } @@ -856,6 +878,11 @@ fn align_to(@block_ctxt cx, ValueRef off, ValueRef align) -> ValueRef { ret cx.build.And(bumped, cx.build.Not(mask)); } +// Returns the real size of the given type for the current target. +fn llsize_of_real(@crate_ctxt cx, TypeRef t) -> uint { + ret llvm.LLVMStoreSizeOfType(cx.td.lltd, t); +} + fn llsize_of(TypeRef t) -> ValueRef { ret llvm.LLVMConstIntCast(lib.llvm.llvm.LLVMSizeOf(t), T_int(), False); } @@ -878,6 +905,49 @@ fn align_of(@block_ctxt cx, @ty.t t) -> result { ret dynamic_align_of(cx, t); } +// Computes the size of the data part of a non-dynamically-sized tag. +fn static_size_of_tag(@crate_ctxt cx, @ty.t t) -> uint { + if (ty.type_has_dynamic_size(t)) { + log "dynamically sized type passed to static_size_of_tag()"; + fail; + } + + if (cx.tag_sizes.contains_key(t)) { + ret cx.tag_sizes.get(t); + } + + auto tid = tup(0, 0); // FIXME (#250): typestate botch + let vec[@ty.t] subtys = vec(); // FIXME (#250): typestate botch + alt (t.struct) { + case (ty.ty_tag(?tid_, ?subtys_)) { + tid = tid_; + subtys = subtys_; + } + case (_) { + log "non-tag passed to static_size_of_tag()"; + fail; + } + } + + // Compute max(variant sizes). + auto max_size = 0u; + auto variants = tag_variants(cx, tid); + for (ast.variant variant in variants) { + let vec[@ty.t] tys = variant_types(cx, variant); + auto tup_ty = ty.plain_ty(ty.ty_tup(tys)); + + // Here we possibly do a recursive call. + auto this_size = llsize_of_real(cx, type_of(cx, tup_ty)); + + if (max_size < this_size) { + max_size = this_size; + } + } + + cx.tag_sizes.insert(t, max_size); + ret max_size; +} + fn dynamic_size_of(@block_ctxt cx, @ty.t t) -> result { fn align_elements(@block_ctxt cx, vec[@ty.t] elts) -> result { // @@ -974,10 +1044,10 @@ fn dynamic_align_of(@block_ctxt cx, @ty.t t) -> result { } // Replacement for the LLVM 'GEP' instruction when field-indexing into a -// tuple-like structure (tup, rec, tag) with a static index. This one is -// driven off ty.struct and knows what to do when it runs into a ty_param -// stuck in the middle of the thing it's GEP'ing into. Much like size_of and -// align_of, above. +// tuple-like structure (tup, rec) with a static index. This one is driven off +// ty.struct and knows what to do when it runs into a ty_param stuck in the +// middle of the thing it's GEP'ing into. Much like size_of and align_of, +// above. fn GEP_tup_like(@block_ctxt cx, @ty.t t, ValueRef base, vec[int] ixs) -> result { @@ -1076,6 +1146,53 @@ fn GEP_tup_like(@block_ctxt cx, @ty.t t, ret res(bcx, bcx.build.PointerCast(bumped, typ)); } +// Replacement for the LLVM 'GEP' instruction when field indexing into a tag. +// This function uses GEP_tup_like() above and automatically performs casts as +// appropriate. @llblobptr is the data part of a tag value; its actual type is +// meaningless, as it will be cast away. +fn GEP_tag(@block_ctxt cx, ValueRef llblobptr, &ast.variant variant, int ix) + -> result { + // Synthesize a tuple type so that GEP_tup_like() can work its magic. + // Separately, store the type of the element we're interested in. + auto arg_tys = arg_tys_of_fn(variant.ann); + auto elem_ty = ty.plain_ty(ty.ty_nil); // typestate infelicity + auto i = 0; + let vec[@ty.t] true_arg_tys = vec(); + for (ty.arg a in arg_tys) { + true_arg_tys += vec(a.ty); + if (i == ix) { + elem_ty = a.ty; + } + + i += 1; + } + auto tup_ty = ty.plain_ty(ty.ty_tup(true_arg_tys)); + + // Cast the blob pointer to the appropriate type, if we need to (i.e. if + // the blob pointer isn't dynamically sized). + let ValueRef llunionptr; + if (!ty.type_has_dynamic_size(tup_ty)) { + auto llty = type_of(cx.fcx.ccx, tup_ty); + llunionptr = cx.build.TruncOrBitCast(llblobptr, T_ptr(llty)); + } else { + llunionptr = llblobptr; + } + + // Do the GEP_tup_like(). + auto rslt = GEP_tup_like(cx, tup_ty, llunionptr, vec(0, ix)); + + // Cast the result to the appropriate type, if necessary. + auto val; + if (!ty.type_has_dynamic_size(elem_ty)) { + auto llelemty = type_of(rslt.bcx.fcx.ccx, elem_ty); + val = rslt.bcx.build.PointerCast(rslt.val, T_ptr(llelemty)); + } else { + val = rslt.val; + } + + ret res(rslt.bcx, val); +} + fn trans_raw_malloc(@block_ctxt cx, TypeRef llptr_ty, ValueRef llsize) -> result { @@ -1527,6 +1644,7 @@ fn variant_types(@crate_ctxt cx, &ast.variant v) -> vec[@ty.t] { tys += vec(arg.ty); } } + case (ty.ty_tag(_, _)) { /* nothing */ } case (_) { fail; } } ret tys; @@ -1647,8 +1765,6 @@ fn iter_structural_ty_full(@block_ctxt cx, } } case (ty.ty_tag(?tid, ?tps)) { - auto info = cx.fcx.ccx.tags.get(mk_plain_tag(tid)); - auto variants = tag_variants(cx.fcx.ccx, tid); auto n_variants = _vec.len[ast.variant](variants); @@ -4653,14 +4769,6 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, auto arg_tys = arg_tys_of_fn(variant.ann); copy_args_to_allocas(bcx, none[TypeRef], fn_args, arg_tys); - // Now synthesize a tuple type for the arguments, so that GEP_tup_like() - // will know what the data part of the variant looks like. - let vec[@ty.t] true_arg_tys = vec(); - for (ty.arg a in arg_tys) { - true_arg_tys += vec(a.ty); - } - auto tup_ty = ty.plain_ty(ty.ty_tup(true_arg_tys)); - // Cast the tag to a type we can GEP into. auto lltagptr = bcx.build.PointerCast(fcx.llretptr, T_opaque_tag_ptr(fcx.ccx.tn)); @@ -4672,23 +4780,19 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, auto llblobptr = bcx.build.GEP(lltagptr, vec(C_int(0), C_int(1))); - // Cast the blob pointer to the appropriate type, if we need to (i.e. if - // the blob pointer isn't dynamically sized). - let ValueRef llunionptr; - if (!ty.type_has_dynamic_size(tup_ty)) { - auto llty = type_of(cx, tup_ty); - llunionptr = bcx.build.TruncOrBitCast(llblobptr, T_ptr(llty)); - } else { - llunionptr = llblobptr; - } - i = 0u; for (ast.variant_arg va in variant.args) { - auto llargval = bcx.build.Load(fcx.llargs.get(va.id)); - auto rslt = GEP_tup_like(bcx, tup_ty, llunionptr, vec(0, i as int)); + auto rslt = GEP_tag(bcx, llblobptr, variant, i as int); bcx = rslt.bcx; auto lldestptr = rslt.val; + // If this argument to this function is a tag, it'll have come in to + // this function as an opaque blob due to the way that type_of() + // works. So we have to cast to the destination's view of the type. + auto llargptr = bcx.build.PointerCast(fcx.llargs.get(va.id), + val_ty(lldestptr)); + auto llargval = bcx.build.Load(llargptr); + bcx.build.Store(llargval, lldestptr); i += 1u; } @@ -4747,6 +4851,7 @@ fn trans_item(@crate_ctxt cx, &ast.item item) { case (ast.item_tag(?name, ?variants, ?tps, ?tag_id)) { auto sub_cx = @rec(path=cx.path + sep() + name with *cx); auto i = 0; + log "translating variants for " + name; for (ast.variant variant in variants) { trans_tag_variant(sub_cx, tag_id, variant, i, tps); i += 1; @@ -4885,12 +4990,6 @@ fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { } case (ast.item_tag(_, ?variants, ?tps, ?tag_id)) { - auto vi = new_def_hash[uint](); - auto navi = new_def_hash[uint](); - - auto info = @rec(th=mk_type_handle()); - - cx.tags.insert(mk_plain_tag(tag_id), info); cx.items.insert(tag_id, i); } @@ -4942,58 +5041,6 @@ fn collect_tag_ctors(@crate_ctxt cx, @ast.crate crate) { } -// The tag type resolution pass, which determines all the LLVM types that -// correspond to each tag type in the crate. - -fn resolve_tag_types_for_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt { - alt (i.node) { - case (ast.item_tag(_, ?variants, _, ?tag_id)) { - // FIXME: This is all wrong. Now sizes and alignments are computed - // dynamically instead of up front. - - auto max_align = 0u; - auto max_size = 0u; - - auto info = cx.tags.get(mk_plain_tag(tag_id)); - - for (ast.variant variant in variants) { - if (_vec.len[ast.variant_arg](variant.args) > 0u) { - auto llvariantty = type_of_variant(cx, variant); - auto align = - llvm.LLVMPreferredAlignmentOfType(cx.td.lltd, - llvariantty); - auto size = - llvm.LLVMStoreSizeOfType(cx.td.lltd, - llvariantty) as uint; - if (max_align < align) { max_align = align; } - if (max_size < size) { max_size = size; } - } - } - - // FIXME: alignment is wrong here, manually insert padding I - // guess :( - auto tag_ty = T_struct(vec(T_int(), T_array(T_i8(), max_size))); - auto th = info.th.llth; - llvm.LLVMRefineType(llvm.LLVMResolveTypeHandle(th), tag_ty); - } - case (_) { - // fall through - } - } - - ret cx; -} - -fn resolve_tag_types(@crate_ctxt cx, @ast.crate crate) { - let fold.ast_fold[@crate_ctxt] fld = - fold.new_identity_fold[@crate_ctxt](); - - fld = @rec( update_env_for_item = bind resolve_tag_types_for_item(_,_) - with *fld ); - - fold.fold_crate[@crate_ctxt](cx, fld, crate); -} - // The constant translation pass. fn trans_constant(&@crate_ctxt cx, @ast.item it) -> @crate_ctxt { @@ -5461,7 +5508,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, auto glues = make_glues(llmod, tn); auto hasher = ty.hash_ty; auto eqer = ty.eq_ty; - auto tags = map.mk_hashmap[@ty.t,@tag_info](hasher, eqer); + auto tag_sizes = map.mk_hashmap[@ty.t,uint](hasher, eqer); auto tydescs = map.mk_hashmap[@ty.t,ValueRef](hasher, eqer); let vec[ast.ty_param] obj_typarams = vec(); let vec[ast.obj_field] obj_fields = vec(); @@ -5477,7 +5524,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, item_ids = new_def_hash[ValueRef](), items = new_def_hash[@ast.item](), native_items = new_def_hash[@ast.native_item](), - tags = tags, + tag_sizes = tag_sizes, discrims = new_def_hash[ValueRef](), fn_pairs = new_def_hash[ValueRef](), consts = new_def_hash[ValueRef](), @@ -5492,7 +5539,6 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, create_typedefs(cx); collect_items(cx, crate); - resolve_tag_types(cx, crate); collect_tag_ctors(cx, crate); trans_constants(cx, crate); -- cgit v1.2.3 From 0aa74828e36f2b57822317e9c99435993633a424 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 4 Mar 2011 15:15:12 -0800 Subject: rustc: Remove "translating variants" debug string --- src/comp/middle/trans.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 66539ab2..af62bb9a 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4851,7 +4851,6 @@ fn trans_item(@crate_ctxt cx, &ast.item item) { case (ast.item_tag(?name, ?variants, ?tps, ?tag_id)) { auto sub_cx = @rec(path=cx.path + sep() + name with *cx); auto i = 0; - log "translating variants for " + name; for (ast.variant variant in variants) { trans_tag_variant(sub_cx, tag_id, variant, i, tps); i += 1; -- cgit v1.2.3 From 1dc6bdf33191cbd183bb17331e4a71d5c80ad353 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 4 Mar 2011 17:22:43 -0800 Subject: rustc: Don't recurse forever if type glue needs to refer to its own type descriptor --- src/comp/middle/trans.rs | 61 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index af62bb9a..9b7a501c 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -60,6 +60,10 @@ type glue_fns = rec(ValueRef activate_glue, ValueRef bzero_glue, ValueRef vec_append_glue); +type tydesc_info = rec(ValueRef tydesc, + ValueRef take_glue, + ValueRef drop_glue); + state type crate_ctxt = rec(session.session sess, ModuleRef llmod, target_data td, @@ -78,7 +82,7 @@ state type crate_ctxt = rec(session.session sess, hashmap[ast.def_id, ValueRef] fn_pairs, hashmap[ast.def_id, ValueRef] consts, hashmap[ast.def_id,()] obj_methods, - hashmap[@ty.t, ValueRef] tydescs, + hashmap[@ty.t, @tydesc_info] tydescs, vec[ast.ty_param] obj_typarams, vec[ast.obj_field] obj_fields, @glue_fns glues, @@ -1291,10 +1295,11 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { check (n_params == _vec.len[ValueRef](tys._1)); if (!cx.fcx.ccx.tydescs.contains_key(t)) { - make_tydesc(cx.fcx.ccx, t, tys._0); + declare_tydesc(cx.fcx.ccx, t); + define_tydesc(cx.fcx.ccx, t, tys._0); } - auto root = cx.fcx.ccx.tydescs.get(t); + auto root = cx.fcx.ccx.tydescs.get(t).tydesc; auto tydescs = cx.build.Alloca(T_array(T_ptr(T_tydesc(cx.fcx.ccx.tn)), n_params)); @@ -1329,16 +1334,18 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result { // Otherwise, generate a tydesc if necessary, and return it. if (!cx.fcx.ccx.tydescs.contains_key(t)) { let vec[ast.def_id] defs = vec(); - make_tydesc(cx.fcx.ccx, t, defs); + declare_tydesc(cx.fcx.ccx, t); + define_tydesc(cx.fcx.ccx, t, defs); } - ret res(cx, cx.fcx.ccx.tydescs.get(t)); + ret res(cx, cx.fcx.ccx.tydescs.get(t).tydesc); } -fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { - auto tg = make_take_glue; - auto take_glue = make_generic_glue(cx, t, "take", tg, typaram_defs); - auto dg = make_drop_glue; - auto drop_glue = make_generic_glue(cx, t, "drop", dg, typaram_defs); +// Generates the declaration for (but doesn't fill in) a type descriptor. This +// needs to be separate from make_tydesc() below, because sometimes type glue +// functions needs to refer to their own type descriptors. +fn declare_tydesc(@crate_ctxt cx, @ty.t t) { + auto take_glue = declare_generic_glue(cx, t, "take"); + auto drop_glue = declare_generic_glue(cx, t, "drop"); auto llsize; auto llalign; @@ -1383,18 +1390,40 @@ fn make_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { llvm.LLVMSetGlobalConstant(gvar, True); llvm.LLVMSetLinkage(gvar, lib.llvm.LLVMPrivateLinkage as llvm.Linkage); - cx.tydescs.insert(t, gvar); + + auto info = rec( + tydesc=gvar, + take_glue=take_glue, + drop_glue=drop_glue + ); + + cx.tydescs.insert(t, @info); } -fn make_generic_glue(@crate_ctxt cx, @ty.t t, str name, - val_and_ty_fn helper, - vec[ast.def_id] typaram_defs) -> ValueRef { +// declare_tydesc() above must have been called first. +fn define_tydesc(@crate_ctxt cx, @ty.t t, vec[ast.def_id] typaram_defs) { + auto info = cx.tydescs.get(t); + auto gvar = info.tydesc; + + auto tg = make_take_glue; + auto take_glue = make_generic_glue(cx, t, info.take_glue, tg, + typaram_defs); + auto dg = make_drop_glue; + auto drop_glue = make_generic_glue(cx, t, info.drop_glue, dg, + typaram_defs); +} + +fn declare_generic_glue(@crate_ctxt cx, @ty.t t, str name) -> ValueRef { auto llfnty = T_glue_fn(cx.tn); auto fn_name = cx.names.next("_rust_" + name) + sep() + ty.ty_to_str(t); fn_name = sanitize(fn_name); - auto llfn = decl_fastcall_fn(cx.llmod, fn_name, llfnty); + ret decl_fastcall_fn(cx.llmod, fn_name, llfnty); +} +fn make_generic_glue(@crate_ctxt cx, @ty.t t, ValueRef llfn, + val_and_ty_fn helper, + vec[ast.def_id] typaram_defs) -> ValueRef { auto fcx = new_fn_ctxt(cx, llfn); auto bcx = new_top_block_ctxt(fcx); @@ -5508,7 +5537,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output, auto hasher = ty.hash_ty; auto eqer = ty.eq_ty; auto tag_sizes = map.mk_hashmap[@ty.t,uint](hasher, eqer); - auto tydescs = map.mk_hashmap[@ty.t,ValueRef](hasher, eqer); + auto tydescs = map.mk_hashmap[@ty.t,@tydesc_info](hasher, eqer); let vec[ast.ty_param] obj_typarams = vec(); let vec[ast.obj_field] obj_fields = vec(); -- cgit v1.2.3 From 94b681afe4f8fb09141d459963b268c76fbd0072 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 4 Mar 2011 18:05:48 -0800 Subject: rustc: Use copy_ty() when initializing N-ary tag variants. Un-XFAIL generic-tag.rs. --- src/Makefile | 3 +-- src/comp/middle/trans.rs | 23 ++++++++++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/Makefile b/src/Makefile index 2ec0f9d1..484740b5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -432,8 +432,7 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \ test/compile-fail/tail-non-call.rs \ test/compile-fail/writing-through-read-alias.rs -TEST_XFAILS_RUSTC := $(CONST_TAG_XFAILS) \ - $(addprefix test/run-pass/, \ +TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ acyclic-unwind.rs \ alt-pattern-drop.rs \ alt-type-simple.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 9b7a501c..b5ff4224 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -363,17 +363,22 @@ fn T_taskptr(type_names tn) -> TypeRef { ret T_ptr(T_task(tn)); } -fn T_typaram_ptr(type_names tn) -> TypeRef { +// This type must never be used directly; it must always be cast away. +fn T_typaram(type_names tn) -> TypeRef { auto s = "typaram"; if (tn.name_has_type(s)) { ret tn.get_type(s); } - auto t = T_ptr(T_i8()); + auto t = T_i8(); tn.associate(s, t); ret t; } +fn T_typaram_ptr(type_names tn) -> TypeRef { + ret T_ptr(T_typaram(tn)); +} + fn T_closure_ptr(type_names tn, TypeRef lltarget_ty, TypeRef llbindings_ty, @@ -2068,7 +2073,6 @@ fn call_tydesc_glue(@block_ctxt cx, ValueRef v, @ty.t t, int field) { fn incr_all_refcnts(@block_ctxt cx, ValueRef v, @ty.t t) -> result { - if (!ty.type_is_scalar(t)) { call_tydesc_glue(cx, v, t, abi.tydesc_field_take_glue_off); } @@ -4820,9 +4824,18 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, // works. So we have to cast to the destination's view of the type. auto llargptr = bcx.build.PointerCast(fcx.llargs.get(va.id), val_ty(lldestptr)); - auto llargval = bcx.build.Load(llargptr); - bcx.build.Store(llargval, lldestptr); + auto arg_ty = arg_tys.(i).ty; + auto llargval; + if (ty.type_is_structural(arg_ty)) { + llargval = llargptr; + } else { + llargval = bcx.build.Load(llargptr); + } + + rslt = copy_ty(bcx, INIT, lldestptr, llargval, arg_ty); + bcx = rslt.bcx; + i += 1u; } -- cgit v1.2.3 From d97c800e3179604db82e35bff682ea1ed6ec3909 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Sat, 5 Mar 2011 20:05:02 +0000 Subject: Make ret and fail stmts have 0 out-edges, Closes #250. --- src/boot/me/typestate.ml | 5 +++++ src/comp/front/lexer.rs | 5 +---- src/comp/middle/fold.rs | 4 ++-- src/comp/middle/ty.rs | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/boot/me/typestate.ml b/src/boot/me/typestate.ml index 1c9c90ea..8b7840a2 100644 --- a/src/boot/me/typestate.ml +++ b/src/boot/me/typestate.ml @@ -865,6 +865,11 @@ let rec build_flow_graph_for_stmt | Ast.STMT_block b -> blk predecessors b + | Ast.STMT_fail + | Ast.STMT_ret _ -> + connect predecessors [s.id]; + [] + | _ -> connect predecessors [s.id]; [s.id] diff --git a/src/comp/front/lexer.rs b/src/comp/front/lexer.rs index 99e9217f..0e15e3d8 100644 --- a/src/comp/front/lexer.rs +++ b/src/comp/front/lexer.rs @@ -665,12 +665,9 @@ impure fn next_token(reader rdr) -> token.token { case ('%') { ret binop(rdr, token.PERCENT); } - } - log "lexer stopping at "; - log c; - ret token.EOF; + fail; } diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index c7041b26..935f426b 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -701,7 +701,7 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr { } - ret e; + fail; } @@ -724,7 +724,7 @@ fn fold_stmt[ENV](&ENV env, ast_fold[ENV] fld, &@stmt s) -> @stmt { ret fld.fold_stmt_expr(env_, s.span, ee); } } - ret s; + fail; } fn fold_block[ENV](&ENV env, ast_fold[ENV] fld, &block blk) -> block { diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 2fc3160c..0b6ef53b 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -373,7 +373,7 @@ fn fold_ty(ty_fold fld, @t ty) -> @t { case (ty_param(_)) { ret fld.fold_simple_ty(ty); } } - ret ty; + fail; } // Type utilities -- cgit v1.2.3 From 3eb20f3f6e3e1301897a560629cda1ee2c7c2995 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Sun, 6 Mar 2011 12:46:33 -0800 Subject: Correct signatures and arguments associated with call into vec_append_glue. --- src/comp/middle/trans.rs | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index b5ff4224..c30373e2 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -321,6 +321,10 @@ fn T_vec(TypeRef t) -> TypeRef { )); } +fn T_opaque_vec_ptr() -> TypeRef { + ret T_ptr(T_vec(T_int())); +} + fn T_str() -> TypeRef { ret T_vec(T_i8()); } @@ -2464,20 +2468,23 @@ fn trans_vec_append(@block_ctxt cx, @ty.t t, auto llelt_tydesc = get_tydesc(bcx, elt_ty); bcx = llelt_tydesc.bcx; - ret res(cx, cx.build.FastCall(cx.fcx.ccx.glues.memcpy_glue, - vec(cx.fcx.lltaskptr, - llvec_tydesc.val, - llelt_tydesc.val, - lhs, - load_scalar_or_boxed(cx, rhs, t), - skip_null))); + auto dst = bcx.build.PointerCast(lhs, T_ptr(T_opaque_vec_ptr())); + auto src = bcx.build.PointerCast(rhs, T_opaque_vec_ptr()); + + ret res(bcx, bcx.build.FastCall(cx.fcx.ccx.glues.vec_append_glue, + vec(cx.fcx.lltaskptr, + llvec_tydesc.val, + llelt_tydesc.val, + dst, src, skip_null))); } fn trans_vec_add(@block_ctxt cx, @ty.t t, ValueRef lhs, ValueRef rhs) -> result { auto r = alloc_ty(cx, t); - r = copy_ty(r.bcx, INIT, r.val, lhs, t); - ret trans_vec_append(r.bcx, t, lhs, rhs); + auto tmp = r.val; + find_scope_cx(cx).cleanups += clean(bind drop_ty(_, tmp, t)); + r = copy_ty(r.bcx, INIT, tmp, lhs, t); + ret trans_vec_append(r.bcx, t, tmp, rhs); } @@ -5423,7 +5430,7 @@ fn make_vec_append_glue(ModuleRef llmod, type_names tn) -> ValueRef { * elements can be copied to a newly alloc'ed vec if one must be * created. * - * 3. Dst vec alias (i.e. ptr to ptr to rust_vec, we will mutate it). + * 3. Dst vec ptr (i.e. ptr to ptr to rust_vec). * * 4. Src vec (i.e. ptr to rust_vec). * @@ -5434,9 +5441,9 @@ fn make_vec_append_glue(ModuleRef llmod, type_names tn) -> ValueRef { auto ty = T_fn(vec(T_taskptr(tn), T_ptr(T_tydesc(tn)), T_ptr(T_tydesc(tn)), - T_ptr(T_ptr(T_vec(T_int()))), // a lie. - T_ptr(T_vec(T_int())), // a lie. - T_bool()), T_void()); + T_ptr(T_opaque_vec_ptr()), + T_opaque_vec_ptr(), T_bool()), + T_void()); auto llfn = decl_fastcall_fn(llmod, abi.vec_append_glue_name(), ty); ret llfn; @@ -5488,10 +5495,8 @@ fn trans_vec_append_glue(@crate_ctxt cx) { vp2i(bcx, llvec_tydesc))); bcx = llnew_vec_res.bcx; - auto llnew_vec = vi2p(bcx, - llnew_vec_res.val, - T_ptr(T_vec(T_int())) // a lie. - ); + auto llnew_vec = vi2p(bcx, llnew_vec_res.val, + T_opaque_vec_ptr()); // FIXME: complete this. -- cgit v1.2.3 From 138c55a69d44371e4de04ed538c787dec46a7200 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Sun, 6 Mar 2011 15:12:33 -0800 Subject: Fix return value on trans_vec_add. --- src/comp/middle/trans.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c30373e2..dde5aa60 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2484,7 +2484,8 @@ fn trans_vec_add(@block_ctxt cx, @ty.t t, auto tmp = r.val; find_scope_cx(cx).cleanups += clean(bind drop_ty(_, tmp, t)); r = copy_ty(r.bcx, INIT, tmp, lhs, t); - ret trans_vec_append(r.bcx, t, tmp, rhs); + auto bcx = trans_vec_append(r.bcx, t, tmp, rhs).bcx; + ret res(bcx, load_scalar_or_boxed(bcx, tmp, t)); } -- cgit v1.2.3 From 330c9c6c3592496462dbf9aa716a37e048b00172 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 6 Mar 2011 13:42:50 -0500 Subject: Make _str.bytes use _vec.init_fn. Remove FIXME. --- src/lib/_str.rs | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/src/lib/_str.rs b/src/lib/_str.rs index 6b7ac018..0e0e7650 100644 --- a/src/lib/_str.rs +++ b/src/lib/_str.rs @@ -96,25 +96,10 @@ fn buf(str s) -> sbuf { } fn bytes(str s) -> vec[u8] { - /* FIXME (issue #58): - * Should be... - * - * fn ith(str s, uint i) -> u8 { - * ret s.(i); - * } - * ret _vec.init_fn[u8](bind ith(s, _), byte_len(s)); - * - * but we do not correctly decrement refcount of s when - * the binding dies, so we have to do this manually. - */ - let uint n = _str.byte_len(s); - let vec[u8] v = _vec.alloc[u8](n); - let uint i = 0u; - while (i < n) { - v += vec(s.(i)); - i += 1u; + fn ith(str s, uint i) -> u8 { + ret s.(i); } - ret v; + ret _vec.init_fn[u8](bind ith(s, _), byte_len(s)); } fn from_bytes(vec[u8] v) : is_utf8(v) -> str { -- cgit v1.2.3 From bed457d3a7244b317c54962d80b460294b846c27 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 6 Mar 2011 13:51:42 -0500 Subject: Change io.fileflag to a tag type. Remove FIXME --- src/lib/io.rs | 27 ++++++++------------------- src/test/run-pass/lib-io.rs | 2 +- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/src/lib/io.rs b/src/lib/io.rs index f285f6c8..9f428cee 100644 --- a/src/lib/io.rs +++ b/src/lib/io.rs @@ -85,18 +85,11 @@ fn new_buf_reader(str path) -> buf_reader { ret fd_buf_reader(fd, new_buf()); } -/** - * FIXME (issue #150): This should be - * - * type fileflag = tag(append(), create(), truncate()); - * - * but then the tag value ctors are not found from crate-importers of std, so - * we manually simulate the enum below. - */ -type fileflag = uint; -fn append() -> uint { ret 0u; } -fn create() -> uint { ret 1u; } -fn truncate() -> uint { ret 2u; } +tag fileflag { + append; + create; + truncate; +} fn new_buf_writer(str path, vec[fileflag] flags) -> buf_writer { @@ -129,13 +122,9 @@ fn new_buf_writer(str path, vec[fileflag] flags) -> buf_writer { for (fileflag f in flags) { alt (f) { - // FIXME (issue #150): cf comment above defn of fileflag type - //case (append()) { fflags |= os.libc_constants.O_APPEND(); } - //case (create()) { fflags |= os.libc_constants.O_CREAT(); } - //case (truncate()) { fflags |= os.libc_constants.O_TRUNC(); } - case (0u) { fflags |= os.libc_constants.O_APPEND(); } - case (1u) { fflags |= os.libc_constants.O_CREAT(); } - case (2u) { fflags |= os.libc_constants.O_TRUNC(); } + case (append) { fflags |= os.libc_constants.O_APPEND(); } + case (create) { fflags |= os.libc_constants.O_CREAT(); } + case (truncate) { fflags |= os.libc_constants.O_TRUNC(); } } } diff --git a/src/test/run-pass/lib-io.rs b/src/test/run-pass/lib-io.rs index e0665fb6..0c0bcdcd 100644 --- a/src/test/run-pass/lib-io.rs +++ b/src/test/run-pass/lib-io.rs @@ -11,7 +11,7 @@ fn test_simple(str tmpfilebase) { log frood; { - let io.buf_writer out = io.new_buf_writer(tmpfile, vec(io.create())); + let io.buf_writer out = io.new_buf_writer(tmpfile, vec(io.create)); out.write(_str.bytes(frood)); } -- cgit v1.2.3 From b893bec4bbdfda549a1c45bd5328b3dd78a2e05c Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 6 Mar 2011 13:00:52 -0500 Subject: Flatten conditionals in rustc.rs. Remove FIXME --- src/comp/driver/rustc.rs | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index 69e61aa0..67275b9b 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -113,24 +113,19 @@ impure fn main(vec[str] args) { do_warn = false; } else if (_str.eq(arg, "-shared")) { shared = true; - } else { - // FIXME: rust could use an elif construct. - if (_str.eq(arg, "-o")) { - if (i+1u < len) { - output_file = some(args.(i+1u)); - i += 1u; - } else { - usage(sess, args.(0)); - sess.err("-o requires an argument"); - } + } else if (_str.eq(arg, "-o")) { + if (i+1u < len) { + output_file = some(args.(i+1u)); + i += 1u; } else { - if (_str.eq(arg, "-h")) { - usage(sess, args.(0)); - } else { - usage(sess, args.(0)); - sess.err("unrecognized option: " + arg); - } + usage(sess, args.(0)); + sess.err("-o requires an argument"); } + } else if (_str.eq(arg, "-h")) { + usage(sess, args.(0)); + } else { + usage(sess, args.(0)); + sess.err("unrecognized option: " + arg); } } else { alt (input_file) { -- cgit v1.2.3 From d39da6f97819becd9ea41c194b5f0daa178814fe Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 6 Mar 2011 13:56:38 -0500 Subject: Remove typestate workarounds --- src/comp/driver/rustc.rs | 2 -- src/comp/front/extfmt.rs | 17 ++--------------- src/comp/front/parser.rs | 18 ++++++++---------- src/comp/middle/trans.rs | 10 +++++----- src/comp/middle/ty.rs | 42 +++++++++++++----------------------------- src/comp/middle/typeck.rs | 16 +++++++++------- 6 files changed, 37 insertions(+), 68 deletions(-) diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index 67275b9b..90fe0e0c 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -137,8 +137,6 @@ impure fn main(vec[str] args) { input_file = some[str](arg); } } - // FIXME: dummy node to work around typestate mis-wiring bug. - i = i; } i += 1u; } diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index 7201a17c..255614d0 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -244,9 +244,7 @@ fn parse_count(str s, uint i, uint lim) -> tup(count, uint) { ret tup(count_implied, i); } - // FIXME: These inner functions are just to avoid a rustboot - // "Unsatisfied precondition constraint" bug with alts nested in ifs - fn parse_star_count(str s, uint i, uint lim) -> tup(count, uint) { + if (s.(i) == ('*' as u8)) { auto param = parse_parameter(s, i + 1u, lim); auto j = param._1; alt (param._0) { @@ -257,9 +255,7 @@ fn parse_count(str s, uint i, uint lim) -> tup(count, uint) { ret tup(count_is_param(n), j); } } - } - - fn parse_count_(str s, uint i, uint lim) -> tup(count, uint) { + } else { auto num = peek_num(s, i, lim); alt (num) { case (none[tup(uint, uint)]) { @@ -270,12 +266,6 @@ fn parse_count(str s, uint i, uint lim) -> tup(count, uint) { } } } - - if (s.(i) == ('*' as u8)) { - ret parse_star_count(s, i, lim); - } else { - ret parse_count_(s, i, lim); - } } fn parse_precision(str s, uint i, uint lim) -> tup(count, uint) { @@ -318,9 +308,6 @@ fn parse_type(str s, uint i, uint lim) -> tup(ty, uint) { } else if (_str.eq(tstr, "t")) { t = ty_bits; } else { - // FIXME: This is a hack to avoid 'unsatisfied precondition - // constraint' on uninitialized variable t below - t = ty_bool; log "unknown type in conversion"; fail; } diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 934764e6..8665a425 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1365,7 +1365,7 @@ impure fn parse_initializer(parser p) -> option.t[@ast.expr] { impure fn parse_pat(parser p) -> @ast.pat { auto lo = p.get_span(); auto hi = lo; - auto pat = ast.pat_wild(ast.ann_none); // FIXME: typestate bug + auto pat; alt (p.peek()) { case (token.UNDERSCORE) { @@ -1541,31 +1541,28 @@ fn index_block(vec[@ast.stmt] stmts, option.t[@ast.expr] expr) -> ast.block_ { auto index = new_str_hash[uint](); auto u = 0u; for (@ast.stmt s in stmts) { - // FIXME: typestate bug requires we do this up top, not - // down below loop. Sigh. - u += 1u; alt (s.node) { case (ast.stmt_decl(?d)) { alt (d.node) { case (ast.decl_local(?loc)) { - index.insert(loc.ident, u-1u); + index.insert(loc.ident, u); } case (ast.decl_item(?it)) { alt (it.node) { case (ast.item_fn(?i, _, _, _, _)) { - index.insert(i, u-1u); + index.insert(i, u); } case (ast.item_mod(?i, _, _)) { - index.insert(i, u-1u); + index.insert(i, u); } case (ast.item_ty(?i, _, _, _, _)) { - index.insert(i, u-1u); + index.insert(i, u); } case (ast.item_tag(?i, _, _, _)) { - index.insert(i, u-1u); + index.insert(i, u); } case (ast.item_obj(?i, _, _, _, _)) { - index.insert(i, u-1u); + index.insert(i, u); } } } @@ -1573,6 +1570,7 @@ fn index_block(vec[@ast.stmt] stmts, option.t[@ast.expr] expr) -> ast.block_ { } case (_) { /* fall through */ } } + u += 1u; } ret rec(stmts=stmts, expr=expr, index=index); } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index dde5aa60..e00d5a92 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -929,8 +929,8 @@ fn static_size_of_tag(@crate_ctxt cx, @ty.t t) -> uint { ret cx.tag_sizes.get(t); } - auto tid = tup(0, 0); // FIXME (#250): typestate botch - let vec[@ty.t] subtys = vec(); // FIXME (#250): typestate botch + auto tid; + let vec[@ty.t] subtys; alt (t.struct) { case (ty.ty_tag(?tid_, ?subtys_)) { tid = tid_; @@ -3419,12 +3419,12 @@ fn trans_bind(@block_ctxt cx, @ast.expr f, } // Figure out which tydescs we need to pass, if any. - // FIXME: typestate botch - let @ty.t outgoing_fty = ty.plain_ty(ty.ty_nil); - let vec[ValueRef] lltydescs = vec(); + let @ty.t outgoing_fty; + let vec[ValueRef] lltydescs; alt (f_res.generic) { case (none[generic_info]) { outgoing_fty = ty.expr_ty(f); + lltydescs = vec(); } case (some[generic_info](?ginfo)) { outgoing_fty = ginfo.item_type; diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 0b6ef53b..3f209d3c 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -1018,32 +1018,6 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) ret ures_err(terr_meth_count, expected, actual); } - // FIXME: work around buggy typestate logic for 'alt', sigh. - fn is_ok(&unify_result r) -> bool { - alt (r) { - case (ures_ok(?tfn)) { - ret true; - } - case (_) {} - } - ret false; - } - - fn append_if_ok(&method e_meth, - &unify_result r, &mutable vec[method] result_meths) { - alt (r) { - case (ures_ok(?tfn)) { - alt (tfn.struct) { - case (ty_fn(?proto, ?ins, ?out)) { - result_meths += vec(rec(inputs = ins, - output = out - with e_meth)); - } - } - } - } - } - while (i < expected_len) { auto e_meth = expected_meths.(i); auto a_meth = actual_meths.(i); @@ -1056,10 +1030,20 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler) expected, actual, handler, e_meth.inputs, e_meth.output, a_meth.inputs, a_meth.output); - if (!is_ok(r)) { - ret r; + alt (r) { + case (ures_ok(?tfn)) { + alt (tfn.struct) { + case (ty_fn(?proto, ?ins, ?out)) { + result_meths += vec(rec(inputs = ins, + output = out + with e_meth)); + } + } + } + case (_) { + ret r; + } } - append_if_ok(e_meth, r, result_meths); i += 1u; } auto t = plain_ty(ty_obj(result_meths)); diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index f8f7fc72..c257a167 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -890,7 +890,7 @@ fn are_compatible(&@fn_ctxt fcx, @ty.t expected, @ty.t actual) -> bool { // TODO: enforce this via a predicate. 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 + auto p_1; alt (pat.node) { case (ast.pat_wild(?ann)) { @@ -960,9 +960,7 @@ fn demand_expr(&@fn_ctxt fcx, @ty.t expected, @ast.expr e) -> @ast.expr { fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, autoderef_kind adk) -> @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); + auto e_1; alt (e.node) { case (ast.expr_vec(?es_0, ?ann)) { @@ -1167,6 +1165,10 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e, case (ast.expr_put(_)) { e_1 = e.node; } case (ast.expr_be(_)) { e_1 = e.node; } case (ast.expr_check_expr(_)) { e_1 = e.node; } + case (_) { + fcx.ccx.sess.unimpl("type unification for expression variant"); + fail; + } } ret @fold.respan[ast.expr_](e.span, e_1); @@ -1331,7 +1333,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { } auto rt_0 = next_ty_var(fcx.ccx); - auto t_0 = plain_ty(ty.ty_uint); // FIXME: typestate botch + auto t_0; alt (expr_ty(f_0).struct) { case (ty.ty_fn(?proto, _, _)) { t_0 = plain_ty(ty.ty_fn(proto, arg_tys_0, rt_0)); @@ -1777,9 +1779,9 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr { auto result = check_call_or_bind(fcx, f, args); // Pull the argument and return types out. - auto proto_1 = ast.proto_fn; // FIXME: typestate botch + auto proto_1; let vec[ty.arg] arg_tys_1 = vec(); - auto rt_1 = plain_ty(ty.ty_nil); // FIXME: typestate botch + auto rt_1; alt (expr_ty(result._0).struct) { case (ty.ty_fn(?proto, ?arg_tys, ?rt)) { proto_1 = proto; -- cgit v1.2.3 From 386ba3ae63bd0d642af3349c25370605f5200a05 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Sun, 6 Mar 2011 22:37:14 -0800 Subject: Further work on vec-append. Almost working. --- src/comp/middle/trans.rs | 180 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 135 insertions(+), 45 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index e00d5a92..de9aadae 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1723,6 +1723,8 @@ fn mk_plain_tag(ast.def_id tid) -> @ty.t { } +type val_fn = fn(@block_ctxt cx, ValueRef v) -> result; + type val_and_ty_fn = fn(@block_ctxt cx, ValueRef v, @ty.t t) -> result; type val_pair_and_ty_fn = @@ -1922,23 +1924,17 @@ fn iter_structural_ty_full(@block_ctxt cx, ret r; } -// Iterates through a pair of sequences, until the src* hits the src_lim*. -fn iter_sequence_pair_inner(@block_ctxt cx, - ValueRef dst, // elt* - ValueRef src, // elt* - ValueRef src_lim, // elt* - @ty.t elt_ty, - val_pair_and_ty_fn f) -> result { +// Iterates through a pointer range, until the src* hits the src_lim*. +fn iter_sequence_raw(@block_ctxt cx, + ValueRef src, // elt* + ValueRef src_lim, // elt* + ValueRef elt_sz, + val_fn f) -> result { auto bcx = cx; - auto llunit_ty = type_of(cx.fcx.ccx, elt_ty); - auto unit_sz = size_of(bcx, elt_ty); - bcx = unit_sz.bcx; - let ValueRef src_int = vp2i(bcx, src); let ValueRef src_lim_int = vp2i(bcx, src_lim); - let ValueRef dst_int = vp2i(bcx, dst); auto cond_cx = new_scope_block_ctxt(cx, "sequence-iter cond"); auto body_cx = new_scope_block_ctxt(cx, "sequence-iter body"); @@ -1948,33 +1944,23 @@ fn iter_sequence_pair_inner(@block_ctxt cx, let ValueRef src_curr = cond_cx.build.Phi(T_int(), vec(src_int), vec(bcx.llbb)); - let ValueRef dst_curr = cond_cx.build.Phi(T_int(), - vec(dst_int), vec(bcx.llbb)); - auto end_test = cond_cx.build.ICmp(lib.llvm.LLVMIntNE, + auto end_test = cond_cx.build.ICmp(lib.llvm.LLVMIntULT, src_curr, src_lim_int); cond_cx.build.CondBr(end_test, body_cx.llbb, next_cx.llbb); - auto src_curr_ptr = vi2p(body_cx, src_curr, T_ptr(llunit_ty)); - auto dst_curr_ptr = vi2p(body_cx, dst_curr, T_ptr(llunit_ty)); + auto src_curr_ptr = vi2p(body_cx, src_curr, T_ptr(T_i8())); - auto body_res = f(body_cx, - dst_curr_ptr, - load_scalar_or_boxed(body_cx, src_curr_ptr, elt_ty), - elt_ty); + auto body_res = f(body_cx, src_curr_ptr); body_cx = body_res.bcx; - auto src_next = body_cx.build.Add(src_curr, unit_sz.val); - auto dst_next = body_cx.build.Add(dst_curr, unit_sz.val); + auto src_next = body_cx.build.Add(src_curr, elt_sz); body_cx.build.Br(cond_cx.llbb); cond_cx.build.AddIncomingToPhi(src_curr, vec(src_next), vec(body_cx.llbb)); - cond_cx.build.AddIncomingToPhi(dst_curr, vec(dst_next), - vec(body_cx.llbb)); - ret res(next_cx, C_nil()); } @@ -1985,15 +1971,17 @@ fn iter_sequence_inner(@block_ctxt cx, @ty.t elt_ty, val_and_ty_fn f) -> result { fn adaptor_fn(val_and_ty_fn f, + @ty.t elt_ty, @block_ctxt cx, - ValueRef av, - ValueRef bv, - @ty.t t) -> result { - ret f(cx, bv, t); + ValueRef v) -> result { + auto llty = type_of(cx.fcx.ccx, elt_ty); + auto p = cx.build.PointerCast(v, T_ptr(llty)); + ret f(cx, load_scalar_or_boxed(cx, p, elt_ty), elt_ty); } - be iter_sequence_pair_inner(cx, src, src, src_lim, elt_ty, - bind adaptor_fn(f, _, _, _, _)); + auto elt_sz = size_of(cx, elt_ty); + be iter_sequence_raw(elt_sz.bcx, src, src_lim, elt_sz.val, + bind adaptor_fn(f, elt_ty, _, _)); } @@ -5475,34 +5463,136 @@ fn trans_vec_append_glue(@crate_ctxt cx) { auto bcx = new_top_block_ctxt(fcx); + auto lldst_vec = bcx.build.Load(lldst_vec_ptr); + // First the dst vec needs to grow to accommodate the src vec. // To do this we have to figure out how many bytes to add. - auto n_bytes = - bcx.build.Load(bcx.build.GEP(llsrc_vec, - vec(C_int(0), - C_int(abi.vec_elt_fill)))); - n_bytes = bcx.build.Select(llskipnull, - bcx.build.Sub(n_bytes, C_int(1)), - n_bytes); + fn vec_fill(@block_ctxt bcx, ValueRef v) -> ValueRef { + ret bcx.build.Load(bcx.build.GEP(v, vec(C_int(0), + C_int(abi.vec_elt_fill)))); + } + + fn put_vec_fill(@block_ctxt bcx, ValueRef v, ValueRef fill) -> ValueRef { + ret bcx.build.Store(fill, + bcx.build.GEP(v, + vec(C_int(0), + C_int(abi.vec_elt_fill)))); + } + fn vec_fill_adjusted(@block_ctxt bcx, ValueRef v, + ValueRef skipnull) -> ValueRef { + auto f = bcx.build.Load(bcx.build.GEP(v, + vec(C_int(0), + C_int(abi.vec_elt_fill)))); + ret bcx.build.Select(skipnull, bcx.build.Sub(f, C_int(1)), f); + } - auto llneed_copy_ptr = bcx.build.Alloca(T_int()); + fn vec_p0(@block_ctxt bcx, ValueRef v) -> ValueRef { + auto p = bcx.build.GEP(v, vec(C_int(0), + C_int(abi.vec_elt_data))); + ret bcx.build.PointerCast(p, T_ptr(T_i8())); + } + + + fn vec_p1(@block_ctxt bcx, ValueRef v) -> ValueRef { + auto len = vec_fill(bcx, v); + ret bcx.build.GEP(vec_p0(bcx, v), vec(len)); + } + + fn vec_p1_adjusted(@block_ctxt bcx, ValueRef v, + ValueRef skipnull) -> ValueRef { + auto len = vec_fill_adjusted(bcx, v, skipnull); + ret bcx.build.GEP(vec_p0(bcx, v), vec(len)); + } + + + auto llcopy_dst_ptr = bcx.build.Alloca(T_int()); auto llnew_vec_res = trans_upcall(bcx, "upcall_vec_grow", - vec(vp2i(bcx, bcx.build.Load(lldst_vec_ptr)), - n_bytes, - vp2i(bcx, llneed_copy_ptr), + vec(vp2i(bcx, lldst_vec), + vec_fill_adjusted(bcx, llsrc_vec, llskipnull), + vp2i(bcx, llcopy_dst_ptr), vp2i(bcx, llvec_tydesc))); bcx = llnew_vec_res.bcx; auto llnew_vec = vi2p(bcx, llnew_vec_res.val, T_opaque_vec_ptr()); + put_vec_fill(bcx, llnew_vec, C_int(0)); - // FIXME: complete this. + auto copy_dst_cx = new_sub_block_ctxt(bcx, "copy new <- dst"); + auto copy_src_cx = new_sub_block_ctxt(bcx, "copy new <- src"); - bcx.build.RetVoid(); + auto pp0 = bcx.build.Alloca(T_ptr(T_i8())); + bcx.build.Store(vec_p0(bcx, llnew_vec), pp0); + + bcx.build.CondBr(bcx.build.TruncOrBitCast + (bcx.build.Load(llcopy_dst_ptr), + T_i1()), + copy_dst_cx.llbb, + copy_src_cx.llbb); + + + fn copy_elts(@block_ctxt cx, + ValueRef elt_tydesc, + ValueRef dst, + ValueRef src, + ValueRef n_bytes) -> result { + + auto src_lim = cx.build.GEP(src, vec(n_bytes)); + + auto elt_llsz = + cx.build.Load(cx.build.GEP(elt_tydesc, + vec(C_int(0), + C_int(abi.tydesc_field_size)))); + + fn take_one(ValueRef elt_tydesc, + @block_ctxt cx, ValueRef v) -> result { + call_tydesc_glue_full(cx, v, + elt_tydesc, + abi.tydesc_field_take_glue_off); + ret res(cx, v); + } + + auto bcx = iter_sequence_raw(cx, src, src_lim, + elt_llsz, bind take_one(elt_tydesc, + _, _)).bcx; + + ret call_memcpy(bcx, dst, src, n_bytes); + } + + // Copy any dst elements in, omitting null if doing str. + auto n_bytes = vec_fill_adjusted(copy_dst_cx, lldst_vec, llskipnull); + copy_dst_cx = copy_elts(copy_dst_cx, + llelt_tydesc, + copy_dst_cx.build.Load(pp0), + vec_p0(copy_dst_cx, lldst_vec), + n_bytes).bcx; + + put_vec_fill(copy_dst_cx, llnew_vec, n_bytes); + copy_dst_cx.build.Store(vec_p1_adjusted(copy_dst_cx, + llnew_vec, llskipnull), + pp0); + copy_dst_cx.build.Br(copy_src_cx.llbb); + + + // Copy any src elements in, carrying along null if doing str. + n_bytes = vec_fill(copy_src_cx, llsrc_vec); + copy_src_cx = copy_elts(copy_src_cx, + llelt_tydesc, + copy_src_cx.build.Load(pp0), + vec_p0(copy_src_cx, llsrc_vec), + n_bytes).bcx; + + put_vec_fill(copy_src_cx, llnew_vec, + copy_src_cx.build.Add(vec_fill(copy_src_cx, + llnew_vec), + n_bytes)); + + // Write new_vec back through the alias we were given. + copy_src_cx.build.Store(llnew_vec, lldst_vec_ptr); + copy_src_cx.build.RetVoid(); } -- cgit v1.2.3 From 2cbfb8795d48028f216ffcaf921add36b9d60499 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Sun, 6 Mar 2011 23:06:01 -0800 Subject: Fix off-by-one in vector append code. --- src/comp/middle/trans.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index de9aadae..05aadee2 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -5571,9 +5571,7 @@ fn trans_vec_append_glue(@crate_ctxt cx) { n_bytes).bcx; put_vec_fill(copy_dst_cx, llnew_vec, n_bytes); - copy_dst_cx.build.Store(vec_p1_adjusted(copy_dst_cx, - llnew_vec, llskipnull), - pp0); + copy_dst_cx.build.Store(vec_p1(copy_dst_cx, llnew_vec), pp0); copy_dst_cx.build.Br(copy_src_cx.llbb); -- cgit v1.2.3 From 60657fa8aa1706fec7925b74dffdb1a0c82ceb0b Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 7 Mar 2011 00:13:56 -0800 Subject: Set the cleanup on the post-growth vector, not the temporary one. --- src/comp/middle/trans.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 05aadee2..0c0d92d4 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2470,10 +2470,11 @@ fn trans_vec_add(@block_ctxt cx, @ty.t t, ValueRef lhs, ValueRef rhs) -> result { auto r = alloc_ty(cx, t); auto tmp = r.val; - find_scope_cx(cx).cleanups += clean(bind drop_ty(_, tmp, t)); r = copy_ty(r.bcx, INIT, tmp, lhs, t); auto bcx = trans_vec_append(r.bcx, t, tmp, rhs).bcx; - ret res(bcx, load_scalar_or_boxed(bcx, tmp, t)); + tmp = load_scalar_or_boxed(bcx, tmp, t); + find_scope_cx(cx).cleanups += clean(bind drop_ty(_, tmp, t)); + ret res(bcx, tmp); } -- cgit v1.2.3 From f017a9e71fde98dbfdb2edb9fbc2af8781611664 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 7 Mar 2011 00:18:10 -0800 Subject: Un-XFAIL str-concat.rs. --- src/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 484740b5..81ca965d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -495,7 +495,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ spawn-module-qualified.rs \ spawn.rs \ str-append.rs \ - str-concat.rs \ syntax-extension-fmt.rs \ syntax-extension-shell.rs \ task-comm-0.rs \ -- cgit v1.2.3 From 1ce6cfbe7c7bf3ffa587d7762825990510f7bfbb Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 7 Mar 2011 15:29:06 +0100 Subject: use a precedence table for operator parsing --- src/comp/front/parser.rs | 196 ++++++++++++++++------------------------------- 1 file changed, 65 insertions(+), 131 deletions(-) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 8665a425..5b677e9b 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -35,6 +35,7 @@ state type parser = fn get_session() -> session.session; fn get_span() -> common.span; fn next_def_id() -> ast.def_id; + fn get_prec_table() -> vec[op_spec]; }; impure fn new_parser(session.session sess, @@ -50,7 +51,8 @@ impure fn new_parser(session.session sess, mutable ast.def_num def, mutable restriction res, ast.crate_num crate, - lexer.reader rdr) + lexer.reader rdr, + vec[op_spec] precs) { fn peek() -> token.token { ret tok; @@ -100,6 +102,9 @@ impure fn new_parser(session.session sess, ret env; } + fn get_prec_table() -> vec[op_spec] { + ret precs; + } } auto ftype = SOURCE_FILE; if (_str.ends_with(path, ".rc")) { @@ -109,7 +114,8 @@ impure fn new_parser(session.session sess, auto rdr = lexer.new_reader(srdr, path); auto npos = rdr.get_curr_pos(); ret stdio_parser(sess, env, ftype, lexer.next_token(rdr), - npos, npos, 0, UNRESTRICTED, crate, rdr); + npos, npos, 0, UNRESTRICTED, crate, rdr, + prec_table()); } impure fn unexpected(parser p, token.token t) { @@ -975,144 +981,72 @@ impure fn parse_prefix_expr(parser p) -> @ast.expr { ret @spanned(lo, hi, ex); } -impure fn parse_binops(parser p, - (impure fn(parser) -> @ast.expr) sub, - vec[tup(token.binop, ast.binop)] ops) +type op_spec = rec(token.token tok, ast.binop op, int prec); + +fn prec_table() -> vec[op_spec] { + ret vec(rec(tok=token.BINOP(token.STAR), op=ast.mul, prec=11), + rec(tok=token.BINOP(token.SLASH), op=ast.div, prec=11), + rec(tok=token.BINOP(token.PERCENT), op=ast.rem, prec=11), + rec(tok=token.BINOP(token.PLUS), op=ast.add, prec=10), + rec(tok=token.BINOP(token.MINUS), op=ast.sub, prec=10), + rec(tok=token.BINOP(token.LSL), op=ast.lsl, prec=9), + rec(tok=token.BINOP(token.LSR), op=ast.lsr, prec=9), + rec(tok=token.BINOP(token.ASR), op=ast.asr, prec=9), + rec(tok=token.BINOP(token.AND), op=ast.bitand, prec=8), + rec(tok=token.BINOP(token.CARET), op=ast.bitxor, prec=6), + rec(tok=token.BINOP(token.OR), op=ast.bitor, prec=6), + // ast.mul is a bogus placeholder here, AS is special + // cased in parse_more_binops + rec(tok=token.AS, op=ast.mul, prec=5), + rec(tok=token.LT, op=ast.lt, prec=4), + rec(tok=token.LE, op=ast.le, prec=4), + rec(tok=token.GE, op=ast.ge, prec=4), + rec(tok=token.GT, op=ast.gt, prec=4), + rec(tok=token.EQEQ, op=ast.eq, prec=3), + rec(tok=token.NE, op=ast.ne, prec=3), + rec(tok=token.ANDAND, op=ast.and, prec=2), + rec(tok=token.OROR, op=ast.or, prec=1)); +} + +impure fn parse_binops(parser p) -> @ast.expr { + ret parse_more_binops(p, parse_prefix_expr(p), 0); +} + +impure fn parse_more_binops(parser p, @ast.expr lhs, int min_prec) -> @ast.expr { - auto lo = p.get_span(); - auto hi = lo; - auto e = sub(p); - auto more = true; - while (more) { - more = false; - for (tup(token.binop, ast.binop) pair in ops) { - alt (p.peek()) { - case (token.BINOP(?op)) { - if (pair._0 == op) { - p.bump(); - auto rhs = sub(p); - hi = rhs.span; - auto exp = ast.expr_binary(pair._1, e, rhs, - ast.ann_none); - e = @spanned(lo, hi, exp); - more = true; - } + // Magic nonsense to work around rustboot bug + fn op_eq(token.token a, token.token b) -> bool { + if (a == b) {ret true;} + else {ret false;} + } + auto peeked = p.peek(); + for (op_spec cur in p.get_prec_table()) { + if (cur.prec > min_prec && op_eq(cur.tok, peeked)) { + p.bump(); + alt (cur.tok) { + case (token.AS) { + auto rhs = parse_ty(p); + auto _as = ast.expr_cast(lhs, rhs, ast.ann_none); + auto span = @spanned(lhs.span, rhs.span, _as); + ret parse_more_binops(p, span, min_prec); + } + case (_) { + auto rhs = parse_more_binops(p, parse_prefix_expr(p), + cur.prec); + auto bin = ast.expr_binary(cur.op, lhs, rhs, + ast.ann_none); + auto span = @spanned(lhs.span, rhs.span, bin); + ret parse_more_binops(p, span, min_prec); } - case (_) { /* fall through */ } - } - } - } - ret e; -} - -impure fn parse_binary_exprs(parser p, - (impure fn(parser) -> @ast.expr) sub, - vec[tup(token.token, ast.binop)] ops) - -> @ast.expr { - auto lo = p.get_span(); - auto hi = lo; - auto e = sub(p); - auto more = true; - while (more) { - more = false; - for (tup(token.token, ast.binop) pair in ops) { - if (pair._0 == p.peek()) { - p.bump(); - auto rhs = sub(p); - hi = rhs.span; - auto exp = ast.expr_binary(pair._1, e, rhs, ast.ann_none); - e = @spanned(lo, hi, exp); - more = true; - } - } - } - ret e; -} - -impure fn parse_factor_expr(parser p) -> @ast.expr { - auto sub = parse_prefix_expr; - ret parse_binops(p, sub, vec(tup(token.STAR, ast.mul), - tup(token.SLASH, ast.div), - tup(token.PERCENT, ast.rem))); -} - -impure fn parse_term_expr(parser p) -> @ast.expr { - auto sub = parse_factor_expr; - ret parse_binops(p, sub, vec(tup(token.PLUS, ast.add), - tup(token.MINUS, ast.sub))); -} - -impure fn parse_shift_expr(parser p) -> @ast.expr { - auto sub = parse_term_expr; - ret parse_binops(p, sub, vec(tup(token.LSL, ast.lsl), - tup(token.LSR, ast.lsr), - tup(token.ASR, ast.asr))); -} - -impure fn parse_bitand_expr(parser p) -> @ast.expr { - auto sub = parse_shift_expr; - ret parse_binops(p, sub, vec(tup(token.AND, ast.bitand))); -} - -impure fn parse_bitxor_expr(parser p) -> @ast.expr { - auto sub = parse_bitand_expr; - ret parse_binops(p, sub, vec(tup(token.CARET, ast.bitxor))); -} - -impure fn parse_bitor_expr(parser p) -> @ast.expr { - auto sub = parse_bitxor_expr; - ret parse_binops(p, sub, vec(tup(token.OR, ast.bitor))); -} - -impure fn parse_cast_expr(parser p) -> @ast.expr { - auto lo = p.get_span(); - auto e = parse_bitor_expr(p); - auto hi = e.span; - while (true) { - alt (p.peek()) { - case (token.AS) { - p.bump(); - auto t = parse_ty(p); - hi = t.span; - e = @spanned(lo, hi, ast.expr_cast(e, t, ast.ann_none)); - } - - case (_) { - ret e; } } } - ret e; -} - -impure fn parse_relational_expr(parser p) -> @ast.expr { - auto sub = parse_cast_expr; - ret parse_binary_exprs(p, sub, vec(tup(token.LT, ast.lt), - tup(token.LE, ast.le), - tup(token.GE, ast.ge), - tup(token.GT, ast.gt))); -} - - -impure fn parse_equality_expr(parser p) -> @ast.expr { - auto sub = parse_relational_expr; - ret parse_binary_exprs(p, sub, vec(tup(token.EQEQ, ast.eq), - tup(token.NE, ast.ne))); -} - -impure fn parse_and_expr(parser p) -> @ast.expr { - auto sub = parse_equality_expr; - ret parse_binary_exprs(p, sub, vec(tup(token.ANDAND, ast.and))); -} - -impure fn parse_or_expr(parser p) -> @ast.expr { - auto sub = parse_and_expr; - ret parse_binary_exprs(p, sub, vec(tup(token.OROR, ast.or))); + ret lhs; } impure fn parse_assign_expr(parser p) -> @ast.expr { auto lo = p.get_span(); - auto lhs = parse_or_expr(p); + auto lhs = parse_binops(p); alt (p.peek()) { case (token.EQ) { p.bump(); -- cgit v1.2.3 From e621f1ef9e9d1488078513398bce7479d509edeb Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 7 Mar 2011 08:19:28 -0800 Subject: Add Marijn to AUTHORS.txt. --- AUTHORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.txt b/AUTHORS.txt index ceaa0f82..a6e9935d 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -15,6 +15,7 @@ Jason Orendorff Jeff Balogh Jeff Mulzelaar Jeffrey Yasskin +Marijn Haverbeke Matt Brubeck Michael Bebenita Or Brostovski -- cgit v1.2.3 From 5041944fd2736ad9782df07f792c19dcc97db8f7 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 7 Mar 2011 08:41:48 -0800 Subject: Yell louder when a linkage error in rt occurs, as compiler output fails quietly on null return. --- src/rt/rust_crate_cache.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/rt/rust_crate_cache.cpp b/src/rt/rust_crate_cache.cpp index adf1bbfc..62fd7c01 100644 --- a/src/rt/rust_crate_cache.cpp +++ b/src/rt/rust_crate_cache.cpp @@ -49,7 +49,8 @@ rust_crate_cache::c_sym::c_sym(rust_dom *dom, lib *library, char const *name) dom->log(rust_log::CACHE, "resolved symbol '%s' to 0x%" PRIxPTR, name, val); } else { - dom->log(rust_log::CACHE, "unresolved symbol '%s', null lib handle", + dom->log(rust_log::CACHE | rust_log::ERR, + "unresolved symbol '%s', null lib handle", name); } } @@ -79,7 +80,7 @@ rust_crate_cache::rust_sym::rust_sym(rust_dom *dom, typedef rust_crate_reader::die die; rust_crate const *crate = (rust_crate*)crate_sym->get_val(); if (!crate) { - dom->log(rust_log::CACHE, + dom->log(rust_log::CACHE | rust_log::ERR, "failed to resolve symbol, null crate symbol"); return; } -- cgit v1.2.3 From 44bceb84a71a2dcf71be1545e595e290f35e1fe1 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 7 Mar 2011 10:02:01 -0800 Subject: Complain on unexpected native symbol, rather than failing with none-exhaustive match. --- src/comp/front/parser.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 5b677e9b..67eec424 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1836,6 +1836,9 @@ impure fn parse_native_item(parser p) -> @ast.native_item { case (token.FN) { ret parse_item_native_fn(p, eff); } + case (?t) { + unexpected(p, t); + } } } -- cgit v1.2.3 From dfa85968c346e7d7892a7399cc2b79bfb7e0e5ef Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 7 Mar 2011 10:33:04 -0800 Subject: Stage the last compile fix to put out fire. Thanks git. --- src/comp/front/parser.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 67eec424..8141595b 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1838,6 +1838,7 @@ impure fn parse_native_item(parser p) -> @ast.native_item { } case (?t) { unexpected(p, t); + fail; } } } -- cgit v1.2.3 From 90f299e710c49d689d5bc815e32db375cca00394 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 7 Mar 2011 11:48:43 -0800 Subject: Permit view items in native modules. --- src/comp/front/ast.rs | 25 ++++++++++++++++++++++--- src/comp/front/parser.rs | 22 ++++++++++++++++++++-- src/comp/middle/fold.rs | 9 ++++++++- src/comp/middle/resolve.rs | 14 +++++++++++--- 4 files changed, 61 insertions(+), 9 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index a8bf4b00..ed1e2114 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -265,6 +265,11 @@ tag mod_index_entry { mie_tag_variant(@item /* tag item */, uint /* variant index */); } +tag native_mod_index_entry { + nmie_view_item(@view_item); + nmie_item(@native_item); +} + type mod_index = hashmap[ident,mod_index_entry]; type _mod = rec(vec[@view_item] view_items, vec[@item] items, @@ -277,9 +282,10 @@ tag native_abi { type native_mod = rec(str native_name, native_abi abi, + vec[@view_item] view_items, vec[@native_item] items, native_mod_index index); -type native_mod_index = hashmap[ident,@native_item]; +type native_mod_index = hashmap[ident,native_mod_index_entry]; type variant_arg = rec(@ty ty, def_id id); type variant = rec(str name, vec[variant_arg] args, def_id id, ann ann); @@ -359,10 +365,23 @@ fn index_item(mod_index index, @item it) { fn index_native_item(native_mod_index index, @native_item it) { alt (it.node) { case (ast.native_item_ty(?id, _)) { - index.insert(id, it); + index.insert(id, ast.nmie_item(it)); } case (ast.native_item_fn(?id, _, _, _, _)) { - index.insert(id, it); + index.insert(id, ast.nmie_item(it)); + } + } +} + +fn index_native_view_item(native_mod_index index, @view_item it) { + alt (it.node) { + case(ast.view_item_import(?def_ident,_,_,_)) { + index.insert(def_ident, ast.nmie_view_item(it)); + } + case(ast.view_item_export(_)) { + // NB: don't index these, they might collide with + // the import or use that they're exporting. Have + // to do linear search for exports. } } } diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 8141595b..6f3111c7 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1846,8 +1846,11 @@ impure fn parse_native_item(parser p) -> @ast.native_item { impure fn parse_native_mod_items(parser p, str native_name, ast.native_abi abi) -> ast.native_mod { - auto index = new_str_hash[@ast.native_item](); + auto index = new_str_hash[ast.native_mod_index_entry](); let vec[@ast.native_item] items = vec(); + + auto view_items = parse_native_view(p, index); + while (p.peek() != token.RBRACE) { auto item = parse_native_item(p); items += vec(item); @@ -1856,7 +1859,9 @@ impure fn parse_native_mod_items(parser p, ast.index_native_item(index, item); } ret rec(native_name=native_name, abi=abi, - items=items, index=index); + view_items=view_items, + items=items, + index=index); } fn default_native_name(session.session sess, str id) -> str { @@ -2230,6 +2235,19 @@ impure fn parse_view(parser p, ast.mod_index index) -> vec[@ast.view_item] { ret items; } +impure fn parse_native_view(parser p, ast.native_mod_index index) + -> vec[@ast.view_item] { + let vec[@ast.view_item] items = vec(); + while (is_view_item(p.peek())) { + auto item = parse_view_item(p); + items += vec(item); + + ast.index_native_view_item(index, item); + } + ret items; +} + + impure fn parse_crate_from_source_file(parser p) -> @ast.crate { auto lo = p.get_span(); auto hi = lo; diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs index 935f426b..8a1dc70f 100644 --- a/src/comp/middle/fold.rs +++ b/src/comp/middle/fold.rs @@ -957,8 +957,14 @@ fn fold_native_item[ENV](&ENV env, ast_fold[ENV] fld, fn fold_native_mod[ENV](&ENV e, ast_fold[ENV] fld, &ast.native_mod m) -> ast.native_mod { + let vec[@view_item] view_items = vec(); let vec[@native_item] items = vec(); - auto index = new_str_hash[@ast.native_item](); + auto index = new_str_hash[ast.native_mod_index_entry](); + + for (@view_item vi in m.view_items) { + auto new_vi = fold_view_item[ENV](e, fld, vi); + append[@view_item](view_items, new_vi); + } for (@native_item i in m.items) { auto new_item = fold_native_item[ENV](e, fld, i); @@ -968,6 +974,7 @@ fn fold_native_mod[ENV](&ENV e, ast_fold[ENV] fld, ret fld.fold_native_mod(e, rec(native_name=m.native_name, abi=m.abi, + view_items=view_items, items=items, index=index)); } diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index a2f4da63..5b6db631 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -300,11 +300,19 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] { } fn check_native_mod(ast.ident i, ast.native_mod m) -> option.t[def_wrap] { + alt (m.index.find(i)) { - case (some[@ast.native_item](?item)) { - ret some(found_def_native_item(item)); + case (some[ast.native_mod_index_entry](?ent)) { + alt (ent) { + case (ast.nmie_view_item(?view_item)) { + ret some(found_def_view(view_item)); + } + case (ast.nmie_item(?item)) { + ret some(found_def_native_item(item)); + } + } } - case (_) { + case (none[ast.native_mod_index_entry]) { ret none[def_wrap]; } } -- cgit v1.2.3 From 8047957b9981c4f3539ba3d307a65e0255477e81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Mon, 7 Mar 2011 15:37:40 -0500 Subject: Construct the wrappers to native functions. Hello world now works :-) --- src/comp/middle/trans.rs | 40 ++++++++++++++++++++++++++++++++++------ src/comp/middle/ty.rs | 7 +++++++ 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 0c0d92d4..61715fd2 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4972,11 +4972,6 @@ fn decl_native_fn_and_pair(@crate_ctxt cx, let str s = cx.names.next("_rust_wrapper") + sep() + name; let ValueRef wrapper_fn = decl_fastcall_fn(cx.llmod, s, wrapper_type); - // Build the wrapper. - auto fcx = new_fn_ctxt(cx, wrapper_fn); - auto bcx = new_top_block_ctxt(fcx); - bcx.build.RetVoid(); - // Declare the global constant pair that points to it. auto wrapper_pair_type = T_fn_pair(cx.tn, wrapper_type); let str ps = cx.names.next("_rust_wrapper_pair") + sep() + name; @@ -4985,7 +4980,40 @@ fn decl_native_fn_and_pair(@crate_ctxt cx, // Declare the function itself. auto llfty = get_pair_fn_ty(node_type(cx, ann)); - decl_cdecl_fn(cx.llmod, name, llfty); + auto function = decl_cdecl_fn(cx.llmod, name, llfty); + + // Build the wrapper. + auto fcx = new_fn_ctxt(cx, wrapper_fn); + auto bcx = new_top_block_ctxt(fcx); + auto fn_type = node_ann_type(cx, ann); + + let vec[ValueRef] call_args = vec(); + auto abi = ty.ty_fn_abi(fn_type); + auto arg_n = 3u; + alt (abi) { + case (ast.native_abi_rust) { + call_args += vec(fcx.lltaskptr); + auto num_ty_param = ty.count_ty_params(plain_ty(fn_type.struct)); + for each (uint i in _uint.range(0u, num_ty_param)) { + auto llarg = llvm.LLVMGetParam(fcx.llfn, arg_n); + check (llarg as int != 0); + call_args += vec(llarg); + arg_n += 1u; + } + } + case (ast.native_abi_cdecl) { + } + } + auto args = ty.ty_fn_args(fn_type); + for (ty.arg arg in args) { + auto llarg = llvm.LLVMGetParam(fcx.llfn, arg_n); + check (llarg as int != 0); + call_args += vec(llarg); + arg_n += 1u; + } + auto r = bcx.build.Call(function, call_args); + bcx.build.Store(r, fcx.llretptr); + bcx.build.RetVoid(); } fn collect_native_item(&@crate_ctxt cx, @ast.native_item i) -> @crate_ctxt { diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 3f209d3c..62d9a2f0 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -645,6 +645,13 @@ fn ty_fn_proto(@t fty) -> ast.proto { fail; } +fn ty_fn_abi(@t fty) -> ast.native_abi { + alt (fty.struct) { + case (ty.ty_native_fn(?a, _, _)) { ret a; } + } + fail; +} + fn ty_fn_ret(@t fty) -> @t { alt (fty.struct) { case (ty.ty_fn(_, _, ?r)) { ret r; } -- cgit v1.2.3 From 0624f9db4aeaa5681941750c3a1a17ca5fbb7e72 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 4 Mar 2011 07:22:43 +0100 Subject: Add a pretty-printer Adds a -pp option to the compiler which will cause it to simply pretty-print the given file. --- src/comp/driver/rustc.rs | 39 ++- src/comp/front/ast.rs | 36 +++ src/comp/front/parser.rs | 1 + src/comp/front/pretty.rs | 2 + src/comp/middle/ty.rs | 2 + src/comp/pretty/pp.rs | 207 ++++++++++++++ src/comp/pretty/pprust.rs | 716 ++++++++++++++++++++++++++++++++++++++++++++++ src/comp/rustc.rc | 5 + src/lib/io.rs | 30 +- 9 files changed, 1013 insertions(+), 25 deletions(-) create mode 100644 src/comp/pretty/pp.rs create mode 100644 src/comp/pretty/pprust.rs diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index 90fe0e0c..7ad0cdc7 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -61,6 +61,14 @@ impure fn compile_input(session.session sess, trans.trans_crate(sess, crate, output, shared); } +impure fn pretty_print_input(session.session sess, + eval.env env, + str input) { + auto p = front.parser.new_parser(sess, env, 0, input); + auto crate = front.parser.parse_crate_from_source_file(p); + pretty.pprust.print_ast(crate.node.module); +} + fn warn_wrong_compiler() { log "This is the rust 'self-hosted' compiler."; log "The one written in rust."; @@ -75,6 +83,7 @@ fn usage(session.session sess, str argv0) { log " -o write output to "; log " -nowarn suppress wrong-compiler warning"; log " -shared compile a shared-library crate"; + log " -pp pretty-print the input instead of compiling"; log " -h display this message"; log ""; log ""; @@ -101,6 +110,7 @@ impure fn main(vec[str] args) { let option.t[str] output_file = none[str]; let bool do_warn = true; let bool shared = false; + let bool pretty = false; auto i = 1u; auto len = _vec.len[str](args); @@ -113,6 +123,8 @@ impure fn main(vec[str] args) { do_warn = false; } else if (_str.eq(arg, "-shared")) { shared = true; + } else if (_str.eq(arg, "-pp")) { + pretty = true; } else if (_str.eq(arg, "-o")) { if (i+1u < len) { output_file = some(args.(i+1u)); @@ -153,24 +165,27 @@ impure fn main(vec[str] args) { case (some[str](?ifile)) { auto env = default_environment(sess, args.(0), ifile); - - alt (output_file) { - case (none[str]) { - let vec[str] parts = _str.split(ifile, '.' as u8); - parts = _vec.pop[str](parts); - parts += ".bc"; - auto ofile = _str.concat(parts); - compile_input(sess, env, ifile, ofile, shared); - } - case (some[str](?ofile)) { - compile_input(sess, env, ifile, ofile, shared); + if (pretty) { + pretty_print_input(sess, env, ifile); + } + else { + alt (output_file) { + case (none[str]) { + let vec[str] parts = _str.split(ifile, '.' as u8); + parts = _vec.pop[str](parts); + parts += ".bc"; + auto ofile = _str.concat(parts); + compile_input(sess, env, ifile, ofile, shared); + } + case (some[str](?ofile)) { + compile_input(sess, env, ifile, ofile, shared); + } } } } } } - // Local Variables: // mode: rust // fill-column: 78; diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index ed1e2114..d45260f3 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -122,6 +122,31 @@ tag binop { gt; } +fn binop_to_str(binop op) -> str { + alt (op) { + case (add) {ret "+";} + case (sub) {ret "-";} + case (mul) {ret "*";} + case (div) {ret "/";} + case (rem) {ret "%";} + case (and) {ret "&&";} + case (or) {ret "||";} + case (bitxor) {ret "^";} + case (bitand) {ret "&";} + case (bitor) {ret "|";} + case (lsl) {ret "<<";} + case (lsr) {ret ">>";} + case (asr) {ret ">>>";} + case (eq) {ret "==";} + case (lt) {ret "<";} + case (le) {ret "<=";} + case (ne) {ret "!=";} + case (ge) {ret ">=";} + case (gt) {ret ">";} + } +} + + tag unop { box; deref; @@ -131,6 +156,17 @@ tag unop { _mutable; } +fn unop_to_str(unop op) -> str { + alt (op) { + case (box) {ret "@";} + case (deref) {ret "*";} + case (bitnot) {ret "~";} + case (not) {ret "!";} + case (neg) {ret "-";} + case (_mutable) {ret "mutable";} + } +} + tag mode { val; alias; diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 6f3111c7..f60ff36b 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -983,6 +983,7 @@ impure fn parse_prefix_expr(parser p) -> @ast.expr { type op_spec = rec(token.token tok, ast.binop op, int prec); +// FIXME make this a const, don't store it in parser state fn prec_table() -> vec[op_spec] { ret vec(rec(tok=token.BINOP(token.STAR), op=ast.mul, prec=11), rec(tok=token.BINOP(token.SLASH), op=ast.div, prec=11), diff --git a/src/comp/front/pretty.rs b/src/comp/front/pretty.rs index 267763e3..2fd58126 100644 --- a/src/comp/front/pretty.rs +++ b/src/comp/front/pretty.rs @@ -5,6 +5,8 @@ import std._vec; export print_expr; +// FIXME this is superseded by ../pretty/pprust.rs. can it be dropped? + fn unknown() -> str { ret ""; } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 62d9a2f0..c33b5d8d 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -169,6 +169,8 @@ fn path_to_str(&ast.path pth) -> str { ret result; } +// FIXME use the pretty-printer for this once it has a concept of an +// abstract stream fn ty_to_str(&@t typ) -> str { fn fn_input_to_str(&rec(ast.mode mode, @t ty) input) -> str { diff --git a/src/comp/pretty/pp.rs b/src/comp/pretty/pp.rs new file mode 100644 index 00000000..43a9220f --- /dev/null +++ b/src/comp/pretty/pp.rs @@ -0,0 +1,207 @@ +import std.io; +import std._vec; +import std._str; + +tag boxtype {box_h; box_v; box_hv; box_align;} +tag contexttype {cx_h; cx_v;} + +tag token { + brk(uint); + word(str); + cword(str); // closing token + open(boxtype, uint); + close; +} + +type context = rec(contexttype tp, uint indent); + +type ps = @rec(mutable vec[context] context, + uint width, + mutable vec[token] buffered, + mutable uint scandepth, + mutable uint bufferedcol, + mutable uint col, + mutable bool start_of_line); + +fn mkstate(uint width) -> ps { + let vec[context] stack = vec(rec(tp=cx_v, indent=0u)); + let vec[token] buff = vec(); + ret @rec(mutable context=stack, + width=width, + mutable buffered=buff, + mutable scandepth=0u, + mutable bufferedcol=0u, + mutable col=0u, + mutable start_of_line=true); +} + +impure fn push_context(ps p, contexttype tp, uint indent) { + before_print(p, false); + p.context = _vec.push[context](p.context, rec(tp=tp, indent=base_indent(p) + + indent)); +} + +impure fn pop_context(ps p) { + p.context = _vec.pop[context](p.context); +} + +impure fn add_token(ps p, token tok) { + if (p.scandepth == 0u) {do_token(p, tok);} + else {buffer_token(p, tok);} +} + +impure fn buffer_token(ps p, token tok) { + p.buffered += vec(tok); + p.bufferedcol += token_size(tok); + alt (p.buffered.(0)) { + case (brk(_)) { + alt (tok) { + case (brk(_)) { + if (p.scandepth == 1u) {finish_break_scan(p);} + } + case (open(box_h,_)) {p.scandepth += 1u;} + case (open(_,_)) {finish_break_scan(p);} + case (close) { + p.scandepth -= 1u; + if (p.scandepth == 0u) {finish_break_scan(p);} + } + case (_) {} + } + } + case (open(_,_)) { + if (p.bufferedcol > p.width) {finish_block_scan(p, cx_v);} + else { + alt (tok) { + case (open(_,_)) {p.scandepth += 1u;} + case (close) { + p.scandepth -= 1u; + if (p.scandepth == 0u) {finish_block_scan(p, cx_h);} + } + case (_) {} + } + } + } + } +} + +impure fn finish_block_scan(ps p, contexttype tp) { + auto indent; + alt (p.buffered.(0)){ + case (open(box_hv,?ind)) { + indent = ind; + } + case (open(box_align, _)) { + indent = p.col - base_indent(p); + } + } + p.scandepth = 0u; + push_context(p, tp, indent); + for (token t in _vec.shift[token](p.buffered)) {add_token(p, t);} +} + +impure fn finish_break_scan(ps p) { + if (p.bufferedcol > p.width) { + write_str("\n"); + p.col = 0u; + } + else { + auto width; + alt (p.buffered.(0)) {case(brk(?w)) {width = w;}} + auto i = 0u; + while (i < width) {write_str(" "); i+=1u;} + p.col += width; + } + p.scandepth = 0u; + for (token t in _vec.shift[token](p.buffered)) {add_token(p, t);} +} + +impure fn start_scan(ps p, token tok) { + p.buffered = vec(tok); + p.scandepth = 1u; + p.bufferedcol = p.col; +} + +fn cur_context(ps p) -> context { + ret p.context.(_vec.len[context](p.context)-1u); +} +fn base_indent(ps p) -> uint { + auto i = _vec.len[context](p.context); + while (i > 0u) { + i -= 1u; + auto cx = p.context.(i); + if (cx.tp == cx_v) {ret cx.indent;} + } +} + +impure fn do_token(ps p, token tok) { + alt (tok) { + case (brk(?sz)) { + alt (cur_context(p).tp) { + case (cx_h) { + before_print(p, false); + start_scan(p, tok); + } + case (cx_v) { + write_str("\n"); + p.col = 0u; + p.start_of_line = true; + } + } + } + case (word(?w)) { + before_print(p, false); + write_str(w); + p.col += _str.byte_len(w); // TODO char_len + } + case (cword(?w)) { + before_print(p, true); + write_str(w); + p.col += _str.byte_len(w); // TODO char_len + } + case (open(?tp, ?indent)) { + alt (tp) { + case (box_hv) {start_scan(p, tok);} + case (box_align) {start_scan(p, tok);} + case (box_h) {push_context(p, cx_h, indent);} + case (box_v) {push_context(p, cx_v, indent);} + } + } + case (close) {pop_context(p);} + } +} + +impure fn before_print(ps p, bool closing) { + if (p.start_of_line) { + p.start_of_line = false; + auto ind; + if (closing) {ind = base_indent(p);} + else {ind = cur_context(p).indent;} + p.col = ind; + while (ind > 0u) {write_str(" "); ind -= 1u;} + } +} + +fn write_str(str s) { + io.writefd(1, _str.bytes(s)); +} + +fn token_size(token tok) -> uint { + alt (tok) { + case (brk(?sz)) {ret sz;} + case (word(?w)) {ret _str.byte_len(w);} + case (cword(?w)) {ret _str.byte_len(w);} + case (open(_, _)) {ret 0u;} // TODO exception for V blocks? + case (close) {ret 0u;} + } +} + +impure fn box(ps p, uint indent) {add_token(p, open(box_hv, indent));} +impure fn abox(ps p) {add_token(p, open(box_align, 0u));} +impure fn vbox(ps p, uint indent) {add_token(p, open(box_v, indent));} +impure fn hbox(ps p, uint indent) {add_token(p, open(box_h, indent));} +impure fn end(ps p) {add_token(p, close);} +impure fn wrd(ps p, str wrd) {add_token(p, word(wrd));} +impure fn cwrd(ps p, str wrd) {add_token(p, cword(wrd));} +impure fn space(ps p) {add_token(p, brk(1u));} +impure fn spaces(ps p, uint n) {add_token(p, brk(n));} +impure fn line(ps p) {add_token(p, brk(0u));} diff --git a/src/comp/pretty/pprust.rs b/src/comp/pretty/pprust.rs new file mode 100644 index 00000000..d10f5e7c --- /dev/null +++ b/src/comp/pretty/pprust.rs @@ -0,0 +1,716 @@ +import std._vec; +import std._str; +import std.option; +import front.ast; +import pp.box; import pp.abox; import pp.vbox; +import pp.end; import pp.wrd; import pp.space; import pp.line; +import pp.ps; + +import foo = std.io; + +const uint indent_unit = 2u; +const int as_prec = 5; + +impure fn print_ast(ast._mod _mod) { + auto s = pp.mkstate(80u); + for (@ast.view_item vitem in _mod.view_items) {print_view_item(s, vitem);} + line(s); + for (@ast.item item in _mod.items) {print_item(s, item);} +} + +impure fn hbox(ps s) { + pp.hbox(s, indent_unit); +} +impure fn wrd1(ps s, str word) { + wrd(s, word); + space(s); +} +impure fn popen(ps s) { + wrd(s, "("); + abox(s); +} +impure fn pclose(ps s) { + end(s); + wrd(s, ")"); +} +impure fn bopen(ps s) { + wrd1(s, "{"); + vbox(s, indent_unit); + line(s); +} +impure fn bclose(ps s) { + end(s); + pp.cwrd(s, "}"); +} +impure fn commasep[IN](ps s, vec[IN] elts, impure fn (ps, IN) op) { + auto first = true; + for (IN elt in elts) { + if (first) {first = false;} + else {wrd1(s, ",");} + op(s, elt); + } +} + +impure fn print_type(ps s, @ast.ty ty) { + hbox(s); + alt (ty.node) { + case (ast.ty_nil) {wrd(s, "()");} + case (ast.ty_bool) {wrd(s, "bool");} + case (ast.ty_int) {wrd(s, "int");} + case (ast.ty_uint) {wrd(s, "uint");} + case (ast.ty_machine(?tm)) {wrd(s, util.common.ty_mach_to_str(tm));} + case (ast.ty_char) {wrd(s, "char");} + case (ast.ty_str) {wrd(s, "str");} + case (ast.ty_box(?t)) {wrd(s, "@"); print_type(s, t);} + case (ast.ty_vec(?t)) {wrd(s, "vec["); print_type(s, t); wrd(s, "]");} + case (ast.ty_type) {wrd(s, "type");} + case (ast.ty_tup(?elts)) { + wrd(s, "tup"); + popen(s); + auto f = print_type; + commasep[@ast.ty](s, elts, f); + pclose(s); + } + case (ast.ty_rec(?fields)) { + wrd(s, "rec"); + popen(s); + impure fn print_field(ps s, ast.ty_field f) { + hbox(s); + print_type(s, f.ty); + space(s); + wrd(s, f.ident); + end(s); + } + auto f = print_field; + commasep[ast.ty_field](s, fields, f); + pclose(s); + } + case (ast.ty_fn(?proto,?inputs,?output)) { + if (proto == ast.proto_fn) {wrd(s, "fn");} + else {wrd(s, "iter");} + popen(s); + impure fn print_arg(ps s, ast.ty_arg input) { + if (middle.ty.mode_is_alias(input.mode)) {wrd(s, "&");} + print_type(s, input.ty); + } + auto f = print_arg; + commasep[ast.ty_arg](s, inputs, f); + pclose(s); + if (output.node != ast.ty_nil) { + space(s); + hbox(s); + wrd1(s, "->"); + print_type(s, output); + end(s); + } + } + case (ast.ty_path(?path,_)) { + print_path(s, path); + } + case (ast.ty_mutable(?t)) { + wrd1(s, "mutable"); + print_type(s, t); + } + } + end(s); +} + +impure fn print_item(ps s, @ast.item item) { + hbox(s); + alt (item.node) { + case (ast.item_const(?id, ?ty, ?expr, _, _)) { + wrd1(s, "const"); + print_type(s, ty); + space(s); + wrd1(s, id); + wrd1(s, "="); + print_expr(s, expr); + wrd(s, ";"); + } + case (ast.item_fn(?name,?_fn,?typarams,_,_)) { + print_fn(s, _fn.decl, name, typarams); + space(s); + print_block(s, _fn.body); + } + case (ast.item_mod(?id,?_mod,_)) { + wrd1(s, "mod"); + wrd1(s, id); + bopen(s); + for (@ast.item itm in _mod.items) {print_item(s, itm);} + bclose(s); + } + case (ast.item_native_mod(?id,?nmod,_)) { + wrd1(s, "native"); + alt (nmod.abi) { + case (ast.native_abi_rust) {wrd1(s, "\"rust\"");} + case (ast.native_abi_cdecl) {wrd1(s, "\"cdecl\"");} + } + wrd1(s, "mod"); + wrd1(s, id); + bopen(s); + for (@ast.native_item item in nmod.items) { + hbox(s); + alt (item.node) { + case (ast.native_item_ty(?id,_)) { + wrd1(s, "type"); + wrd(s, id); + } + case (ast.native_item_fn(?id,?decl,?typarams,_,_)) { + print_fn(s, decl, id, typarams); + } + } + wrd(s, ";"); + end(s); + } + bclose(s); + } + case (ast.item_ty(?id,?ty,?params,_,_)) { + wrd1(s, "type"); + wrd(s, id); + print_type_params(s, params); + space(s); + wrd1(s, "="); + print_type(s, ty); + wrd(s, ";"); + } + case (ast.item_tag(?id,?variants,?params,_)) { + wrd1(s, "tag"); + wrd(s, id); + print_type_params(s, params); + space(s); + bopen(s); + for (ast.variant v in variants) { + wrd(s, v.name); + if (_vec.len[ast.variant_arg](v.args) > 0u) { + popen(s); + impure fn print_variant_arg(ps s, ast.variant_arg arg) { + print_type(s, arg.ty); + } + auto f = print_variant_arg; + commasep[ast.variant_arg](s, v.args, f); + pclose(s); + } + wrd(s, ";"); + line(s); + } + bclose(s); + } + case (ast.item_obj(?id,?_obj,?params,_,_)) { + wrd1(s, "obj"); + wrd(s, id); + print_type_params(s, params); + popen(s); + impure fn print_field(ps s, ast.obj_field field) { + hbox(s); + print_type(s, field.ty); + space(s); + wrd(s, field.ident); + end(s); + } + auto f = print_field; + commasep[ast.obj_field](s, _obj.fields, f); + pclose(s); + space(s); + bopen(s); + for (@ast.method meth in _obj.methods) { + hbox(s); + let vec[ast.ty_param] typarams = vec(); + print_fn(s, meth.node.meth.decl, meth.node.ident, typarams); + space(s); + print_block(s, meth.node.meth.body); + end(s); + line(s); + } + alt (_obj.dtor) { + case (option.some[ast.block](?dtor)) { + hbox(s); + wrd1(s, "close"); + print_block(s, dtor); + end(s); + line(s); + } + case (_) {} + } + bclose(s); + } + } + end(s); + line(s); + line(s); +} + +impure fn print_block(ps s, ast.block blk) { + bopen(s); + for (@ast.stmt st in blk.node.stmts) { + alt (st.node) { + case (ast.stmt_decl(?decl)) {print_decl(s, decl);} + case (ast.stmt_expr(?expr)) {print_expr(s, expr);} + } + if (front.parser.stmt_ends_with_semi(st)) {wrd(s, ";");} + line(s); + } + alt (blk.node.expr) { + case (option.some[@ast.expr](?expr)) { + print_expr(s, expr); + line(s); + } + case (_) {} + } + bclose(s); +} + +impure fn print_literal(ps s, @ast.lit lit) { + alt (lit.node) { + case (ast.lit_str(?st)) {print_string(s, st);} + case (ast.lit_char(?ch)) { + wrd(s, "'" + escape_str(_str.from_bytes(vec(ch as u8)), '\'') + "'"); + } + case (ast.lit_int(?val)) { + wrd(s, util.common.istr(val)); + } + case (ast.lit_uint(?val)) { // TODO clipping? uistr? + wrd(s, util.common.istr(val as int) + "u"); + } + case (ast.lit_mach_int(?mach,?val)) { + wrd(s, util.common.istr(val as int)); + wrd(s, util.common.ty_mach_to_str(mach)); + } + case (ast.lit_nil) {wrd(s, "()");} + case (ast.lit_bool(?val)) { + if (val) {wrd(s, "true");} else {wrd(s, "false");} + } + } +} + +impure fn print_expr(ps s, @ast.expr expr) { + auto pe = print_expr; + hbox(s); + alt (expr.node) { + case (ast.expr_vec(?exprs,_)) { + wrd(s, "vec"); + popen(s); + commasep[@ast.expr](s, exprs, pe); + pclose(s); + } + case (ast.expr_tup(?exprs,_)) { + impure fn printElt(ps s, ast.elt elt) { + hbox(s); + if (elt.mut == ast.mut) {wrd1(s, "mutable");} + print_expr(s, elt.expr); + end(s); + } + wrd(s, "tup"); + popen(s); + auto f = printElt; + commasep[ast.elt](s, exprs, f); + pclose(s); + } + case (ast.expr_rec(?fields,_,_)) { + impure fn print_field(ps s, ast.field field) { + hbox(s); + if (field.mut == ast.mut) {wrd1(s, "mutable");} + wrd(s, field.ident); + wrd(s, "="); + print_expr(s, field.expr); + end(s); + } + wrd(s, "rec"); + popen(s); + auto f = print_field; + commasep[ast.field](s, fields, f); + pclose(s); + } + case (ast.expr_call(?func,?args,_)) { + print_expr(s, func); + popen(s); + commasep[@ast.expr](s, args, pe); + pclose(s); + } + case (ast.expr_bind(?func,?args,_)) { + impure fn print_opt(ps s, option.t[@ast.expr] expr) { + alt (expr) { + case (option.some[@ast.expr](?expr)) { + print_expr(s, expr); + } + case (_) {wrd(s, "_");} + } + } + wrd1(s, "bind"); + print_expr(s, func); + popen(s); + auto f = print_opt; + commasep[option.t[@ast.expr]](s, args, f); + pclose(s); + } + case (ast.expr_binary(?op,?lhs,?rhs,_)) { + auto prec = operator_prec(op); + print_maybe_parens(s, lhs, prec); + space(s); + wrd1(s, ast.binop_to_str(op)); + print_maybe_parens(s, rhs, prec + 1); + } + case (ast.expr_unary(?op,?expr,_)) { + wrd(s, ast.unop_to_str(op)); + if (op == ast._mutable) {space(s);} + print_expr(s, expr); + } + case (ast.expr_lit(?lit,_)) { + print_literal(s, lit); + } + case (ast.expr_cast(?expr,?ty,_)) { + print_maybe_parens(s, expr, as_prec); + space(s); + wrd1(s, "as"); + print_type(s, ty); + } + case (ast.expr_if(?test,?block,?clauses,?_else,_)) { + impure fn print_clause(ps s, @ast.expr test, ast.block blk) { + wrd1(s, "if"); + popen(s); + print_expr(s, test); + pclose(s); + space(s); + print_block(s, blk); + } + print_clause(s, test, block); + for (tup(@ast.expr, ast.block) clause in clauses) { + space(s); + wrd1(s, "else"); + print_clause(s, clause._0, clause._1); + } + alt (_else) { + case (option.some[ast.block](?blk)) { + space(s); + wrd1(s, "else"); + print_block(s, blk); + } + } + } + case (ast.expr_while(?test,?block,_)) { + wrd1(s, "while"); + popen(s); + print_expr(s, test); + pclose(s); + space(s); + print_block(s, block); + } + case (ast.expr_for(?decl,?expr,?block,_)) { + wrd1(s, "for"); + popen(s); + print_decl(s, decl); + space(s); + wrd1(s, "in"); + print_expr(s, expr); + pclose(s); + space(s); + print_block(s, block); + } + case (ast.expr_for_each(?decl,?expr,?block,_)) { + wrd1(s, "for each"); + popen(s); + print_decl(s, decl); + space(s); + wrd1(s, "in"); + print_expr(s, expr); + space(s); + print_block(s, block); + } + case (ast.expr_do_while(?block,?expr,_)) { + wrd1(s, "do"); + space(s); + print_block(s, block); + space(s); + wrd1(s, "while"); + popen(s); + print_expr(s, expr); + pclose(s); + } + case (ast.expr_alt(?expr,?arms,_)) { + wrd1(s, "alt"); + popen(s); + print_expr(s, expr); + pclose(s); + space(s); + bopen(s); + for (ast.arm arm in arms) { + hbox(s); + wrd1(s, "case"); + popen(s); + print_pat(s, arm.pat); + pclose(s); + space(s); + print_block(s, arm.block); + end(s); + line(s); + } + bclose(s); + } + case (ast.expr_block(?block,_)) { + print_block(s, block); + } + case (ast.expr_assign(?lhs,?rhs,_)) { + print_expr(s, lhs); + space(s); + wrd1(s, "="); + print_expr(s, rhs); + } + case (ast.expr_assign_op(?op,?lhs,?rhs,_)) { + print_expr(s, lhs); + space(s); + wrd(s, ast.binop_to_str(op)); + wrd1(s, "="); + print_expr(s, rhs); + } + case (ast.expr_field(?expr,?id,_)) { + print_expr(s, expr); + wrd(s, "."); + wrd(s, id); + } + case (ast.expr_index(?expr,?index,_)) { + print_expr(s, expr); + wrd(s, "."); + popen(s); + print_expr(s, index); + pclose(s); + } + case (ast.expr_path(?path,_,_)) { + print_path(s, path); + } + case (ast.expr_fail) { + wrd(s, "fail"); + } + case (ast.expr_ret(?result)) { + wrd(s, "ret"); + alt (result) { + case (option.some[@ast.expr](?expr)) { + space(s); + print_expr(s, expr); + } + case (_) {} + } + } + case (ast.expr_put(?result)) { + wrd(s, "put"); + alt (result) { + case (option.some[@ast.expr](?expr)) { + space(s); + print_expr(s, expr); + } + case (_) {} + } + } + case (ast.expr_be(?result)) { + wrd1(s, "be"); + print_expr(s, result); + } + case (ast.expr_log(?expr)) { + wrd1(s, "log"); + print_expr(s, expr); + } + case (ast.expr_check_expr(?expr)) { + wrd1(s, "check"); + print_expr(s, expr); + } + case (_) {wrd(s, "X");} + // TODO expr_ext(path, vec[@expr], option.t[@expr], @expr, ann); + } + end(s); +} + +impure fn print_decl(ps s, @ast.decl decl) { + hbox(s); + alt (decl.node) { + case (ast.decl_local(?loc)) { + alt (loc.ty) { + case (option.some[@ast.ty](?ty)) { + wrd1(s, "let"); + print_type(s, ty); + space(s); + } + case (_) { + wrd1(s, "auto"); + } + } + wrd(s, loc.ident); + alt (loc.init) { + case (option.some[@ast.expr](?init)) { + space(s); + wrd1(s, "="); + print_expr(s, init); + } + case (_) {} + } + } + case (ast.decl_item(?item)) { + print_item(s, item); + } + } + end(s); +} + +impure fn print_path(ps s, ast.path path) { + auto first = true; + for (str id in path.node.idents) { + if (first) {first = false;} + else {wrd(s, ".");} + wrd(s, id); + } + if (_vec.len[@ast.ty](path.node.types) > 0u) { + wrd(s, "["); + auto f = print_type; + commasep[@ast.ty](s, path.node.types, f); + wrd(s, "]"); + } +} + +impure fn print_pat(ps s, @ast.pat pat) { + alt (pat.node) { + case (ast.pat_wild(_)) {wrd(s, "_");} + case (ast.pat_bind(?id,_,_)) {wrd(s, "?" + id);} + case (ast.pat_lit(?lit,_)) {print_literal(s, lit);} + case (ast.pat_tag(?path,?args,_,_)) { + print_path(s, path); + if (_vec.len[@ast.pat](args) > 0u) { + popen(s); + auto f = print_pat; + commasep[@ast.pat](s, args, f); + pclose(s); + } + } + } +} + +impure fn print_fn(ps s, ast.fn_decl decl, str name, + vec[ast.ty_param] typarams) { + alt (decl.effect) { + case (ast.eff_impure) {wrd1(s, "impure");} + case (ast.eff_unsafe) {wrd1(s, "unsafe");} + case (_) {} + } + wrd1(s, "fn"); + wrd(s, name); + print_type_params(s, typarams); + popen(s); + impure fn print_arg(ps s, ast.arg x) { + hbox(s); + print_type(s, x.ty); + space(s); + wrd(s, x.ident); + end(s); + } + auto f = print_arg; + commasep[ast.arg](s, decl.inputs, f); + pclose(s); + if (decl.output.node != ast.ty_nil) { + space(s); + hbox(s); + wrd1(s, "->"); + print_type(s, decl.output); + end(s); + } +} + +impure fn print_type_params(ps s, vec[ast.ty_param] params) { + if (_vec.len[ast.ty_param](params) > 0u) { + wrd(s, "["); + impure fn printParam(ps s, ast.ty_param param) {wrd(s, param.ident);} + auto f = printParam; + commasep[ast.ty_param](s, params, f); + wrd(s, "]"); + } +} + +impure fn print_view_item(ps s, @ast.view_item item) { + hbox(s); + alt (item.node) { + case (ast.view_item_use(?id,?mta,_)) { + wrd1(s, "use"); + wrd(s, id); + if (_vec.len[@ast.meta_item](mta) > 0u) { + popen(s); + impure fn print_meta(ps s, @ast.meta_item item) { + hbox(s); + wrd1(s, item.node.name); + wrd1(s, "="); + print_string(s, item.node.value); + end(s); + } + auto f = print_meta; + commasep[@ast.meta_item](s, mta, f); + pclose(s); + } + } + case (ast.view_item_import(?id,?ids,_,_)) { + wrd1(s, "import"); + if (!_str.eq(id, ids.(_vec.len[str](ids)-1u))) { + wrd1(s, id); + wrd1(s, "="); + } + auto first = true; + for (str elt in ids) { + if (first) {first = false;} + else {wrd(s, ".");} + wrd(s, elt); + } + } + case (ast.view_item_export(?id)) { + wrd1(s, "export"); + wrd(s, id); + } + } + end(s); + wrd(s, ";"); + line(s); +} + +// FIXME: The fact that this builds up the table anew for every call is +// not good. Eventually, table should be a const. +fn operator_prec(ast.binop op) -> int { + for (front.parser.op_spec spec in front.parser.prec_table()) { + if (spec.op == op) {ret spec.prec;} + } + fail; +} + +impure fn print_maybe_parens(ps s, @ast.expr expr, int outer_prec) { + auto add_them; + alt (expr.node) { + case (ast.expr_binary(?op,_,_,_)) { + add_them = operator_prec(op) < outer_prec; + } + case (ast.expr_cast(_,_,_)) { + add_them = as_prec < outer_prec; + } + case (_) { + add_them = false; + } + } + if (add_them) {popen(s);} + print_expr(s, expr); + if (add_them) {pclose(s);} +} + +// TODO non-ascii +fn escape_str(str st, char to_escape) -> str { + let str out = ""; + auto len = _str.byte_len(st); + auto i = 0u; + while (i < len) { + alt (st.(i) as char) { + case ('\n') {out += "\\n";} + case ('\t') {out += "\\t";} + case ('\r') {out += "\\r";} + case ('\\') {out += "\\\\";} + case (?cur) { + if (cur == to_escape) {out += "\\";} + out += cur as u8; + } + } + i += 1u; + } + ret out; +} + +impure fn print_string(ps s, str st) { + wrd(s, "\""); wrd(s, escape_str(st, '"')); wrd(s, "\""); +} diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc index 43a04117..e4833409 100644 --- a/src/comp/rustc.rc +++ b/src/comp/rustc.rc @@ -31,6 +31,11 @@ mod driver { mod session; } +mod pretty { + mod pp; + mod pprust; +} + mod util { mod common; } diff --git a/src/lib/io.rs b/src/lib/io.rs index 9f428cee..0c4eb39e 100644 --- a/src/lib/io.rs +++ b/src/lib/io.rs @@ -91,24 +91,28 @@ tag fileflag { truncate; } +fn writefd(int fd, vec[u8] v) { + auto len = _vec.len[u8](v); + auto count = 0u; + auto vbuf; + while (count < len) { + vbuf = _vec.buf_off[u8](v, count); + auto nout = os.libc.write(fd, vbuf, len); + if (nout < 0) { + log "error dumping buffer"; + log sys.rustrt.last_os_error(); + fail; + } + count += nout as uint; + } +} + fn new_buf_writer(str path, vec[fileflag] flags) -> buf_writer { state obj fd_buf_writer(int fd) { fn write(vec[u8] v) { - auto len = _vec.len[u8](v); - auto count = 0u; - auto vbuf; - while (count < len) { - vbuf = _vec.buf_off[u8](v, count); - auto nout = os.libc.write(fd, vbuf, len); - if (nout < 0) { - log "error dumping buffer"; - log sys.rustrt.last_os_error(); - fail; - } - count += nout as uint; - } + writefd(fd, v); } drop { -- cgit v1.2.3 From abbcc0385dfde85c4254ea0278add7b4c6945885 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 7 Mar 2011 14:05:16 -0800 Subject: Poison ty_param values in trans; fix buggy parametric obj and box malloc paths. Add generic-box test. --- src/comp/middle/trans.rs | 32 +++++++++++++++----------------- src/test/run-pass/generic-box.rs | 8 ++++++++ 2 files changed, 23 insertions(+), 17 deletions(-) create mode 100644 src/test/run-pass/generic-box.rs diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 61715fd2..aa904674 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -661,7 +661,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t, bool boxed) -> TypeRef { fail; } case (ty.ty_param(_)) { - llty = T_typaram_ptr(cx.tn); + llty = T_i8(); } case (ty.ty_type) { llty = T_ptr(T_tydesc(cx.tn)); } } @@ -1216,17 +1216,14 @@ fn trans_raw_malloc(@block_ctxt cx, TypeRef llptr_ty, ValueRef llsize) ret rslt; } -fn trans_malloc_without_cleanup(@block_ctxt cx, @ty.t t) -> result { - auto llty = type_of(cx.fcx.ccx, t); - auto llsize = llsize_of(llvm.LLVMGetElementType(llty)); - ret trans_raw_malloc(cx, llty, llsize); -} - -fn trans_malloc(@block_ctxt cx, @ty.t t) -> result { - auto scope_cx = find_scope_cx(cx); - auto rslt = trans_malloc_without_cleanup(cx, t); - scope_cx.cleanups += clean(bind drop_ty(_, rslt.val, t)); - ret rslt; +fn trans_malloc_boxed(@block_ctxt cx, @ty.t t) -> result { + // Synthesize a fake box type structurally so we have something + // to measure the size of. + auto boxed_body = plain_ty(ty.ty_tup(vec(plain_ty(ty.ty_int), t))); + auto box_ptr = plain_ty(ty.ty_box(t)); + auto sz = size_of(cx, boxed_body); + auto llty = type_of(cx.fcx.ccx, box_ptr); + ret trans_raw_malloc(sz.bcx, llty, sz.val); } @@ -2256,7 +2253,11 @@ fn trans_unary(@block_ctxt cx, ast.unop op, case (ast.box) { 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_ty = node_ann_type(sub.bcx.fcx.ccx, a); + sub = trans_malloc_boxed(sub.bcx, e_ty); + find_scope_cx(cx).cleanups += + clean(bind drop_ty(_, sub.val, box_ty)); + auto box = sub.val; auto rc = sub.bcx.build.GEP(box, vec(C_int(0), @@ -4707,11 +4708,8 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, fields_ty))); let @ty.t boxed_body_ty = plain_ty(ty.ty_box(body_ty)); - let TypeRef llboxed_body_ty = type_of(cx, boxed_body_ty); - // Malloc a box for the body. - auto box = trans_raw_malloc(bcx, llboxed_body_ty, - llsize_of(llvm.LLVMGetElementType(llboxed_body_ty))); + auto box = trans_malloc_boxed(bcx, body_ty); bcx = box.bcx; auto rc = GEP_tup_like(bcx, boxed_body_ty, box.val, vec(0, abi.box_rc_field_refcnt)); diff --git a/src/test/run-pass/generic-box.rs b/src/test/run-pass/generic-box.rs new file mode 100644 index 00000000..856f3aff --- /dev/null +++ b/src/test/run-pass/generic-box.rs @@ -0,0 +1,8 @@ +fn box[T](&tup(T,T,T) x) -> @tup(T,T,T) { + ret @x; +} + +fn main() { + let @tup(int,int,int) x = box[int](tup(1,2,3)); + check (x._1 == 2); +} \ No newline at end of file -- cgit v1.2.3 From eeb2d6d32cbdc975fcc0a0c82adca37913ed6dff Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 7 Mar 2011 14:28:52 -0800 Subject: rustc: Un-XFAIL box-unbox.rs --- src/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 81ca965d..17fb737e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -442,7 +442,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ basic-2.rs \ basic.rs \ bind-obj-ctor.rs \ - box-unbox.rs \ child-outlives-parent.rs \ clone-with-exterior.rs \ comm.rs \ -- cgit v1.2.3 From 7fa8936ece50c5d58edcf3c3166e9570ba6e6197 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 7 Mar 2011 14:48:24 -0800 Subject: Un-XFAIL 5 more tests that pass lately. --- src/Makefile | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Makefile b/src/Makefile index 17fb737e..ac822932 100644 --- a/src/Makefile +++ b/src/Makefile @@ -437,7 +437,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ alt-pattern-drop.rs \ alt-type-simple.rs \ append-units.rs \ - autoderef-objfn.rs \ basic-1.rs \ basic-2.rs \ basic.rs \ @@ -447,10 +446,8 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ comm.rs \ constrained-type.rs \ destructor-ordering.rs \ - drop-on-empty-block-exit.rs \ drop-parametric-closure-with-bound-box.rs \ export-non-interference.rs \ - exterior.rs \ foreach-nested-2.rs \ foreach-nested.rs \ foreach-put-structured.rs \ @@ -482,7 +479,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ mlist-cycle.rs \ mlist.rs \ mutable-alias-vec.rs \ - native-opaque-type.rs \ obj-as.rs \ obj-dtor.rs \ obj-return-polytypes.rs \ @@ -523,7 +519,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ utf8.rs \ vec-alloc-append.rs \ vec-append.rs \ - vec-concat.rs \ vec-slice.rs \ while-prelude-drop.rs \ while-with-break.rs \ -- cgit v1.2.3 From 3869b3bfe489fc8db37b4436a9a38e732cc3d219 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 7 Mar 2011 15:12:41 -0800 Subject: Modernize test/run-pass/generic-recursive-tag.rs. Un-XFAIL it in rustboot. --- src/Makefile | 1 - src/test/run-pass/generic-recursive-tag.rs | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Makefile b/src/Makefile index ac822932..a1c13918 100644 --- a/src/Makefile +++ b/src/Makefile @@ -410,7 +410,6 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \ test/run-pass/vec-slice.rs \ test/run-pass/fn-lval.rs \ test/run-pass/generic-fn-box.rs \ - test/run-pass/generic-recursive-tag.rs \ test/run-pass/generic-tup.rs \ test/run-pass/iter-ret.rs \ test/run-pass/lib-io.rs \ diff --git a/src/test/run-pass/generic-recursive-tag.rs b/src/test/run-pass/generic-recursive-tag.rs index ad06345b..b9596b0d 100644 --- a/src/test/run-pass/generic-recursive-tag.rs +++ b/src/test/run-pass/generic-recursive-tag.rs @@ -1,8 +1,9 @@ tag list[T] { cons(@T, @list[T]); - nil(); + nil; } fn main() { - let list[int] a = cons[int](10, cons[int](12, cons[int](13, nil[int]()))); -} \ No newline at end of file + let list[int] a = cons[int](@10, @cons[int](@12, @cons[int](@13, + @nil[int]))); +} -- cgit v1.2.3 From df3038e68bf1189cd9cb0fc81e57da2c23594b63 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Mon, 7 Mar 2011 15:38:20 -0800 Subject: Parse opacity (and drop on the floor), so std.rc parses now. --- src/comp/front/ast.rs | 5 +++++ src/comp/front/parser.rs | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index d45260f3..52ae66c8 100644 --- a/src/comp/front/ast.rs +++ b/src/comp/front/ast.rs @@ -83,6 +83,11 @@ tag mutability { imm; } +tag opacity { + op_abstract; + op_transparent; +} + tag layer { layer_value; layer_state; diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index f60ff36b..71e592ff 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -1830,6 +1830,8 @@ impure fn parse_item_native_fn(parser p, ast.effect eff) -> @ast.native_item { impure fn parse_native_item(parser p) -> @ast.native_item { let ast.effect eff = parse_effect(p); + let ast.opacity opa = parse_opacity(p); + let ast.layer lyr = parse_layer(p); alt (p.peek()) { case (token.TYPE) { ret parse_item_native_type(p); @@ -1978,6 +1980,19 @@ impure fn parse_item_tag(parser p) -> @ast.item { ret @spanned(lo, hi, item); } +impure fn parse_opacity(parser p) -> ast.opacity { + alt (p.peek()) { + case (token.ABS) { + p.bump(); + ret ast.op_abstract; + } + case (_) { + ret ast.op_transparent; + } + } + fail; +} + impure fn parse_layer(parser p) -> ast.layer { alt (p.peek()) { case (token.STATE) { @@ -2033,6 +2048,7 @@ fn peeking_at_item(parser p) -> bool { impure fn parse_item(parser p) -> @ast.item { let ast.effect eff = parse_effect(p); + let ast.opacity opa = parse_opacity(p); let ast.layer lyr = parse_layer(p); alt (p.peek()) { -- cgit v1.2.3 From 6f7e21ddac7bd956db55ea6885fbcfd3fb9f29a7 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 7 Mar 2011 15:43:55 -0800 Subject: rustc: Truncate or zero-extend indexes appropriately. Un-XFAIL integral-indexing.rs. --- src/Makefile | 1 - src/comp/middle/trans.rs | 17 +++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Makefile b/src/Makefile index a1c13918..2a6e7b15 100644 --- a/src/Makefile +++ b/src/Makefile @@ -456,7 +456,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ generic-recursive-tag.rs \ generic-tag-alt.rs \ generic-tag-values.rs \ - integral-indexing.rs \ iter-range.rs \ iter-ret.rs \ lazychan.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index aa904674..7ad96ba2 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3209,10 +3209,23 @@ fn trans_index(@block_ctxt cx, &ast.span sp, @ast.expr base, auto v = lv.val; auto bcx = ix.bcx; + // Cast to an LLVM integer. Rust is less strict than LLVM in this regard. + auto ix_val; + auto ix_size = llsize_of_real(cx.fcx.ccx, val_ty(ix.val)); + auto int_size = llsize_of_real(cx.fcx.ccx, T_int()); + if (ix_size < int_size) { + ix_val = bcx.build.ZExt(ix.val, T_int()); + } else if (ix_size > int_size) { + ix_val = bcx.build.Trunc(ix.val, T_int()); + } else { + ix_val = ix.val; + } + auto llunit_ty = node_type(cx.fcx.ccx, ann); auto unit_sz = size_of(bcx, node_ann_type(cx.fcx.ccx, ann)); bcx = unit_sz.bcx; - auto scaled_ix = bcx.build.Mul(ix.val, unit_sz.val); + + auto scaled_ix = bcx.build.Mul(ix_val, unit_sz.val); auto lim = bcx.build.GEP(v, vec(C_int(0), C_int(abi.vec_elt_fill))); lim = bcx.build.Load(lim); @@ -3229,7 +3242,7 @@ fn trans_index(@block_ctxt cx, &ast.span sp, @ast.expr base, fail_res.bcx.build.Br(next_cx.llbb); auto body = next_cx.build.GEP(v, vec(C_int(0), C_int(abi.vec_elt_data))); - auto elt = next_cx.build.GEP(body, vec(C_int(0), ix.val)); + auto elt = next_cx.build.GEP(body, vec(C_int(0), ix_val)); ret lval_mem(next_cx, elt); } -- cgit v1.2.3 From 6ed226c6b3a28f3c10d2176d7dba7e339bf0ab99 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 7 Mar 2011 16:35:00 -0800 Subject: rustc: Cast the LLVM representations of tag types when constructing boxes. Un-XFAIL list.rs. --- src/Makefile | 1 - src/comp/middle/trans.rs | 9 +++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 2a6e7b15..8855a2d1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -472,7 +472,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ lib-uint.rs \ lib-vec-str-conversions.rs \ lib-vec.rs \ - list.rs \ many.rs \ mlist-cycle.rs \ mlist.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 7ad96ba2..723a845d 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -2266,6 +2266,15 @@ fn trans_unary(@block_ctxt cx, ast.unop op, vec(C_int(0), C_int(abi.box_rc_field_body))); sub.bcx.build.Store(C_int(1), rc); + + // Cast the body type to the type of the value. This is needed to + // make tags work, since tags have a different LLVM type depending + // on whether they're boxed or not. + if (!ty.type_has_dynamic_size(e_ty)) { + auto llety = T_ptr(type_of(sub.bcx.fcx.ccx, e_ty)); + body = sub.bcx.build.PointerCast(body, llety); + } + sub = copy_ty(sub.bcx, INIT, body, e_val, e_ty); ret res(sub.bcx, box); } -- cgit v1.2.3