Handle the new ty_native_fn in type check.

This commit is contained in:
Rafael Ávila de Espíndola 2011-02-23 11:59:07 -05:00
parent 3b7e9dc393
commit 6849abcf7d
2 changed files with 96 additions and 25 deletions

View file

@ -346,6 +346,14 @@ fn fold_ty(ty_fold fld, @t ty) -> @t {
}
ret rewrap(ty, ty_fn(proto, new_args, fold_ty(fld, ret_ty)));
}
case (ty_native_fn(?args, ?ret_ty)) {
let vec[arg] new_args = vec();
for (arg a in args) {
auto new_ty = fold_ty(fld, a.ty);
new_args += vec(rec(mode=a.mode, ty=new_ty));
}
ret rewrap(ty, ty_native_fn(new_args, fold_ty(fld, ret_ty)));
}
case (ty_obj(?methods)) {
let vec[method] new_methods = vec();
for (method m in methods) {
@ -588,6 +596,7 @@ fn count_ty_params(@t ty) -> uint {
fn ty_fn_args(@t fty) -> vec[arg] {
alt (fty.struct) {
case (ty.ty_fn(_, ?a, _)) { ret a; }
case (ty.ty_native_fn(?a, _)) { ret a; }
}
}
@ -600,12 +609,14 @@ fn ty_fn_proto(@t fty) -> ast.proto {
fn ty_fn_ret(@t fty) -> @t {
alt (fty.struct) {
case (ty.ty_fn(_, _, ?r)) { ret r; }
case (ty.ty_native_fn(_, ?r)) { ret r; }
}
}
fn is_fn_ty(@t fty) -> bool {
alt (fty.struct) {
case (ty.ty_fn(_, _, _)) { ret true; }
case (ty.ty_native_fn(_, _)) { ret true; }
case (_) { ret false; }
}
ret false;
@ -826,24 +837,23 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
ret ures_err(terr_mismatch, expected, actual);
}
fn unify_fn(@hashmap[int,@ty.t] bindings,
ast.proto e_proto,
ast.proto a_proto,
@ty.t expected,
@ty.t actual,
&unify_handler handler,
vec[arg] expected_inputs, @t expected_output,
vec[arg] actual_inputs, @t actual_output)
-> unify_result {
if (e_proto != a_proto) {
ret ures_err(terr_mismatch, expected, actual);
}
tag fn_common_res {
fn_common_res_err(unify_result);
fn_common_res_ok(vec[arg], @t);
}
fn unify_fn_common(@hashmap[int,@ty.t] bindings,
@ty.t expected,
@ty.t actual,
&unify_handler handler,
vec[arg] expected_inputs, @t expected_output,
vec[arg] actual_inputs, @t actual_output)
-> fn_common_res {
auto expected_len = _vec.len[arg](expected_inputs);
auto actual_len = _vec.len[arg](actual_inputs);
if (expected_len != actual_len) {
ret ures_err(terr_arg_count, expected, actual);
ret fn_common_res_err(ures_err(terr_arg_count,
expected, actual));
}
// TODO: as above, we should have an iter2 iterator.
@ -874,7 +884,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
}
case (_) {
ret result;
ret fn_common_res_err(result);
}
}
@ -882,24 +892,67 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
}
// Check the output.
auto result_out;
auto result = unify_step(bindings,
expected_output,
actual_output,
handler);
alt (result) {
case (ures_ok(?rty)) {
result_out = rty;
ret fn_common_res_ok(result_ins, rty);
}
case (_) {
ret result;
ret fn_common_res_err(result);
}
}
}
auto t = plain_ty(ty.ty_fn(e_proto, result_ins, result_out));
ret ures_ok(t);
fn unify_fn(@hashmap[int,@ty.t] bindings,
ast.proto e_proto,
ast.proto a_proto,
@ty.t expected,
@ty.t actual,
&unify_handler handler,
vec[arg] expected_inputs, @t expected_output,
vec[arg] actual_inputs, @t actual_output)
-> unify_result {
if (e_proto != a_proto) {
ret ures_err(terr_mismatch, expected, actual);
}
auto t = unify_fn_common(bindings, expected, actual,
handler, expected_inputs, expected_output,
actual_inputs, actual_output);
alt (t) {
case (fn_common_res_err(?r)) {
ret r;
}
case (fn_common_res_ok(?result_ins, ?result_out)) {
auto t2 = plain_ty(ty.ty_fn(e_proto, result_ins, result_out));
ret ures_ok(t2);
}
}
}
fn unify_native_fn(@hashmap[int,@ty.t] bindings,
@ty.t expected,
@ty.t actual,
&unify_handler handler,
vec[arg] expected_inputs, @t expected_output,
vec[arg] actual_inputs, @t actual_output)
-> unify_result {
auto t = unify_fn_common(bindings, expected, actual,
handler, expected_inputs, expected_output,
actual_inputs, actual_output);
alt (t) {
case (fn_common_res_err(?r)) {
ret r;
}
case (fn_common_res_ok(?result_ins, ?result_out)) {
auto t2 = plain_ty(ty.ty_native_fn(result_ins, result_out));
ret ures_ok(t2);
}
}
}
fn unify_obj(@hashmap[int,@ty.t] bindings,
@ -1258,6 +1311,20 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
}
}
case (ty.ty_native_fn(?expected_inputs, ?expected_output)) {
alt (actual.struct) {
case (ty.ty_native_fn(?actual_inputs, ?actual_output)) {
ret unify_native_fn(bindings,
expected, actual, handler,
expected_inputs, expected_output,
actual_inputs, actual_output);
}
case (_) {
ret ures_err(terr_mismatch, expected, actual);
}
}
}
case (ty.ty_obj(?expected_meths)) {
alt (actual.struct) {
case (ty.ty_obj(?actual_meths)) {

View file

@ -1336,18 +1336,21 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
}
}
auto proto_0 = ast.proto_fn; // FIXME: typestate botch
auto rt_0 = next_ty_var(fcx.ccx);
auto t_0 = plain_ty(ty.ty_uint); // FIXME: typestate botch
alt (expr_ty(f_0).struct) {
case (ty.ty_fn(?proto, _, _)) { proto_0 = proto; }
case (ty.ty_fn(?proto, _, _)) {
t_0 = plain_ty(ty.ty_fn(proto, arg_tys_0, rt_0));
}
case (ty.ty_native_fn(_, _)) {
t_0 = plain_ty(ty.ty_native_fn(arg_tys_0, rt_0));
}
case (_) {
log "check_call_or_bind(): fn expr doesn't have fn type";
fail;
}
}
auto rt_0 = next_ty_var(fcx.ccx);
auto t_0 = plain_ty(ty.ty_fn(proto_0, arg_tys_0, rt_0));
// Unify and write back to the function.
auto f_1 = demand_expr(fcx, t_0, f_0);
@ -1824,6 +1827,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
auto rt_1 = plain_ty(ty.ty_nil); // FIXME: typestate botch
alt (expr_ty(result._0).struct) {
case (ty.ty_fn(_,_,?rt)) { rt_1 = rt; }
case (ty.ty_native_fn(_,?rt)) { rt_1 = rt; }
case (_) {
log "LHS of call expr didn't have a function type?!";
fail;