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.
24 // Please note that the code is not yet matured.
28 (function () { // Logging
29 // The logging node containing tracing information.
33 // Style properties of the logging node.
34 var styles = { border: '1px solid black',
35 font: 'normal normal normal small monospace',
41 // Toggle logging on and off. PARENT if non-null specifies the
42 // parent of the log node. The log node is appended to PARENT.
43 // If PARENT is null, 'body' node is assumed.
44 Xex.LogToggle = function (parent)
48 log.parentNode.removeChild (log);
53 parent = document.getElementsByTagName ('body')[0];
54 log = document.createElement ('ol');
55 for (var prop in styles)
56 log.style[prop] = styles[prop];
57 parent.appendChild (log);
62 // Log ARG (string). INDENT if specified is a number of columns to
63 // indent. If INDENT is -1, ARG is appended to the last log.
64 Xex.Log = function (arg, indent)
70 while (log.childNodes.length > 0)
71 log.removeChild (log.firstChild);
78 log.lastChild.innerText += arg;
84 node = log.firstElement ();
85 log.start = lines - 254;
88 node = document.createElement ('li');
89 if (indent != undefined)
90 node.style.textIndent = (indent + 1) + 'em';
92 node.style.textIndent = '0px';
94 log.appendChild (node);
95 log.scrollTop = log.scrollHeight;
102 UnknownError: "unknown-error",
103 WrongArgument: "wrong-argument",
105 InvalidInteger: "invalid-integer",
106 TermTypeInvalid: "term-type-invalid",
107 FunctionConflict: "function-conflict",
108 VariableTypeConflict: "variable-type-conflict",
109 VariableRangeConflict: "variable-range-conflict",
110 VariableWrongRange: "variable-wrong-range",
111 VariableWrongValue: "variable-wrong-value",
113 UnknownFunction: "unknown-function",
114 MacroExpansionError: "macro-expansion-error",
115 NoVariableName: "no-variable-name",
116 NoFunctionName: "no-funcion-name",
119 ArithmeticError: "arithmetic-error",
120 WrongType: "wrong-type",
121 IndexOutOfRange: "index-out-of-range",
122 ValueOutOfRange: "value-out-of-range",
123 NoLoopToBreak: "no-loop-to-break",
124 UncaughtThrow: "uncaught-throw"
127 Xex.Variable = function (name, desc, val, range)
138 Xex.Variable.prototype = {
141 return new Xex.Variable (this.name, this.desc, this.val, this.range);
143 equals: function (obj)
145 return ((obj instanceof Xex.Variable)
146 && obj.name == this.name);
148 SetValue: function (term)
156 Xex.Function = function (name, with_var, min_args, max_args)
159 this.with_var = with_var;
160 this.min_args = min_args;
161 this.max_args = max_args;
164 Xex.Subrountine = function (builtin, name, with_var, min_args, max_args)
166 Xex.Function.apply (this, [name, with_var, min_args, max_args]);
167 this.builtin = builtin;
170 Xex.Subrountine.prototype.Call = function (domain, vari, args)
172 var newargs = new Array ();
173 for (var i = 0; i < args.length; i++)
175 newargs[i] = args[i].Eval (domain);
176 if (domain.Thrown ())
179 return this.builtin (domain, vari, newargs)
182 Xex.SpecialForm = function (builtin, name, with_var, min_args, max_args)
184 Xex.Function.apply (this, [name, with_var, min_args, max_args]);
185 this.builtin = builtin;
188 Xex.SpecialForm.prototype.Call = function (domain, vari, args)
190 return this.builtin (domain, vari, args)
193 Xex.Lambda = function (name, min_args, max_args, args, body)
195 Xex.Function.apply (this, [name, false, min_args, max_args]);
200 Xex.Lambda.prototype.Call = function (domain, vari, args)
202 var current = domain.bindings;
203 var result = Xex.Zero;
204 var limit = max_args >= 0 ? args.length : args.length - 1;
208 for (i = 0; i < limit; i++)
210 result = args[i].Eval (domain);
211 if (domain.Thrown ())
213 domain.Bind (this.args[i], result);
217 var list = new Array ();
218 for (i = 0; i < args[limit].length; i++)
220 result = args[limit].Eval (domain);
221 if (domain.Thrown ())
225 domain.Bind (this.args[limit], list);
228 domain.Catch (Xex.CatchTag.Return);
229 for (var term in this.body)
231 result = term.Eval (domain);
232 if (domain.Thrown ())
239 domain.UnboundTo (current);
244 Xex.Macro = function (name, min_args, max_args, args, body)
246 Xex.Function.apply (this, [name, false, min_args, max_args]);
251 Xex.Macro.prototype.Call = function (domain, vari, args)
253 var current = domain.bindings;
254 var result = Xex.Zero;
258 for (i = 0; i < args.length; i++)
259 domain.Bind (this.args[i], args[i]);
261 domain.Catch (Xex.CatchTag.Return);
262 for (var i in this.body)
264 result = this.body[i].Eval (domain);
265 if (domain.Thrown ())
272 domain.UnboundTo (current);
277 Xex.Bindings = function (vari)
280 this.old_value = vari.val;
283 Xex.Bindings.prototype.UnboundTo = function (boundary)
285 for (var b = this; b != boundary; b = b.next)
286 b.vari.val = b.old_value;
290 Xex.Bind = function (bindings, vari, val)
292 var b = new Xex.Bindings (vari);
303 Xex.Domain = function (name, parent, context)
306 this.context = context;
309 if (name != 'basic' && ! parent)
310 parent = Xex.BasicDomain
311 this.parent = parent;
318 for (elt in parent.termtypes)
319 this.termtypes[elt] = parent.termtypes[elt];
320 for (elt in parent.functions)
321 this.functions[elt] = parent.functions[elt];
322 for (elt in parent.variables)
324 var vari = parent.variables[elt];
325 this.variables[elt] = new Xex.Variable (vari.name, vari.desc,
326 vari.val, vari.range);
330 this.call_stack = new Array ();
331 this.bindings = null;
332 this.catch_stack = new Array ();
333 this.catch_count = 0;
337 Xex.Domain.prototype = {
338 CallStackCount: function () { return this.call_stack.length; },
339 CallStackPush: function (term) { this.call_stack.push (term); },
340 CallStackPop: function () { this.call_stack.pop (); },
341 Bind: function (vari, val)
343 this.bindings = Xex.Bind (this.bindings, vari, val);
345 UnboundTo: function (boundary)
348 this.bindings = this.bindings.UnboundTo (boundary);
350 Catch: function (tag) { this.catch_stack.push (tag); this.catch_count++; },
353 this.catch_stack.pop ();
354 if (this.catch_count > this.catch_stack.length)
359 if (this.catch_count < this.catch_stack.length)
361 this.caught = (this.catch_count == this.catch_stack.length - 1);
367 ThrowReturn: function ()
369 for (var i = this.catch_stack.length - 1; i >= 0; i--)
372 if (this.catch_stack[i] == Xex.CatchTag.Return)
376 ThrowBreak: function ()
378 if (this.catch_stack[this.catch_stack.length - 1] != Xex.CatchTag.Break)
379 throw new Xex.ErrTerm (Xex.Error.NoLoopToBreak,
380 "No surrounding loop to break");
383 ThrowSymbol: function (tag)
385 var i = this.catch_count;
386 for (var j = this.catch_stack.length - 1; j >= 0; j--)
389 if (Xex.CatchTag.Matches (this.catch_stack[i], tag))
391 this.catch_count = i;
395 throw new Xex.ErrTerm (Xex.Error.UncaughtThrow,
396 "No corresponding catch: " + tag);
398 DefType: function (obj)
401 if (this.termtypes[type])
402 throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid,
403 "Already defined: " + type);
404 if (this.functions[type])
405 throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid,
406 "Already defined as a funciton or a macro: "
408 this.termtypes[type] = obj.Parser;
410 DefSubr: function (builtin, name, with_var, min_args, max_args)
412 this.functions[name] = new Xex.Subrountine (builtin, name, with_var,
415 DefSpecial: function (builtin, name, with_var, min_args, max_args)
417 this.functions[name] = new Xex.SpecialForm (builtin, name, with_var,
420 Defun: function (name, min_args, max_args, args, body)
422 this.functions[name] = new Xex.Lambda (name, min_args, max_args,
425 DefunByFunc: function (func) { this.functions[func.name] = func; },
426 Defmacro: function (name, min_args, max_args, args, body)
428 this.functions[name] = new Xex.Macro (name, min_args, max_args,
431 DefAlias: function (alias, fname)
433 var func = this.functions[fname];
436 throw new Xex.ErrTerm (Xex.Error.UnknownFunction, fname);
437 if (this.termtypes[alias])
438 throw new Xex.ErrTerm (Xex.Error.FunctionConflict,
439 "Already defined as a term type: " + alias);
440 if (this.functions[alias])
441 throw new Xex.ErrTerm (Xex.Error.FunctionConflict,
442 "Already defined as a function: " + alias);
443 this.functions[alias] = func;
445 Defvar: function (name, desc, val, range)
447 var vari = new Xex.Variable (name, desc, val, range);
448 this.variables[name] = vari;
451 GetFunc: function (name)
453 var func = this.functions[name];
455 throw new Xex.ErrTerm (Xex.Error.UnknownFunction,
456 "Unknown function: " + name);
459 CopyFunc: function (domain, name)
461 var func = this.functions[name];
462 domain.DefunByFunc (func);
465 CopyFuncAll: function (domain)
467 for (var elt in this.functions)
468 domain.DefunByFunc (this.functions[elt]);
470 GetVarCreate: function (name)
472 var vari = this.variables[name];
474 vari = this.variables[name] = new Xex.Variable (name, null,
478 GetVar: function (name) { return this.variables[name]; },
479 SaveValues: function ()
482 for (var elt in this.variables)
483 values[elt] = this.variables[elt].val.Clone ();
486 RestoreValues: function (values)
491 var vari = this.variables[name];
492 vari.val = values[name];
497 Xex.Term = function (type) { this.type = type; }
498 Xex.Term.prototype = {
499 IsTrue: function () { return true; },
500 Eval: function (domain) { return this.Clone (); },
501 Clone: function (domain) { return this; },
502 equals: function (obj)
504 return (this.type == obj.type
505 && this.val != undefined
506 && obj.val == this.val);
508 Matches: function (obj) { return this.equals (obj); },
509 toString: function ()
511 if (this.val != undefined)
512 return '<' + this.type + '>' + this.val + '</' + this.type + '>';
513 return '<' + this.type + '/>';
515 Intval: function () { throw new Xex.ErrTerm (Xex.Error.WrongType,
516 "Not an integer"); },
517 Strval: function () { throw new Xex.ErrTerm (Xex.Error.WrongType,
521 Node.prototype.firstElement = function ()
523 for (var n = this.firstChild; n; n = n.nextSibling)
529 Node.prototype.nextElement = function ()
531 for (var n = this.nextSibling; n; n = n.nextSibling)
538 function parse_defvar (domain, node)
540 var name = node.attributes['vname'].nodeValue;
542 throw new Xex.ErrTerm (Xex.Error.NoVariableName, node, '');
543 var vari = domain.variables[name];
544 var desc, val = null, range;
547 desc = vari.description;
551 node = node.firstElement ();
552 if (node && node.nodeName == 'description')
554 desc = node.firstChild.nodeValue;
555 node = node.nextElement ();
559 val = Xex.Term.Parse (domain, node);
560 node = node.nextElement ();
561 if (node && node.nodeName == 'possible-values')
562 for (node = node.firstElement (); node; node = node.nextElement ())
565 if (node.nodeName == 'range')
568 throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid,
569 'Range not allowed for ' + name);
571 for (var n = node.firstElement (); n; n = n.nextElement ())
573 var v = Xex.Term.Parse (domain, n);
575 throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid,
576 'Invalid range value: ' + val);
582 pval = Xex.Term.Parse (domain, node);
583 if (val.type != pval.type)
584 throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid,
585 'Invalid possible value: ' + pval);
588 range = new Array ();
594 domain.Defvar (name, desc, val, range);
598 function parse_defun_head (domain, node)
600 var name = node.attributes['fname'].nodeValue;
602 throw new Xex.ErrTerm (Xex.Error.NoFunctionName, node, '');
603 var args = new Array ();
604 var nfixed = 0, noptional = 0, nrest = 0;
606 node = node.firstElement ();
607 if (node && node.nodeName == 'args')
610 for (n = n.firstElement (); n; n = n.nextElement ())
612 if (n.nodeName == 'fixed')
614 else if (n.nodeName == 'optional')
616 else if (n.nodeName == 'rest')
619 throw new Xex.ErrTerm (Xex.Error.WrongType, n, n.nodeName);
622 throw new Xex.ErrTerm (Xex.Error.WrongType, n, 'Too many <rest>');
623 for (n = node.firstElement (); n; n = n.nextElement ())
624 args.push (domain.DefVar (n.attributes['vname'].nodeValue));
626 args.min_args = nfixed;
627 args.max_args = nrest == 0 ? nfixed + noptional : -1;
629 if (node.nodeName == 'defun')
630 domain.Defun (name, args, null);
632 domain.Defmacro (name, args, null);
636 function parse_defun_body (domain, node)
638 var name = node.attributes['fname'].nodeValue;
639 var func = domain.GetFunc (name);
641 for (node = node.firstElement (); node; node = node.nextElement ())
642 if (node.nodeName != 'description' && node.nodeName != 'args')
644 body = Xex.Term.Parse (domain, node, null);
648 Xex.Term.Parse = function (domain, node, stop)
650 if (arguments.length == 2)
652 var name = node.nodeName;
653 var parser = domain.termtypes[name];
656 return parser (domain, node);
657 if (name == 'defun' || name == 'defmacro')
659 name = parse_defun_head (domain, node);
660 parse_defun_body (domain, node);
661 return new Xex.StrTerm (name);
663 if (name == 'defvar')
665 name = parse_defvar (domain, node);
666 return new Xex.StrTerm (name);
668 return new Xex.Funcall.prototype.Parser (domain, node);
670 for (var n = node; n && n != stop; n = n.nextElement ())
671 if (n.nodeName == 'defun' || n.nodeName == 'defmacro')
672 parse_defun_head (domain, n);
674 for (var n = node; n && n != stop; n = n.nextElement ())
676 if (n.nodeName == 'defun' || n.nodeName == 'defmacro')
677 parse_defun_body (domain, n);
678 else if (n.nodeName == 'defvar')
679 parse_defvar (domain, n);
683 terms = new Array ();
684 terms.push (Xex.Term.Parse (domain, n));
691 Xex.Varref = function (vname)
697 var proto = new Xex.Term ('varref');
699 proto.Clone = function () { return new Xex.Varref (this.val); }
700 proto.Eval = function (domain)
702 var vari = domain.GetVarCreate (this.val);
703 Xex.Log (this.ToString () + '=>' + vari.val, domain.depth);
707 proto.Parser = function (domain, node)
709 return new Xex.Varref (node.attributes['vname'].nodeValue);
712 proto.ToString = function ()
714 return '<varref vname="' + this.val + '"/>';
717 Xex.Varref.prototype = proto;
720 var null_args = new Array ();
722 Xex.Funcall = function (func, vname, args)
726 this.args = args || null_args;
730 var proto = new Xex.Term ('funcall');
732 proto.Parser = function (domain, node)
734 var fname = node.nodeName;
737 if (fname == 'funcall')
738 fname = node.attributes['fname'].nodeValue;
739 var func = domain.GetFunc (fname);
741 attr = node.attributes['vname'];
742 vname = attr != undefined ? attr.nodeValue : null;
743 var args = Xex.Term.Parse (domain, node.firstElement (), null);
744 return new Xex.Funcall (func, vname, args);
747 proto.New = function (domain, fname, vname, args)
749 var func = domain.GetFunc (fname);
750 var funcall = new Xex.Funcall (func, vname, args);
751 if (func instanceof Xex.Macro)
752 funcall = funcall.Eval (domain);
756 proto.Eval = function (domain)
758 Xex.Log (this, domain.depth);
761 vari = domain.GetVarCreate (this.vname);
765 result = this.func.Call (domain, vari, this.args);
767 Xex.Log (' => ' + result, --domain.depth,
768 this.func instanceof Xex.Subrountine);
773 proto.Clone = function ()
775 return new Xex.Funcall (this.func, this.vari, this.args);
778 proto.equals = function (obj)
780 return (obj.type == 'funcall'
781 && obj.func == this.func
782 && obj.vari.equals (this.vari)
783 && obj.args.length == this.func.length);
786 proto.toString = function ()
789 var len = this.args.length;
790 var str = '<' + this.func.name;
792 str += ' vname="' + this.vname + '"';
795 if (this.func instanceof Xex.Subrountine)
796 for (var i = 0; i < len; i++)
797 arglist += this.args[i].toString ();
799 for (var i = 0; i < len; i++)
801 return str + '>' + arglist + '</' + this.func.name + '>';
804 Xex.Funcall.prototype = proto;
807 Xex.ErrTerm = function (ename, message, stack)
810 this.message = message;
815 var proto = new Xex.Term ('error');
817 proto.IsError = true;
819 proto.Parser = function (domain, node)
821 return new Xex.ErrTerm (node.attributes['ename'].nodeValue,
822 node.innerText, false);
825 proto.CallStack = function () { return stack; }
827 proto.SetCallStack = function (value) { statck = value; }
829 proto.Clone = function ()
831 return new Xex.ErrTerm (ename, message, false);
834 proto.equals = function (obj)
837 && obj.ename == ename && obj.message == message
838 && (obj.stack ? (stack && stack.length == obj.stack.length)
842 proto.Matches = function (obj)
844 return (obj.IsError && obj.ename == ename);
847 proto.toString = function ()
849 return '<error ename="' + this.ename + '">' + this.message + '</error>';
852 Xex.ErrTerm.prototype = proto;
855 Xex.IntTerm = function (num) { this.val = num; };
857 var proto = new Xex.Term ('integer');
859 proto.Intval = function () { return this.val; };
860 proto.IsTrue = function () { return this.val != 0; }
861 proto.Clone = function () { return new Xex.IntTerm (this.val); }
862 proto.Parser = function (domain, node)
864 var str = node.firstChild.nodeValue;
866 if (str.charAt (0) == '?' && str.length == 2)
867 return new Xex.IntTerm (str.charCodeAt (1));
868 return new Xex.IntTerm (parseInt (node.firstChild.nodeValue));
870 Xex.IntTerm.prototype = proto;
873 Xex.StrTerm = function (str) { this.val = str; };
875 var proto = new Xex.Term ('string');
877 proto.Strval = function () { return this.val; };
878 proto.IsTrue = function () { return this.val.length > 0; }
879 proto.Clone = function () { return new Xex.StrTerm (this.val); }
880 proto.Parser = function (domain, node)
882 return new Xex.StrTerm (node.firstChild ? node.firstChild.nodeValue : '');
884 Xex.StrTerm.prototype = proto;
887 Xex.SymTerm = function (str) { this.val = str; };
889 var proto = new Xex.Term ('symbol');
890 proto.IsSymbol = true;
891 proto.IsTrue = function () { return this.val != 'nil'; }
892 proto.Clone = function () { return new Xex.SymTerm (this.val); }
893 proto.Parser = function (domain, node)
895 return new Xex.SymTerm (node.firstChild.nodeValue);
897 Xex.SymTerm.prototype = proto;
900 Xex.LstTerm = function (list) { this.val = list; };
902 var proto = new Xex.Term ('list');
904 proto.IsTrue = function () { return this.val.length > 0; }
905 proto.Clone = function () { return new Xex.LstTerm (this.val.slice (0)); }
907 proto.equals = function (obj)
909 if (obj.type != 'list' || obj.val.length != this.val.length)
911 var i, len = this.val.length;
912 for (i = 0; i < len; i++)
913 if (! this.val[i].equals (obj.val[i]))
918 proto.Parser = function (domain, node)
920 var list = Xex.Term.Parse (domain, node.firstElement (), null);
921 return new Xex.LstTerm (list);
924 proto.toString = function ()
926 var len = this.val.length;
931 for (var i = 0; i < len; i++)
932 str += this.val[i].toString ();
933 return str + '</list>';
935 Xex.LstTerm.prototype = proto;
939 var basic = new Xex.Domain ('basic', null, null);
941 function Fset (domain, vari, args)
944 throw new Xex.ErrTerm (Xex.Error.NoVariableName,
945 'No variable name to set');
946 vari.SetValue (args[0]);
950 function Fnot (domain, vari, args)
952 return (args[0].IsTrue () ? Xex.Zero : Xex.One);
955 function maybe_set_intvar (vari, n)
957 var term = new Xex.IntTerm (n);
959 vari.SetValue (term);
963 function Fadd (domain, vari, args)
965 var n = vari ? vari.val.Intval () : 0;
966 var len = args.length;
968 for (var i = 0; i < len; i++)
969 n += args[i].Intval ();
970 return maybe_set_intvar (vari, n);
973 function Fmul (domain, vari, args)
975 var n = vari ? vari.val.Intval () : 1;
976 for (var i = 0; i < args.length; i++)
977 n *= args[i].Intval ();
978 return maybe_set_intvar (vari, n);
981 function Fsub (domain, vari, args)
987 n = args[0].Intval ();
992 n = vari.val.Intval ();
995 while (i < args.length)
996 n -= args[i++].Intval ();
997 return maybe_set_intvar (vari, n);
1000 function Fdiv (domain, vari, args)
1006 n = args[0].Intval ();
1011 n = vari.val.Intval ();
1014 while (i < args.length)
1015 n /= args[i++].Intval ();
1016 return maybe_set_intvar (vari, n);
1019 function Fmod (domain, vari, args)
1021 return maybe_set_intvar (vari, args[0].Intval () % args[1].Intval ());
1024 function Flogior (domain, vari, args)
1026 var n = vari == null ? 0 : vari.val;
1027 for (var i = 0; i < args.length; i++)
1029 return maybe_set_intvar (vari, n);
1032 function Flogand (domain, vari, args)
1037 Xex.Log ("logand arg args[0]" + args[0]);
1038 n = args[0].Intval ()
1043 Xex.Log ("logand arg var " + vari);
1044 n = vari.val.Intval ();
1047 while (n > 0 && i < args.length)
1049 Xex.Log ("logand arg " + args[i]);
1052 return maybe_set_intvar (vari, n);
1055 function Flsh (domain, vari, args)
1057 return maybe_set_intvar (vari, args[0].Intval () << args[1].Intval ());
1060 function Frsh (domain, vari, args)
1062 return maybe_set_intvar (vari, args[0].Intval () >> args[1].Intval ());
1065 function Fand (domain, vari, args)
1067 var len = args.length;
1068 for (var i = 0; i < len; i++)
1070 var result = args[i].Eval (domain);
1071 if (domain.Thrown ())
1073 if (! result.IsTrue ())
1079 function For (domain, vari, args)
1081 var len = args.length;
1082 for (var i = 0; i < len; i++)
1084 var result = args[i].Eval (domain);
1085 if (domain.Thrown ())
1087 if (result.IsTrue ())
1093 function Feq (domain, vari, args)
1095 for (var i = 1; i < args.length; i++)
1096 if (! args[i - 1].equals (args[i]))
1101 function Fnoteq (domain, vari, args)
1103 return (Feq (domain, vari, args) == Xex.One ? Xex.Zero : Xex.One);
1106 function Flt (domain, vari, args)
1108 var n = args[0].Intval ();
1110 for (var i = 1; i < args.length; i++)
1112 var n1 = args[i].Intval ();
1120 function Fle (domain, vari, args)
1122 var n = args[0].Intval ();
1123 for (var i = 1; i < args.length; i++)
1125 var n1 = args[i].Intval ();
1133 function Fgt (domain, vari, args)
1135 var n = args[0].Intval ();
1136 for (var i = 1; i < args.length; i++)
1138 var n1 = args[i].Intval ();
1146 function Fge (domain, vari, args)
1148 var n = args[0].Intval ();
1149 for (var i = 1; i < args.length; i++)
1151 var n1 = args[i].Intval ();
1159 function Fprogn (domain, vari, args)
1161 var result = Xex.One;
1162 var len = args.length;
1164 for (var i = 0; i < len; i++)
1166 result = args[i].Eval (domain);
1167 if (domain.Thrown ())
1173 function Fif (domain, vari, args)
1175 var result = args[0].Eval (domain);
1177 if (domain.Thrown ())
1179 if (result.IsTrue ())
1180 return args[1].Eval (domain);
1181 if (args.length == 2)
1183 return args[2].Eval (domain);
1186 function Fcond (domain, vari, args)
1188 for (var i = 0; i < args.length; i++)
1191 var result = list.val[0].Eval (domain);
1192 if (result.IsTrue ())
1194 for (var j = 1; j < list.val.length; j++)
1197 result = list.val[j].Eval (domain);
1199 if (domain.Thrown ())
1208 function eval_terms (domain, terms, idx)
1210 var result = Xex.Zero;
1211 domain.caught = false;
1212 for (var i = idx; i < terms.length; i++)
1214 result = terms[i].Eval (domain);
1215 if (domain.Thrown ())
1221 function Fcatch (domain, vari, args)
1226 if (args[0].IsError)
1229 result = eval_terms (domain, args, 1);
1231 if (e instanceof Xex.ErrTerm)
1233 if (! args[0].Matches (e))
1241 else if (args[0].IsSymbol)
1244 domain.Catch (args[0].val);
1245 result = eval_terms (domain, args, 1);
1249 vari.SetValue (result);
1257 throw new Xex.ErrTerm (Xex.Error.WrongArgument,
1258 "Not a symbol nor an error: " + args[0]);
1261 function Fthrow (domain, vari, args)
1263 if (args[0].IsSymbl)
1265 domain.ThrowSymbol (args[0]);
1266 return (args[args.length - 1]);
1268 if (args[0].IsError)
1272 throw new Xex.ErrTerm (Xex.Error.WrongArgument,
1273 "Not a symbol nor an error:" + args[0]);
1276 Xex.BasicDomain = basic;
1278 basic.DefSubr (Fset, "set", true, 1, 1);
1279 basic.DefAlias ("=", "set");
1280 basic.DefSubr (Fnot, "not", false, 1, 1);
1281 basic.DefAlias ("!", "not");
1282 basic.DefSubr (Fadd, "add", true, 1, -1);
1283 basic.DefSubr (Fmul, "mul", true, 1, -1);
1284 basic.DefAlias ("*", "mul");
1285 basic.DefSubr (Fsub, "sub", true, 1, -1);
1286 basic.DefAlias ("-", "sub");
1287 basic.DefSubr (Fdiv, "div", true, 1, -1);
1288 basic.DefAlias ("/", "div");
1289 basic.DefSubr (Fmod, "mod", true, 1, 2);
1290 basic.DefAlias ("%", "mod");
1291 basic.DefSubr (Flogior, "logior", true, 1, -1);
1292 basic.DefAlias ('|', "logior");
1293 basic.DefSubr (Flogand, "logand", true, 1, -1);
1294 basic.DefAlias ("&", "logand");
1295 basic.DefSubr (Flsh, "lsh", true, 1, 2);
1296 basic.DefAlias ("<<", "lsh");
1297 basic.DefSubr (Frsh, "rsh", true, 1, 2);
1298 basic.DefAlias (">>", "rsh");
1299 basic.DefSubr (Feq, "eq", false, 2, -1);
1300 basic.DefAlias ("==", "eq");
1301 basic.DefSubr (Fnoteq, "noteq", false, 2, 2);
1302 basic.DefAlias ("!=", "noteq");
1303 basic.DefSubr (Flt, "lt", false, 2, -1);
1304 basic.DefAlias ("<", "lt");
1305 basic.DefSubr (Fle, "le", false, 2, -1);
1306 basic.DefAlias ("<=", "le");
1307 basic.DefSubr (Fgt, "gt", false, 2, -1);
1308 basic.DefAlias (">", "gt");
1309 basic.DefSubr (Fge, "ge", false, 2, -1);
1310 basic.DefAlias (">=", "ge");
1311 basic.DefSubr (Fthrow, "throw", false, 1, 2);
1313 //basic.DefSubr (Fappend, "append", true, 0, -1);
1314 //basic.DefSubr (Fconcat, "concat", true, 0, -1);
1315 //basic.DefSubr (Fnth, "nth", false, 2, 2);
1316 //basic.DefSubr (Fcopy, "copy", false, 1, 1);
1317 //basic.DefSubr (Fins, "ins", true, 2, 2);
1318 //basic.DefSubr (Fdel, "del", true, 2, 2);
1319 //basic.DefSubr (Feval, "eval", false, 1, 1);
1320 //basic.DefSubr (Fbreak, "break", false, 0, 1);
1321 //basic.DefSubr (Freturn, "return", false, 0, 1);
1322 //basic.DefSubr (Fthrow, "throw", false, 1, 2);
1324 basic.DefSpecial (Fand, "and", false, 1, -1);
1325 basic.DefAlias ("&&", "and");
1326 basic.DefSpecial (For, "or", false, 1, -1);
1327 basic.DefAlias ("||", "or");
1328 basic.DefSpecial (Fprogn, "progn", false, 1, -1);
1329 basic.DefAlias ("expr", "progn");
1330 basic.DefSpecial (Fif, "if", false, 2, 3);
1331 //basic.DefSpecial (Fwhen, "when", false, 1, -1);
1332 //basic.DefSpecial (Floop, "loop", false, 1, -1);
1333 //basic.DefSpecial (Fwhile, "while", false, 1, -1);
1334 basic.DefSpecial (Fcond, "cond", false, 1, -1);
1335 //basic.DefSpecial (Fforeach, "foreach", true, 2, -1);
1336 //basic.DefSpecial (Fquote, "quote", false, 1, 1);
1337 //basic.DefSpecial (Ftype, "type", false, 1, 1);
1338 basic.DefSpecial (Fcatch, "catch", true, 2, -1);
1340 basic.DefType (Xex.Funcall.prototype);
1341 basic.DefType (Xex.Varref.prototype);
1342 basic.DefType (Xex.ErrTerm.prototype);
1343 basic.DefType (Xex.IntTerm.prototype);
1344 basic.DefType (Xex.StrTerm.prototype);
1345 basic.DefType (Xex.SymTerm.prototype);
1346 basic.DefType (Xex.LstTerm.prototype);
1350 Xex.Zero = new Xex.IntTerm (0);
1351 Xex.One = new Xex.IntTerm (1);
1352 Xex.nil = new Xex.SymTerm ('nil');
1354 Xex.Load = function (server, file)
1356 var obj = new XMLHttpRequest ();
1357 var url = server ? server + '/' + file : file;
1358 obj.open ('GET', url, false);
1359 obj.overrideMimeType ('text/xml');
1361 return (obj.responseXML && obj.responseXML.firstElement ());
1365 function getxml (event)
1367 var parser = new DOMParser ();
1368 Xex.xml = parser.parseFromString (event.data, 'text/xml');
1371 Xex.LoadTesting = function (server, file)
1373 var body = document.getElementsByTagName ('body')[0];
1374 Xex.xml = undefined;
1375 window.addEventListener ('message', getxml, false);
1376 var iframe = document.createElement ('iframe');
1377 iframe.src = server + '/loadxml.html#' + file;
1378 alert ('iframe created');
1379 body.appendChild (iframe);
1382 alert ('wait loading ' + file);
1383 window.removeEventListener ('message', getxml, false);
1384 body.removeChild (iframe);
1385 return (Xex.xml.firstChild);