#include "share/atspre_staload.hats"
symintr memo
extern fun {o:t@ype} memo0 (() -> o): () -> o
extern fun {i,o:t@ype} memo1 (i -> o): i -> o
extern fun {i1,i2,o:t@ype} memo2 ((i1, i2) -> o): (i1, i2) -> o
overload memo with memo0
overload memo with memo1
overload memo with memo2
implement {o} memo0 (f) = let
val p = f ()
in
lam () => p
end
implement {i,o} memo1 (f) = let
staload "libats/ML/SATS/funmap.sats"
staload _ = "libats/ML/DATS/funmap.dats"
staload _ = "libats/DATS/funmap_avltree.dats"
val table = ref<map(i,o)> (funmap_nil ())
in
lam a =>
case+ funmap_search (!table, a) of
| ~Some_vt p => p
| ~None_vt _ => let
val p = f a
var t = !table
val- ~None_vt _ = funmap_insert (t, a, p)
val _ = !table := t
in
p
end
end
implement {i1,i2,o} memo2 (f) = let
staload "libats/ML/SATS/funmap.sats"
staload _ = "libats/ML/DATS/funmap.dats"
staload _ = "libats/DATS/funmap_avltree.dats"
val table = ref<map(@(i1,i2),o)> (funmap_nil ())
in
lam (a, b) =>
case+ funmap_search (!table, @(a, b)) of
| ~Some_vt p => p
| ~None_vt _ => let
val p = f (a, b)
var t = !table
val- ~None_vt _ = funmap_insert (t, @(a, b), p)
val _ = !table := t
in
p
end
end
extern fun {} add (int, int): int
implement {} add = memo (lam (x:int, y:int):int => x + y)
implement main0 () = print (add (1, 2))