X-Git-Url: http://git.chise.org/gitweb/?p=m17n%2Fm17n-lib-js.git;a=blobdiff_plain;f=xex.js;h=19683a1883e4501b645a42f3cb4554efac5a62ac;hp=0024512758601d09c1a7f4cb3f47586906e75c5a;hb=39ade7f8b19281d743552e5282dcefc691e35f8f;hpb=02ddd0caed0fdf2abfefc8365fb18f6bd876dda0 diff --git a/xex.js b/xex.js index 0024512..19683a1 100644 --- a/xex.js +++ b/xex.js @@ -1,35 +1,99 @@ -// -* coding: utf-8; -* +// xex.js -- Xex (XML Expression) interpreter +// Copyright (C) 2010 +// National Institute of Advanced Industrial Science and Technology (AIST) +// Registration Number H15PRO112 -var Xex = {}; +// This file is part of the m17n database; a sub-part of the m17n +// library. -Xex.Alist = function () -{ - this.count = 0; -} +// 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. -Xex.Alist.prototype.put = function (key, val) -{ - this.count++; - return (this[key] = val); -} -Xex.Alist.prototype.clone = function () -{ - var alist = new Xex.Alist (); - for (key in this) - alist[key] = this[key]; - return alist; -} -Xex.Alist.prototype.toString = function () -{ - var str = 'alist:'; - for (key in this) - str += '"' + key + '"'; - return str; -} +// 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. + +var Xex = {}; -// Xex.alist = new Xex.Alist (); -// Xex.alist.put ('abc', "ABC"); -// alert (Xex.alist['abc']); +(function () { // Tracing + // 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: '100%', + 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 the 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; + } + + // Log ARG + Xex.Log = function (arg, indent) + { + if (! log) + return; + if (! arg) + { + while (log.childNodes.length > 0) + log.removeChild (log.firstChild); + lines = 0; + } + else + { + var node; + if (indent == -1) + log.lastChild.innerText += arg; + else + { + lines++; + if (lines >= 60) + { + node = log.firstElement (); + log.start = lines - 58; + } + else + node = document.createElement ('li'); + if (indent != undefined) + node.style.textIndent = (indent + 1) + 'em'; + else + node.style.textIndent = '0px'; + node.innerText = arg; + log.appendChild (node); + log.scrollTop = log.scrollHeight; + } + } + } +}) (); Xex.Error = { UnknownError: "unknown-error", @@ -45,7 +109,8 @@ Xex.Error = { UnknownFunction: "unknown-function", MacroExpansionError: "macro-expansion-error", - NoVariableName: "no-variable-anme", + NoVariableName: "no-variable-name", + NoFunctionName: "no-funcion-name", // Run time errors. ArithmeticError: "arithmetic-error", @@ -56,35 +121,43 @@ Xex.Error = { UncaughtThrow: "uncaught-throw" }; -Xex.Variable = function (domain, name, val) +Xex.Variable = function (domain, name, desc, val, range) { this.domain = domain; this.name = name; + this.desc = desc; this.val = val; + this.range = range; } -Xex.Variable.prototype.clone = function () { - return new Xex.Variable (this.domain, this.name, this.value); +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) { +Xex.Variable.prototype.Equals = function (obj) +{ return ((obj instanceof Xex.Variable) && obj.name == this.name); } -Xex.Variable.prototype.SetValue = function (term) { +Xex.Variable.prototype.SetValue = function (term) +{ this.val = term; return term; } -Xex.Function = function (name, with_var, min_args, max_args) { +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) { +Xex.Subrountine = function (builtin, name, with_var, min_args, max_args) +{ this.name = name; this.with_var = with_var; this.min_args = min_args; @@ -94,7 +167,7 @@ Xex.Subrountine = function (builtin, name, with_var, min_args, max_args) { Xex.Subrountine.prototype.Call = function (domain, vari, args) { - newargs = new Array (); + var newargs = new Array (); for (var i = 0; i < args.length; i++) { newargs[i] = args[i].Eval (domain); @@ -121,7 +194,6 @@ Xex.SpecialForm.prototype.Call = function (domain, vari, args) Xex.Lambda = function (name, min_args, max_args, args, body) { this.name = name; - this.with_var = with_var; this.min_args = min_args; this.max_args = max_args; this.args = args; @@ -175,7 +247,6 @@ Xex.Lambda.prototype.Call = function (domain, vari, args) Xex.Macro = function (name, min_args, max_args, args, body) { this.name = name; - this.with_var = with_var; this.min_args = min_args; this.max_args = max_args; this.args = args; @@ -193,9 +264,9 @@ Xex.Macro.prototype.Call = function (domain, vari, args) domain.Bind (this.args[i], args[i]); try { domain.Catch (Xex.CatchTag.Return); - for (var term in body) + for (var i in this.body) { - result = term.Eval (domain); + result = this.body[i].Eval (domain); if (domain.Thrown ()) break; } @@ -254,7 +325,11 @@ Xex.Domain = function (name, parent, context) for (elt in parent.functions) this.functions[elt] = parent.functions[elt]; for (elt in parent.variables) - this.variables[elt] = parent.variables[elt]; + { + var vari = parent.variables[elt]; + this.variables[elt] = new Xex.Variable (this, vari.name, vari.desc, + vari.val, vari.range); + } } this.call_stack = new Array (); @@ -352,7 +427,7 @@ Xex.Domain.prototype = { this.functions[name] = new Xex.Lambda (name, min_args, max_args, args, body); }, - DefunByFunc: function (func) { this.functions[func.Name] = func; }, + DefunByFunc: function (func) { this.functions[func.name] = func; }, Defmacro: function (name, min_args, max_args, args, body) { this.functions[name] = new Xex.Macro (name, min_args, max_args, @@ -362,30 +437,20 @@ Xex.Domain.prototype = { { var func = this.functions[fname]; + if (! func) + throw new Xex.ErrTerm (Xex.Error.UnknownFunction, fname); if (this.termtypes[alias]) throw new Xex.ErrTerm (Xex.Error.FunctionConflict, "Already defined as a term type: " + alias); if (this.functions[alias]) throw new Xex.ErrTerm (Xex.Error.FunctionConflict, "Already defined as a function: " + alias); - if (! func) - throw new Xex.ErrTerm (Xex.Error.UnknownFunction, fname); this.functions[alias] = func; }, - Defvar: function (name) + Defvar: function (name, desc, val, range) { - var vari = this.variables[name]; - if (vari) - { - if (vari.Typed) - throw new Xex.ErrTerm (Xex.Error.VariableTypeConflict, - "Not a non-typed variable: " + name); - } - else - { - vari = new Xex.Variable (this, name, Xex.Zero); - this.variables[name] = vari; - } + var vari = new Xex.Variable (this, name, desc, val, range); + this.variables[name] = vari; return vari; }, GetFunc: function (name) @@ -393,7 +458,7 @@ Xex.Domain.prototype = { var func = this.functions[name]; if (! func) throw new Xex.ErrTerm (Xex.Error.UnknownFunction, - "Unknown function: " + this + ':' + name); + "Unknown function: " + name); return func; }, CopyFunc: function (domain, name) @@ -411,7 +476,8 @@ Xex.Domain.prototype = { { var vari = this.variables[name]; if (! vari) - vari = this.variables[name] = new Xex.Variable (this, name, Xex.Zero); + vari = this.variables[name] = new Xex.Variable (this, name, null, + Xex.Zero, null); return vari; }, GetVar: function (name) { return this.variables[name]; }, @@ -441,7 +507,7 @@ Xex.Term.prototype = { Equals: function (obj) { return (this.type == obj.type - && this.val + && this.val != undefined && obj.val == this.val); }, Matches: function (obj) { return this.Equals (obj); }, @@ -450,52 +516,182 @@ Xex.Term.prototype = { if (this.val != undefined) return '<' + this.type + '>' + this.val + ''; return '<' + this.type + '/>'; - } + }, + Intval: function () { throw new Xex.ErrTerm (Xex.Error.WrongType, + "Not an integer"); }, + Strval: function () { throw new Xex.ErrTerm (Xex.Error.WrongType, + "Not a string"); } }; -Xex.ParseTerm = function (domain, node) +Node.prototype.firstElement = function () { - var name = node.nodeName; - var parser = domain.termtypes[name]; - - if (parser) - return parser (domain, node); - if (name == 'defun' || name == 'defmacro') - { - name = parse_defun_head (domain, node); - parse_defun_body (domain, node); - return new Xex.StrTerm (name); - } - if (name == 'defvar') - { - name = parse_defvar (doamin, node); - return new Xex.StrTerm (nanme); - } - - return new Xex.Funcall.prototype.Parser (domain, node); + for (var n = this.firstChild; n; n = n.nextSibling) + if (n.nodeType == 1) + return n; + return null; } -Xex.ParseTermList = function (domain, node) +Node.prototype.nextElement = function () { - for (var n = node; n; n = n.nextSibling) + for (var n = this.nextSibling; n; n = n.nextSibling) if (n.nodeType == 1) + return n; + return null; +}; + +(function () { + function parse_defvar (domain, node) + { + var name = node.attributes['vname'].nodeValue; + if (! name) + throw new Xex.ErrTerm (Xex.Error.NoVariableName, node, ''); + var vari = domain.variables[name]; + var desc, val = null, range; + if (vari) { - if (n.nodeName == 'defun' || n.nodeName == 'defmacro') - Xex.parse_defun_head (domain, n); + desc = vari.description; + val = vari.val; + range = vari.range; } - var terms = new Array (); - for (var n = node; n; n = n.nextSibling) - if (n.nodeType == 1) + node = node.firstElement (); + if (node && node.nodeName == 'description') + { + desc = node.firstChild.nodeValue; + node = node.nextElement (); + } + if (node) + { + val = Xex.Term.Parse (domain, node); + node = node.nextElement (); + if (node && node.nodeName == 'possible-values') + for (node = node.firstElement (); node; node = node.nextElement ()) + { + var pval; + if (node.nodeName == 'range') + { + if (! val.IsInt) + throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid, + 'Range not allowed for ' + name); + pval = new Array (); + for (var n = node.firstElement (); n; n = n.nextElement ()) + { + var v = Xex.Term.Parse (domain, n); + if (! v.IsInt) + throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid, + 'Invalid range value: ' + val); + pval.push (v); + } + } + else + { + pval = Xex.Term.Parse (domain, node); + if (val.type != pval.type) + throw new Xex.ErrTerm (Xex.Error.TermTypeInvalid, + 'Invalid possible value: ' + pval); + } + if (! range) + range = new Array (); + range.push (pval); + } + } + if (val == null) + val = Xex.Zero; + domain.Defvar (name, desc, val, range); + return name; + } + + function parse_defun_head (domain, node) + { + var name = node.attributes['fname'].nodeValue; + if (! name) + throw new Xex.ErrTerm (Xex.Error.NoFunctionName, node, ''); + var args = new Array (); + var nfixed = 0, noptional = 0, nrest = 0; + + node = node.firstElement (); + if (node && node.nodeName == 'args') + { + var n; + for (n = n.firstElement (); n; n = n.nextElement ()) + { + if (n.nodeName == 'fixed') + nfixed++; + else if (n.nodeName == 'optional') + noptional++; + else if (n.nodeName == 'rest') + nrest++; + else + throw new Xex.ErrTerm (Xex.Error.WrongType, n, n.nodeName); + } + if (nrest > 1) + throw new Xex.ErrTerm (Xex.Error.WrongType, n, 'Too many '); + for (n = node.firstElement (); n; n = n.nextElement ()) + args.push (domain.DefVar (n.attributes['vname'].nodeValue)); + } + args.min_args = nfixed; + args.max_args = nrest == 0 ? nfixed + noptional : -1; + + if (node.nodeName == 'defun') + domain.Defun (name, args, null); + else + domain.Defmacro (name, args, null); + return name; + } + + function parse_defun_body (domain, node) + { + var name = node.attributes['fname'].nodeValue; + var func = domain.GetFunc (name); + var body; + for (node = node.firstElement (); node; node = node.nextElement ()) + if (node.nodeName != 'description' && node.nodeName != 'args') + break; + body = Xex.Term.Parse (domain, node, null); + func.body = body; + } + + Xex.Term.Parse = function (domain, node, stop) + { + if (arguments.length == 2) + { + var name = node.nodeName; + var parser = domain.termtypes[name]; + + if (parser) + return parser (domain, node); + if (name == 'defun' || name == 'defmacro') + { + name = parse_defun_head (domain, node); + parse_defun_body (domain, node); + return new Xex.StrTerm (name); + } + if (name == 'defvar') + { + name = parse_defvar (domain, node); + return new Xex.StrTerm (name); + } + return new Xex.Funcall.prototype.Parser (domain, node); + } + for (var n = node; n && n != stop; n = n.nextElement ()) + if (n.nodeName == 'defun' || n.nodeName == 'defmacro') + parse_defun_head (domain, n); + var terms = null; + for (var n = node; n && n != stop; n = n.nextElement ()) { if (n.nodeName == 'defun' || n.nodeName == 'defmacro') - Xex.parse_defun_body (domain, n); + parse_defun_body (domain, n); else if (n.nodeName == 'defvar') - Xex.parse_defvar (domain, n); + parse_defvar (domain, n); else - terms.push (Xex.ParseTerm (domain, n)); + { + if (! terms) + terms = new Array (); + terms.push (Xex.Term.Parse (domain, n)); + } } - return terms; -} + return terms; + } +}) (); Xex.Varref = function (vname) { @@ -508,9 +704,9 @@ Xex.Varref = function (vname) proto.Clone = function () { return new Xex.Varref (this.val); } proto.Eval = function (domain) { - if (! this.vari || this.vari.domain != domain) - this.vari = domain.GetVarCreate (this.val); - return this.vari.val; + var vari = domain.GetVarCreate (this.val); + Xex.Log (this.ToString () + '=>' + vari.val, domain.depth); + return vari.val; } proto.Parser = function (domain, node) @@ -518,15 +714,20 @@ Xex.Varref = function (vname) return new Xex.Varref (node.attributes['vname'].nodeValue); } + proto.ToString = function () + { + return ''; + } + Xex.Varref.prototype = proto; }) (); var null_args = new Array (); -Xex.Funcall = function (func, vari, args) +Xex.Funcall = function (func, vname, args) { this.func = func; - this.vari = vari; + this.vname = vname; this.args = args || null_args; }; @@ -539,20 +740,19 @@ Xex.Funcall = function (func, vari, args) var attr; if (fname == 'funcall') - fname = node.attributes['fname'] + fname = node.attributes['fname'].nodeValue; var func = domain.GetFunc (fname); - var vari; + var vname; attr = node.attributes['vname']; - vari = attr != undefined ? domain.GetVarCreate (attr.nodeValue) : false; - var args = Xex.ParseTermList (domain, node.firstChild); - return new Xex.Funcall (func, vari, args); + vname = attr != undefined ? attr.nodeValue : null; + var args = Xex.Term.Parse (domain, node.firstElement (), null); + return new Xex.Funcall (func, vname, args); } proto.New = function (domain, fname, vname, args) { var func = domain.GetFunc (fname); - var vari = vname ? domain.GetVarCreate (vname) : null; - var funcall = new Xex.Funcall (func, vari, args); + var funcall = new Xex.Funcall (func, vname, args); if (func instanceof Xex.Macro) funcall = funcall.Eval (domain); return funcall; @@ -560,7 +760,19 @@ Xex.Funcall = function (func, vari, args) proto.Eval = function (domain) { - return this.func.Call (domain, this.vari, this.args); + Xex.Log (this, domain.depth); + var vari; + if (this.vname) + vari = domain.GetVarCreate (this.vname); + domain.depth++; + var result; + try { + result = this.func.Call (domain, vari, this.args); + } finally { + Xex.Log (' => ' + result, --domain.depth, + this.func instanceof Xex.Subrountine); + } + return result; } proto.Clone = function () @@ -580,11 +792,18 @@ Xex.Funcall = function (func, vari, args) { var arglist = '' var len = this.args.length; + var str = '<' + this.func.name; + if (this.vname) + str += ' vname="' + this.vname + '"'; if (len == 0) - return '<' + this.func.name + '/>'; - for (var i = 0; i < len; i++) - arglist += this.args[i].toString (); - return '<' + this.func.name + '>' + arglist + ''; + return str + '/>'; + if (this.func instanceof Xex.Subrountine) + for (var i = 0; i < len; i++) + arglist += this.args[i].toString (); + else + for (var i = 0; i < len; i++) + arglist += '.'; + return str + '>' + arglist + ''; } Xex.Funcall.prototype = proto; @@ -642,6 +861,7 @@ Xex.IntTerm = function (num) { this.val = num; }; (function () { var proto = new Xex.Term ('integer'); proto.IsInt = true; + proto.Intval = function () { return this.val; }; proto.IsTrue = function () { return this.val != 0; } proto.Clone = function () { return new Xex.IntTerm (this.val); } proto.Parser = function (domain, node) @@ -659,11 +879,12 @@ Xex.StrTerm = function (str) { this.val = str; }; (function () { var proto = new Xex.Term ('string'); proto.IsStr = true; + proto.Strval = function () { return this.val; }; proto.IsTrue = function () { return this.val.length > 0; } proto.Clone = function () { return new Xex.StrTerm (this.val); } proto.Parser = function (domain, node) { - return new Xex.StrTerm (node.firstChild.nodeValue); + return new Xex.StrTerm (node.firstChild ? node.firstChild.nodeValue : ''); } Xex.StrTerm.prototype = proto; }) (); @@ -701,7 +922,7 @@ Xex.LstTerm = function (list) { this.val = list; }; proto.Parser = function (domain, node) { - var list = Xex.ParseTermList (domain, node.firstChild); + var list = Xex.Term.Parse (domain, node.firstElement (), null); return new Xex.LstTerm (list); } @@ -724,27 +945,128 @@ Xex.LstTerm = function (list) { this.val = list; }; function Fset (domain, vari, args) { - return vari.SetValue (args[0]); + if (! vari) + throw new Xex.ErrTerm (Xex.Error.NoVariableName, + 'No variable name to set'); + vari.SetValue (args[0]); + return args[0]; + } + + function Fnot (domain, vari, args) + { + return (args[0].IsTrue () ? Xex.Zero : Xex.One); } function maybe_set_intvar (vari, n) { var term = new Xex.IntTerm (n); - if (vari != null) + if (vari) vari.SetValue (term); return term; } function Fadd (domain, vari, args) { - var n = vari ? vari.val.val : 0; + var n = vari ? vari.val.Intval () : 0; var len = args.length; for (var i = 0; i < len; i++) - n += args[i].val; + n += args[i].Intval (); + return maybe_set_intvar (vari, n); + } + + function Fmul (domain, vari, args) + { + var n = vari ? vari.val.Intval () : 1; + for (var i = 0; i < args.length; i++) + n *= args[i].Intval (); + return maybe_set_intvar (vari, n); + } + + function Fsub (domain, vari, args) + { + var n, i; + + if (! vari) + { + n = args[0].Intval (); + i = 1; + } + else + { + n = vari.val.Intval (); + i = 0; + } + while (i < args.length) + n -= args[i++].Intval (); + return maybe_set_intvar (vari, n); + } + + function Fdiv (domain, vari, args) + { + var n, i; + + if (! vari == null) + { + n = args[0].Intval (); + i = 1; + } + else + { + n = vari.val.Intval (); + i = 0; + } + while (i < args.length) + n /= args[i++].Intval (); + return maybe_set_intvar (vari, n); + } + + function Fmod (domain, vari, args) + { + return maybe_set_intvar (vari, args[0].Intval () % args[1].Intval ()); + } + + function Flogior (domain, vari, args) + { + var n = vari == null ? 0 : vari.val; + for (var i = 0; i < args.length; i++) + n |= args[i].val; + return maybe_set_intvar (vari, n); + } + + function Flogand (domain, vari, args) + { + var n, i; + if (vari == null) + { + Xex.Log ("logand arg args[0]" + args[0]); + n = args[0].Intval () + i = 1; + } + else + { + Xex.Log ("logand arg var " + vari); + n = vari.val.Intval (); + i = 0; + } + while (n > 0 && i < args.length) + { + Xex.Log ("logand arg " + args[i]); + n &= args[i++].val; + } return maybe_set_intvar (vari, n); } + function Flsh (domain, vari, args) + { + return maybe_set_intvar (vari, args[0].Intval () << args[1].Intval ()); + } + + function Frsh (domain, vari, args) + { + return maybe_set_intvar (vari, args[0].Intval () >> args[1].Intval ()); + } + function Fand (domain, vari, args) { var len = args.length; @@ -753,7 +1075,7 @@ Xex.LstTerm = function (list) { this.val = list; }; var result = args[i].Eval (domain); if (domain.Thrown ()) return result; - if (! result.IsTrue) + if (! result.IsTrue ()) return Xex.Zero; } return Xex.One; @@ -767,12 +1089,78 @@ Xex.LstTerm = function (list) { this.val = list; }; var result = args[i].Eval (domain); if (domain.Thrown ()) return result; - if (result.IsTrue) + if (result.IsTrue ()) return Xex.One; } return Xex.Zero; } + function Feq (domain, vari, args) + { + for (var i = 1; i < args.length; i++) + if (! args[i - 1].Equals (args[i])) + return Xex.Zero; + return Xex.One; + } + + function Fnoteq (domain, vari, args) + { + return (Feq (domain, vari, args) == Xex.One ? Xex.Zero : Xex.One); + } + + function Flt (domain, vari, args) + { + var n = args[0].Intval (); + + for (var i = 1; i < args.length; i++) + { + var n1 = args[i].Intval (); + if (n >= n1) + return Xex.Zero; + n = n1; + } + return Xex.One; + } + + function Fle (domain, vari, args) + { + var n = args[0].Intval (); + for (var i = 1; i < args.length; i++) + { + var n1 = args[i].Intval (); + if (n > n1) + return Xex.Zero; + n = n1; + } + return Xex.One; + } + + function Fgt (domain, vari, args) + { + var n = args[0].Intval (); + for (var i = 1; i < args.length; i++) + { + var n1 = args[i].Intval (); + if (n <= n1) + return Xex.Zero; + n = n1; + } + return Xex.One; + } + + function Fge (domain, vari, args) + { + var n = args[0].Intval (); + for (var i = 1; i < args.length; i++) + { + var n1 = args[i].Intval (); + if (n < n1) + return Xex.Zero; + n = n1; + } + return Xex.One; + } + function Fprogn (domain, vari, args) { var result = Xex.One; @@ -793,13 +1181,35 @@ Xex.LstTerm = function (list) { this.val = list; }; if (domain.Thrown ()) return result; - if (result.IsTrue) + if (result.IsTrue ()) return args[1].Eval (domain); - if (args.Length == 2) - return Zero; + if (args.length == 2) + return Xex.Zero; return args[2].Eval (domain); } + function Fcond (domain, vari, args) + { + for (var i = 0; i < args.length; i++) + { + var list = args[i]; + var result = list.val[0].Eval (domain); + if (result.IsTrue ()) + { + for (var j = 1; j < list.val.length; j++) + { + domain.depth++; + result = list.val[j].Eval (domain); + domain.depth--; + if (domain.Thrown ()) + return result; + } + return result; + } + } + return Xex.Zero; + } + function eval_terms (domain, terms, idx) { var result = Xex.Zero; @@ -871,14 +1281,65 @@ Xex.LstTerm = function (list) { this.val = list; }; Xex.BasicDomain = basic; basic.DefSubr (Fset, "set", true, 1, 1); + basic.DefAlias ("=", "set"); + basic.DefSubr (Fnot, "not", false, 1, 1); + basic.DefAlias ("!", "not"); basic.DefSubr (Fadd, "add", true, 1, -1); + basic.DefSubr (Fmul, "mul", true, 1, -1); + basic.DefAlias ("*", "mul"); + basic.DefSubr (Fsub, "sub", true, 1, -1); + basic.DefAlias ("-", "sub"); + basic.DefSubr (Fdiv, "div", true, 1, -1); + basic.DefAlias ("/", "div"); + basic.DefSubr (Fmod, "mod", true, 1, 2); + basic.DefAlias ("%", "mod"); + basic.DefSubr (Flogior, "logior", true, 1, -1); + basic.DefAlias ('|', "logior"); + basic.DefSubr (Flogand, "logand", true, 1, -1); + basic.DefAlias ("&", "logand"); + basic.DefSubr (Flsh, "lsh", true, 1, 2); + basic.DefAlias ("<<", "lsh"); + basic.DefSubr (Frsh, "rsh", true, 1, 2); + basic.DefAlias (">>", "rsh"); + basic.DefSubr (Feq, "eq", false, 2, -1); + basic.DefAlias ("==", "eq"); + basic.DefSubr (Fnoteq, "noteq", false, 2, 2); + basic.DefAlias ("!=", "noteq"); + basic.DefSubr (Flt, "lt", false, 2, -1); + basic.DefAlias ("<", "lt"); + basic.DefSubr (Fle, "le", false, 2, -1); + basic.DefAlias ("<=", "le"); + basic.DefSubr (Fgt, "gt", false, 2, -1); + basic.DefAlias (">", "gt"); + basic.DefSubr (Fge, "ge", false, 2, -1); + basic.DefAlias (">=", "ge"); basic.DefSubr (Fthrow, "throw", false, 1, 2); + //basic.DefSubr (Fappend, "append", true, 0, -1); + //basic.DefSubr (Fconcat, "concat", true, 0, -1); + //basic.DefSubr (Fnth, "nth", false, 2, 2); + //basic.DefSubr (Fcopy, "copy", false, 1, 1); + //basic.DefSubr (Fins, "ins", true, 2, 2); + //basic.DefSubr (Fdel, "del", true, 2, 2); + //basic.DefSubr (Feval, "eval", false, 1, 1); + //basic.DefSubr (Fbreak, "break", false, 0, 1); + //basic.DefSubr (Freturn, "return", false, 0, 1); + //basic.DefSubr (Fthrow, "throw", false, 1, 2); + basic.DefSpecial (Fand, "and", false, 1, -1); + basic.DefAlias ("&&", "and"); basic.DefSpecial (For, "or", false, 1, -1); - basic.DefAlias ("=", "set"); + basic.DefAlias ("||", "or"); basic.DefSpecial (Fprogn, "progn", false, 1, -1); + basic.DefAlias ("expr", "progn"); basic.DefSpecial (Fif, "if", false, 2, 3); + //basic.DefSpecial (Fwhen, "when", false, 1, -1); + //basic.DefSpecial (Floop, "loop", false, 1, -1); + //basic.DefSpecial (Fwhile, "while", false, 1, -1); + basic.DefSpecial (Fcond, "cond", false, 1, -1); + //basic.DefSpecial (Fforeach, "foreach", true, 2, -1); + //basic.DefSpecial (Fquote, "quote", false, 1, 1); + //basic.DefSpecial (Ftype, "type", false, 1, 1); basic.DefSpecial (Fcatch, "catch", true, 2, -1); basic.DefType (Xex.Funcall.prototype); @@ -893,6 +1354,7 @@ Xex.LstTerm = function (list) { this.val = list; }; Xex.Zero = new Xex.IntTerm (0); Xex.One = new Xex.IntTerm (1); +Xex.nil = new Xex.SymTerm ('nil'); Xex.Load = function (server, file) { @@ -901,1046 +1363,5 @@ Xex.Load = function (server, file) obj.open ('GET', url, false); obj.overrideMimeType ('text/xml'); obj.send (''); - return obj.responseXML.firstChild; -} - -var MIM = { - // URL of the input method server. - server: "http://www.m17n.org/common/mim-js", - // Boolean flag to tell if MIM is active or not. - enabled: true, - // Boolean flag to tell if MIM is running in debug mode or not. - debug: false, - // List of registered input methods. - im_list: {}, - // Global input method data - im_global: null, - // Currently selected input method. - current: false, - - // enum - LoadStatus: { NotLoaded:0, Loading:1, Loaded:2, Error:-1 }, - ChangedStatus: { - None: 0x00, - StateTitle: 0x01, - PreeditText:0x02, - CursorPos: 0x04, - CandidateList:0x08, - CandidateIndex:0x10, - CandidateShow:0x20, - Preedit: 0x06, // PreeditText | CursorPos - Candidate: 0x38 // CandidateList | CandidateIndex | CandidateShow - }, - KeyModifier: { - SL: 0x00400000, - SR: 0x00800000, - S: 0x00C00000, - CL: 0x01000000, - CR: 0x02000000, - C: 0x03000000, - AL: 0x04000000, - AR: 0x08000000, - A: 0x0C000000, - ML: 0x04000000, - MR: 0x08000000, - M: 0x0C000000, - G: 0x10000000, - s: 0x20000000, - H: 0x40000000, - High: 0x70000000, - All: 0x7FC00000 - }, - Error: { - ParseError: "parse-error" - } -}; - -(function () { - var keysyms = new Array (); - keysyms["bs"] = "backspace"; - keysyms["lf"] = "linefeed"; - keysyms["cr"] = keysyms["enter"] = "return"; - keysyms["esc"] = "escape"; - keysyms["spc"] = "space"; - keysyms["del"] = "delete"; - - function decode_keysym (str) { - var parts = str.split ("-"); - var len = parts.length, i; - var has_modifier = len > 1; - - for (i = 0; i < len - 1; i++) - if (! MIM.KeyModifier.hasOwnProperty (parts[i])) - return false; - var key = parts[len - 1]; - if (key.length > 1) - { - key = keysyms[key.toLowerCase ()]; - if (key) - { - if (len > 1) - { - str = parts[0]; - for (i = 1; i < len - 1; i++) - str += '-' + parts[i]; - str += '-' + key; - } - else - str = key; - } - } - if (has_modifier) - { - parts = new Array (); - parts.push (str); - return parts; - } - return str; - } - - MIM.Key = function (val) - { - this.key; - this.has_modifier = false; - if (typeof val == 'string' || val instanceof String) - { - this.key = decode_keysym (val); - if (! this.key) - throw new Xex.ErrTerm (MIM.Error.ParseError, "Invalid key: " + val); - if (this.key instanceof Array) - { - this.key = this.key[0]; - this.has_modifier = true; - } - } - else if (typeof val == 'number' || val instanceof Number) - this.key = String.fromCharCode (val); - else - throw new Xex.ErrTerm (MIM.Error.ParseError, "Invalid key: " + val); - } - - MIM.Key.prototype.toString = function () { return this.key; }; -}) (); - -(function () { - MIM.KeySeq = function (seq) - { - this.val = new Array (); - this.has_modifier = false; - - if (seq) - { - if (seq.IsList) - { - var len = seq.val.length; - for (var i = 0; i < len; i++) - { - var v = seq.val[i]; - if (v.type != 'string' && v.type != 'integer' - && v.type != 'symbol') - throw new Xex.ErrTerm (MIM.Error.ParseError, - "Invalid key: " + v); - var key = new MIM.Key (v.val); - this.val.push (key); - if (key.has_modifier) - this.has_modifier = true; - } - } - else if (seq.IsStr) - { - var len = seq.val.length; - for (var i = 0; i < len; i++) - this.val.push (new MIM.Key (seq.val.charCodeAt (i))); - } - else - throw new Xex.ErrTerm (MIM.Error.ParseError, "Invalid key: " + seq); - } - } - - var proto = new Xex.Term ('keyseq'); - proto.Clone = function () { return this; } - proto.Parser = function (domain, node) - { - var seq = new Array (); - for (node = node.firstChild; node; node = node.nextSibling) - if (node.nodeType == 1) - { - var term = Xex.ParseTerm (domain, node); - return new MIM.KeySeq (term); - } - throw new Xex.ErrTerm (MIM.Error.ParseError, "Invalid keyseq"); - } - proto.toString = function () - { - var len = this.val.length; - if (len == 0) - return ''; - var first = true; - var str = ''; - for (var i = 0; i < len; i++) - { - if (first) - first = false; - else if (this.has_modifier) - str += ' '; - str += this.val[i].toString (); - } - return str + ''; - } - - MIM.KeySeq.prototype = proto; -}) (); - -(function () { - MIM.Marker = function () { } - MIM.Marker.prototype = new Xex.Term ('marker'); - MIM.Marker.prototype.CharAt = function (ic) - { - var p = this.Position (ic); - if (p < 0) - return ic.GetSurroundingChar (p); - else if (pos >= ic.preedit.length) - return ic.GetSurroundingChar (p - ic.preedit.length); - return ic.preedit.charCodeAt (p); - } - - MIM.NamedMarker = function (name) { this.val = name; } - MIM.NamedMarker.prototype = new MIM.Marker (); - MIM.NamedMarker.prototype.Position = function (ic) - { - var p = ic.marker_positions[this.val]; - return (p == undefined ? 0 : p); - } - MIM.NamedMarker.prototype.Mark = function (ic) - { - ic.marker_positions[this.val] = ic.cursor_pos; - } - - MIM.PredefinedMarker = function (name) { this.val = name; } - MIM.PredefinedMarker.prototype = new MIM.Marker (); - MIM.PredefinedMarker.prototype.Position = function (ic) - { - if (typeof this.pos == 'number') - return this.pos; - return this.pos (ic); - } - - var predefined = { } - - function def_predefined (name, position) - { - predefined[name] = new MIM.PredefinedMarker (name); - predefined[name].pos = position; - } - - def_predefined ('@<', 0); - def_predefined ('@>', function (ic) { return ic.preedit.length; }); - def_predefined ('@-', function (ic) { return ic.cursor_pos - 1; }); - def_predefined ('@+', function (ic) { return ic.cursor_pos + 1; }); - def_predefined ('@[', function (ic) { - if (ic.cursor_pos > 0) - { - var pos = ic.cursor_pos; - return ic.preedit.FindProp ('candidates', pos - 1).from; - } - return 0; - }); - def_predefined ('@]', function (ic) { - if (ic.cursor_pos < ic.preedit.length - 1) - { - var pos = ic.cursor_pos; - return ic.preedit.FindProp ('candidates', pos).to; - } - return ic.preedit.length; - }); - for (var i = 0; i < 10; i++) - def_predefined ("@" + i, i); - predefined['@first'] = predefined['@<']; - predefined['@last'] = predefined['@>']; - predefined['@previous'] = predefined['@-']; - predefined['@next'] = predefined['@+']; - predefined['@previous-candidate-change'] = predefined['@[']; - predefined['@next-candidate-change'] = predefined['@]']; - - MIM.SurroundMarker = function (name) - { - this.val = name; - this.distance = parseInt (name.slice (2)); - if (isNaN (this.distance)) - throw new Xex.ErrTerm (MIM.Error.ParseError, "Invalid marker: " + name); - } - MIM.SurroundMarker.prototype = new MIM.Marker (); - MIM.SurroundMarker.prototype.Position = function (ic) - { - return ic.cursor_pos + this.distance; - } - - MIM.Marker.prototype.Parser = function (domain, node) - { - var name = node.firstChild.nodeValue; - if (name.charAt (0) == '@') - { - var n = predefined[name]; - if (n) - return n; - if (name.charAt (1) == '-') - return new MIM.SurroundMarker (name); - throw new Xex.ErrTerm (MIM.Error.ParseError, - "Invalid marker: " + name); - } - return new MIM.NamedMarker (name); - } -}) (); - -MIM.Selector = function (name) -{ - this.val = name; -} -MIM.Selector.prototype = new Xex.Term ('selector'); -(function () { - var selectors = {}; - selectors["@<"] = selectors["@first"] = new MIM.Selector ('@<'); - selectors["@="] = selectors["@current"] = new MIM.Selector ('@='); - selectors["@>"] = selectors["@last"] = new MIM.Selector ('@>'); - selectors["@-"] = selectors["@previous"] = new MIM.Selector ('@-'); - selectors["@+"] = selectors["@next"] = new MIM.Selector ('@+'); - selectors["@["] = selectors["@previous-candidate-change"] - = new MIM.Selector ('@['); - selectors["@]"] = selectors["@next-candidate-change"] - = new MIM.Selector ('@]'); - - MIM.Selector.prototype.Parser = function (domain, node) - { - var name = node.firstChild.nodeValue; - var s = selectors[name]; - if (! s) - throw new Xex.ErrTerm (MIM.Error.ParseError, - "Invalid selector: " + name); - return s; - } -}) (); - -MIM.Rule = function (keyseq, actions) -{ - this.keyseq = keyseq; - this.actions = actions; -} -MIM.Rule.prototype = new Xex.Term ('rule'); -MIM.Rule.prototype.Parser = function (domain, node) -{ - var n; - for (n = node.firstChild; n && n.nodeType != 1; n = n.nextSibling); - if (! n) - throw new Xex.ErrTerm (MIM.Error.ParseError, "invalid rule:" + node); - var keyseq = Xex.ParseTerm (domain, n); - if (keyseq.type != 'keyseq') - throw new Xex.ErrTerm (MIM.Error.ParseError, "invalid rule:" + node); - var actions = Xex.ParseTermList (domain, n.nextSibling); - return new MIM.Rule (keyseq, actions); -} -MIM.Rule.prototype.toString = function () -{ - return ''; -} - -MIM.Map = function (name) -{ - this.name = name; - this.rules = new Array (); -}; -(function () { - var proto = new Xex.Term ('map'); - - proto.Parser = function (domain, node) - { - var name = node.attributes['mname'].nodeValue; - if (! name) - throw new Xex.ErrTerm (MIM.Error.ParseError, "invalid map"); - var map = new MIM.Map (name); - for (var n = node.firstChild; n; n = n.nextSibling) - if (n.nodeType == 1) - map.rules.push (Xex.ParseTerm (domain, n)); - return map; - } - - proto.toString = function () - { - var str = ''; - var len = this.rules.length; - for (i = 0; i < len; i++) - str += this.rules[i]; - return str + ''; - } - - MIM.Map.prototype = proto; -}) (); - -Xex.CatchTag._mimtag = new Xex.SymTerm ('@mimtag'); - -MIM.Action = function (domain, terms) -{ - var args = new Array (); - args.push (Xex.CatchTag_.mimtag); - for (var i = 0; i < terms.length; i++) - args.push (terms[i]); - this.action = Xex.Funcall.prototype.New (domain, 'catch', null, args); -} - -MIM.Action.prototype.Run = function (domain) -{ - var result = this.action.Eval (domain); - if (result.type == 'error') - { - domain.context.Error = result.toString (); - return false; - } - return (result != Xex.CatchTag._mimtag); -} - -MIM.Keymap = function () -{ - this.submaps = null; - this.actions = null; -}; -(function () { - var proto = {}; - - function add_rule (keymap, rule) - { - var keyseq = rule.keyseq; - var len = keyseq.val.length; - - for (var i = 0; i < len; i++) - { - var key = keyseq.val[i]; - var sub; - - if (! keymap.submaps) - keymap.submaps = {}; - else - sub = keymap.submaps[key.key]; - if (! sub) - keymap.submaps[key.key] = sub = new MIM.Keymap (); - keymap = sub; - } - keymap.actions = rule.actions; - } - - proto.Add = function (map) - { - var rules = map.rules; - var len = rules.length; - - for (var i = 0; i < len; i++) - add_rule (this, rules[i]); - } - proto.Lookup = function (keys, index) - { - var sub; - - if (index < keys.val.length && this.submaps - && (sub = this.submaps[keys.val[index].key])) - { - index++; - return sub.Lookup (keys, index); - } - return { map: this, index: index }; - } - - MIM.Keymap.prototype = proto; -}) (); - -MIM.State = function (name) -{ - this.name = name; - this.keymap = new MIM.Keymap (); -}; -(function () { - var proto = new Xex.Term ('state'); - - proto.Parser = function (domain, node) - { - var map_list = domain.map_list; - var name = node.attributes['sname'].nodeValue; - if (! name) - throw new Xex.ErrTerm (MIM.Error.ParseError, "invalid map"); - var state = new MIM.State (name); - for (node = node.firstChild; node; node = node.nextSibling) - { - if (node.nodeType != 1) - continue; - if (node.nodeName == 'branch') - { - state.keymap.Add (map_list[node.attributes['mname'].nodeValue]); - state.keymap.actions = Xex.ParseTermList (domain, node.firstChild); - } - else if (node.nodeName == 'state-hook') - state.enter_actions = Xex.ParseTermList (domain, node.firstChild); - else if (node.nodeName == 'catch-all-branch') - state.fallback_actions = Xex.ParseTermList (domain, node.firstChild); - else if (node.nodeName == 'title') - state.title = node.firstChild.nodeValue; - } - return state; - } - - proto.toString = function () - { - return '' + this.keymap + ''; - } - - MIM.State.prototype = proto; -}) (); - -MIM.im_domain = new Xex.Domain ('input-method', null, null); -MIM.im_domain.DefType (MIM.KeySeq.prototype); -MIM.im_domain.DefType (MIM.Marker.prototype); -MIM.im_domain.DefType (MIM.Selector.prototype); -MIM.im_domain.DefType (MIM.Rule.prototype); -MIM.im_domain.DefType (MIM.Map.prototype); -MIM.im_domain.DefType (MIM.State.prototype); - -(function () { - var im_domain = MIM.im_domain; - - function Finsert (domain, vari, args) - { - domain.context.insert (args[0].val, null); - } - - im_domain.DefSubr (Finsert, "insert", false, 1, 1); -}) (); - -(function () { - var parsers = { }; - parsers['description'] = function (node) - { - this.description = node.firstChild.nodeValue; - } - parsers['title'] = function (node) - { - this.title = node.firstChild.nodeValue; - } - parsers['map-list'] = function (node) - { - for (node = node.firstChild; node; node = node.nextSibling) - { - if (node.nodeType != 1 || node.nodeName != 'map') - continue; - var map = Xex.ParseTerm (this.domain, node); - this.map_list[map.name] = map; - } - } - parsers['state-list'] = function (node) - { - this.domain.map_list = this.map_list; - for (node = node.firstChild; node; node = node.nextSibling) - { - if (node.nodeType != 1 || node.nodeName != 'state') - continue; - var state = Xex.ParseTerm (this.domain, node); - if (! state.title) - state.title = this.title; - if (! this.initial_state) - this.initial_state = state; - this.state_list[state.name] = state; - } - delete this.domain.map_list; - } - - MIM.IM = function (lang, name, extra_id, file) - { - this.lang = lang; - this.name = name; - this.extra_id = extra_id; - this.file = file; - this.load_status = MIM.LoadStatus.NotLoaded; - this.domain = new Xex.Domain (this.lang + '-' + this.name, - MIM.im_domain, null); - } - - var proto = { - Load: function () - { - var node = Xex.Load (null, this.file); - if (! node) - { - this.load_status = MIM.LoadStatus.Error; - return false; - } - this.map_list = {}; - this.initial_state = null; - this.state_list = {}; - for (node = node.firstChild; node; node = node.nextSibling) - { - if (node.nodeType != 1) - continue; - var name = node.nodeName; - var parser = parsers[name]; - if (parser) - parser.call (this, node); - } - this.load_status = MIM.LoadStatus.Loaded; - return true; - } - } - - MIM.IM.prototype = proto; - - MIM.IC = function (im) - { - if (im.load_status == MIM.LoadStatus.NotLoaded) - im.Load (); - if (im.load_status != MIM.LoadStatus.Loaded) - alert ('im:' + im.name + ' error:' + im.load_status); - this.im = im; - this.domain = new Xex.Domain ('context', im.domain, this); - this.active = true; - this.reset (); - } - - MIM.CandidateTable = function () - { - this.table = new Array (); - } - - MIM.CandidateTable.prototype.get = function (from) - { - for (var i = 0; i < this.table.length; i++) - { - var elt = this.table[i]; - if (elt.from <= from && elt.to > from) - return elt.val; - } - } - - MIM.CandidateTable.prototype.put = function (from, to, candidates) - { - for (var i = 0; i < this.table.length; i++) - { - var elt = this.table[i]; - if (elt.from >= from && elt.from < to - || elt.to >= from && elt.to < to) - { - elt.from = from; - elt.to = to; - elt.val = candidates; - return; - } - } - this.table.push ({ from: from, to: to, val: candidates }); - } - - MIM.CandidateTable.prototype.adjust = function (from, to, inserted) - { - var diff = inserted - (to - from); - for (var i = 0; i < this.table.length; i++) - { - var elt = this.table[i]; - if (elt.from >= to) - { - elt.from += diff; - elt.to += diff; - } - } - } - - MIM.CandidateTable.prototype.clear = function () - { - this.table.length = 0; - } - - function set_cursor (prefix, pos) - { - this.cursor_pos = pos; - if (pos > 0) - this.candidates = this.candidate_table.get (pos - 1); - else - this.candidates = null; - } - - function save_state () - { - this.state_var_values = this.domain.SaveValues (); - this.state_preedit = this.preedit; - this.state_key_head = this.key_head; - this.state_pos = this.cursor_pos; - } - - function restore_state () - { - this.domain.RestoreValues (this.state_var_values); - this.preedit = this.state_preedit; - set_cursor.call (this, "restore", this.state_pos); - } - - function handle_key () - { - var out = this.keymap.Lookup (this.keys, this.key_head); - var sub = out.map; - - alert ('handling ' + this.keys.val[this.key_head]); - this.key_head = out.index; - if (sub != this.keymap) - { - restore_state.call (this); - this.keymap = sub; - alert ('submap found, taking map actions:' + sub.actions); - if (this.keymap.actions != null) - { - if (! this.take_actions (this.keymap.actions)) - return false; - } - else if (this.keymap.submaps != null) - { - for (var i = this.state_key_head; i < this.key_head; i++) - this.preedit_replace (this.cursor_pos, this.cursor_pos, - this.keys.val[i].key, null); - } - if (this.keymap.submaps == null) - { - if (this.keymap.branch_actions != null) - { - if (! this.take_actions (this.keymap.branch_actions)) - return false; - } - if (this.keymap != this.state.keymap) - this.shift (this.state); - } - } - else - { - var current_state = this.state; - - if (this.keymap.branch_actions != null) - { - if (! this.take_actions (this.keymap.branch_actions)) - return false; - } - if (this.state == current_state) - { - if (this.state == this.initial_state - && this.key_head < this.keys.val.length) - return false; - if (this.keymap != this.state.keymap) - this.shift (this.state); - else if (this.keymap.branch_actions == null) - this.shift (this.initial_state); - } - } - return true; - } - - proto = { - init: function () - { - this.produced = null; - this.preedit = ''; - this.cursor_pos = 0; - this.marker_positions = {}; - this.candidates = null; - this.candidate_show = false; - this.state = null; - this.prev_state = null; - this.initial_state = this.im.initial_state; - this.title = this.initial_state.title; - this.state_preedit = ''; - this.state_key_head = 0; - this.state_var_values = {}; - this.state_pos = 0; - this.keymap = null; - this.keys = new MIM.KeySeq (); - this.key_head = 0; - this.key_unhandled = false; - this.unhandled_key = null; - this.changed = MIM.ChangedStatus.None; - this.error_message = ''; - this.title = this.initial_state.title; - this.produced = null; - this.preedit = ''; - this.marker_positions = {}; - this.candidate_table = new MIM.CandidateTable (); - this.candidates = null; - this.candidate_show = false; - }, - - reset: function () - { - this.init (); - this.state_var_values = {}; - this.shift (this.initial_state); - }, - - catch_args: new Array (Xex.CatchTag._mimtag, null), - - take_actions: function (actions) - { - var func_progn = this.domain.GetFunc ('progn'); - var func_catch = this.domain.GetFunc ('catch'); - this.catch_args[1] = new Xex.Funcall (func_progn, null, actions); - var term = new Xex.Funcall (func_catch, null, this.catch_args); - term = term.Eval (this.domain); - return (! term.IsSymbol || term.val != '@mimtag'); - }, - - GetSurroundingChar: function (pos) - { - if (pos < 0 ? this.caret_pos < - pos : this.target.value.length < pos) - return 0; - return this.target.value.charCodeAt (this.caret_pos + pos); - }, - - adjust_markers: function (from, to, inserted) - { - var diff = inserted - (to - from); - - for (var m in this.marker_positions) - if (this.marker_positions[m] > from) - this.marker_positions[m] = (this.marker_positions[m] >= to - ? pos + diff : from); - if (this.cursor_pos >= to) - set_cursor.call (this, 'adjust', this.cursor_pos + diff); - else if (this.cursor_pos > from) - set_cursor.call (this, 'adjust', from) - }, - - preedit_replace: function (from, to, text, candidates) - { - this.preedit = (this.preedit.substring (0, from) - + text + this.preedit.substring (to)); - this.adjust_markers (from, to, text.length); - this.candidate_table.adjust (from, to, text.length); - if (candidates) - this.candidate_table.put (from, from + text.length, candidates) - }, - - insert: function (text, candidates) - { - this.preedit_replace (this.cursor_pos, this.cursor_pos, text, candidates); - this.changed = MIM.ChangedStatus.Preedit | MIM.ChangedStatus.CursorPos; - }, - - del: function (pos) - { - if (pos < 0) - { - this.DelSurroundText (pos); - pos = 0; - } - else if (pos > this.preedit.length) - { - this.DelSurroundText (pos - this.preedit.length); - pos = this.preedit.length; - } - if (pos < this.cursor_pos) - this.preedit = (this.predit.substring (0, pos) - + this.preedit.substring (this.cursor_pos)); - else - this.preedit = (this.preedit.substring (0, this.cursor_pos) - + this.predit.substring (pos)); - }, - - show: function () - { - this.candidate_show = true; - this.changed |= MIM.ChangedStatus.CandidateShow; - }, - - hide: function () - { - this.candidate_show = false; - this.changed |= MIM.ChangedStatus.CandidateShow; - }, - - move: function (pos) - { - if (pos < 0) - pos = 0; - else if (pos > this.preedit.length) - pos = this.preedit.length; - if (pos != this.cursor_pos) - { - set_cursor.call (this, 'move', pos); - this.changed |= MIM.ChangedStatus.Preedit; - } - }, - - pushback: function (n) - { - if (n instanceof MIM.KeySeq) - { - if (this.key_head > 0) - this.key_head--; - if (this.key_head < this.keys.val.length) - this.keys.val.splice (this.key_head, - this.keys.val.length - this.key_head); - for (var i = 0; i < n.val.length; i++) - this.keys.val.push (n.val[i]); - return; - } - if (n > 0) - { - this.key_head -= n; - if (this.key_head < 0) - this.key_head = 0; - } - else if (n == 0) - this.key_head = 0; - else - { - this.key_head = - n; - if (this.key_head > this.keys.val.length) - this.key_head = this.keys.val.length; - } - }, - - pop: function () - { - if (this.key_head < this.keys.val.length) - this.keys.val.splice (this.key_head, 1); - }, - - commit: function () - { - if (this.preedit.length > 0) - { - this.candidate_table.clear (); - this.produced += this.preedit; - this.preedit_replace.call (this, 0, this.preedit.Length, '', null); - } - }, - - shift: function (state) - { - if (state == null) - { - if (this.prev_state == null) - return; - state = this.prev_state; - } - - if (state == this.initial_state) - { - this.commit (); - this.keys.val.splice (0, this.key_head); - this.key_head = 0; - if (state != this.state) - { - this.domain.RestoreValues (this.state_initial_var_values); - if (state.enter_actions != null) - take_actions.call (state.enter_actions); - } - this.prev_state = null; - } - else - { - if (state != this.state && state.enter_actions != null) - take_actions.call (state.enter_actions); - this.prev_state = this.state; - } - save_state.call (this); - if (! this.state || this.state.title != state.title) - this.changed |= MIM.ChangedStatus.StateTitle; - this.state = state; - this.keymap = state.keymap; - }, - - Filter: function (key) - { - if (! this.active) - { - this.key_unhandled = true; - this.unhandled_key = key; - return false; - } - if (key.key == '_reload') - return true; - this.changed = MIM.ChangedStatus.None; - this.produced = ''; - this.key_unhandled = false; - this.keys.val.push (key); - var count = 0; - while (this.key_head < this.keys.val.length) - { - if (! handle_key.call (this)) - { - this.unhandled_key = this.keys.val[this.key_head++]; - this.key_unhandled = true; - break; - } - if (++count == 10) - break; - } - this.keys.val.splice (0, this.key_head); - this.key_head = 0; - return (! this.key_unhandled && this.produced.length == 0); - } - } - - MIM.IC.prototype = proto; - - var node = Xex.Load (null, "imlist.xml"); - for (node = node.firstChild; node; node = node.nextSibling) - if (node.nodeName == 'input-method') - { - var lang, name, extra_id, file; - - for (var n = node.firstChild; n; n = n.nextSibling) - { - if (n.nodeName == 'language') - lang = n.firstChild.nodeValue; - else if (n.nodeName == 'name') - name = n.firstChild.nodeValue; - else if (n.nodeName == 'extra-id') - extra_id = n.firstChild.nodeValue; - else if (n.nodeName == 'filename') - file = n.firstChild.nodeValue; - } - if (! MIM.im_list[lang]) - MIM.im_list[lang] = {}; - MIM.im_list[lang][name] = new MIM.IM (lang, name, extra_id, file); - } - node = undefined; -}) (); - -(function () { - - MIMTEST = function (name) { this.nam = name; }; - - function testshow () { alert (this.nam); }; - - MIMTEST.prototype.show = function () { testshow.call (this); } - MIMTEST.prototype.cut = function (from, to) { - this.val.splice (from, to -from); return this.val; } - - MIMTEST2 = function (name) { this.nam = name; - this.val = new Array (1,2,3,4,5);} - - MIMTEST2.prototype = MIMTEST.prototype; - - var x = new MIMTEST2 ('test2'); -}) (); - -MIM.test = function () -{ - var im = MIM.im_list['t']['latn-post']; - var ic = new MIM.IC (im); - - document.AIM = im; - - ic.Filter (new MIM.Key ('a')); - ic.Filter (new MIM.Key ("'")); - - if (true) - document.getElementById ('text').value = ic.preedit; - else { - try { - document.getElementById ('text').value - = Xex.ParseTerm (domain, body).Eval (domain).toString (); - } catch (e) { - if (e instanceof Xex.ErrTerm) - alert (e); - throw e; - } - } + return (obj.responseXML && obj.responseXML.firstChild); }