+ public object[] candidates;
+
+ public Variable (MPlist p)
+ {
+ name = p.Symbol;
+ p = p.Next;
+ description = parse_description (p);
+ if (description == null)
+ description = new MText ("No description");
+ else
+ p = p.next;
+ type = (p.IsMText ? typeof (MText)
+ : p.IsInteger ? typeof (int)
+ : p.IsSymbol ? typeof (MSymbol)
+ : typeof (object));
+ value = p.val;
+ p = p.next;
+ candidates = new object[p.Count];
+ for (int i = 0; ! p.IsEmpty; i++, p = p.next)
+ candidates[i] = p.val;
+ }
+
+ private static Type parse_value (XmlNode node, out object value)
+ {
+ string typename = node.Attributes["type"].Value;
+ Type type;
+
+ if (typename == "integer")
+ {
+ int i;
+ if (! Int32.TryParse (node.InnerText, out i))
+ i = 0;
+ value = i;
+ type = typeof (int);
+ }
+ else if (typename == "string")
+ {
+ MText mt = node.InnerText;
+ value = mt;
+ type = typeof (MText);
+ }
+ else if (typename == "symbol")
+ {
+ MSymbol sym = node.InnerText;
+ value = sym;
+ type = typeof (MSymbol);
+ }
+ else
+ {
+ value = null;
+ type = typeof (object);
+ }
+ return type;
+ }
+
+ public Variable (XmlNode node)
+ {
+ name = node.Attributes["id"].Value;
+ for (node = node.FirstChild; node != null; node = node.NextSibling)
+ if (node.NodeType == XmlNodeType.Element)
+ {
+ if (node.Name == "description")
+ description = parse_description (node);
+ else if (node.Name == "value")
+ type = parse_value (node, out value);
+ else if (node.Name == "valiable-value-candidate")
+ {
+ XmlNodeList n_list = node.ChildNodes;
+ candidates = new object[n_list.Count];
+ for (int i = 0; i < n_list.Count; i++)
+ {
+ object val;
+ parse_value (n_list[i], out val);
+ candidates[i] = val;
+ }
+ }
+ }
+ }
+
+ public override string ToString ()
+ {
+ return ("(" + name + " \"" + (string) description
+ + "\" " + type + " " + value + " " + candidates + ")");
+ }
+ }
+
+ public class Command
+ {
+ public MSymbol name;
+ public MText description;
+ public List<KeySeq> keys;
+
+ public Command (MPlist p)
+ {
+ name = p.Symbol;
+ p = p.Next;
+ description = parse_description (p);
+ if (description == null)
+ description = "No description";
+ keys = new List<KeySeq> ();
+ for (p = p.next; ! p.IsEmpty; p = p.next)
+ {
+ if (p.IsMText)
+ keys.Add (new KeySeq (p.Text));
+ else if (p.IsPlist)
+ keys.Add (new KeySeq (p.Plist));
+ }
+ }
+
+ public Command (XmlNode node)
+ {
+ name = node.Attributes["id"].Value;
+ keys = new List<KeySeq> ();
+ for (node = node.FirstChild; node != null; node = node.NextSibling)
+ {
+ if (node.Name == "description")
+ description = parse_description (node);
+ else if (node.Name == "keyseq")
+ keys.Add (new KeySeq (node));
+ }
+ }
+
+ public override string ToString ()
+ {
+ string str = "(" + name + " \"" + (string) description;
+ foreach (KeySeq keyseq in keys)
+ str += " " + keyseq;
+ return str + ")";
+ }
+ }
+
+ internal class Plugin
+ {
+ private string name;
+ private Assembly assembly;
+ private Type plugin_type;
+
+ public Plugin (string name)
+ {
+ this.name = name;
+ }
+
+ public MethodInfo GetMethod (Xex.Symbol name)
+ {
+ if (assembly == null)
+ {
+ assembly = Assembly.LoadFrom (name + ".dll");
+ plugin_type = assembly.GetType ("M17n.MInputMethod.Plugin");
+ }
+
+ MethodInfo info = plugin_type.GetMethod ((string) name);
+ if (info == null)
+ throw new Exception ("Invalid plugin method: " + name);
+ return info;
+ }
+
+ public override string ToString ()
+ {
+ return String.Format ("(module {0}", name);
+ }
+ }
+
+ internal class PluginMethod : Xex.Function
+ {
+ private Plugin plugin;
+ private MethodInfo method_info;
+ object[] parameters = new object[2];
+
+ public PluginMethod (Plugin plugin, string name)
+ : base ((Xex.Symbol) name, 0, -1)
+ {
+ this.plugin = plugin;
+ }
+
+ public override Xex.Term Call (Xex.Domain domain, Xex.Variable vari,
+ Xex.Term[] args)
+ {
+ args = (Xex.Term[]) args.Clone ();
+ for (int i = 0; i < args.Length; i++)
+ {
+ args[i] = args[i].Eval (domain);
+ if (domain.Thrown)
+ return args[i];
+ }
+ if (method_info == null)
+ method_info = plugin.GetMethod (name);
+ parameters[0] = domain.context;
+ parameters[1] = args;
+ return (Xex.Term) method_info.Invoke (null, parameters);
+ }
+ }
+
+ internal abstract class Marker : Xex.TermValue
+ {
+ MSymbol name;
+
+ public Marker (MSymbol name)
+ {
+ this.name = name;
+ }
+
+ public abstract int Position (MInputContext ic);
+ public abstract void Mark (MInputContext ic);
+
+ public class Named : Marker
+ {
+ int pos;
+
+ public Named (MSymbol name) : this (name, 0) { }
+
+ private Named (MSymbol name, int p) : base (name) { pos = p; }
+
+ public override int Position (MInputContext ic) { return pos; }
+
+ public override void Mark (MInputContext ic) { pos = ic.cursor_pos; }
+
+ public override Xex.TermValue Clone ()
+ {
+ return new Named (name, pos);
+ }
+ }
+
+ public class Predefined : Marker
+ {
+ public Predefined (MSymbol name) : base (name) { }
+
+ public override int Position (MInputContext ic)
+ {
+ switch (name.Name[1]) {
+ case '<': return 0;
+ case '>': return ic.preedit.Length;
+ case '-': return ic.cursor_pos - 1;
+ case '+': return ic.cursor_pos + 1;
+ case '[':
+ if (ic.cursor_pos > 0)
+ {
+ int pos = ic.cursor_pos;
+ int to;
+ ic.preedit.FindProp (MInputMethod.Mcandidates, pos - 1,
+ out pos, out to);
+ return pos;
+ }
+ return 0;
+ case ']':
+ if (ic.cursor_pos < ic.preedit.Length - 1)
+ {
+ int pos = ic.cursor_pos;
+ int from;
+ ic.preedit.FindProp (MInputMethod.Mcandidates, pos,
+ out from, out pos);
+ return pos;
+ }
+ return ic.preedit.Length;
+ default:
+ return name.Name[1] - '0';
+ }
+ }
+
+ public override void Mark (MInputContext ic)
+ {
+ throw new Exception ("Can't set predefined marker: " + name);
+ }
+
+ public override Xex.TermValue Clone ()
+ {
+ return new Predefined (name);
+ }
+ }
+
+ static internal Dictionary<MSymbol,Predefined> predefined_markers;
+
+ static Marker ()
+ {
+ predefined_markers = new Dictionary<MSymbol,Predefined> ();
+ MSymbol[] symlist = new MSymbol[] {"@<", "@>", "@-", "@+", "@[", "@]",
+ "@0", "@1", "@2", "@3", "@4",
+ "@5", "@6", "@7", "@8", "@9" };
+ foreach (MSymbol s in symlist)
+ predefined_markers[s] = new Predefined (s);
+ }
+
+ public static Marker Get (MInputContext ic, MSymbol name)
+ {
+ Predefined pred;
+ Marker m;
+
+ if (predefined_markers.TryGetValue (name, out pred))
+ return pred;
+ if (name.Name[0] == '@')
+ throw new Exception ("Invalid marker name: " + name);
+ m = (Marker) ic.markers.Get (name);
+ if (m == null)
+ {
+ m = new Named (name);
+ ic.markers.Put (name, m);
+ }
+ return m;
+ }
+ }
+
+ internal class Map
+ {
+ public MSymbol name;
+ public Dictionary<Key, Map> submaps;
+ public Xex.Term actions;
+
+ public void Add (KeySeq keys, int index, Xex.Term actions)
+ {
+ Map sub = null;
+
+ if (submaps == null)
+ submaps = new Dictionary<Key, Map> ();
+ else
+ submaps.TryGetValue (keys.keyseq[index], out sub);
+ if (sub == null)
+ {
+ Key key = keys.keyseq[index];
+ submaps[key] = sub = new Map ();
+ }
+ if (index + 1 < keys.keyseq.Count)
+ sub.Add (keys, index + 1, actions);
+ else
+ this.actions = actions;
+ }
+
+ public Xex.Term Lookup (KeySeq keys, int index)
+ {
+ Map sub;
+
+ if (index + 1 == keys.keyseq.Count)
+ return actions;
+ if (submaps.TryGetValue (keys.keyseq[index], out sub))
+ return sub.Lookup (keys, index + 1);
+ return Tnil;
+ }
+
+ private void describe (MText mt, KeySeq keyseq)
+ {
+ if (keyseq.keyseq.Count > 0)
+ {
+ mt.Cat (" (").Cat (keyseq.ToString ());
+ mt.Cat (' ').Cat (actions.ToString ());
+ mt.Cat (')');
+ }
+ if (submaps != null)
+ foreach (KeyValuePair<Key, Map> kv in submaps)
+ {
+ keyseq.keyseq.Add (kv.Key);
+ kv.Value.describe (mt, keyseq);
+ keyseq.keyseq.RemoveAt (keyseq.keyseq.Count - 1);
+ }
+ }
+
+ public override string ToString ()
+ {
+ MText mt = "(" + name.Name;
+ KeySeq keyseq = new KeySeq ();
+
+ describe (mt, keyseq);
+ mt.Cat (')');
+ return (string) mt;
+ }
+ }
+
+ internal class State
+ {
+ public MSymbol name;
+ public MText title;
+ public MPlist branches = new MPlist ();
+
+ public State (MSymbol name)
+ {
+ this.name = name;
+ }
+
+ public override string ToString ()
+ {
+ MText mt = "(" + name.Name;
+
+ if (title != null)
+ mt.Cat (" \"" + title + "\"");
+ for (MPlist p = branches; ! p.IsEmpty; p = p.next)
+ mt.Cat (" (" + p.Key + " " + (Xex) p.Val + ")");
+ return (string) mt + ")";
+ }
+ }
+
+ // Instance members
+ internal Xex.Domain domain;
+
+ private LoadStatus load_status = LoadStatus.None;
+ private MDatabase.Tag tag;
+ private MDatabase mdb;
+
+ private MText description;
+ internal MText title;
+ internal Command[] commands;
+ internal Xex.Symbol[] var_names;
+ internal Dictionary<MSymbol, Plugin> plugins;
+ internal Dictionary<MSymbol, Map> maps;
+ internal MPlist states;
+
+ static MInputMethod ()
+ {
+ im_domain.DefSubr (Finsert, "insert", true, 1, 1);
+ im_domain.DefSubr (Finsert_candidates, "candidates", true, 1, -1);
+ im_domain.DefSubr (Fdelete, "delete", true, 1, 1);
+ im_domain.DefSubr (Fselect, "select", true, 1, 1);
+ im_domain.DefSubr (Fshow, "show", true, 0, 0);
+ im_domain.DefSubr (Fhide, "hide", true, 0, 0);
+ im_domain.DefSubr (Fmove, "move", true, 1, 1);
+ im_domain.DefSubr (Fmark, "mark", true, 1, 1);
+ im_domain.DefSubr (Fpushback, "pushback", true, 1, 1);
+ im_domain.DefSubr (Fpop, "pop", true, 0, 0);
+ im_domain.DefSubr (Fundo, "undo", true, 0, 1);
+ im_domain.DefSubr (Fcommit, "commit", true, 0, 0);
+ im_domain.DefSubr (Funhandle, "unhandle", true, 0, 0);
+ im_domain.DefSubr (Fshift, "shift", true, 1, 1);
+ im_domain.DefSubr (Fmarker, "marker", true, 1, 1);
+ im_domain.DefSubr (Fchar_at, "char-at", true, 1, 1);
+ im_domain.DefSubr (Fkeyseq, "keyseq", true, 1, -1);
+
+ MDatabase.Tag tag = new MDatabase.Tag (Minput_method, "*", "*", "*");
+ List<MDatabase> list = MDatabase.List (tag);
+ M17n.DebugPrint ("Found {0} input methods\n", list.Count);
+ foreach (MDatabase mdb in list)
+ im_table[mdb.tag] = new MInputMethod (mdb.tag);
+ }
+
+ // Constructor
+ private MInputMethod (MDatabase.Tag tag)
+ {
+ this.tag = tag;
+ }
+
+ // Instance Properties
+ public MSymbol Language { get { return tag[1]; } }
+ public MSymbol Name { get { return tag[2]; } }
+ public MSymbol SubName { get { return tag[3]; } }
+
+ public bool Info (out MText description,
+ out MText title,
+ out Xex.Variable[] variables,
+ out Command[] commands)
+ {
+ if ((load_status & LoadStatus.Header) != LoadStatus.Header
+ && ! load_header ())
+ {
+ description = null;
+ title = null;
+ variables = null;
+ commands = null;
+ return false;
+ }
+ description = this.description;
+ title = this.title;
+ if (var_names == null)
+ variables = null;
+ else
+ {
+ variables = new Xex.Variable[var_names.Length];
+ int i = 0;
+ foreach (Xex.Symbol name in var_names)
+ variables[i++] = domain.GetVar (name, false);
+ }
+ commands = this.commands;
+ return true;
+ }
+
+ public static MInputMethod Find (MSymbol language, MSymbol name)
+ {
+ return Find (language, name, MSymbol.nil);
+ }
+
+ public static MInputMethod Find (MSymbol language, MSymbol name,
+ MSymbol subname)
+ {
+ MDatabase.Tag tag = new MDatabase.Tag (Minput_method, language,
+ name, subname);
+ MInputMethod im;
+
+ return (im_table.TryGetValue (tag, out im) ? im : null);
+ }
+
+ public bool Open ()
+ {
+ return ((load_status == LoadStatus.Full) || load_body ());
+ }
+
+ public static MInputMethod[] List ()
+ {
+ MInputMethod[] array = new MInputMethod[im_table.Count];
+ int i = 0;
+
+ foreach (KeyValuePair<MDatabase.Tag, MInputMethod> kv in im_table)
+ array[i++] = kv.Value;
+ return array;
+ }
+
+ private bool load_header ()
+ {
+ mdb = MDatabase.Find (tag);
+ if (mdb == null)
+ return false;
+ try {
+ MSymbol format = mdb.Format;
+
+ if (format == MSymbol.plist)
+ load ((MPlist) mdb.Load (Mmap), false);
+ else
+ {
+ XmlDocument doc = (XmlDocument) mdb.Load (Mmap_list);
+ load (doc.DocumentElement, false);
+ }
+ } catch (Exception e) {
+ Console.WriteLine ("{0}\n", e);
+ load_status = LoadStatus.Error;
+ return false;
+ }
+ load_status |= LoadStatus.Header;
+ return true;
+ }
+
+ private bool load_body ()
+ {
+ domain = new Xex.Domain (im_domain, null);
+ mdb = MDatabase.Find (tag);
+ if (mdb == null)
+ return false;
+ try {
+ object obj = mdb.Load ();
+ if (obj is MPlist)
+ load ((MPlist) obj, true);
+ else
+ load ((XmlDocument) obj, true);
+ } catch (Exception e) {
+ Console.WriteLine (e);
+ load_status = LoadStatus.Error;
+ return false;
+ }
+ load_status = LoadStatus.Full;
+ return true;
+ }
+
+ private void load (MPlist plist, bool full)
+ {
+ maps = new Dictionary<MSymbol, Map> ();
+ states = new MPlist ();
+
+ for (; ! plist.IsEmpty; plist = plist.next)
+ if (plist.IsPlist)
+ {
+ MPlist pl = plist.Plist;
+ if (pl.IsSymbol)
+ {
+ MSymbol sym = pl.Symbol;
+
+ pl = pl.next;
+ if (sym == Mdescription)
+ description = parse_description (pl);
+ else if (sym == Mtitle)
+ {
+ if (pl.IsMText)
+ title = pl.Text;
+ }
+ else if (sym == Mvariable)
+ parse_variables (pl);
+ else if (sym == Mcommand)
+ parse_commands (pl);
+ else if (full)
+ {
+ if (sym == Mmodule)
+ parse_plugins (pl);
+ else if (sym == Minclude)
+ parse_include (pl);
+ else if (sym == Mmacro)
+ parse_macros (pl);
+ else if (sym == Mmap)
+ parse_maps (pl);
+ else if (sym == Mstate)
+ parse_states (pl);
+ }
+ }
+ }
+ if (description == null)
+ description = (MText) "No description";
+ if (title == null)
+ title = new MText (tag[2].Name);
+ if (commands == null)
+ commands = new Command[0];
+ if (! full)
+ return;
+ if (states.IsEmpty)
+ {
+ State state = new State ((MSymbol) "init");
+ plist = new MPlist ();
+ foreach (KeyValuePair<MSymbol, Map>kv in maps)
+ state.branches.Add (kv.Key, null);
+ states.Add (state.name, state);
+ }
+ }
+
+ private void load (XmlNode node, bool full)
+ {
+ bool skip_header = load_status == LoadStatus.Header;
+
+ maps = new Dictionary<MSymbol, Map> ();
+ states = new MPlist ();
+
+ if (node.NodeType == XmlNodeType.Document)
+ node = node.FirstChild;
+ while (node.NodeType != XmlNodeType.Element)
+ node = node.NextSibling;
+ for (node = node.FirstChild; node != null; node = node.NextSibling)
+ {
+ if (node.NodeType != XmlNodeType.Element)
+ continue;
+ if (! skip_header)
+ {
+ if (node.Name == "description")
+ description = parse_description (node);
+ else if (node.Name == "title")
+ title = parse_title (node);
+ else if (node.Name == "variable-list")
+ parse_variables (node);
+ else if (node.Name == "command-list")
+ parse_commands (node);
+ }
+ else if (full)
+ {
+ if (node.Name == "module-list")
+ parse_plugins (node);
+ else if (node.Name == "macro-list")
+ parse_macros (node);
+ else if (node.Name == "map-list")
+ parse_maps (node);
+ else if (node.Name == "state-list")
+ parse_states (node);
+ }
+ }
+ if (description == null)
+ description = (MText) "No description";
+ if (title == null)
+ title = new MText (tag[2].Name);
+ if (commands == null)
+ commands = new Command[0];
+ if (! full)
+ return;
+ if (states.IsEmpty)
+ {
+ State state = new State ((MSymbol) "init");
+ foreach (KeyValuePair<MSymbol, Map>kv in maps)
+ state.branches.Add (kv.Key, null);
+ states.Add (state.name, state);
+ }
+ }
+
+ private static void transform (MPlist plist)
+ {
+ for (; ! plist.IsEmpty; plist = plist.next)
+ {
+ if (plist.IsMText)
+ {
+ MPlist p = new MPlist ();
+ p.Add (MSymbol.symbol, Minsert);
+ p.Add (MSymbol.mtext, plist.Text);
+ plist.Set (MSymbol.plist, p);
+ }
+ else if (plist.IsInteger)
+ {
+ MPlist p = new MPlist ();
+ p.Add (MSymbol.symbol, Minsert);
+ p.Add (MSymbol.integer, plist.Integer);
+ plist.Set (MSymbol.plist, p);
+ }
+ else if (plist.IsPlist)
+ {
+ MPlist pl = plist.Plist;
+
+ if (pl.IsSymbol)
+ {
+ if (pl.Symbol == Madd)
+ pl.Set (MSymbol.symbol, (MSymbol) "+=");
+ else if (pl.Symbol == Msub)
+ pl.Set (MSymbol.symbol, (MSymbol) "-=");
+ else if (pl.Symbol == Mmul)
+ pl.Set (MSymbol.symbol, (MSymbol) "*=");
+ else if (pl.Symbol == Mdiv)
+ pl.Set (MSymbol.symbol, (MSymbol) "/=");
+ else if (pl.Symbol == Minsert)
+ {
+ // (insert (CANDIDATES ...))
+ // => (candidates CANDIDATES ...)
+ if (pl.next.IsPlist)
+ {
+ pl.Set (MSymbol.symbol, Mcandidates);
+ pl = pl.next;
+ MPlist p = pl.Plist;
+ pl.Set (p.key, p.val);
+ for (p = p.next; ! p.IsEmpty; p = p.next);
+ pl.Add (p.key, p.val);
+ }
+ }
+ else if (pl.Symbol == Mif)
+ {
+ pl = pl.next;
+ if (! pl.IsEmpty)
+ transform (pl.next);
+ }
+ else if (pl.Symbol == Mcond)
+ {
+ for (pl = pl.next; ! pl.IsEmpty; pl = pl.next)
+ if (pl.IsPlist)
+ {
+ MPlist p = pl.Plist;
+
+ if (p.IsPlist)
+ transform (p);
+ else
+ transform (p.next);
+ }
+ }
+ else if (pl.Symbol == Mdelete
+ || pl.Symbol == Mmove
+ || pl.Symbol == Mmark)
+ {
+ pl = pl.next;
+ if (pl.IsSymbol)
+ {
+ MSymbol sym = pl.Symbol;
+ MPlist p = new MPlist ();
+ p.Add (MSymbol.symbol, Mmarker);
+ p.Add (MSymbol.symbol, sym);
+ pl.Set (MSymbol.plist, p);
+ }
+ }
+ else if (pl.Symbol == Mpushback)
+ {
+ pl = pl.next;
+ if (pl.IsPlist)
+ pl.Plist.Push (MSymbol.symbol, Mkeyseq);
+ }
+ }
+ else if (pl.IsMText)
+ {
+ // (CANDIDATES ...) => (candidates CANDIDATES ...)
+ pl.Push (MSymbol.symbol, Mcandidates);
+ }
+ }
+ else if (plist.IsSymbol)
+ {
+ MSymbol sym = plist.Symbol;
+
+ if (sym.Name.Length >= 3
+ && sym.Name[0] == '@'
+ && (sym.Name[1] == '-' || sym.Name[1] == '+'))
+ {
+ int pos = int.Parse (sym.Name.Substring (1));
+ MPlist p = new MPlist ();
+
+ if (pos == 0)
+ {
+ p.Add (MSymbol.symbol, Msurrounding_text_p);
+ }
+ else
+ {
+ if (sym.Name[1] == '+')
+ pos--;
+ p.Add (MSymbol.symbol, Mchar_at);
+ p.Add (MSymbol.integer, pos);
+ }
+ plist.Set (MSymbol.plist, p);
+ }
+ }
+ }
+ }
+
+ private static MText parse_description (MPlist plist)
+ {
+ if (plist.IsMText)
+ return plist.Text;
+ if (plist.IsPlist)
+ {
+ plist = plist.Plist;
+ if (plist.IsSymbol && plist.Symbol == (MSymbol) "_"
+ && plist.next.IsMText)
+ return plist.next.Text;
+ }
+ return null;
+ }
+
+ private static MText parse_description (XmlNode node)
+ {
+ if (node.HasChildNodes)
+ node = node.FirstChild;
+ return node.InnerText;
+ }
+
+ private static MText parse_title (XmlNode node)
+ {
+ return node.InnerText;
+ }
+
+ private void new_variable (Xex.Symbol name, string desc, int val,
+ MPlist pl, Xex.Variable vari)
+ {
+ int[] range;
+
+ if (pl.IsEmpty)
+ range = null;
+ else
+ {
+ range = new int[pl.Count * 2];
+ for (int i = 0; i < range.Length; i++)
+ {
+ if (pl.IsPlist)
+ {
+ MPlist p = pl.Plist;
+
+ if (! p.IsInteger || ! p.next.IsInteger)
+ throw new Exception ("Invalid range: " + p);
+ range[i * 2] = p.Integer;
+ range[i * 2 + 1] = p.next.Integer;
+ }
+ else if (pl.IsInteger)
+ range[i * 2] = range[i * 2 + 1] = pl.Integer;
+ else
+ throw new Exception ("Invalid range: " + pl);
+ }
+ }
+ if (vari == null)
+ domain.Defvar (new Xex.Variable.Int (name, desc, val, range));
+ else
+ {
+ Xex.Term term = new Xex.Term (val);
+ vari.Value = term;
+ vari.DefaultValue = term;
+ vari.Range = range;
+ }
+ }
+
+ private void new_variable (Xex.Symbol name, string desc, MText val,
+ MPlist pl, Xex.Variable vari)
+ {
+ string[] range;
+
+ if (pl.IsEmpty)
+ range = null;
+ else
+ {
+ range = new string[pl.Count * 2];
+ for (int i = 0; i < range.Length; i++)
+ {
+ if (pl.IsMText)
+ range[i] = (string) pl.Text;
+ else
+ throw new Exception ("Invalid range: " + pl);
+ }
+ }
+ if (vari == null)
+ domain.Defvar (new Xex.Variable.Str (name, desc, (string) val, range));
+ else
+ {
+ Xex.Term term = new Xex.Term ((string) val);
+ vari.Value = term;
+ vari.DefaultValue = term;
+ vari.Range = range;
+ }
+ }
+
+ private void new_variable (Xex.Symbol name, string desc, MSymbol val,
+ MPlist pl, Xex.Variable vari)
+ {
+ Xex.Symbol[] range;
+ Xex.Symbol sym = val.Name;
+
+ if (pl.IsEmpty)
+ range = null;
+ else
+ {
+ range = new Xex.Symbol[pl.Count * 2];
+ for (int i = 0; i < range.Length; i++)
+ {
+ if (pl.IsSymbol)
+ range[i] = pl.Symbol.Name;
+ else
+ throw new Exception ("Invalid range: " + pl);
+ }
+ }
+ if (vari == null)
+ domain.Defvar (new Xex.Variable.Sym (name, desc, sym, range));
+ else
+ {
+ Xex.Term term = new Xex.Term (sym);
+ vari.Value = term;
+ vari.DefaultValue = term;
+ vari.Range = range;
+ }