Skip to content

Commit 1e2803c

Browse files
committed
add a test case
1 parent 1ed21d1 commit 1e2803c

File tree

3 files changed

+168
-0
lines changed

3 files changed

+168
-0
lines changed

jscomp/test/build.ninja

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,7 @@ build test/tfloat_record_test.cmi test/tfloat_record_test.cmj : cc test/tfloat_r
704704
build test/ticker.cmi test/ticker.cmj : cc test/ticker.ml | $stdlib
705705
build test/to_string_test.cmi test/to_string_test.cmj : cc test/to_string_test.ml | test/mt.cmj $stdlib
706706
build test/topsort_test.cmi test/topsort_test.cmj : cc test/topsort_test.ml | $stdlib
707+
build test/tramp_fib.cmi test/tramp_fib.cmj : cc test/tramp_fib.ml | test/mt.cmj $stdlib
707708
build test/tscanf_test.cmi test/tscanf_test.cmj : cc test/tscanf_test.ml | test/mt.cmj test/mt_global.cmj test/testing.cmj $stdlib
708709
build test/tuple_alloc.cmi test/tuple_alloc.cmj : cc test/tuple_alloc.ml | $stdlib
709710
build test/typeof_test.cmi test/typeof_test.cmj : cc test/typeof_test.ml | test/mt.cmj $stdlib

jscomp/test/tramp_fib.js

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
'use strict';
2+
3+
var Mt = require("./mt.js");
4+
5+
var suites = {
6+
contents: /* [] */0
7+
};
8+
9+
var test_id = {
10+
contents: 0
11+
};
12+
13+
function eq(loc, x, y) {
14+
return Mt.eq_suites(test_id, suites, loc, x, y);
15+
}
16+
17+
function fib(n, k) {
18+
if (n === 0 || n === 1) {
19+
return k(1);
20+
} else {
21+
return {
22+
TAG: /* Suspend */1,
23+
_0: (function () {
24+
return fib(n - 1 | 0, (function (v0) {
25+
return fib(n - 2 | 0, (function (v1) {
26+
return k(v0 + v1 | 0);
27+
}));
28+
}));
29+
})
30+
};
31+
}
32+
}
33+
34+
var u = fib(10, (function (x) {
35+
return {
36+
TAG: /* Continue */0,
37+
_0: x
38+
};
39+
}));
40+
41+
function iter(_bounce) {
42+
while(true) {
43+
var bounce = _bounce;
44+
if (!bounce.TAG) {
45+
return bounce._0;
46+
}
47+
_bounce = bounce._0();
48+
continue ;
49+
};
50+
}
51+
52+
function isEven(n) {
53+
if (n !== 0) {
54+
if (n !== 1) {
55+
return {
56+
TAG: /* Suspend */1,
57+
_0: (function () {
58+
return isOdd(n - 1 | 0);
59+
})
60+
};
61+
} else {
62+
return {
63+
TAG: /* Continue */0,
64+
_0: false
65+
};
66+
}
67+
} else {
68+
return {
69+
TAG: /* Continue */0,
70+
_0: true
71+
};
72+
}
73+
}
74+
75+
function isOdd(n) {
76+
if (n !== 0) {
77+
if (n !== 1) {
78+
return isEven(n - 1 | 0);
79+
} else {
80+
return {
81+
TAG: /* Continue */0,
82+
_0: true
83+
};
84+
}
85+
} else {
86+
return {
87+
TAG: /* Continue */0,
88+
_0: false
89+
};
90+
}
91+
}
92+
93+
eq("File \"tramp_fib.ml\", line 56, characters 6-13", iter(u), 89);
94+
95+
eq("File \"tramp_fib.ml\", line 58, characters 6-13", iter(isEven(20000)), true);
96+
97+
Mt.from_pair_suites("File \"tramp_fib.ml\", line 60, characters 23-30", suites.contents);
98+
99+
exports.suites = suites;
100+
exports.test_id = test_id;
101+
exports.eq = eq;
102+
exports.fib = fib;
103+
exports.u = u;
104+
exports.iter = iter;
105+
exports.isEven = isEven;
106+
exports.isOdd = isOdd;
107+
/* u Not a pure module */

jscomp/test/tramp_fib.ml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
[@@@bs.config {flags = [|"-w";"a";"-bs-noassertfalse"|]}]
2+
3+
let suites : Mt.pair_suites ref = ref []
4+
let test_id = ref 0
5+
let eq loc x y = Mt.eq_suites ~test_id ~suites loc x y
6+
7+
8+
type 'a bounce = Continue of 'a | Suspend of (unit -> 'a bounce [@bs])
9+
(* https://eli.thegreenplace.net/2017/on-recursion-continuations-and-trampolines/ *)
10+
(* http://gallium.inria.fr/seminaires/transparents/20141027.Frederic.Bour.pdf *)
11+
(* http://www.usrsb.in/blog/blog/2012/08/12/bouncing-pythons-generators-with-a-trampoline/ *)
12+
(* http://glat.info/jscheck/tomrec.html *)
13+
let rec fib n k =
14+
match n with
15+
| 0 | 1 ->
16+
(* k (Continue 1) [@bs] *)
17+
(* Suspend (fun [@bs]() -> k (Continue 1 ) [@bs]) *)
18+
k 1 [@bs]
19+
| _ ->
20+
Suspend (fun [@bs] () ->
21+
fib (n-1) (fun [@bs] v0 ->
22+
fib (n-2) (fun [@bs] v1 ->
23+
k (v0 + v1) [@bs]
24+
(* match v0,v1 with
25+
| Continue v0, Continue v1 -> *)
26+
(* k (Continue (v0 + v1)) [@bs] *)
27+
(* Suspend (fun [@bs]() -> k (Continue (v0 + v1)) [@bs]) *)
28+
(* | _ -> assert false *)
29+
(* FIXME: this branch completly gone*)
30+
)
31+
)
32+
)
33+
34+
let u = fib 10 (fun [@bs] x -> Continue x)
35+
36+
37+
let rec iter (bounce : 'a bounce) : 'a =
38+
match bounce with
39+
| Continue v -> v
40+
| Suspend f -> iter (f () [@bs])
41+
42+
43+
(* first it needs to be tailcall *)
44+
let rec isEven n =
45+
match n with
46+
| 0 -> Continue true
47+
| 1 -> Continue false
48+
| _ -> Suspend (fun [@bs] () -> isOdd (n - 1))
49+
and isOdd n =
50+
match n with
51+
| 0 -> Continue false
52+
| 1 -> Continue true
53+
| _ ->
54+
isEven (n - 1)
55+
(* Suspend (fun [@bs] () -> isEven (n - 1)) *)
56+
;; eq __LOC__ (iter u) 89
57+
58+
;; eq __LOC__ (isEven 20_000 |. iter ) true
59+
60+
;; Mt.from_pair_suites __LOC__ !suites

0 commit comments

Comments
 (0)