+// -* coding: utf-8; -*
+
+var XEX = {};
+
+XEX.Variable = function (domain, name, val)
+{
+ this.domain = domain;
+ this.name = name;
+ this.val = val;
+}
+
+XEX.Variable.prototype = {
+ value: function () { return this.val; },
+ set_value: function (val) {
+ this.val = val;
+ return val;
+ },
+ clone: function () {
+ {
+ return new XEX.Variable (this.domain, this.name, this.value);
+ }
+ }
+}
+
+XEX.Function = function (name, with_var, min_args, max_args) {
+ this.name = name;
+ this.with_var = with_var;
+ this.min_args = min_args;
+ this.max_args = max_args;
+};
+
+XEX.Subrountine = function (builtin, name, with_var, min_args, max_args) {
+ this.prototype = new XEX.Function (name, with_var, min_args, max_args);
+ this.builtin = builtin;
+};
+
+XEX.Subrountine.prototype.Call = function (domain, vari, args)
+{
+ newargs = new Array ();
+ for (var i = 0; i < args.length; i++)
+ {
+ newargs[i] = args[i].Eval (domain);
+ if (domain.Thrown ())
+ return newargs[i];
+ }
+ return this.builtin (domain, vari, newargs)
+}
+
+XEX.SpecialForm = function (builtin, name, with_var, min_args, max_args)
+{
+ this.prototype = new XEX.Function (name, with_var, min_args, max_args);
+ this.builtin = builtin;
+}
+
+XEX.SpecialForm.prototype.Call = function (domain, vari, args)
+{
+ return this.builtin (domain, vari, args)
+}
+
+XEX.Lambda = function (name, min_args, max_args, args, body)
+{
+ this.prototype = new XEX.Function (name, false, min_args, max_args);
+ this.args = args;
+ this.body = body;
+}
+
+XEX.Lambda.prototype.Call = function (domain, vari, args)
+{
+ var current = domain.bindings;
+ var result = XEX.Term.zero;
+ var limit = max_args >= 0 ? args.length : args.length - 1;
+ var i;
+
+ try {
+ for (i = 0; i < limit; i++)
+ {
+ result = args[i].Eval (domain);
+ if (domain.Thrown ())
+ return result;
+ domain.Bind (this.args[i], result);
+ }
+ if (max_args < 0)
+ {
+ var list = new Array ();
+ for (i = 0; i < args[limit].length; i++)
+ {
+ result = args[limit].Eval (domain);
+ if (domain.Thrown ())
+ return result;
+ list[i] = result;
+ }
+ domain.Bind (this.args[limit], list);
+ }
+ try {
+ domain.Catch (XEX.CatchTag.Return);
+ for (var term in this.body)
+ {
+ result = term.Eval (domain);
+ if (domain.Thrown ())
+ return result;
+ }
+ } finally {
+ domain.Uncatch ();
+ }
+ } finally {
+ domain.UnboundTo (current);
+ }
+ return result;
+}
+
+XEX.Macro = function (name, min_args, max_args, args, body)
+{
+ this.prototype = new XEX.Function (name, false, min_args, max_args);
+ this.args = args;
+ this.body = body;
+}
+
+XEX.Macro.prototype.Call = function (domain, vari, args)
+{
+ var current = domain.bindings;
+ var result = XEX.Term.Zero;
+ var i;
+
+ try {
+ for (i = 0; i < args.length; i++)
+ domain.Bind (this.args[i], args[i]);
+ try {
+ domain.Catch (XEX.CatchTag.Return);
+ for (var term in body)
+ {
+ result = term.Eval (domain);
+ if (domain.Thrown ())
+ break;
+ }
+ } finally {
+ domain.Uncatch ();
+ }
+ } finally {
+ domain.UnboundTo (current);
+ }
+ return result;
+}
+
+XEX.EvalConstant = function (domain)
+{
+ if (this.nodeName == 'integer')
+ alert ("integer:" + this.attributes[0].nodeValue);
+ else if (this.nodeName == 'string')
+ alert ("string:" + this.firstChild.nodeValue);
+ return this;
+};
+
+XEX.EvalFuncall = function (domain)
+{
+ try {
+ domain.CallStackPush (this);
+ } catch (e) {
+ alert (e);
+ }
+}
+
+var obj = new XMLHttpRequest ();
+obj.open ('GET', 'xex.xml', false);
+obj.send ('');
+var body = obj.responseXML.firstChild;
+for (var i = body.childNodes.length - 1; i >= 0 ; i--)
+ {
+ var node = body.childNodes[i];
+ if (node.nodeType == 1)
+ node.Eval = XEX.EvalConstant;
+ else
+ body.removeChild (node);
+ }
+for (var i = 0; i < body.childNodes.length; i++)
+ {
+ var node = body.childNodes[i];
+ node.Eval ();
+ }
+
+