1
Fork 0

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; eff_unsafe;
} }
tag proto {
proto_iter;
proto_fn;
}
tag binop { tag binop {
add; add;
sub; sub;
@ -187,7 +192,8 @@ tag lit_ {
type ty_field = rec(ident ident, @ty ty); type ty_field = rec(ident ident, @ty ty);
type ty_arg = rec(mode mode, @ty ty); type ty_arg = rec(mode mode, @ty ty);
// TODO: effect // 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_]; type ty = spanned[ty_];
tag ty_ { tag ty_ {
ty_nil; ty_nil;
@ -201,7 +207,7 @@ tag ty_ {
ty_vec(@ty); ty_vec(@ty);
ty_tup(vec[@ty]); ty_tup(vec[@ty]);
ty_rec(vec[ty_field]); 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_obj(vec[ty_method]);
ty_path(path, option.t[def]); ty_path(path, option.t[def]);
ty_mutable(@ty); ty_mutable(@ty);
@ -210,10 +216,10 @@ tag ty_ {
type arg = rec(mode mode, @ty ty, ident ident, def_id id); type arg = rec(mode mode, @ty ty, ident ident, def_id id);
type fn_decl = rec(effect effect, type fn_decl = rec(effect effect,
proto proto,
vec[arg] inputs, vec[arg] inputs,
@ty output); @ty output);
type _fn = rec(fn_decl decl, type _fn = rec(fn_decl decl,
bool is_iter,
block body); 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) { impure fn parse_fn_input_ty(parser p) -> rec(ast.mode mode, @ast.ty ty) {
auto mode; auto mode;
if (p.peek() == token.BINOP(token.AND)) { 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); 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_ { 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. // FIXME: do something with this, currently it's dropped on the floor.
let ast.effect eff = parse_effect(p); let ast.effect eff = parse_effect(p);
let ast.proto proto = parse_proto(p);
expect(p, token.FN);
auto ident = parse_ident(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); expect(p, token.SEMI);
alt (f) { alt (f) {
case (ast.ty_fn(?inputs, ?output)) { case (ast.ty_fn(?proto, ?inputs, ?output)) {
ret rec(ident=ident, inputs=inputs, output=output); ret rec(proto=proto, ident=ident,
inputs=inputs, output=output);
} }
} }
fail; fail;
@ -286,9 +296,20 @@ impure fn parse_ty(parser p) -> @ast.ty {
case (token.FN) { case (token.FN) {
auto flo = p.get_span(); auto flo = p.get_span();
p.bump(); p.bump();
t = parse_ty_fn(p, flo); t = parse_ty_fn(ast.proto_fn, p, flo);
alt (t) { 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; hi = out.span;
} }
} }
@ -1537,7 +1558,8 @@ impure fn parse_ty_params(parser p) -> vec[ast.ty_param] {
ret ty_params; 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; auto pf = parse_arg;
let util.common.spanned[vec[ast.arg]] inputs = let util.common.spanned[vec[ast.arg]] inputs =
// FIXME: passing parse_arg as an lval doesn't work at the // 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 { } else {
output = @spanned(inputs.span, inputs.span, ast.ty_nil); 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 { impure fn parse_fn(parser p, ast.effect eff, ast.proto proto) -> ast._fn {
auto decl = parse_fn_decl(p, eff); auto decl = parse_fn_decl(p, proto, eff);
auto body = parse_block(p); auto body = parse_block(p);
ret rec(decl = decl, ret rec(decl = decl,
is_iter = is_iter,
body = body); body = body);
} }
impure fn parse_fn_header(parser p, bool is_iter) -> tup(span, ast.ident, impure fn parse_fn_header(parser p)
vec[ast.ty_param]) { -> tup(span, ast.proto, ast.ident, vec[ast.ty_param]) {
auto lo = p.get_span(); auto lo = p.get_span();
if (is_iter) { auto proto = parse_proto(p);
expect(p, token.ITER);
} else {
expect(p, token.FN);
}
auto id = parse_ident(p); auto id = parse_ident(p);
auto ty_params = parse_ty_params(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, impure fn parse_item_fn_or_iter(parser p, ast.effect eff) -> @ast.item {
bool is_iter) -> @ast.item { auto t = parse_fn_header(p);
auto t = parse_fn_header(p, is_iter); auto f = parse_fn(p, eff, t._1);
auto f = parse_fn(p, eff, is_iter); auto item = ast.item_fn(t._2, f, t._3,
auto item = ast.item_fn(t._1, f, t._2,
p.next_def_id(), ast.ann_none); p.next_def_id(), ast.ann_none);
ret @spanned(t._0, f.body.span, item); 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 { impure fn parse_method(parser p) -> @ast.method {
auto lo = p.get_span(); auto lo = p.get_span();
auto eff = parse_effect(p); auto eff = parse_effect(p);
auto is_iter = false; auto proto = parse_proto(p);
alt (p.peek()) {
case (token.FN) { p.bump(); }
case (token.ITER) { p.bump(); is_iter = true; }
case (?t) { unexpected(p, t); }
}
auto ident = parse_ident(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, auto meth = rec(ident=ident, meth=f,
id=p.next_def_id(), ann=ast.ann_none); id=p.next_def_id(), ann=ast.ann_none);
ret @spanned(lo, f.body.span, meth); 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 { impure fn parse_item_native_fn(parser p, ast.effect eff) -> @ast.native_item {
auto t = parse_fn_header(p, false); auto t = parse_fn_header(p);
auto decl = parse_fn_decl(p, eff); auto decl = parse_fn_decl(p, t._1, eff);
auto hi = p.get_span(); auto hi = p.get_span();
expect(p, token.SEMI); 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); ast.ann_none);
ret @spanned(t._0, hi, item); ret @spanned(t._0, hi, item);
} }
@ -1883,11 +1895,11 @@ impure fn parse_item(parser p) -> @ast.item {
case (token.FN) { case (token.FN) {
check (lyr == ast.layer_value); 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) { case (token.ITER) {
check (lyr == ast.layer_value); 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) { case (token.MOD) {
check (eff == ast.eff_pure); check (eff == ast.eff_pure);

View file

@ -59,6 +59,7 @@ type ast_fold[ENV] =
vec[ast.ty_method] meths) -> @ty) fold_ty_obj, vec[ast.ty_method] meths) -> @ty) fold_ty_obj,
(fn(&ENV e, &span sp, (fn(&ENV e, &span sp,
ast.proto proto,
vec[rec(ast.mode mode, @ty ty)] inputs, vec[rec(ast.mode mode, @ty ty)] inputs,
@ty output) -> @ty) fold_ty_fn, @ty output) -> @ty) fold_ty_fn,
@ -252,11 +253,10 @@ type ast_fold[ENV] =
&ast.block_) -> block) fold_block, &ast.block_) -> block) fold_block,
(fn(&ENV e, &fn_decl decl, (fn(&ENV e, &fn_decl decl,
bool is_iter,
&block body) -> ast._fn) fold_fn, &block body) -> ast._fn) fold_fn,
(fn(&ENV e, ast.effect effect, (fn(&ENV e, ast.effect effect,
vec[arg] inputs, ast.proto proto, vec[arg] inputs,
@ty output) -> ast.fn_decl) fold_fn_decl, @ty output) -> ast.fn_decl) fold_fn_decl,
(fn(&ENV e, &ast._mod m) -> ast._mod) fold_mod, (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)) { case (ast.ty_obj(?meths)) {
let vec[ast.ty_method] meths_ = vec(); let vec[ast.ty_method] meths_ = vec();
for (ast.ty_method m in meths) { 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) { alt (tfn.node) {
case (ast.ty_fn(?ins, ?out)) { case (ast.ty_fn(?p, ?ins, ?out)) {
append[ast.ty_method] 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_); ret fld.fold_ty_mutable(env_, t.span, ty_);
} }
case (ast.ty_fn(?inputs, ?output)) { case (ast.ty_fn(?proto, ?inputs, ?output)) {
ret fold_ty_fn(env_, fld, t.span, 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, fn fold_ty_fn[ENV](&ENV env, ast_fold[ENV] fld, &span sp,
ast.proto proto,
vec[rec(ast.mode mode, @ty ty)] inputs, vec[rec(ast.mode mode, @ty ty)] inputs,
@ty output) -> @ty { @ty output) -> @ty {
auto output_ = fold_ty(env, fld, output); 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); auto input_ = rec(ty=ty_ with input);
inputs_ += vec(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 { 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); inputs += fold_arg(env, fld, a);
} }
auto output = fold_ty[ENV](env, fld, decl.output); 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 { 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); 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, fn identity_fold_ty_fn[ENV](&ENV env, &span sp,
ast.proto proto,
vec[rec(ast.mode mode, @ty ty)] inputs, vec[rec(ast.mode mode, @ty ty)] inputs,
@ty output) -> @ty { @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, 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, fn identity_fold_fn_decl[ENV](&ENV e,
ast.effect effect, ast.effect effect,
ast.proto proto,
vec[arg] inputs, vec[arg] inputs,
@ty output) -> ast.fn_decl { @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 identity_fold_fn[ENV](&ENV e,
&fn_decl decl, &fn_decl decl,
bool is_iter,
&block body) -> ast._fn { &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 { 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_tup = bind identity_fold_ty_tup[ENV](_,_,_),
fold_ty_rec = bind identity_fold_ty_rec[ENV](_,_,_), fold_ty_rec = bind identity_fold_ty_rec[ENV](_,_,_),
fold_ty_obj = bind identity_fold_ty_obj[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_path = bind identity_fold_ty_path[ENV](_,_,_,_),
fold_ty_mutable = bind identity_fold_ty_mutable[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](_,_,_,_,_,_), bind identity_fold_view_item_import[ENV](_,_,_,_,_,_),
fold_block = bind identity_fold_block[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_fn_decl = bind identity_fold_fn_decl[ENV](_,_,_,_,_),
fold_mod = bind identity_fold_mod[ENV](_,_), fold_mod = bind identity_fold_mod[ENV](_,_),
fold_native_mod = bind identity_fold_native_mod[ENV](_,_), fold_native_mod = bind identity_fold_native_mod[ENV](_,_),
fold_crate = bind identity_fold_crate[ENV](_,_,_), fold_crate = bind identity_fold_crate[ENV](_,_,_),

View file

@ -449,8 +449,7 @@ fn type_of_explicit_args(@crate_ctxt cx,
// - trans_args // - trans_args
fn type_of_fn_full(@crate_ctxt cx, fn type_of_fn_full(@crate_ctxt cx,
// FIXME: change bool flag to tag ast.proto proto,
bool is_iter,
option.t[TypeRef] obj_self, option.t[TypeRef] obj_self,
vec[ty.arg] inputs, vec[ty.arg] inputs,
@ty.t output) -> TypeRef { @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... // Args >3: ty params, if not acquired via capture...
if (obj_self == none[TypeRef]) { if (obj_self == none[TypeRef]) {
auto ty_param_count = 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; auto i = 0u;
while (i < ty_param_count) { while (i < ty_param_count) {
atys += T_ptr(T_tydesc(cx.tn)); 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 // 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 // *input* type of the function we're given as our iter-block
// argument. // argument.
atys += T_fn_pair(cx.tn, 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)), vec(rec(mode=ast.val, ty=output)),
plain_ty(ty.ty_nil))); plain_ty(ty.ty_nil)));
} }
@ -505,10 +506,9 @@ fn type_of_fn_full(@crate_ctxt cx,
} }
fn type_of_fn(@crate_ctxt cx, fn type_of_fn(@crate_ctxt cx,
// FIXME: change bool flag to tag ast.proto proto,
bool is_iter,
vec[ty.arg] inputs, @ty.t output) -> TypeRef { 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, 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); ret T_struct(tys);
} }
case (ty.ty_fn(?args, ?out)) { case (ty.ty_fn(?proto, ?args, ?out)) {
// FIXME: put iter in ty_fn. ret T_fn_pair(cx.tn, type_of_fn(cx, proto, args, out));
ret T_fn_pair(cx.tn, type_of_fn(cx, false, args, out));
} }
case (ty.ty_native_fn(?args, ?out)) { case (ty.ty_native_fn(?args, ?out)) {
ret T_fn_pair(cx.tn, type_of_native_fn(cx, 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(); let vec[TypeRef] mtys = vec();
for (ty.method m in meths) { for (ty.method m in meths) {
let TypeRef mty = let TypeRef mty =
type_of_fn_full(cx, type_of_fn_full(cx, m.proto,
// FIXME: support method iters
false,
some[TypeRef](self_ty), some[TypeRef](self_ty),
m.inputs, m.output); m.inputs, m.output);
mtys += T_ptr(mty); 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)); T_int(), C_int(0));
} }
case (ty.ty_fn(_,_)) { case (ty.ty_fn(_,_,_)) {
fn hit_zero(@block_ctxt cx, ValueRef v) -> result { fn hit_zero(@block_ctxt cx, ValueRef v) -> result {
// Call through the closure's own fields-drop glue first. // 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 { fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef {
let vec[TypeRef] lltys = vec(); let vec[TypeRef] lltys = vec();
alt (ty.ann_to_type(v.ann).struct) { alt (ty.ann_to_type(v.ann).struct) {
case (ty.ty_fn(?args, _)) { case (ty.ty_fn(_, ?args, _)) {
for (ty.arg arg in args) { for (ty.arg arg in args) {
lltys += vec(type_of(cx, arg.ty)); 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); auto fn_ty = ty.ann_to_type(variants.(i).ann);
alt (fn_ty.struct) { alt (fn_ty.struct) {
case (ty.ty_fn(?args, _)) { case (ty.ty_fn(_, ?args, _)) {
auto llvarp = variant_cx.build. auto llvarp = variant_cx.build.
TruncOrBitCast(llunion_ptr, TruncOrBitCast(llunion_ptr,
T_ptr(llvarty)); T_ptr(llvarty));
@ -1584,7 +1581,7 @@ fn iter_structural_ty(@block_ctxt cx,
ret res(next_cx, C_nil()); ret res(next_cx, C_nil());
} }
case (ty.ty_fn(_,_)) { case (ty.ty_fn(_,_,_)) {
auto box_cell = auto box_cell =
cx.build.GEP(v, cx.build.GEP(v,
vec(C_int(0), 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 // 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. // 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], auto iter_body_llty = type_of_fn_full(cx.fcx.ccx, ast.proto_fn,
vec(rec(mode=ast.val, ty=decl_ty)), none[TypeRef],
plain_ty(ty.ty_nil)); vec(rec(mode=ast.val, ty=decl_ty)),
plain_ty(ty.ty_nil));
let ValueRef llforeach = decl_fastcall_fn(cx.fcx.ccx.llmod, let ValueRef lliterbody = decl_fastcall_fn(cx.fcx.ccx.llmod,
s, foreach_llty); s, iter_body_llty);
// FIXME: handle ty params properly. // FIXME: handle ty params properly.
let vec[ast.ty_param] ty_params = vec(); 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); auto bcx = new_top_block_ctxt(fcx);
// FIXME: populate lllocals from llenv here. // FIXME: populate lllocals from llenv here.
@ -2282,13 +2280,16 @@ fn trans_for_each(@block_ctxt cx,
res.bcx.build.RetVoid(); 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) { alt (seq.node) {
case (ast.expr_call(?f, ?args, ?ann)) { case (ast.expr_call(?f, ?args, ?ann)) {
// FIXME_ finish here by transferring to trans_call,
// suitably refactored. // log "lliterbody: " + val_str(cx.fcx.ccx.tn, lliterbody);
cx.fcx.ccx.sess.unimpl("for each loop in trans"); ret trans_call(cx, f,
some[ValueRef](lliterbody),
args,
ann);
} }
} }
fail; fail;
@ -2933,6 +2934,7 @@ fn trans_args(@block_ctxt cx,
ValueRef llenv, ValueRef llenv,
option.t[ValueRef] llobj, option.t[ValueRef] llobj,
option.t[generic_info] gen, option.t[generic_info] gen,
option.t[ValueRef] lliterbody,
&vec[@ast.expr] es, &vec[@ast.expr] es,
@ty.t fn_ty) @ty.t fn_ty)
-> tup(@block_ctxt, vec[ValueRef], ValueRef) { -> tup(@block_ctxt, vec[ValueRef], ValueRef) {
@ -2993,6 +2995,14 @@ fn trans_args(@block_ctxt cx,
// Args >3: ty_params ... // Args >3: ty_params ...
llargs += lltydescs; llargs += lltydescs;
// ... then possibly an lliterbody argument.
alt (lliterbody) {
case (none[ValueRef]) {}
case (some[ValueRef](?lli)) {
llargs += lli;
}
}
// ... then explicit args. // ... then explicit args.
auto i = 0u; auto i = 0u;
for (@ast.expr e in es) { 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, 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 f_res = trans_lval(cx, f);
auto faddr = f_res.res.val; auto faddr = f_res.res.val;
auto llenv = C_null(T_opaque_closure_ptr(cx.fcx.ccx.tn)); 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, auto args_res = trans_args(f_res.res.bcx,
llenv, f_res.llobj, llenv, f_res.llobj,
f_res.generic, f_res.generic,
lliterbody,
args, fn_ty); args, fn_ty);
auto bcx = args_res._0; auto bcx = args_res._0;
auto llargs = args_res._1; auto llargs = args_res._1;
auto llretslot = args_res._2; 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); bcx.build.FastCall(faddr, llargs);
auto retval = C_nil(); 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)) { 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)) { case (ast.expr_cast(?e, _, ?ann)) {
@ -3707,8 +3728,7 @@ fn new_fn_ctxt(@crate_ctxt cx,
// - trans_args // - trans_args
fn create_llargs_for_fn_args(&@fn_ctxt cx, fn create_llargs_for_fn_args(&@fn_ctxt cx,
// FIXME: change bool flag to tag ast.proto proto,
bool is_iter,
option.t[TypeRef] ty_self, option.t[TypeRef] ty_self,
@ty.t ret_ty, @ty.t ret_ty,
&vec[ast.arg] args, &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); auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n);
check (llarg as int != 0); check (llarg as int != 0);
cx.lliterbody = some[ValueRef](llarg); 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] { fn arg_tys_of_fn(ast.ann ann) -> vec[ty.arg] {
alt (ty.ann_to_type(ann).struct) { alt (ty.ann_to_type(ann).struct) {
case (ty.ty_fn(?arg_tys, _)) { case (ty.ty_fn(_, ?arg_tys, _)) {
ret 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 { fn ret_ty_of_fn_ty(@ty.t t) -> @ty.t {
alt (t.struct) { alt (t.struct) {
case (ty.ty_fn(_, ?ret_ty)) { case (ty.ty_fn(_, _, ?ret_ty)) {
ret 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); cx.item_names.insert(cx.path, llfndecl);
auto fcx = new_fn_ctxt(cx, 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), ty_self, ret_ty_of_fn(ann),
f.decl.inputs, ty_params); f.decl.inputs, ty_params);
auto bcx = new_top_block_ctxt(fcx); auto bcx = new_top_block_ctxt(fcx);
@ -3915,10 +3935,8 @@ fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty,
auto llfnty = T_nil(); auto llfnty = T_nil();
alt (node_ann_type(cx, m.node.ann).struct) { alt (node_ann_type(cx, m.node.ann).struct) {
case (ty.ty_fn(?inputs, ?output)) { case (ty.ty_fn(?proto, ?inputs, ?output)) {
llfnty = type_of_fn_full(cx, llfnty = type_of_fn_full(cx, proto,
// FIXME: support method iters.
false,
some[TypeRef](self_ty), some[TypeRef](self_ty),
inputs, output); 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); 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), none[TypeRef], ret_ty_of_fn(ann),
fn_args, ty_params); 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); let ValueRef llfndecl = cx.item_ids.get(variant.id);
auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); 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), none[TypeRef], ret_ty_of_fn(variant.ann),
fn_args, ty_params); fn_args, ty_params);

View file

@ -19,7 +19,10 @@ import util.common.span;
type arg = rec(ast.mode mode, @t ty); type arg = rec(ast.mode mode, @t ty);
type field = rec(ast.ident ident, @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 // NB: If you change this, you'll probably want to change the corresponding
// AST structure in front/ast.rs as well. // AST structure in front/ast.rs as well.
@ -37,7 +40,7 @@ tag sty {
ty_vec(@t); ty_vec(@t);
ty_tup(vec[@t]); ty_tup(vec[@t]);
ty_rec(vec[field]); 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_native_fn(vec[arg], @t); // TODO: effect
ty_obj(vec[method]); ty_obj(vec[method]);
ty_var(int); // ephemeral type var ty_var(int); // ephemeral type var
@ -122,9 +125,13 @@ fn ast_ty_to_str(&@ast.ty ty) -> str {
s += ")"; s += ")";
} }
case (ast.ty_fn(?inputs, ?output)) { case (ast.ty_fn(?proto, ?inputs, ?output)) {
auto f = ast_fn_input_to_str; 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); auto is = _vec.map[rec(ast.mode mode, @ast.ty ty),str](f, inputs);
s += _str.connect(is, ", "); s += _str.connect(is, ", ");
s += ")"; s += ")";
@ -175,10 +182,14 @@ fn ty_to_str(&@t typ) -> str {
ret s + ty_to_str(input.ty); 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 { vec[arg] inputs, @t output) -> str {
auto f = fn_input_to_str; auto f = fn_input_to_str;
auto s = "fn"; auto s = "fn";
if (proto == ast.proto_iter) {
s = "iter";
}
alt (ident) { alt (ident) {
case (some[ast.ident](?i)) { case (some[ast.ident](?i)) {
s += " "; s += " ";
@ -198,7 +209,8 @@ fn ty_to_str(&@t typ) -> str {
} }
fn method_to_str(&method m) -> 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 { fn field_to_str(&field f) -> str {
@ -245,12 +257,12 @@ fn ty_to_str(&@t typ) -> str {
} }
} }
case (ty_fn(?inputs, ?output)) { case (ty_fn(?proto, ?inputs, ?output)) {
s = fn_to_str(none[ast.ident], inputs, output); 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(none[ast.ident], inputs, output); s = fn_to_str(ast.proto_fn, none[ast.ident], inputs, output);
} }
case (ty_obj(?meths)) { case (ty_obj(?meths)) {
@ -326,13 +338,13 @@ fn fold_ty(ty_fold fld, @t ty) -> @t {
} }
ret rewrap(ty, ty_rec(new_fields)); 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(); let vec[arg] new_args = vec();
for (arg a in args) { for (arg a in args) {
auto new_ty = fold_ty(fld, a.ty); auto new_ty = fold_ty(fld, a.ty);
new_args += vec(rec(mode=a.mode, ty=new_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)) { case (ty_obj(?methods)) {
let vec[method] new_methods = vec(); 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) { for (arg a in m.inputs) {
new_args += vec(rec(mode=a.mode, ty=fold_ty(fld, a.ty))); 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))); output=fold_ty(fld, m.output)));
} }
ret rewrap(ty, ty_obj(new_methods)); 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_tup(_)) { ret true; }
case (ty_rec(_)) { ret true; } case (ty_rec(_)) { ret true; }
case (ty_tag(_,_)) { ret true; } case (ty_tag(_,_)) { ret true; }
case (ty_fn(_,_)) { ret true; } case (ty_fn(_,_,_)) { ret true; }
case (ty_obj(_)) { ret true; } case (ty_obj(_)) { ret true; }
case (_) { ret false; } case (_) { ret false; }
} }
@ -573,23 +586,29 @@ fn count_ty_params(@t ty) -> uint {
// Type accessors for substructures of types // Type accessors for substructures of types
fn ty_fn_args(@t fty) -> vec[arg] { fn ty_fn_args(@t fty) -> vec[arg] {
alt (fty.struct) { alt (fty.struct) {
case (ty.ty_fn(?a, _)) { ret a; } 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 { fn ty_fn_ret(@t fty) -> @t {
alt (fty.struct) { alt (fty.struct) {
case (ty.ty_fn(_, ?r)) { ret r; } case (ty.ty_fn(_, _, ?r)) { ret r; }
} }
} }
fn is_fn_ty(@t fty) -> bool { fn is_fn_ty(@t fty) -> bool {
alt (fty.struct) { alt (fty.struct) {
case (ty.ty_fn(_, _)) { ret true; } case (ty.ty_fn(_, _, _)) { ret true; }
case (_) { ret false; } case (_) { ret false; }
} }
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, fn unify_fn(@hashmap[int,@ty.t] bindings,
ast.proto e_proto,
ast.proto a_proto,
@ty.t expected, @ty.t expected,
@ty.t actual, @ty.t actual,
&unify_handler handler, &unify_handler handler,
vec[arg] expected_inputs, @t expected_output, vec[arg] expected_inputs, @t expected_output,
vec[arg] actual_inputs, @t actual_output) vec[arg] actual_inputs, @t actual_output)
-> unify_result { -> 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);
}
// TODO: as above, we should have an iter2 iterator. if (e_proto != a_proto) {
let vec[arg] result_ins = vec(); ret ures_err(terr_mismatch, expected, actual);
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 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, auto result = unify_step(bindings,
actual_input.ty, expected_output,
expected_input.ty, actual_output,
handler); handler);
alt (result) { alt (result) {
case (ures_ok(?rty)) { case (ures_ok(?rty)) {
result_ins += vec(rec(mode=result_mode, result_out = rty;
ty=rty)); }
}
case (_) { case (_) {
ret result; ret result;
} }
} }
i += 1u; auto t = plain_ty(ty.ty_fn(e_proto, result_ins, result_out));
} ret ures_ok(t);
// 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);
} }
fn unify_obj(@hashmap[int,@ty.t] bindings, fn unify_obj(@hashmap[int,@ty.t] bindings,
@ty.t expected, @ty.t expected,
@ty.t actual, @ty.t actual,
&unify_handler handler, &unify_handler handler,
vec[method] expected_meths, vec[method] expected_meths,
vec[method] actual_meths) -> unify_result { vec[method] actual_meths) -> unify_result {
let vec[method] result_meths = vec(); let vec[method] result_meths = vec();
let uint i = 0u; let uint i = 0u;
let uint expected_len = _vec.len[method](expected_meths); 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. // FIXME: work around buggy typestate logic for 'alt', sigh.
fn is_ok(&unify_result r) -> bool { fn is_ok(&unify_result r) -> bool {
alt (r) { alt (r) {
case (ures_ok(?tfn)) { case (ures_ok(?tfn)) {
ret true; ret true;
}
case (_) {}
} }
case (_) {} ret false;
}
ret false;
} }
fn append_if_ok(&method e_meth, fn append_if_ok(&method e_meth,
&unify_result r, &mutable vec[method] result_meths) { &unify_result r, &mutable vec[method] result_meths) {
alt (r) { alt (r) {
case (ures_ok(?tfn)) { case (ures_ok(?tfn)) {
alt (tfn.struct) { alt (tfn.struct) {
case (ty_fn(?ins, ?out)) { case (ty_fn(?proto, ?ins, ?out)) {
result_meths += vec(rec(inputs = ins, result_meths += vec(rec(inputs = ins,
output = out output = out
with e_meth)); with e_meth));
}
}
} }
}
} }
}
} }
while (i < expected_len) { 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), ret ures_err(terr_obj_meths(e_meth.ident, a_meth.ident),
expected, actual); 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, e_meth.inputs, e_meth.output,
a_meth.inputs, a_meth.output); a_meth.inputs, a_meth.output);
if (!is_ok(r)) { 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) { alt (actual.struct) {
case (ty.ty_fn(?actual_inputs, ?actual_output)) { case (ty.ty_fn(?ap, ?actual_inputs, ?actual_output)) {
ret unify_fn(bindings, expected, actual, handler, ret unify_fn(bindings, ep, ap,
expected_inputs, expected_output, expected, actual, handler,
actual_inputs, actual_output); expected_inputs, expected_output,
actual_inputs, actual_output);
} }
case (_) { case (_) {
@ -1230,15 +1259,15 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
} }
case (ty.ty_obj(?expected_meths)) { case (ty.ty_obj(?expected_meths)) {
alt (actual.struct) { alt (actual.struct) {
case (ty.ty_obj(?actual_meths)) { case (ty.ty_obj(?actual_meths)) {
ret unify_obj(bindings, expected, actual, handler, ret unify_obj(bindings, expected, actual, handler,
expected_meths, actual_meths); 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)) { 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); 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 f = bind ast_arg_to_arg(getter, _);
auto i = _vec.map[ast.ty_arg, arg](f, inputs); 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)) { 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 ins = _vec.map[ast.ty_arg, arg](f, m.inputs);
auto out = ast_ty_to_ty(getter, m.output); auto out = ast_ty_to_ty(getter, m.output);
append[ty.method](tmeths, append[ty.method](tmeths,
rec(ident=m.ident, rec(proto=m.proto,
ident=m.ident,
inputs=ins, inputs=ins,
output=out)); 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 { ast.def_id def_id) -> @ty.t {
auto input_tys = _vec.map[ast.arg,arg](ty_of_arg, decl.inputs); auto input_tys = _vec.map[ast.arg,arg](ty_of_arg, decl.inputs);
auto output_ty = convert(decl.output); 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); item_to_ty.insert(def_id, t_fn);
ret 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 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 inputs = _vec.map[ast.arg,arg](f, m.node.meth.decl.inputs);
auto output = convert(m.node.meth.decl.output); 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, 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); auto t_field = ast_ty_to_ty(g, f.ty);
append[arg](t_inputs, rec(mode=ast.alias, ty=t_field)); 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; 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)); args += vec(rec(mode=ast.alias, ty=arg_ty));
} }
auto tag_t = plain_ty(ty.ty_tag(tag_id, ty_param_tys)); 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); 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] { fn get_ctor_obj_methods(@ty.t t) -> vec[method] {
alt (t.struct) { alt (t.struct) {
case (ty.ty_fn(_,?tobj)) { case (ty.ty_fn(_,_,?tobj)) {
alt (tobj.struct) { alt (tobj.struct) {
case (ty.ty_obj(?tm)) { case (ty.ty_obj(?tm)) {
ret 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 method meth_ty = meth_tys.(ix);
let ast.method_ m_; let ast.method_ m_;
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)); meth_ty.output));
m_ = rec(ann=ast.ann_type(meth_tfn) with meth.node); m_ = rec(ann=ast.ann_type(meth_tfn) with meth.node);
m = @rec(node=m_ with *meth); 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); check (subpats_len == 0u);
p_1 = ast.pat_tag(id, subpats, vdef_opt, ast.ann_type(t)); 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(); let vec[@ast.pat] new_subpats = vec();
auto i = 0u; auto i = 0u;
for (arg a in args) { 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); auto last_id = p.node.idents.(len - 1u);
alt (t.struct) { alt (t.struct) {
// N-ary variants have function types. // 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 arg_len = _vec.len[arg](args);
auto subpats_len = _vec.len[@ast.pat](subpats); auto subpats_len = _vec.len[@ast.pat](subpats);
if (arg_len != subpats_len) { 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)); 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 vec[arg] arg_tys_0 = ty.ty_fn_args(t_0);
let @ty.t rt_0 = ty.ty_fn_ret(t_0); let @ty.t rt_0 = ty.ty_fn_ret(t_0);
let vec[option.t[@ast.expr]] args_1 = vec(); 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; 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, ret @fold.respan[ast.expr_](expr.span,
ast.expr_bind(f_0, args_1, ast.expr_bind(f_0, args_1,
ast.ann_type(t_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))); append[arg](arg_tys_0, rec(mode=ast.val, ty=expr_ty(a_0)));
} }
auto rt_0 = next_ty_var(fcx.ccx); 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. // Unify and write back to the function.
auto f_1 = demand_expr(fcx, t_0, f_0); 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"); "bad index on obj");
} }
auto meth = methods.(ix); 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); auto ann = ast.ann_type(t);
ret @fold.respan[ast.expr_](expr.span, ret @fold.respan[ast.expr_](expr.span,
ast.expr_field(base_1, 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); ret @fold.respan[ast.item_](sp, item);
} }
fn check_fn(&@crate_ctxt ccx, &ast.fn_decl decl, fn check_fn(&@crate_ctxt ccx, &ast.fn_decl decl, &ast.block body) -> ast._fn {
bool is_iter, &ast.block body) -> ast._fn {
auto local_ty_table = @common.new_def_hash[@ty.t](); auto local_ty_table = @common.new_def_hash[@ty.t]();
// FIXME: duplicate work: the item annotation already has the arg types // 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_t = check_block(fcx, body);
auto block_wb = writeback(fcx, block_t); auto block_wb = writeback(fcx, block_t);
auto fn_t = rec(decl=decl, is_iter=is_iter, auto fn_t = rec(decl=decl,
body=block_wb); body=block_wb);
ret fn_t; 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 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 fn_ann = ast.ann_type(plain_ty(fn_sty));
auto item = ast.item_fn(ident, f, ty_params, id, fn_ann); 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](); auto fld = fold.new_identity_fold[@crate_ctxt]();
fld = @rec(update_env_for_item = bind update_obj_fields(_, _), 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(_,_,_,_,_,_,_) fold_item_fn = bind check_item_fn(_,_,_,_,_,_,_)
with *fld); with *fld);
ret fold.fold_crate[@crate_ctxt](ccx, fld, result._0); ret fold.fold_crate[@crate_ctxt](ccx, fld, result._0);