aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/comp/middle/ty.rs107
-rw-r--r--src/comp/middle/typeck.rs14
2 files changed, 96 insertions, 25 deletions
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index 68c21140..0f277329 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -346,6 +346,14 @@ fn fold_ty(ty_fold fld, @t ty) -> @t {
}
ret rewrap(ty, ty_fn(proto, new_args, fold_ty(fld, ret_ty)));
}
+ case (ty_native_fn(?args, ?ret_ty)) {
+ let vec[arg] new_args = vec();
+ for (arg a in args) {
+ auto new_ty = fold_ty(fld, a.ty);
+ new_args += vec(rec(mode=a.mode, ty=new_ty));
+ }
+ ret rewrap(ty, ty_native_fn(new_args, fold_ty(fld, ret_ty)));
+ }
case (ty_obj(?methods)) {
let vec[method] new_methods = vec();
for (method m in methods) {
@@ -588,6 +596,7 @@ fn count_ty_params(@t ty) -> uint {
fn ty_fn_args(@t fty) -> vec[arg] {
alt (fty.struct) {
case (ty.ty_fn(_, ?a, _)) { ret a; }
+ case (ty.ty_native_fn(?a, _)) { ret a; }
}
}
@@ -600,12 +609,14 @@ fn ty_fn_proto(@t fty) -> ast.proto {
fn ty_fn_ret(@t fty) -> @t {
alt (fty.struct) {
case (ty.ty_fn(_, _, ?r)) { ret r; }
+ case (ty.ty_native_fn(_, ?r)) { ret r; }
}
}
fn is_fn_ty(@t fty) -> bool {
alt (fty.struct) {
case (ty.ty_fn(_, _, _)) { ret true; }
+ case (ty.ty_native_fn(_, _)) { ret true; }
case (_) { ret false; }
}
ret false;
@@ -826,24 +837,23 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
ret ures_err(terr_mismatch, expected, actual);
}
- fn unify_fn(@hashmap[int,@ty.t] bindings,
- ast.proto e_proto,
- ast.proto a_proto,
- @ty.t expected,
- @ty.t actual,
- &unify_handler handler,
- vec[arg] expected_inputs, @t expected_output,
- vec[arg] actual_inputs, @t actual_output)
- -> unify_result {
-
- if (e_proto != a_proto) {
- ret ures_err(terr_mismatch, expected, actual);
- }
+ tag fn_common_res {
+ fn_common_res_err(unify_result);
+ fn_common_res_ok(vec[arg], @t);
+ }
+ fn unify_fn_common(@hashmap[int,@ty.t] bindings,
+ @ty.t expected,
+ @ty.t actual,
+ &unify_handler handler,
+ vec[arg] expected_inputs, @t expected_output,
+ vec[arg] actual_inputs, @t actual_output)
+ -> fn_common_res {
auto expected_len = _vec.len[arg](expected_inputs);
auto actual_len = _vec.len[arg](actual_inputs);
if (expected_len != actual_len) {
- ret ures_err(terr_arg_count, expected, actual);
+ ret fn_common_res_err(ures_err(terr_arg_count,
+ expected, actual));
}
// TODO: as above, we should have an iter2 iterator.
@@ -874,7 +884,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
}
case (_) {
- ret result;
+ ret fn_common_res_err(result);
}
}
@@ -882,24 +892,67 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
}
// Check the output.
- auto result_out;
auto result = unify_step(bindings,
expected_output,
actual_output,
handler);
alt (result) {
case (ures_ok(?rty)) {
- result_out = rty;
+ ret fn_common_res_ok(result_ins, rty);
}
case (_) {
- ret result;
+ ret fn_common_res_err(result);
}
}
+ }
- auto t = plain_ty(ty.ty_fn(e_proto, result_ins, result_out));
- ret ures_ok(t);
+ fn unify_fn(@hashmap[int,@ty.t] bindings,
+ ast.proto e_proto,
+ ast.proto a_proto,
+ @ty.t expected,
+ @ty.t actual,
+ &unify_handler handler,
+ vec[arg] expected_inputs, @t expected_output,
+ vec[arg] actual_inputs, @t actual_output)
+ -> unify_result {
+ if (e_proto != a_proto) {
+ ret ures_err(terr_mismatch, expected, actual);
+ }
+ auto t = unify_fn_common(bindings, expected, actual,
+ handler, expected_inputs, expected_output,
+ actual_inputs, actual_output);
+ alt (t) {
+ case (fn_common_res_err(?r)) {
+ ret r;
+ }
+ case (fn_common_res_ok(?result_ins, ?result_out)) {
+ auto t2 = plain_ty(ty.ty_fn(e_proto, result_ins, result_out));
+ ret ures_ok(t2);
+ }
+ }
+ }
+
+ fn unify_native_fn(@hashmap[int,@ty.t] bindings,
+ @ty.t expected,
+ @ty.t actual,
+ &unify_handler handler,
+ vec[arg] expected_inputs, @t expected_output,
+ vec[arg] actual_inputs, @t actual_output)
+ -> unify_result {
+ auto t = unify_fn_common(bindings, expected, actual,
+ handler, expected_inputs, expected_output,
+ actual_inputs, actual_output);
+ alt (t) {
+ case (fn_common_res_err(?r)) {
+ ret r;
+ }
+ case (fn_common_res_ok(?result_ins, ?result_out)) {
+ auto t2 = plain_ty(ty.ty_native_fn(result_ins, result_out));
+ ret ures_ok(t2);
+ }
+ }
}
fn unify_obj(@hashmap[int,@ty.t] bindings,
@@ -1258,6 +1311,20 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
}
}
+ case (ty.ty_native_fn(?expected_inputs, ?expected_output)) {
+ alt (actual.struct) {
+ case (ty.ty_native_fn(?actual_inputs, ?actual_output)) {
+ ret unify_native_fn(bindings,
+ expected, actual, handler,
+ expected_inputs, expected_output,
+ actual_inputs, actual_output);
+ }
+ case (_) {
+ ret ures_err(terr_mismatch, expected, actual);
+ }
+ }
+ }
+
case (ty.ty_obj(?expected_meths)) {
alt (actual.struct) {
case (ty.ty_obj(?actual_meths)) {
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 8f19e3ad..0d583c5e 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -1336,18 +1336,21 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
}
}
- auto proto_0 = ast.proto_fn; // FIXME: typestate botch
+ auto rt_0 = next_ty_var(fcx.ccx);
+ auto t_0 = plain_ty(ty.ty_uint); // FIXME: typestate botch
alt (expr_ty(f_0).struct) {
- case (ty.ty_fn(?proto, _, _)) { proto_0 = proto; }
+ case (ty.ty_fn(?proto, _, _)) {
+ t_0 = plain_ty(ty.ty_fn(proto, arg_tys_0, rt_0));
+ }
+ case (ty.ty_native_fn(_, _)) {
+ t_0 = plain_ty(ty.ty_native_fn(arg_tys_0, rt_0));
+ }
case (_) {
log "check_call_or_bind(): fn expr doesn't have fn type";
fail;
}
}
- auto rt_0 = next_ty_var(fcx.ccx);
- auto t_0 = plain_ty(ty.ty_fn(proto_0, arg_tys_0, rt_0));
-
// Unify and write back to the function.
auto f_1 = demand_expr(fcx, t_0, f_0);
@@ -1824,6 +1827,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
auto rt_1 = plain_ty(ty.ty_nil); // FIXME: typestate botch
alt (expr_ty(result._0).struct) {
case (ty.ty_fn(_,_,?rt)) { rt_1 = rt; }
+ case (ty.ty_native_fn(_,?rt)) { rt_1 = rt; }
case (_) {
log "LHS of call expr didn't have a function type?!";
fail;