1 | const {compile, and, or, root, arg0, setter, splice} = require('../../index');
|
2 | const {
|
3 | describeCompilers,
|
4 | evalOrLoad,
|
5 | currentValues,
|
6 | funcLibrary,
|
7 | expectTapFunctionToHaveBeenCalled,
|
8 | rand
|
9 | } = require('../test-utils');
|
10 | const _ = require('lodash');
|
11 |
|
12 | describe('testing recursion', () => {
|
13 | describeCompilers(['simple', 'optimizing', 'bytecode'], compiler => {
|
14 | it('simple sum', () => {
|
15 | const model = {
|
16 | sum: root.recursiveMap((loop, val, key) =>
|
17 | key
|
18 | .gt(0)
|
19 | .ternary(val.plus(key.minus(1).recur(loop)), val)
|
20 | .call('tap', key)
|
21 | ),
|
22 | set: setter(arg0)
|
23 | };
|
24 | const optModel = evalOrLoad(compile(model, {compiler}));
|
25 | const inst = optModel([1, 2, 3, 4, 5], funcLibrary);
|
26 | expectTapFunctionToHaveBeenCalled(5, compiler);
|
27 | expect(inst.sum).toEqual([1, 3, 6, 10, 15]);
|
28 | inst.set(2, 13);
|
29 | expectTapFunctionToHaveBeenCalled(3, compiler);
|
30 | expect(inst.sum).toEqual([1, 3, 16, 20, 25]);
|
31 | });
|
32 | it('chains', () => {
|
33 | const model = {
|
34 | chain: root.recursiveMap((loop, val, key) =>
|
35 | val
|
36 | .gte(0)
|
37 | .ternary(val.recur(loop), val)
|
38 | .call('tap', key)
|
39 | ),
|
40 | set: setter(arg0)
|
41 | };
|
42 | const optModel = evalOrLoad(compile(model, {compiler}));
|
43 | const initialData = [1, 2, 3, -1, -2, 4];
|
44 | const inst = optModel(initialData, funcLibrary);
|
45 | expect(inst.chain).toEqual([-1, -1, -1, -1, -2, -2]);
|
46 | expectTapFunctionToHaveBeenCalled(6, compiler);
|
47 | inst.set(2, 5);
|
48 | expectTapFunctionToHaveBeenCalled(3, compiler);
|
49 | expect(inst.chain).toEqual([-2, -2, -2, -1, -2, -2]);
|
50 | });
|
51 | it('recursiveMapValues', () => {
|
52 | const model = {
|
53 | allDone: root.recursiveMapValues((loop, todo, idx) =>
|
54 | and(
|
55 | todo.get('done'),
|
56 | todo
|
57 | .get('subTasks')
|
58 | .any((idx, _, context) => idx.recur(context).not(), loop)
|
59 | .not()
|
60 | ).call('tap')
|
61 | ),
|
62 | setDone: setter(arg0, 'done'),
|
63 | spliceBlockedBy: splice(arg0, 'subTasks')
|
64 | };
|
65 | const optModel = evalOrLoad(compile(model, {compiler}));
|
66 | const initialData = {
|
67 | a: {done: true, subTasks: []},
|
68 | b: {done: false, subTasks: ['c']},
|
69 | c: {done: false, subTasks: ['d']},
|
70 | d: {done: true, subTasks: []},
|
71 | e: {done: false, subTasks: ['a', 'c']}
|
72 | };
|
73 | const inst = optModel(initialData, funcLibrary);
|
74 | expect(inst.allDone).toEqual({a: true, b: false, c: false, d: true, e: false});
|
75 | inst.setDone('c', true);
|
76 | expect(inst.allDone).toEqual({a: true, b: false, c: true, d: true, e: false});
|
77 | inst.setDone('d', false);
|
78 | expect(inst.allDone).toEqual({a: true, b: false, c: false, d: false, e: false});
|
79 | });
|
80 | it('join', () => {
|
81 | const initialData = ['a', 'b', 'c'];
|
82 | const model = {
|
83 | result: root.join('~')
|
84 | };
|
85 | const optModel = evalOrLoad(compile(model, {compiler}));
|
86 | const inst = optModel(initialData);
|
87 | expect(inst.result).toEqual('a~b~c');
|
88 | });
|
89 | it('join with empty array', () => {
|
90 | const initialData = [];
|
91 | const model = {
|
92 | result: root.join('~')
|
93 | };
|
94 | const optModel = evalOrLoad(compile(model, {compiler}));
|
95 | const inst = optModel(initialData);
|
96 | expect(inst.result).toEqual('');
|
97 | });
|
98 | it('reduce', () => {
|
99 | const model = {
|
100 | result: root.reduce((agg, value) => agg.plus(value).call('tap'), 0),
|
101 | set: setter(arg0)
|
102 | };
|
103 | const optModel = evalOrLoad(compile(model, {compiler}));
|
104 | const initialData = [1, 3, 5];
|
105 | const inst = optModel(initialData, funcLibrary);
|
106 | expect(inst.result).toEqual(9);
|
107 | expectTapFunctionToHaveBeenCalled(3, compiler);
|
108 | inst.set(2, 1);
|
109 | expect(inst.result).toEqual(5);
|
110 | expectTapFunctionToHaveBeenCalled(1, compiler);
|
111 | });
|
112 | it('reduce with empty array', () => {
|
113 | const model = {
|
114 | result: root.reduce((agg, value) => agg.plus(value).call('tap'), 0),
|
115 | set: setter(arg0)
|
116 | };
|
117 | const optModel = evalOrLoad(compile(model, {compiler}));
|
118 | const initialData = [];
|
119 | const inst = optModel(initialData, funcLibrary);
|
120 | expect(inst.result).toEqual(0);
|
121 | });
|
122 | });
|
123 | });
|