Ken Wakita (https://wakita.github.io/fp2018/)
Nov 1, 2018
Assume no optimization is performed
f
)
x
and y
) as well as Free variables (a
and b
)Issue: How do we emulate FP-style function application in C-style syntax?
let apply_2args_2freevars closure arg1 arg2 =
let a_function_implementation, (fv1, fv2) = closure in
a_function_implementation arg1 arg2 fv1 fv2 in
let rec f_implementation x y a b =
a * x + b * y in
let a = 3 in
let b = 4 in
let closure = (f_implementation, (a, b)) in
Printf.printf "Closure-call: %d\n" (apply_2args_2freevars closure 5 6)
typedef int (*IntInt_IntInt_Int)(int, int, int, int);
typedef IntInt_IntInt_Int Implementation;
// { Args: (Int, Int), FreeVars: (Int, Int) } -> Int
typedef struct Closure_IntInt_IntInt_Int {
Implementation implementation;
int fv1; int fv2;
} Closure;
\[\begin {align} {\cal C}: \text {KNormal.t} &\rightarrow \text {Closure.t} \\ {\cal C}(e: \text {KNormal.t}) &= p: \text {Closure.t} \end {align}\]
\[\begin {align} {\cal C}(x\ y_1 \ldots y_n) = \mathit {apply\_closure}(x, y_1, \ldots, y_n) \end {align}\]
Convert function definitions to closure allocations. (Fig. 14 of overview.pdf
)
\[\begin {align} {\cal C}(\text {let rec } &x\ y_1 \ldots y_n = e_1 \text { in } e_2 = \\ & {\cal D} \text { += } \mathtt {L}_x(y_1, \ldots, y_n)(z_1, \ldots, z_m) = e_1'; \\ & \mathit {make\_closure}\ x = (\mathtt {L}_x, (z_1, \ldots, z_m)) \text { in } e_2' \\ & \text {where } e_1' = {\cal C}(e_1), e_2' = {\cal C}(e_2),\\ & \text {and } \{z_1, \ldots, z_m\} = \mathit {FV}(e_1') \setminus \{x, y_1, \ldots, y_n\} \end {align}\]
\[{\cal C}(x\ y_1\ \ldots\ y_n) = \mathit {apply\_closure}(x, y_1, \ldots, y_n)\]
\[\begin {align} {\cal C}&: \text {S.t} \rightarrow \text {KNormal.t} \rightarrow \text {Closure.t} \\ s&: \text {The set of known closed functions} \end {align}\]
A closured function is a function that does not reference any free variable.
\[{\cal C}_s(e: \text {KNormal.t}) = p: \text {Closure.t}\]
\[\begin {align} {\cal C}_s&(\text {let rec } x\ y_1 \ldots y_n = e_1 \text { in } e_2 = \\ & {\cal D} \text { += } \mathtt {L}_x(y_1, \ldots, y_n)(z_1, \ldots, z_m) = e_1'; \\ & \begin {cases} \mathit {make\_closure}\ x = (\mathtt {L}_x, ()) \text { in } e_2' \\ \text {where } e_1' = {\cal C}_{s'}(e_1), e_2' = {\cal C}_{s'}(e_2), \\ \text {and } s' = s \cup \{ x \} & \text {when } \mathit {FV}(e_1') \setminus \{y_1, \ldots, y_n\} = \emptyset \\ \\ \mathit {make\_closure}\ x = (\mathtt {L}_x, (z_1, \ldots, z_m)) \text { in } e_2' \\ \text {where } e_1' = {\cal C}_s(e_1), e_2' = {\cal C}_s(e_2),\\ \text {and } \{z_1, \ldots, z_m\} = \mathit {FV}(e_1') \setminus \{x, y_1, \ldots, y_n\} & \text {otherwise} \end {cases} \end {align}\]
\[\begin {align} {\cal C}_s(x\ y_1\ldots y_n) &= \begin {cases} \mathit {apply\_closure}(x, y_1, \ldots, y_n) & x \not\in s \\ \mathit {apply\_direct}(\mathtt {L}_x, y_1, \ldots, y_n) & x \in s \end {cases} \end {align}\]
make_closure
)