Make a tag for iterness / fnness, teach many places about it.

This commit is contained in:
Graydon Hoare 2011-02-18 17:30:57 -08:00
parent 3aba50ff33
commit 34c60b6edb
6 changed files with 305 additions and 230 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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](_,_,_),

View file

@ -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);

View file

@ -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)) {

View file

@ -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);