-// -* coding: utf-8; -*
+// xex.js -- Xex (XML Expression) interpreter
+// Copyright (C) 2010
+// National Institute of Advanced Industrial Science and Technology (AIST)
+// Registration Number H15PRO112
+
+// This file is part of the m17n database; a sub-part of the m17n
+// library.
+
+// The m17n library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License
+// as published by the Free Software Foundation; either version 2.1 of
+// the License, or (at your option) any later version.
+
+// The m17n library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with the m17n library; if not, write to the Free
+// Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+// Please note that the code is not yet matured.
+
+var Xex = {};
+
+(function () { // Logging
+ // The logging node containing tracing information.
+ var log = null;
+ // Number of lines.
+ var lines;
+ // Style properties of the logging node.
+ var styles = { border: '1px solid black',
+ font: 'normal normal normal small monospace',
+ width: '600px',
+ minHeight: '300px',
+ maxHeight: '300px',
+ overflow: 'auto' };
+
+ // Toggle logging on and off. PARENT if non-null specifies the
+ // parent of the log node. The log node is appended to PARENT.
+ // If PARENT is null, 'body' node is assumed.
+ Xex.LogToggle = function (parent)
+ {
+ if (log)
+ {
+ log.parentNode.removeChild (log);
+ log = null;
+ return;
+ }
+ if (! parent)
+ parent = document.getElementsByTagName ('body')[0];
+ log = document.createElement ('ol');
+ for (var prop in styles)
+ log.style[prop] = styles[prop];
+ parent.appendChild (log);
+ lines = 0;
+ return log;
+ }
-var Xex = {
- LogNode: null,
- LogNodeLen: 0,
- Log: function (arg, indent, cont)
+ // Log ARG (string). INDENT if specified is a number of columns to
+ // indent. If INDENT is -1, ARG is appended to the last log.
+ Xex.Log = function (arg, indent)
{
- if (! Xex.LogNode)
+ if (! log)
return;
if (! arg)
{
- while (Xex.LogNode.childNodes.length > 0)
- Xex.LogNode.removeChild (Xex.LogNode.firstChild);
- LogNodeLen = 0;
+ while (log.childNodes.length > 0)
+ log.removeChild (log.firstChild);
+ lines = 0;
}
else
{
var node;
- if (cont)
- Xex.LogNode.lastChild.innerText += arg;
+ if (indent == -1)
+ log.lastChild.innerText += arg;
else
{
- LogNodeLen++;
- if (LogNodeLen >= 1000)
- node = Xex.LogNode.firstElement ();
+ lines++;
+ if (lines >= 256)
+ {
+ node = log.firstElement ();
+ log.start = lines - 254;
+ }
else
- node = document.createElement ('div');
+ node = document.createElement ('li');
if (indent != undefined)
node.style.textIndent = (indent + 1) + 'em';
else
node.style.textIndent = '0px';
- node.innerText = LogNodeLen + ': ' + arg;
- Xex.LogNode.appendChild (node);
- Xex.LogNode.scrollTop = Xex.LogNode.scrollHeight;
+ node.innerText = arg;
+ log.appendChild (node);
+ log.scrollTop = log.scrollHeight;
}
}
}
-};
+}) ();
Xex.Error = {
UnknownError: "unknown-error",
UncaughtThrow: "uncaught-throw"
};
-Xex.Variable = function (domain, name, desc, val, range)
+Xex.Variable = function (name, desc, val, range)
{
- this.domain = domain;
- this.name = name;
- this.desc = desc;
+ if (name)
+ this.name = name;
+ if (desc)
+ this.desc = desc;
this.val = val;
- this.range = range;
+ if (range)
+ this.range = range;
}
-Xex.Variable.prototype.clone = function ()
-{
- return new Xex.Variable (this.domain, this.name, this.desc,
- this.val, this.range);
-}
-
-Xex.Variable.prototype.Equals = function (obj)
-{
- return ((obj instanceof Xex.Variable)
- && obj.name == this.name);
-}
+Xex.Variable.prototype = {
+ clone: function ()
+ {
+ return new Xex.Variable (this.name, this.desc, this.val, this.range);
+ },
+ equals: function (obj)
+ {
+ return ((obj instanceof Xex.Variable)
+ && obj.name == this.name);
+ },
+ SetValue: function (term)
+ {
+ this.val = term;
+ return term;
+ }
+}
-Xex.Variable.prototype.SetValue = function (term)
-{
- this.val = term;
- return term;
-}
Xex.Function = function (name, with_var, min_args, max_args)
{
Xex.Subrountine = function (builtin, 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.Function.apply (this, [name, with_var, min_args, max_args]);
this.builtin = builtin;
}
Xex.SpecialForm = function (builtin, 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.Function.apply (this, [name, with_var, min_args, max_args]);
this.builtin = builtin;
}
Xex.Lambda = function (name, min_args, max_args, args, body)
{
- this.name = name;
- this.min_args = min_args;
- this.max_args = max_args;
+ Xex.Function.apply (this, [name, false, min_args, max_args]);
this.args = args;
this.body = body;
}
Xex.Macro = function (name, min_args, max_args, args, body)
{
- this.name = name;
- this.min_args = min_args;
- this.max_args = max_args;
+ Xex.Function.apply (this, [name, false, min_args, max_args]);
this.args = args;
this.body = body;
}
for (elt in parent.variables)
{
var vari = parent.variables[elt];
- this.variables[elt] = new Xex.Variable (this, vari.name, vari.desc,
+ this.variables[elt] = new Xex.Variable (vari.name, vari.desc,
vari.val, vari.range);
}
}
},
Defvar: function (name, desc, val, range)
{
- var vari = new Xex.Variable (this, name, desc, val, range);
+ var vari = new Xex.Variable (name, desc, val, range);
this.variables[name] = vari;
return vari;
},
{
var vari = this.variables[name];
if (! vari)
- vari = this.variables[name] = new Xex.Variable (this, name, null,
+ vari = this.variables[name] = new Xex.Variable (name, null,
Xex.Zero, null);
return vari;
},
IsTrue: function () { return true; },
Eval: function (domain) { return this.Clone (); },
Clone: function (domain) { return this; },
- Equals: function (obj)
+ equals: function (obj)
{
return (this.type == obj.type
&& this.val != undefined
&& obj.val == this.val);
},
- Matches: function (obj) { return this.Equals (obj); },
+ Matches: function (obj) { return this.equals (obj); },
toString: function ()
{
if (this.val != undefined)
return new Xex.Funcall (this.func, this.vari, this.args);
}
- proto.Equals = function (obj)
+ proto.equals = function (obj)
{
return (obj.type == 'funcall'
&& obj.func == this.func
- && obj.vari.Equals (this.vari)
+ && obj.vari.equals (this.vari)
&& obj.args.length == this.func.length);
}
return new Xex.ErrTerm (ename, message, false);
}
- proto.Equals = function (obj)
+ proto.equals = function (obj)
{
return (obj.IsError
&& obj.ename == ename && obj.message == message
proto.IsTrue = function () { return this.val.length > 0; }
proto.Clone = function () { return new Xex.LstTerm (this.val.slice (0)); }
- proto.Equals = function (obj)
+ proto.equals = function (obj)
{
if (obj.type != 'list' || obj.val.length != this.val.length)
return false;
var i, len = this.val.length;
for (i = 0; i < len; i++)
- if (! this.val[i].Equals (obj.val[i]))
+ if (! this.val[i].equals (obj.val[i]))
return false;
return true;
}
function Feq (domain, vari, args)
{
for (var i = 1; i < args.length; i++)
- if (! args[i - 1].Equals (args[i]))
+ if (! args[i - 1].equals (args[i]))
return Xex.Zero;
return Xex.One;
}
Xex.One = new Xex.IntTerm (1);
Xex.nil = new Xex.SymTerm ('nil');
-Xex.Load = function (server, file)
-{
- var obj = new XMLHttpRequest ();
- var url = server ? server + '/' + file : file;
- obj.open ('GET', url, false);
- obj.overrideMimeType ('text/xml');
- obj.send ('');
- return obj.responseXML.firstChild;
-}
+(function () {
+ var queue = new Array ();
+ var iframe = null;
+
+ function receiver (event)
+ {
+ var request = queue.shift ();
+ //alert ('received: ' + request[0]);
+ var parser = new DOMParser ();
+ var xml = parser.parseFromString (event.data, 'text/xml');
+ if (queue.length > 0)
+ {
+ document.getElementsByTagName ('body')[0].removeChild (iframe);
+ iframe.src = queue[0][0];
+ document.getElementsByTagName ('body')[0].appendChild (iframe);
+ }
+ else
+ {
+ window.removeEventListener ('message', receiver, false);
+ document.getElementsByTagName ('body')[0].removeChild (iframe);
+ }
+ request[1] (xml.firstElement (), request[2]);
+ event.preventDefault ();
+ };
+
+ Xex.Load = function (server, file, callback, arg)
+ {
+ var url = server + '/loadxml.html#' + file;
+ //alert ('loading file:' + file);
+ queue.push ([url, callback, arg]);
+ if (queue.length == 1)
+ {
+ window.addEventListener ('message', receiver, false);
+ iframe = document.createElement ('iframe');
+ iframe.style.display = 'none';
+ iframe.src = url;
+ //alert ('iframe created');
+ document.getElementsByTagName ('body')[0].appendChild (iframe);
+ }
+ }
+}) ();