1 // xex.js -- Xex (XML Expression) interpreter
3 // National Institute of Advanced Industrial Science and Technology (AIST)
4 // Registration Number H15PRO112
6 // This file is part of the m17n database; a sub-part of the m17n
9 // The m17n library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public License
11 // as published by the Free Software Foundation; either version 2.1 of
12 // the License, or (at your option) any later version.
14 // The m17n library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with the m17n library; if not, write to the Free
21 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 // Boston, MA 02110-1301, USA.
26 (function () { // Tracing
27 // The logging node containing tracing information.
31 // Style properties of the logging node.
32 var styles = { border: '1px solid black',
33 font: 'normal normal normal small monospace',
39 // Toggle logging on and off. PARENT if non-null specifies the
40 // parent of the log node. The log node is appended to the parent.
41 // If PARENT is null, 'body' node is assumed.
42 Xex.LogToggle = function (parent)
46 log.parentNode.removeChild (log);
51 parent = document.getElementsByTagName ('body')[0];
52 log = document.createElement ('ol');
53 for (var prop in styles)
54 log.style[prop] = styles[prop];
55 parent.appendChild (log);
61 Xex.Log = function (arg, indent)
67 while (log.childNodes.length > 0)
68 log.removeChild (log.firstChild);
75 log.lastChild.innerText += arg;
81 node = log.firstElement ();
82 log.start = lines - 58;
85 node = document.createElement ('li');
86 if (indent != undefined)
87 node.style.textIndent = (indent + 1) + 'em';
89 node.style.textIndent = '0px';
91 log.appendChild (node);
92 log.scrollTop = log.scrollHeight;
99 UnknownError: "unknown-error",
100 WrongArgument: "wrong-argument",
102 InvalidInteger: "invalid-integer",
103 TermTypeInvalid: "term-type-invalid",
104 FunctionConflict: "function-conflict",
105 VariableTypeConflict: "variable-type-conflict",
106 VariableRangeConflict: "variable-range-conflict",
107 VariableWrongRange: "variable-wrong-range",
108 VariableWrongValue: "variable-wrong-value",
110 UnknownFunction: "unknown-function",
111 MacroExpansionError: "macro-expansion-error",
112 NoVariableName: "no-variable-name",
113 NoFunctionName: "no-funcion-name",
116 ArithmeticError: "arithmetic-error",
117 WrongType: "wrong-type",
118 IndexOutOfRange: "index-out-of-range",
119 ValueOutOfRange: "value-out-of-range",
120 NoLoopToBreak: "no-loop-to-break",
121 UncaughtThrow: "uncaught-throw"
124 Xex.Variable = function (domain, name, desc, val, range)
126 this.domain = domain;
133 Xex.Variable.prototype.clone = function ()
135 return new Xex.Variable (this.domain, this.name, this.desc,
136 this.val, this.range);
139 Xex.Variable.prototype.Equals = function (obj)
141 return ((obj instanceof Xex.Variable)
142 && obj.name == this.name);
145 Xex.Variable.prototype.SetValue = function (term)
151 Xex.Function = function (name, with_var, min_args, max_args)
154 this.with_var = with_var;
155 this.min_args = min_args;
156 this.max_args = max_args;
159 Xex.Subrountine = function (builtin, name, with_var, min_args, max_args)
162 this.with_var = with_var;
163 this.min_args = min_args;
164 this.max_args = max_args;
165 this.builtin = builtin;
168 Xex.Subrountine.prototype.Call = function (domain, vari, args)
170 var newargs = new Array ();
171 for (var i = 0; i < args.length; i++)
173 newargs[i] = args[i].Eval (domain);
174 if (domain.Thrown ())
177 return this.builtin (domain, vari, newargs)
180 Xex.SpecialForm = function (builtin, name, with_var, min_args, max_args)
183 this.with_var = with_var;
184 this.min_args = min_args;
185 this.max_args = max_args;
186 this.builtin = builtin;
189 Xex.SpecialForm.prototype.Call = function (domain, vari, args)
191 return this.builtin (domain, vari, args)
194 Xex.Lambda = function (name, min_args, max_args, args, body)
197 this.min_args = min_args;
198 this.max_args = max_args;
203 Xex.Lambda.prototype.Call = function (domain, vari, args)
205 var current = domain.bindings;
206 var result = Xex.Zero;
207 var limit = max_args >= 0 ? args.length : args.length - 1;
211 for (i = 0; i < limit; i++)
213 result = args[i].Eval (domain);
214 if (domain.Thrown ())
216 domain.Bind (this.args[i], result);
220 var list = new Array ();
221 for (i = 0; i < args[limit].length; i++)
223 result = args[limit].Eval (domain);
224 if (domain.Thrown ())
228 domain.Bind (this.args[limit], list);
231 domain.Catch (Xex.CatchTag.Return);
232 for (var term in this.body)
234 result = term.Eval (domain);
235 if (domain.Thrown ())
242 domain.UnboundTo (current);
247 Xex.Macro = function (name, min_args, max_args, args, body)
250 this.min_args = min_args;
251 this.max_args = max_args;
256 Xex.Macro.prototype.Call = function (domain, vari, args)
258 var current = domain.bindings;
259 var result = Xex.Zero;
263 for (i = 0; i < args.length; i++)
264 domain.Bind (this.args[i], args[i]);
266 domain.Catch (Xex.CatchTag.Return);
267 for (var i in this.body)
269 result = this.body[i].Eval (domain);
270 if (domain.Thrown ())
277 domain.UnboundTo (current);
282 Xex.Bindings = function (vari)
285 this.old_value = vari.val;
288 Xex.Bindings.prototype.UnboundTo = function (boundary)
290 for (var b = this; b != boundary; b = b.next)
291 b.vari.val = b.old_value;
295 Xex.Bind = function (bindings, vari, val)
297 var b = new Xex.Bindings (vari);
308 Xex.Domain = function (name, parent, context)
311 this.context = context;
314 if (name != 'basic' && ! parent)
315 parent = Xex.BasicDomain
316 this.parent = parent;
323 for (elt in parent.termtypes)
324 this.termtypes[elt] = parent.termtypes[elt];
325 for (elt in parent.functions)
326 this.functions[elt] = parent.functions[elt];
327 for (elt in parent.variables)
329 var vari = parent.variables[elt];
330 this.variables[elt] = new Xex.Variable (this, vari.name, vari.desc,
331 vari.val, vari.range);
335 this.call_stack = new Array ();
336 this.bindings = null;
337 this.catch_stack = new Array ();
338 this.catch_count = 0;
342 Xex.Domain.prototype = {
343 CallStackCount: function () { return this.call_stack.length; },
344 CallStackPush: function (term) { this.call_stack.push (term); },
345 CallStackPop: function () { this.call_stack.pop (); },
346 Bind: function (vari, val)
348 this.bindings = Xex.Bind (this.bindings, vari, val);
350 UnboundTo: function (boundary)
353 this.bindings = this.bindings.UnboundTo (boundary);
355 Catch: function (tag) { this.catch_stack.push (tag); this.catch_count++; },
358 this.catch_stack.pop ();
359 if (this.catch_count > this.catch_stack.length)
364 if (this.catch_count < this.catch_stack.length)
366 this.caught = (this.catch_count == this.catch_stack.length - 1);
372 ThrowReturn: function ()
374 for (var i = this.catch_stack.length - 1; i >= 0; i--)
377 if (this.catch_stack[i] == Xex.CatchTag.Return)
381 ThrowBreak: function ()
383 if (this.catch_stack[this.catch_stack.length - 1] != Xex.CatchTag.Break)
384 throw new Xex.ErrTerm (Xex.Error.NoLoopToBreak,
385 "No surrounding loop to break");
388 ThrowSymbol: function (tag)
390 var i = this.catch_count;
391 for (var j = this.catch_stack.length - 1; j >= 0; j--)
394 if (Xex.CatchTag.Matches (this.catch_stack[i], tag))
396 this.catch_count = i;
400 throw new Xex.ErrTerm (Xex.Error.UncaughtThrow,
401 "No corresponding catch: " + tag);
403 DefType: function (obj)
406 if (this.termtypes[type])
407 throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid,
408 "Already defined: " + type);
409 if (this.functions[type])
410 throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid,
411 "Already defined as a funciton or a macro: "
413 this.termtypes[type] = obj.Parser;
415 DefSubr: function (builtin, name, with_var, min_args, max_args)
417 this.functions[name] = new Xex.Subrountine (builtin, name, with_var,
420 DefSpecial: function (builtin, name, with_var, min_args, max_args)
422 this.functions[name] = new Xex.SpecialForm (builtin, name, with_var,
425 Defun: function (name, min_args, max_args, args, body)
427 this.functions[name] = new Xex.Lambda (name, min_args, max_args,
430 DefunByFunc: function (func) { this.functions[func.name] = func; },
431 Defmacro: function (name, min_args, max_args, args, body)
433 this.functions[name] = new Xex.Macro (name, min_args, max_args,
436 DefAlias: function (alias, fname)
438 var func = this.functions[fname];
441 throw new Xex.ErrTerm (Xex.Error.UnknownFunction, fname);
442 if (this.termtypes[alias])
443 throw new Xex.ErrTerm (Xex.Error.FunctionConflict,
444 "Already defined as a term type: " + alias);
445 if (this.functions[alias])
446 throw new Xex.ErrTerm (Xex.Error.FunctionConflict,
447 "Already defined as a function: " + alias);
448 this.functions[alias] = func;
450 Defvar: function (name, desc, val, range)
452 var vari = new Xex.Variable (this, name, desc, val, range);
453 this.variables[name] = vari;
456 GetFunc: function (name)
458 var func = this.functions[name];
460 throw new Xex.ErrTerm (Xex.Error.UnknownFunction,
461 "Unknown function: " + name);
464 CopyFunc: function (domain, name)
466 var func = this.functions[name];
467 domain.DefunByFunc (func);
470 CopyFuncAll: function (domain)
472 for (var elt in this.functions)
473 domain.DefunByFunc (this.functions[elt]);
475 GetVarCreate: function (name)
477 var vari = this.variables[name];
479 vari = this.variables[name] = new Xex.Variable (this, name, null,
483 GetVar: function (name) { return this.variables[name]; },
484 SaveValues: function ()
487 for (var elt in this.variables)
488 values[elt] = this.variables[elt].val.Clone ();
491 RestoreValues: function (values)
496 var vari = this.variables[name];
497 vari.val = values[name];
502 Xex.Term = function (type) { this.type = type; }
503 Xex.Term.prototype = {
504 IsTrue: function () { return true; },
505 Eval: function (domain) { return this.Clone (); },
506 Clone: function (domain) { return this; },
507 Equals: function (obj)
509 return (this.type == obj.type
510 && this.val != undefined
511 && obj.val == this.val);
513 Matches: function (obj) { return this.Equals (obj); },
514 toString: function ()
516 if (this.val != undefined)
517 return '<' + this.type + '>' + this.val + '</' + this.type + '>';
518 return '<' + this.type + '/>';
520 Intval: function () { throw new Xex.ErrTerm (Xex.Error.WrongType,
521 "Not an integer"); },
522 Strval: function () { throw new Xex.ErrTerm (Xex.Error.WrongType,
526 Node.prototype.firstElement = function ()
528 for (var n = this.firstChild; n; n = n.nextSibling)
534 Node.prototype.nextElement = function ()
536 for (var n = this.nextSibling; n; n = n.nextSibling)
543 function parse_defvar (domain, node)
545 var name = node.attributes['vname'].nodeValue;
547 throw new Xex.ErrTerm (Xex.Error.NoVariableName, node, '');
548 var vari = domain.variables[name];
549 var desc, val = null, range;
552 desc = vari.description;
556 node = node.firstElement ();
557 if (node && node.nodeName == 'description')
559 desc = node.firstChild.nodeValue;
560 node = node.nextElement ();
564 val = Xex.Term.Parse (domain, node);
565 node = node.nextElement ();
566 if (node && node.nodeName == 'possible-values')
567 for (node = node.firstElement (); node; node = node.nextElement ())
570 if (node.nodeName == 'range')
573 throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid,
574 'Range not allowed for ' + name);
576 for (var n = node.firstElement (); n; n = n.nextElement ())
578 var v = Xex.Term.Parse (domain, n);
580 throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid,
581 'Invalid range value: ' + val);
587 pval = Xex.Term.Parse (domain, node);
588 if (val.type != pval.type)
589 throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid,
590 'Invalid possible value: ' + pval);
593 range = new Array ();
599 domain.Defvar (name, desc, val, range);
603 function parse_defun_head (domain, node)
605 var name = node.attributes['fname'].nodeValue;
607 throw new Xex.ErrTerm (Xex.Error.NoFunctionName, node, '');
608 var args = new Array ();
609 var nfixed = 0, noptional = 0, nrest = 0;
611 node = node.firstElement ();
612 if (node && node.nodeName == 'args')
615 for (n = n.firstElement (); n; n = n.nextElement ())
617 if (n.nodeName == 'fixed')
619 else if (n.nodeName == 'optional')
621 else if (n.nodeName == 'rest')
624 throw new Xex.ErrTerm (Xex.Error.WrongType, n, n.nodeName);
627 throw new Xex.ErrTerm (Xex.Error.WrongType, n, 'Too many <rest>');
628 for (n = node.firstElement (); n; n = n.nextElement ())
629 args.push (domain.DefVar (n.attributes['vname'].nodeValue));
631 args.min_args = nfixed;
632 args.max_args = nrest == 0 ? nfixed + noptional : -1;
634 if (node.nodeName == 'defun')
635 domain.Defun (name, args, null);
637 domain.Defmacro (name, args, null);
641 function parse_defun_body (domain, node)
643 var name = node.attributes['fname'].nodeValue;
644 var func = domain.GetFunc (name);
646 for (node = node.firstElement (); node; node = node.nextElement ())
647 if (node.nodeName != 'description' && node.nodeName != 'args')
649 body = Xex.Term.Parse (domain, node, null);
653 Xex.Term.Parse = function (domain, node, stop)
655 if (arguments.length == 2)
657 var name = node.nodeName;
658 var parser = domain.termtypes[name];
661 return parser (domain, node);
662 if (name == 'defun' || name == 'defmacro')
664 name = parse_defun_head (domain, node);
665 parse_defun_body (domain, node);
666 return new Xex.StrTerm (name);
668 if (name == 'defvar')
670 name = parse_defvar (domain, node);
671 return new Xex.StrTerm (name);
673 return new Xex.Funcall.prototype.Parser (domain, node);
675 for (var n = node; n && n != stop; n = n.nextElement ())
676 if (n.nodeName == 'defun' || n.nodeName == 'defmacro')
677 parse_defun_head (domain, n);
679 for (var n = node; n && n != stop; n = n.nextElement ())
681 if (n.nodeName == 'defun' || n.nodeName == 'defmacro')
682 parse_defun_body (domain, n);
683 else if (n.nodeName == 'defvar')
684 parse_defvar (domain, n);
688 terms = new Array ();
689 terms.push (Xex.Term.Parse (domain, n));
696 Xex.Varref = function (vname)
702 var proto = new Xex.Term ('varref');
704 proto.Clone = function () { return new Xex.Varref (this.val); }
705 proto.Eval = function (domain)
707 var vari = domain.GetVarCreate (this.val);
708 Xex.Log (this.ToString () + '=>' + vari.val, domain.depth);
712 proto.Parser = function (domain, node)
714 return new Xex.Varref (node.attributes['vname'].nodeValue);
717 proto.ToString = function ()
719 return '<varref vname="' + this.val + '"/>';
722 Xex.Varref.prototype = proto;
725 var null_args = new Array ();
727 Xex.Funcall = function (func, vname, args)
731 this.args = args || null_args;
735 var proto = new Xex.Term ('funcall');
737 proto.Parser = function (domain, node)
739 var fname = node.nodeName;
742 if (fname == 'funcall')
743 fname = node.attributes['fname'].nodeValue;
744 var func = domain.GetFunc (fname);
746 attr = node.attributes['vname'];
747 vname = attr != undefined ? attr.nodeValue : null;
748 var args = Xex.Term.Parse (domain, node.firstElement (), null);
749 return new Xex.Funcall (func, vname, args);
752 proto.New = function (domain, fname, vname, args)
754 var func = domain.GetFunc (fname);
755 var funcall = new Xex.Funcall (func, vname, args);
756 if (func instanceof Xex.Macro)
757 funcall = funcall.Eval (domain);
761 proto.Eval = function (domain)
763 Xex.Log (this, domain.depth);
766 vari = domain.GetVarCreate (this.vname);
770 result = this.func.Call (domain, vari, this.args);
772 Xex.Log (' => ' + result, --domain.depth,
773 this.func instanceof Xex.Subrountine);
778 proto.Clone = function ()
780 return new Xex.Funcall (this.func, this.vari, this.args);
783 proto.Equals = function (obj)
785 return (obj.type == 'funcall'
786 && obj.func == this.func
787 && obj.vari.Equals (this.vari)
788 && obj.args.length == this.func.length);
791 proto.toString = function ()
794 var len = this.args.length;
795 var str = '<' + this.func.name;
797 str += ' vname="' + this.vname + '"';
800 if (this.func instanceof Xex.Subrountine)
801 for (var i = 0; i < len; i++)
802 arglist += this.args[i].toString ();
804 for (var i = 0; i < len; i++)
806 return str + '>' + arglist + '</' + this.func.name + '>';
809 Xex.Funcall.prototype = proto;
812 Xex.ErrTerm = function (ename, message, stack)
815 this.message = message;
820 var proto = new Xex.Term ('error');
822 proto.IsError = true;
824 proto.Parser = function (domain, node)
826 return new Xex.ErrTerm (node.attributes['ename'].nodeValue,
827 node.innerText, false);
830 proto.CallStack = function () { return stack; }
832 proto.SetCallStack = function (value) { statck = value; }
834 proto.Clone = function ()
836 return new Xex.ErrTerm (ename, message, false);
839 proto.Equals = function (obj)
842 && obj.ename == ename && obj.message == message
843 && (obj.stack ? (stack && stack.length == obj.stack.length)
847 proto.Matches = function (obj)
849 return (obj.IsError && obj.ename == ename);
852 proto.toString = function ()
854 return '<error ename="' + this.ename + '">' + this.message + '</error>';
857 Xex.ErrTerm.prototype = proto;
860 Xex.IntTerm = function (num) { this.val = num; };
862 var proto = new Xex.Term ('integer');
864 proto.Intval = function () { return this.val; };
865 proto.IsTrue = function () { return this.val != 0; }
866 proto.Clone = function () { return new Xex.IntTerm (this.val); }
867 proto.Parser = function (domain, node)
869 var str = node.firstChild.nodeValue;
871 if (str.charAt (0) == '?' && str.length == 2)
872 return new Xex.IntTerm (str.charCodeAt (1));
873 return new Xex.IntTerm (parseInt (node.firstChild.nodeValue));
875 Xex.IntTerm.prototype = proto;
878 Xex.StrTerm = function (str) { this.val = str; };
880 var proto = new Xex.Term ('string');
882 proto.Strval = function () { return this.val; };
883 proto.IsTrue = function () { return this.val.length > 0; }
884 proto.Clone = function () { return new Xex.StrTerm (this.val); }
885 proto.Parser = function (domain, node)
887 return new Xex.StrTerm (node.firstChild ? node.firstChild.nodeValue : '');
889 Xex.StrTerm.prototype = proto;
892 Xex.SymTerm = function (str) { this.val = str; };
894 var proto = new Xex.Term ('symbol');
895 proto.IsSymbol = true;
896 proto.IsTrue = function () { return this.val != 'nil'; }
897 proto.Clone = function () { return new Xex.SymTerm (this.val); }
898 proto.Parser = function (domain, node)
900 return new Xex.SymTerm (node.firstChild.nodeValue);
902 Xex.SymTerm.prototype = proto;
905 Xex.LstTerm = function (list) { this.val = list; };
907 var proto = new Xex.Term ('list');
909 proto.IsTrue = function () { return this.val.length > 0; }
910 proto.Clone = function () { return new Xex.LstTerm (this.val.slice (0)); }
912 proto.Equals = function (obj)
914 if (obj.type != 'list' || obj.val.length != this.val.length)
916 var i, len = this.val.length;
917 for (i = 0; i < len; i++)
918 if (! this.val[i].Equals (obj.val[i]))
923 proto.Parser = function (domain, node)
925 var list = Xex.Term.Parse (domain, node.firstElement (), null);
926 return new Xex.LstTerm (list);
929 proto.toString = function ()
931 var len = this.val.length;
936 for (var i = 0; i < len; i++)
937 str += this.val[i].toString ();
938 return str + '</list>';
940 Xex.LstTerm.prototype = proto;
944 var basic = new Xex.Domain ('basic', null, null);
946 function Fset (domain, vari, args)
949 throw new Xex.ErrTerm (Xex.Error.NoVariableName,
950 'No variable name to set');
951 vari.SetValue (args[0]);
955 function Fnot (domain, vari, args)
957 return (args[0].IsTrue () ? Xex.Zero : Xex.One);
960 function maybe_set_intvar (vari, n)
962 var term = new Xex.IntTerm (n);
964 vari.SetValue (term);
968 function Fadd (domain, vari, args)
970 var n = vari ? vari.val.Intval () : 0;
971 var len = args.length;
973 for (var i = 0; i < len; i++)
974 n += args[i].Intval ();
975 return maybe_set_intvar (vari, n);
978 function Fmul (domain, vari, args)
980 var n = vari ? vari.val.Intval () : 1;
981 for (var i = 0; i < args.length; i++)
982 n *= args[i].Intval ();
983 return maybe_set_intvar (vari, n);
986 function Fsub (domain, vari, args)
992 n = args[0].Intval ();
997 n = vari.val.Intval ();
1000 while (i < args.length)
1001 n -= args[i++].Intval ();
1002 return maybe_set_intvar (vari, n);
1005 function Fdiv (domain, vari, args)
1011 n = args[0].Intval ();
1016 n = vari.val.Intval ();
1019 while (i < args.length)
1020 n /= args[i++].Intval ();
1021 return maybe_set_intvar (vari, n);
1024 function Fmod (domain, vari, args)
1026 return maybe_set_intvar (vari, args[0].Intval () % args[1].Intval ());
1029 function Flogior (domain, vari, args)
1031 var n = vari == null ? 0 : vari.val;
1032 for (var i = 0; i < args.length; i++)
1034 return maybe_set_intvar (vari, n);
1037 function Flogand (domain, vari, args)
1042 Xex.Log ("logand arg args[0]" + args[0]);
1043 n = args[0].Intval ()
1048 Xex.Log ("logand arg var " + vari);
1049 n = vari.val.Intval ();
1052 while (n > 0 && i < args.length)
1054 Xex.Log ("logand arg " + args[i]);
1057 return maybe_set_intvar (vari, n);
1060 function Flsh (domain, vari, args)
1062 return maybe_set_intvar (vari, args[0].Intval () << args[1].Intval ());
1065 function Frsh (domain, vari, args)
1067 return maybe_set_intvar (vari, args[0].Intval () >> args[1].Intval ());
1070 function Fand (domain, vari, args)
1072 var len = args.length;
1073 for (var i = 0; i < len; i++)
1075 var result = args[i].Eval (domain);
1076 if (domain.Thrown ())
1078 if (! result.IsTrue ())
1084 function For (domain, vari, args)
1086 var len = args.length;
1087 for (var i = 0; i < len; i++)
1089 var result = args[i].Eval (domain);
1090 if (domain.Thrown ())
1092 if (result.IsTrue ())
1098 function Feq (domain, vari, args)
1100 for (var i = 1; i < args.length; i++)
1101 if (! args[i - 1].Equals (args[i]))
1106 function Fnoteq (domain, vari, args)
1108 return (Feq (domain, vari, args) == Xex.One ? Xex.Zero : Xex.One);
1111 function Flt (domain, vari, args)
1113 var n = args[0].Intval ();
1115 for (var i = 1; i < args.length; i++)
1117 var n1 = args[i].Intval ();
1125 function Fle (domain, vari, args)
1127 var n = args[0].Intval ();
1128 for (var i = 1; i < args.length; i++)
1130 var n1 = args[i].Intval ();
1138 function Fgt (domain, vari, args)
1140 var n = args[0].Intval ();
1141 for (var i = 1; i < args.length; i++)
1143 var n1 = args[i].Intval ();
1151 function Fge (domain, vari, args)
1153 var n = args[0].Intval ();
1154 for (var i = 1; i < args.length; i++)
1156 var n1 = args[i].Intval ();
1164 function Fprogn (domain, vari, args)
1166 var result = Xex.One;
1167 var len = args.length;
1169 for (var i = 0; i < len; i++)
1171 result = args[i].Eval (domain);
1172 if (domain.Thrown ())
1178 function Fif (domain, vari, args)
1180 var result = args[0].Eval (domain);
1182 if (domain.Thrown ())
1184 if (result.IsTrue ())
1185 return args[1].Eval (domain);
1186 if (args.length == 2)
1188 return args[2].Eval (domain);
1191 function Fcond (domain, vari, args)
1193 for (var i = 0; i < args.length; i++)
1196 var result = list.val[0].Eval (domain);
1197 if (result.IsTrue ())
1199 for (var j = 1; j < list.val.length; j++)
1202 result = list.val[j].Eval (domain);
1204 if (domain.Thrown ())
1213 function eval_terms (domain, terms, idx)
1215 var result = Xex.Zero;
1216 domain.caught = false;
1217 for (var i = idx; i < terms.length; i++)
1219 result = terms[i].Eval (domain);
1220 if (domain.Thrown ())
1226 function Fcatch (domain, vari, args)
1231 if (args[0].IsError)
1234 result = eval_terms (domain, args, 1);
1236 if (e instanceof Xex.ErrTerm)
1238 if (! args[0].Matches (e))
1246 else if (args[0].IsSymbol)
1249 domain.Catch (args[0].val);
1250 result = eval_terms (domain, args, 1);
1254 vari.SetValue (result);
1262 throw new Xex.ErrTerm (Xex.Error.WrongArgument,
1263 "Not a symbol nor an error: " + args[0]);
1266 function Fthrow (domain, vari, args)
1268 if (args[0].IsSymbl)
1270 domain.ThrowSymbol (args[0]);
1271 return (args[args.length - 1]);
1273 if (args[0].IsError)
1277 throw new Xex.ErrTerm (Xex.Error.WrongArgument,
1278 "Not a symbol nor an error:" + args[0]);
1281 Xex.BasicDomain = basic;
1283 basic.DefSubr (Fset, "set", true, 1, 1);
1284 basic.DefAlias ("=", "set");
1285 basic.DefSubr (Fnot, "not", false, 1, 1);
1286 basic.DefAlias ("!", "not");
1287 basic.DefSubr (Fadd, "add", true, 1, -1);
1288 basic.DefSubr (Fmul, "mul", true, 1, -1);
1289 basic.DefAlias ("*", "mul");
1290 basic.DefSubr (Fsub, "sub", true, 1, -1);
1291 basic.DefAlias ("-", "sub");
1292 basic.DefSubr (Fdiv, "div", true, 1, -1);
1293 basic.DefAlias ("/", "div");
1294 basic.DefSubr (Fmod, "mod", true, 1, 2);
1295 basic.DefAlias ("%", "mod");
1296 basic.DefSubr (Flogior, "logior", true, 1, -1);
1297 basic.DefAlias ('|', "logior");
1298 basic.DefSubr (Flogand, "logand", true, 1, -1);
1299 basic.DefAlias ("&", "logand");
1300 basic.DefSubr (Flsh, "lsh", true, 1, 2);
1301 basic.DefAlias ("<<", "lsh");
1302 basic.DefSubr (Frsh, "rsh", true, 1, 2);
1303 basic.DefAlias (">>", "rsh");
1304 basic.DefSubr (Feq, "eq", false, 2, -1);
1305 basic.DefAlias ("==", "eq");
1306 basic.DefSubr (Fnoteq, "noteq", false, 2, 2);
1307 basic.DefAlias ("!=", "noteq");
1308 basic.DefSubr (Flt, "lt", false, 2, -1);
1309 basic.DefAlias ("<", "lt");
1310 basic.DefSubr (Fle, "le", false, 2, -1);
1311 basic.DefAlias ("<=", "le");
1312 basic.DefSubr (Fgt, "gt", false, 2, -1);
1313 basic.DefAlias (">", "gt");
1314 basic.DefSubr (Fge, "ge", false, 2, -1);
1315 basic.DefAlias (">=", "ge");
1316 basic.DefSubr (Fthrow, "throw", false, 1, 2);
1318 //basic.DefSubr (Fappend, "append", true, 0, -1);
1319 //basic.DefSubr (Fconcat, "concat", true, 0, -1);
1320 //basic.DefSubr (Fnth, "nth", false, 2, 2);
1321 //basic.DefSubr (Fcopy, "copy", false, 1, 1);
1322 //basic.DefSubr (Fins, "ins", true, 2, 2);
1323 //basic.DefSubr (Fdel, "del", true, 2, 2);
1324 //basic.DefSubr (Feval, "eval", false, 1, 1);
1325 //basic.DefSubr (Fbreak, "break", false, 0, 1);
1326 //basic.DefSubr (Freturn, "return", false, 0, 1);
1327 //basic.DefSubr (Fthrow, "throw", false, 1, 2);
1329 basic.DefSpecial (Fand, "and", false, 1, -1);
1330 basic.DefAlias ("&&", "and");
1331 basic.DefSpecial (For, "or", false, 1, -1);
1332 basic.DefAlias ("||", "or");
1333 basic.DefSpecial (Fprogn, "progn", false, 1, -1);
1334 basic.DefAlias ("expr", "progn");
1335 basic.DefSpecial (Fif, "if", false, 2, 3);
1336 //basic.DefSpecial (Fwhen, "when", false, 1, -1);
1337 //basic.DefSpecial (Floop, "loop", false, 1, -1);
1338 //basic.DefSpecial (Fwhile, "while", false, 1, -1);
1339 basic.DefSpecial (Fcond, "cond", false, 1, -1);
1340 //basic.DefSpecial (Fforeach, "foreach", true, 2, -1);
1341 //basic.DefSpecial (Fquote, "quote", false, 1, 1);
1342 //basic.DefSpecial (Ftype, "type", false, 1, 1);
1343 basic.DefSpecial (Fcatch, "catch", true, 2, -1);
1345 basic.DefType (Xex.Funcall.prototype);
1346 basic.DefType (Xex.Varref.prototype);
1347 basic.DefType (Xex.ErrTerm.prototype);
1348 basic.DefType (Xex.IntTerm.prototype);
1349 basic.DefType (Xex.StrTerm.prototype);
1350 basic.DefType (Xex.SymTerm.prototype);
1351 basic.DefType (Xex.LstTerm.prototype);
1355 Xex.Zero = new Xex.IntTerm (0);
1356 Xex.One = new Xex.IntTerm (1);
1357 Xex.nil = new Xex.SymTerm ('nil');
1359 Xex.Load = function (server, file)
1361 var obj = new XMLHttpRequest ();
1362 var url = server ? server + '/' + file : file;
1363 obj.open ('GET', url, false);
1364 obj.overrideMimeType ('text/xml');
1366 return (obj.responseXML && obj.responseXML.firstChild);