diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index ee358432ff1..01739d19f8f 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 a108d2431e3..71b06b45817 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 db215ea9006..abe94b8919e 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 538dfdbe1cf..03d1fad9909 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 a9a4e936039..68c2114078c 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 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); + } + + // 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; + } + + auto result = unify_step(bindings, + actual_input.ty, + expected_input.ty, + handler); + + alt (result) { + case (ures_ok(?rty)) { + result_ins += vec(rec(mode=result_mode, + ty=rty)); + } + + case (_) { + ret result; + } + } + + i += 1u; + } + + // Check the output. + auto result_out; auto result = unify_step(bindings, - actual_input.ty, - expected_input.ty, + expected_output, + actual_output, handler); - alt (result) { - case (ures_ok(?rty)) { - result_ins += vec(rec(mode=result_mode, - ty=rty)); - } + case (ures_ok(?rty)) { + result_out = rty; + } - case (_) { - ret result; - } + case (_) { + ret result; + } } - i += 1u; - } - - // 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); + 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 (_) { - 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 aa5e9fe5a7a..ee92d8d7406 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);