diff options
author | Gabriel Scherer <gabriel.scherer@gmail.com> | 2021-10-18 10:17:45 +0200 |
---|---|---|
committer | Gabriel Scherer <gabriel.scherer@gmail.com> | 2021-11-02 15:42:55 +0100 |
commit | 9242408e05e9c19ee9c9fd4f706d48b5662e6efa (patch) | |
tree | f56a1742f73a2e9073137fdbb22510f6c7023b14 /lambda/tmc.ml | |
parent | 1daea333b616ae5c55566bb6f2283f92df41331d (diff) | |
download | ocaml-9242408e05e9c19ee9c9fd4f706d48b5662e6efa.tar.gz |
TMC: support Tupled functions and partial applications
Partial applications are obviously not considered TMC calls, but this
is also the case for direct calls to Tupled functions that do not take
a direct tuple literal, but another tuple value.
Diffstat (limited to 'lambda/tmc.ml')
-rw-r--r-- | lambda/tmc.ml | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/lambda/tmc.ml b/lambda/tmc.ml index 45197c847d..36e01880e9 100644 --- a/lambda/tmc.ml +++ b/lambda/tmc.ml @@ -520,6 +520,7 @@ type context = { and specialized = { arity: int; dps_id: Ident.t; + direct_kind: function_kind; } let find_candidate = function @@ -532,7 +533,8 @@ let declare_binding ctx (var, def) = | Some lfun -> let arity = List.length lfun.params in let dps_id = Ident.create_local (Ident.name var ^ "_dps") in - let cand = { arity; dps_id } in + let direct_kind = lfun.kind in + let cand = { arity; dps_id; direct_kind; } in { specialized = Ident.Map.add var cand ctx.specialized } let rec choice ctx t = @@ -648,11 +650,24 @@ let rec choice ctx t = Warnings.Tmc_breaks_tailcall; raise No_tmc in + let args = + (* Support of tupled functions: the [function_kind] of the + direct-style function is identical to the one of the + input function, which may be Tupled, but the dps + function is always Curried. + + [find_exact_application] is in charge of recovering the + "real" argument list of a possibly-tupled call. *) + let kind, arity = specialized.direct_kind, specialized.arity in + match Lambda.find_exact_application kind ~arity apply.ap_args with + | None -> raise No_tmc + | Some args -> args + in { Choice.dps = Dps.make (fun ~tail ~dst -> Lapply { apply with ap_func = Lvar specialized.dps_id; - ap_args = add_dst_args dst apply.ap_args; + ap_args = add_dst_args dst args; ap_tailcall = if tail then Tailcall_expectation true @@ -823,7 +838,10 @@ and traverse_binding ctx (var, def) = loc = lfun.loc; } in let dst_lam = { dst with offset = Lvar dst.offset } in - Lambda.duplicate @@ Lfunction { lfun with (* TODO check function_kind *) + Lambda.duplicate @@ Lfunction { lfun with + kind = + (* Support of Tupled function: see [choice_apply]. *) + Curried; params = add_dst_params dst lfun.params; body = Choice.dps ~tail:true ~dst:dst_lam fun_choice; } in |