forked from rulespace/rulespace
-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.js
141 lines (104 loc) · 3.29 KB
/
utils.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import { str2sexp } from "./str2sexp.js";
import { sexp2rsp } from "./sexp2rsp.js";
import { rsp2js } from "./rsp2js.js";
export function compileToRsp(src)
{
const sexp = str2sexp(src);
const rsp = sexp2rsp(sexp);
return rsp;
}
export function compileToConstructor(src, options)
{
const rsp = compileToRsp(src);
const compiled = rsp2js(rsp, {...options, module:false});
return Function(compiled);
}
export function compileToModuleSrc(src, options)
{
const rsp = compileToRsp(src);
const compiled = rsp2js(rsp, {...options, module:true});
return compiled;
}
//////////// unstable, experimental
export function reactive(instanceCtr, deltaObservers)
{
return function ()
{
function notify(delta)
{
deltaObservers.forEach(observer => observer.observe(instance, delta));
return delta;
}
const instance = instanceCtr();
notify({
added() {return instance.toTupleMap(instance.tuples())},
removed() {return new Map()}
});
function wrap(method)
{
return function (...args)
{
const delta = method.apply(instance, args);
notify(delta);
return delta;
}
}
const intercept = ['addTupleMap', 'addTuples', 'removeTupleMap', 'removeTuples'];
const wrappedMethods = new Map(intercept.map(name =>
[name, wrap(instance[name])]
));
return new Proxy(instance, {
get: function (target, prop)
{
return wrappedMethods.get(prop) ?? Reflect.get(target, prop);
}
})
}
}
// // linear composition of instances
// export function linear(instances)
// {
// if (instances.length === 1)
// {
// return instances[0];
// }
// const rest = linear.call(null, instances.slice(1));
// const ds = deltaSource(instances[0]);
// ds.addDeltaObserver(rest.computeDelta);
// return rest;
// }
export function computeMeta(instance) // single-shot
{
const src = `
(rule [TupleLink t1 t2] [Tuple2Product t1 p] [Product2Tuple p t2])
(rule [Tuple t1 pred] [TupleLink t1 _] (:= pred (Reflect.get (Reflect.get t1 "constructor") "name")))
(rule [Tuple t2 pred] [TupleLink _ t2] (:= pred (Reflect.get (Reflect.get t2 "constructor") "name")))
`;
const ctr = compileToConstructor(src);
const meta = ctr();
visitNodes(instance, instance.tuples(),
tuple => meta.addTuples(instance.outProducts(tuple).map(p => new meta.Tuple2Product(tuple, p))),
product => meta.addTuples([instance.outTuple(product)].map(t => new meta.Product2Tuple(product, t)))
);
return meta;
}
//// constructor composition
//// instance composition
// export function metaSpace(instance)
// {
// const src = `
// (rule [TupleLink t1 t2] [Tuple2Product t1 p] [Product2Tuple p t2])
// (rule [Tuple t1] [TupleLink t1 _])
// (rule [Tuple t2] [TupleLink _ t2])
// `;
// const ctr = compileToConstructor(src);
// const meta = ctr();
// const initialMetaMap = new Map();
// visitLinks(meta, meta.tuples(),
// (tuple, product) => MutableMaps.putPushArray(initialMetaMap, meta.Tuple2Product, new meta.Tuple2Product(tuple, product)),
// (product, tuple) => MutableMaps.putPushArray(initialMetaMap, meta.Product2Tuple, new meta.Product2Tuple(product, tuple)))
// const initialDelta =
// const compoundInstance = {
// }
// return { initialDelta, compoundInstance }
// }