-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathfli.js
327 lines (274 loc) · 5.65 KB
/
fli.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
/* Not implemented:
All the nondet foreign stuff. That is supported, but not using the SWI-Prolog interface
Strings
Floats
Pointers
PL_get_chars
PL_predicate_info
PL_copy_term_ref
PL_reset_term_refs
*/
function PL_new_term_ref()
{
// FIXME: Should this go on the heap or the stack?
return alloc_var();
}
function PL_new_term_refs(n)
{
var first = alloc_var();
for (i = 0; i < n-1; i++)
alloc_var();
}
function PL_succeed()
{
return true;
}
function PL_fail()
{
return true;
}
function PL_new_atom(chars)
{
return lookup_atom(chars);
}
function PL_atom_chars(atom)
{
return atable[VAL(atom)];
}
function PL_new_functor(name, arity)
{
return lookup_functor(atable[name], arity);
}
function PL_functor_name(ftor)
{
return ftable[VAL(ftor)][0];
}
function PL_functor_arity(ftor)
{
return ftable[VAL(ftor)][1];
}
function PL_term_type(term)
{
return TAG(term);
}
function PL_is_variable(term)
{
return TAG(term) == TAG_REF;
}
function PL_is_atom(term)
{
return TAG(term) == TAG_ATM;
}
function PL_is_integer(term)
{
return TAG(term) == TAG_INT;
}
function PL_is_compound(term)
{
return TAG(term) == TAG_STR;
}
function PL_is_functor(term, ftor)
{
return TAG(term) == TAG_STR && memory[VAL(term)] == ftor;
}
function PL_is_list(term)
{
return TAG(term) == TAG_LST;
}
function PL_is_atomic(term)
{
return TAG(term) != TAG_STR && TAG(term) != TAG_REF;
}
function PL_is_number(term)
{
return TAG(term) == TAG_INT; // At the moment
}
function PL_get_atom(term)
{
if (TAG(term) == TAG_ATM)
return atom;
throw("type_error: atom");
}
function PL_get_atom_chars(term)
{
if (TAG(term) == TAG_ATOM)
return atable[VAL(term)];
throw("type_error: atom");
}
function PL_get_integer(term)
{
if (TAG(term) == TAG_INT)
return VAL(term);
throw("type_error: integer");
}
function PL_get_functor(term)
{
if (TAG(term) == TAG_STR)
return memory[VAL(term)];
throw("type_error: term");
}
function PL_get_arg(index, term)
{
if (index < 1)
throw("domain_error: term arity");
if (TAG(term) == TAG_STR)
{
if (index > ftable[VAL(memory[VAL(term)])][1]) // Check arity is OK
throw("type_error: term arity");
return memory[VAL(term) + index];
}
throw("type_error: term");
}
// Returns an object with head and tail keys
function PL_get_list(list)
{
if (TAG(list) == TAG_LST)
return {head: memory[VAL(list)],
tail: memory[VAL(list)+1]};
return null;
}
function PL_get_head(list)
{
if (TAG(list) == TAG_LST)
return memory[VAL(list)];
return null;
}
function PL_get_tail(list)
{
if (TAG(list) == TAG_LST)
return memory[VAL(list)+1];
return null;
}
function PL_get_nil()
{
return NIL;
}
function PL_put_variable()
{
return alloc_var();
}
function PL_put_atom(atom)
{
return atom;
}
function PL_put_atom_chars(chars)
{
return lookup_atom(chars);
}
function PL_put_integer(integer)
{
return integer ^ (TAG_INT << WORD_BITS);
}
function PL_put_functor(term, ftor)
{
var r = alloc_structure(ftor);
for (i = 0; i < ftable[VAL(ftor)][1]; i++)
alloc_var();
}
function PL_put_list()
{
var r = alloc_list();
alloc_var();
alloc_var();
}
function PL_put_nil()
{
return NIL;
}
function PL_cons_functor(ftor)
{
if (state.H + arguments.length + 1 >= HEAP_SIZE)
return false; // Not enough heap
var r = state.H ^ (TAG_STR << WORD_BITS);
memory[state.H++] = ftor;
for (i = 1; i < arguments.length; i++)
memory[state.H++] = arguments[i];
}
function PL_cons_list(head, tail)
{
if (state.H +2 >= HEAP_SIZE)
return false;
var result = state.H ^ (TAG_LST << WORD_BITS);
memory[state.H++] = head;
memory[state.H++] = tail;
return result;
}
function PL_unify_integer(term, integer)
{
return unify(term, integer ^ (TAG_INT << WORD_BITS));
}
function PL_unify_atom_chars(term, chars)
{
return unify(term, lookup_atom(string));
}
function PL_unify(t1, t2)
{
return unify(t1, t2);
}
function PL_unify_atom(term, atom)
{
return unify(term, atom);
}
function PL_unify_nil(term)
{
return unify(term, NIL);
}
function PL_unify_arg(index, term, arg)
{
return unify(memory[VAL(term) + 1 + index], arg);
}
function PL_unify_list(list, head, tail)
{
return (TAG(list) == TAG_LST) && unify(memory[VAL(list)], head) && unify(memory[VAL(list) + 1], tail);
}
function PL_pred(ftor, module)
{
if (predicates[ftor] === undefined)
throw("Undefined predicate");
return ftor;
}
function PL_predicate(name, arity, module)
{
return PL_pred(lookup_functor(name, arity), module);
}
function PL_open_query(module, debug, predicate, args)
{
initialize();
allocate_first_frame();
state.P = predicates[predicate];
for (i = 0; i < ftable[predicate][1]; i++)
register[i] = args[i];
return {fresh:true};
}
function PL_next_solution(qid)
{
if (!qid.fresh)
backtrack();
qid.fresh = false;
return wam();
}
function PL_call(term, module)
{
ftor = VAL(memory[VAL(term)]);
initialize();
allocate_first_frame();
state.P = predicates[ftor];
for (i = 0; i < ftable[ftor][1]; i++)
register[i] = memory[VAL(term) + 1 + i];
return wam();
}
function PL_cut_query(qid)
{
// This is not implemented
}
function PL_close_query(qid)
{
// This is not implemented either
}
function PL_call_predicate(module, debug, predicate, args)
{
var qid = PL_open_query(module, debug, predicate, args);
var result = PL_next_solution(qid);
PL_cut_query(qud);
return result;
}