-
Notifications
You must be signed in to change notification settings - Fork 0
/
JScriptLog_Types.js
357 lines (278 loc) · 7.85 KB
/
JScriptLog_Types.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
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
/*******
This file is part of JScriptLog. This notice must remain.
Created by Glendon Holst. Copyright 2005.
JLog is free software licensed under the GNU General Public License.
See the included LICENSE.txt and GNU.txt files.
Check <http://jlogic.sourceforge.net/> for further information.
*******/
///////////////////////////////////
// * Type objects
///////////////////////////////////
var TYPE_ATOM = 1;
var TYPE_NUMBER = 2;
var TYPE_VARIABLE = 3; // children[0] is the index into the Enclosure
var TYPE_OBJECT = 4; // name is an object reference
// type is one of the TYPE_* values,
// name is the name of the term (typically the predicate or function symbol),
// The default is a term with no children.
function Term(type, name)
{
this.type = type;
this.name = name;
this.children = new Array();
//// Other Properties (document here):
// this.ruleset : the ruleset ruleset associated with the term
// this.goal_type : the TYPE_*_GOAL associated with the term
return this;
}
function newAtom(name,terms)
{var term = new Term(TYPE_ATOM,name);
term.children = terms;
return term;
}
function newConstant(name)
{
return new Term(TYPE_ATOM,name);
}
function newNumber(value)
{
return new Term(TYPE_NUMBER,parseFloat(value));
}
function newVariable(name)
{
return new Term(TYPE_VARIABLE,name);
}
function newObjectReference(obj)
{
return new Term(TYPE_OBJECT,obj);
}
function newConsPair(lhs,rhs)
{var term = new Term(TYPE_ATOM,',');
term.children[0] = lhs;
term.children[1] = rhs;
return term;
}
// terms should be a non-empty array of Terms
// returns undefined if terms is empty
// returns terms[0] if terms has only a single Term
function newConsPairsFromTerms(terms)
{var cp;
if (terms.length < 2)
return terms[0];
cp = newConsPair(terms[terms.length-2],terms[terms.length-1]);
for (var i = terms.length - 3; i >= 0; i--)
cp = newConsPair(terms[i],cp);
return cp;
}
function newOrPair(lhs,rhs)
{var term = new Term(TYPE_ATOM,';');
term.children[0] = lhs;
term.children[1] = rhs;
return term;
}
// terms should be a non-empty array of Terms
// returns undefined if terms is empty
// returns terms[0] if terms has only a single Term
function newOrPairsFromTerms(terms)
{var cp;
if (terms.length < 2)
return terms[0];
cp = newOrPair(terms[terms.length-2],terms[terms.length-1]);
for (var i = terms.length - 3; i >= 0; i--)
cp = newOrPair(terms[i],cp);
return cp;
}
function newListPair(lhs,rhs)
{var term = new Term(TYPE_ATOM,'.');
term.children[0] = lhs;
term.children[1] = rhs;
return term;
}
function newListNull()
{
return new Term(TYPE_ATOM,'[]');
}
// Returns a single list term where each element in the list is the element in terms.
// terms should be an array of Terms
function newListFromTerms(terms)
{var cp = newListNull();
for (var i = terms.length - 1; i >= 0; i--)
cp = newListPair(terms[i],cp);
return cp;
}
function newRuleTerm(lhs,rhs)
{var term = new Term(TYPE_ATOM,':-');
term.children[0] = lhs;
term.children[1] = rhs;
return term;
}
function newCommandOp(rhs)
{var term = new Term(TYPE_ATOM,':-');
term.children[0] = rhs;
return term;
}
// Given a term, returns a duplicate of that term.
// Invokes newDuplicateTerm(term,variables) below
function newDuplicateTerm(term)
{var variables = new Array();
return newDuplicateTerm(term,variables);
}
// Given a term, returns a duplicate of that term.
// The term must already have had an enclosure created via newTermEnclosure to bind
// variable children[0] to the enclosure array -- duped vars reference the same enclosure entry.
// The duplicate term has the same type and name, the same number of children,
// and duplicated children -- performs a deep copy.
// Variables in the duplicate term are represented via a single unnamed variable instance
// (i.e., variables lose their names, and the number of variables may be reduced).
// The variables parameter must be an array, with each element either undefined or a Variable
// instance. On completion, variables contains the duplicated variables at the same index they
// point to in the enclosure -- new Variable instances are created only if the variables array
// is undefined at the index position a variable references.
function newDuplicateTerm(term,variables)
{var terms_hash = new Hashtable();
var terms_todo = new Array();
var terms = new Array();
var t;
var t_copy;
terms.push(term);
// find and copy all terms
while ((t = terms.pop()) != undefined)
{
if (isVariable(t))
{
if (variables[t.children[0]] == undefined)
{
t_copy = newVariable('_');
t_copy.children[0] = t.children[0];
variables[t.children[0]] = t_copy;
hashPut(terms_hash,t,t_copy);
}
else
hashPut(terms_hash,t,variables[t.children[0]]);
}
else if (hashGet(terms_hash,t) == undefined)
{
t_copy = new Term(t.type,t.name);
t_copy.children = new Array(t.children.length);
terms_todo.push(t);
hashPut(terms_hash,t,t_copy);
for (var i=0; i < t.children.length; i++)
terms.push(t.children[i]);
}
}
// connect duplicate terms like original ones
while ((t = terms_todo.pop()) != undefined)
{
t_copy = hashGet(terms_hash,t);
for (var i=0; i < t.children.length; i++)
t_copy.children[i] = hashGet(terms_hash,t.children[i]);
}
return hashGet(terms_hash,term);
}
///////////////////////////////////
// * Type test functions
///////////////////////////////////
function isAtom(term)
{
return (term.type == TYPE_ATOM);
}
function isConstant(term)
{
return (term.type == TYPE_ATOM && term.children.length == 0);
}
function isNumber(term)
{
return (term.type == TYPE_NUMBER);
}
function isInteger(term)
{
return (term.type == TYPE_NUMBER && (Math.round(term.name) == term.name));
}
function isVariable(term)
{
return (term.type == TYPE_VARIABLE);
}
function isObjectReference(term)
{
return (term.type == TYPE_OBJECT);
}
function isConsPair(term)
{
return (term.type == TYPE_ATOM && term.name == ',' && term.children.length == 2);
}
function isOrPair(term)
{
return (term.type == TYPE_ATOM && term.name == ';' && term.children.length == 2);
}
function isListPair(term)
{
return (term.type == TYPE_ATOM && term.name == '.' && term.children.length == 2);
}
function isListNull(term)
{
return (term.type == TYPE_ATOM && term.name == '[]' && term.children.length == 0);
}
function isRuleTerm(term)
{
return (term.type == TYPE_ATOM && term.name == ':-' && term.children.length == 2);
}
function isCommandOp(term)
{
return (term.type == TYPE_ATOM && term.name == ':-' && term.children.length == 1);
}
///////////////////////////////////
// * Type getter / setter functions
///////////////////////////////////
function getTermNameArity(term)
{
if (!isAtom(term))
throw new Error("Expected atom.");
return (term.name.toString()+"/"+term.children.length.toString());
}
function getTermNameArityFromNameArity(name,arity)
{
return (name.toString()+"/"+arity.toString());
}
// term should be Terms
// returns empty array if term is undefined
// returns array of terms, where each element is the head of a binary pair (or last tail).
// eval_fn(t) should be true if t is a binary pair (arity 2) of the appropriate type.
function getTermArrayFromBinaryTerm(term,eval_fn)
{var terms = new Array();
if (term != undefined)
{var t = term;
while (eval_fn(t))
{
terms[terms.length] = t.children[0];
t = t.children[1];
}
terms[terms.length] = t;
}
return terms;
}
// Return array of variables in given term
function enumVariables(term)
{var vars = new Array();
var terms_hash = new Hashtable();
var terms = new Array();
var t;
terms.push(term);
// find all variables
while ((t = terms.pop()) != undefined)
{
if (hashGet(terms_hash,t) == undefined)
{
hashPut(terms_hash,t,t);
if (isVariable(t))
{
vars[vars.length] = t;
}
else
{
for (var i = t.children.length - 1; i >= 0; i--)
terms.push(t.children[i]);
}
}
}
return vars;
}