*** empty log message ***
authorhanda <handa>
Thu, 24 Sep 2009 00:08:28 +0000 (00:08 +0000)
committerhanda <handa>
Thu, 24 Sep 2009 00:08:28 +0000 (00:08 +0000)
MInputMethod.cs
Makefile
XmlExpr.cs
xex.cs
xex.txt
xex.xml

index 5bba7b2..6c73951 100644 (file)
@@ -11,6 +11,8 @@ using M17N.Input;
 
 namespace M17N.Input
 {
+  using Xex = System.Xml.Expression.Xexpression;
+
   public class MInputMethod
   {
     // Delegaes
@@ -26,7 +28,7 @@ namespace M17N.Input
     public static Callback GetSurroundingText;
     public static Callback DeleteSurroundingText;
 
-    internal static MExpression.Domain domain = new MExpression.Domain (null);
+    internal static Xex.Domain im_domain = new Xex.Domain (null);
     private static MSymbol Minput_method = "input-method";
     private static MSymbol Mdescription = "description";
     private static MSymbol Mvariable = "variable";
@@ -304,20 +306,22 @@ namespace M17N.Input
       }
     }
 
-    public class KeySeq : List<Key>
+    public class KeySeq : Xex.Object
     {
-      public KeySeq () : base () { }
+      List<Key> keyseq = new List<Key> ();
+
+      public KeySeq () { }
 
-      public KeySeq (MPlist plist) : base ()
+      public KeySeq (MPlist plist)
       {
        foreach (MPlist p in plist)
          {
            if (p.IsSymbol)
-             this.Add (new Key (p.Symbol));
+             keyseq.Add (new Key (p.Symbol));
            else if (p.IsInteger)
-             this.Add (new Key ((char) p.Integer));
+             keyseq.Add (new Key ((char) p.Integer));
            else if (p.IsPlist)
-             this.Add (new Key (p.Plist));
+             keyseq.Add (new Key (p.Plist));
            else
              throw new Exception ("Invalid Key Sequence: " + plist);
          }
@@ -326,7 +330,7 @@ namespace M17N.Input
       public KeySeq (MText mt) : base ()
       {
        for (int i = 0; i < mt.Length; i++)
-         this.Add (new Key ((uint) mt[i]));
+         keyseq.Add (new Key ((uint) mt[i]));
       }
 
       private static uint parse_integer (string str)
@@ -357,7 +361,7 @@ namespace M17N.Input
        return 0;
       }
 
-      public KeySeq (XmlNode node) : base ()
+      public KeySeq (XmlNode node)
        {
          XmlAttributeCollection acol = node.Attributes;
          XmlNode n;
@@ -365,15 +369,26 @@ namespace M17N.Input
          if (acol != null && (n = acol["keys"]) != null)
            {
              foreach (char c in  n.Value)
-               this.Add (new Key ((uint) c));
+               keyseq.Add (new Key ((uint) c));
            }
 
          for (node = node.FirstChild; node != null; node = node.NextSibling)
            {
              if (node.Name == "key-event")
-               this.Add (new Key ((MSymbol) node.InnerText));
+               keyseq.Add (new Key ((MSymbol) node.InnerText));
              else
-               this.Add (new Key (parse_integer (node.InnerText)));
+               keyseq.Add (new Key (parse_integer (node.InnerText)));
+           }
+       }
+
+      public KeySeq (List<Xex.Term> list)
+       {
+         foreach (Xex.Term term in list)
+           {
+             if (term.IsName)
+               keyseq.Add (new Key ((MSymbol) term.Nameval.name));
+             else
+               keyseq.Add (new Key (term.Strval));
            }
        }
 
@@ -552,9 +567,9 @@ namespace M17N.Input
     {
       public MSymbol name;
       public Dictionary<Key, Map> submaps;
-      public MExpression actions;
+      public Xex actions;
 
-      public void Add (KeySeq keys, int index, MExpression actions)
+      public void Add (KeySeq keys, int index, Xex actions)
       {
        Map sub = null;
 
@@ -573,7 +588,7 @@ namespace M17N.Input
          this.actions = actions;
       }
 
-      public MExpression Lookup (KeySeq keys, int index)
+      public Xex Lookup (KeySeq keys, int index)
       {
        Map sub;
 
@@ -631,13 +646,13 @@ namespace M17N.Input
        if (title != null)
          mt.Cat (" \"" + title + "\"");
        for (MPlist p = branches; ! p.IsEmpty; p = p.next)
-         mt.Cat (" (" + p.Key + " " + (MExpression) p.Val + ")");
+         mt.Cat (" (" + p.Key + " " + (Xex) p.Val + ")");
        return (string) mt + ")";
       }
     }
 
     // Instance members
-    internal MExpression.Domain local_domain;
+    internal Xex.Domain domain;
 
     private LoadStatus load_status = LoadStatus.None;
     private MDatabase.Tag tag;
@@ -646,33 +661,31 @@ namespace M17N.Input
     private MText description;
     internal MText title;
     internal Command[] commands;
-    internal Variable[] variables;
+    internal Xex.Name[] var_names;
     internal Dictionary<MSymbol, Plugin> plugins;
-    internal MPlist bindings;
     internal Dictionary<MSymbol, Map> maps;
     internal MPlist states;
 
     static MInputMethod ()
     {
-      domain.Defun ("insert", insert, 1, 1);
-      domain.Defun ("candidates", insert_candidates, 1, -1);
-      domain.Defun ("delete", delete, 1, 1);
-      domain.Defun ("select", select, 1, 1);
-      domain.Defun ("show", show, 0, 0);
-      domain.Defun ("hide", hide, 0, 0);
-      domain.Defun ("move", move, 1, 1);
-      domain.Defun ("mark", mark, 1, 1, true);
-      domain.Defun ("pushback", pushback, 1, 1);
-      domain.Defun ("pop", pop, 0, 0);
-      domain.Defun ("undo", undo, 0, 1);
-      domain.Defun ("commit", commit, 0, 0);
-      domain.Defun ("unhandle", unhandle, 0, 0);
-      domain.Defun ("shift", shift, 1, 1, true);
-      domain.Defun ("call", call, 2, -1, true);
-      // Pseudo functions to make arguments of special objects.
-      domain.Defun ("marker", marker, 1, 1, true);
-      domain.Defun ("char-at", char_at, 1, 1, true);
-      domain.Defun ("keyseq", keyseq, 1, -1, true);
+      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 (Fcall, "call", true, 2, -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);
@@ -692,8 +705,10 @@ namespace M17N.Input
     public MSymbol Name { get { return tag[2]; } }
     public MSymbol SubName { get { return tag[3]; } }
 
-    public bool Info (out MText description, out MText title,
-                     out Variable[] variables, out Command[] commands)
+    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 ())
@@ -706,7 +721,10 @@ namespace M17N.Input
        }
       description = this.description;
       title = this.title;
-      variables = this.variables;
+      variables = new Xex.Variable[var_names.Length];
+      int i = 0;
+      foreach (Xex.Name name in var_names)
+       variables[i++] = domain.GetVar (name);
       commands = this.commands;
       return true;
     }
@@ -767,7 +785,7 @@ namespace M17N.Input
 
     private bool load_body ()
     {
-      local_domain = new MExpression.Domain (domain, null);
+      domain = new Xex.Domain (domain, null);
       mdb = MDatabase.Find (tag);
       if (mdb == null)
        return false;
@@ -845,7 +863,7 @@ namespace M17N.Input
          State state = new State ((MSymbol) "init");
          plist = new MPlist ();
          foreach (KeyValuePair<MSymbol, Map>kv in maps)
-           state.branches.Add (kv.Key, new MExpression (plist, local_domain));
+           state.branches.Add (kv.Key, new Xex (plist, domain));
          states.Add (state.name, state);
        }
     }
@@ -903,7 +921,7 @@ namespace M17N.Input
          State state = new State ((MSymbol) "init");
          MPlist plist = new MPlist ();
          foreach (KeyValuePair<MSymbol, Map>kv in maps)
-           state.branches.Add (kv.Key, new MExpression (plist, local_domain));
+           state.branches.Add (kv.Key, new Xex (plist, domain));
          states.Add (state.name, state);
        }
     }
@@ -1054,13 +1072,132 @@ namespace M17N.Input
       return node.InnerText;
     }
 
+    private void new_variable (Xex.Name name, string desc, int val,
+                              MPlist pl, Xex.Variable vari)
+    {
+      Xex.Term term = new Xex.Term (val);
+      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: " + p);
+           }
+       }
+      if (vari == null)
+       domain.Defvar (new Xex.Variable.Int (name, desc, term, range));
+      else
+       {
+         vari.Value = term;
+         vari.DefaultValue = term;
+         vari.Range = range;
+       }
+    }
+
+    private void new_variable (Xex.Name name, string desc, MText val,
+                              MPlist pl, Xex.Variable vari)
+    {
+      Xex.Term term = new Xex.Term ((string) val);
+      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] = pl.Text;
+             else
+               throw new Exception ("Invalid range: " + p);
+           }
+       }
+      if (vari == null)
+       domain.Defvar (new Xex.Variable.Str (name, desc, term, range));
+      else
+       {
+         vari.Value = term;
+         vari.DefaultValue = term;
+         vari.Range = range;
+       }
+    }
+
+    private void new_variable (Xex.Name name, string desc, MSymbol val,
+                              MPlist pl, Xex.Variable vari)
+    {
+      Xex.Term term = new Xex.Term ((Xex.Name) val.name);
+      Xex.Name[] range;
+
+      if (pl.IsEmpty)
+       range = null;
+      else
+       {
+         range = new Xex.Name[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: " + p);
+           }
+       }
+      if (vari == null)
+       domain.Defvar (new Xex.Variable.Sym (name, desc, term, range));
+      else
+       {
+         vari.Value = term;
+         vari.DefaultValue = term;
+         vari.Range = range;
+       }
+    }
+
     private void parse_variables (MPlist plist)
     {
       variables = new Variable[plist.Count];
 
       for (int i = 0; ! plist.IsEmpty; plist = plist.next)
        if (plist.IsPlist && plist.Plist.IsSymbol)
-         variables[i++] = new Variable (plist.Plist);
+         {
+           MPlist p = plist.Plist;
+           Xex.Name name = (Name) p.Symbol.name;
+           p = p.next;
+           string desc = parse_description (p);
+           Xex.Variable vari = null;
+           Xex.Term val;
+
+           if (im_global.domain.GetVar (name, out vari))
+             domain.Defvar (vari);
+           if (desc != null)
+             p = p.next;
+           if (! p.IsEmpty)
+             {
+               if (p.IsInteger)
+                 new_variable (name, desc, p.Integer, p.next, vari);
+               else if (p.IsMText)
+                 new_variable (name, desc, p.Text, p.next, vari);
+               else if (p.IsSymbol)
+                 new_variable (name, desc, p.Symbol, p.next, vari);
+               else
+                 throw new Exception ("Unknown type: " + p.val);
+             }
+         }
     }
 
     private void parse_variables (XmlNode node)
@@ -1149,18 +1286,18 @@ namespace M17N.Input
            if (im == null || ! im.Open ())
              continue;
            if (id == MSymbol.nil)
-             im.local_domain.CopyFunc (local_domain);
+             im.domain.CopyFunc (domain);
            else
-             im.local_domain.CopyFunc (local_domain, id);
+             im.domain.CopyFunc (domain, id);
          }
       for (XmlNode nn = node.FirstChild; nn != null; nn = nn.NextSibling)
        if (nn.NodeType == XmlNodeType.Element
            && nn.Name != "xi:include")
-         local_domain.Defun ((MSymbol) node.GetAttribute ("id"));
+         domain.Defun ((MSymbol) node.GetAttribute ("id"));
       for (XmlNode nn = node.FirstChild; nn != null; nn = nn.NextSibling)
        if (nn.NodeType == XmlNodeType.Element
            && nn.Name != "xi:include")
-         local_domain.Defun ((MSymbol) node.GetAttribute ("id"), null,
+         domain.Defun ((MSymbol) node.GetAttribute ("id"), null,
                              nn.FirstChild);
     }
 
@@ -1208,9 +1345,9 @@ namespace M17N.Input
       if (target_type == Mmacro)
        {
          if (target_name == MSymbol.nil)
-           im.local_domain.CopyFunc (local_domain);
+           im.domain.CopyFunc (domain);
          else
-           im.local_domain.CopyFunc (local_domain, target_name);
+           im.domain.CopyFunc (domain, target_name);
        }
       else if (target_type == Mmap)
        {
@@ -1251,7 +1388,7 @@ namespace M17N.Input
 
            if (! p.IsSymbol)
              continue;
-           local_domain.Defun (p.Symbol, null, null);
+           domain.Defun (p.Symbol, null, null);
          }
       for (MPlist pl = plist; ! pl.IsEmpty; pl = pl.next)
        if (pl.IsPlist)
@@ -1261,7 +1398,7 @@ namespace M17N.Input
            if (! p.IsSymbol)
              continue;
            transform (p.next);
-           local_domain.Defun (p.Symbol, null, p.next);
+           domain.Defun (p.Symbol, null, p.next);
          }
     }
 
@@ -1293,7 +1430,7 @@ namespace M17N.Input
                if (p.IsEmpty)
                  continue;
                transform (p);
-               MExpression expr = new MExpression (p, local_domain);
+               MXex expr = new MXex (p, domain);
                map.Add (keys, 0, expr);
              }
          }
@@ -1331,147 +1468,144 @@ namespace M17N.Input
                p = p.next;
                transform (p);
                state.branches.Add (map_name,
-                                   new MExpression (p, local_domain));
+                                   new MXex (p, domain));
              }
          }
     }
 
-    private static object insert (MExpression[] args, MExpression.Domain domain)
+    private static Xex.Term Finsert (Xex.Domain domain, Xex.Variable vari,
+                                    Xex.Term[] args)
     {
-      ((MInputContext) domain.context).insert (args[0].Val);
-
-      return true;
+      ((MInputContext) domain.context).insert (args[0]);
+      return args[0];
     }
 
-    private static object insert_candidates (MExpression[] args,
-                                            MExpression.Domain domain)
+    private static Xex.Term Finsert_candidates (Xex.Domain domain,
+                                               Xex.Variable vari,
+                                               Xex.Term[] args)
     {
-      ((MInputContext) domain.context).insert_candidates ((MPlist) args[0].Val);
-
-      return true;
+      ((MInputContext) domain.context).insert_candidates (args[0]);
+      return args[0];
     }
 
-    private static object marker (MExpression[] args, MExpression.Domain domain)
+    private static Xex.Term Fmarker (Xex.Domain domain, Xex.Variable vari,
+                                    Xex.Term[] args)
     {
       MSymbol sym = (MSymbol) args[0].Args[0].Val;
 
       return ((MInputContext) domain.context).marker (sym);
     }
 
-    private static object char_at (MExpression[] args,
-                                  MExpression.Domain domain)
+    private static Xex.Term char_at (Xex.Domain domain, Xex.Variable vari,
+                                    Xex.Term[] args)
     {
       return ((MInputContext) domain.context).char_at ((int) args[0].Val);
     }
 
-    private static object delete (MExpression[] args, MExpression.Domain domain)
+    private static Xex.Term Fdelete (Xex.Domain domain, Xex.Variable vari,
+                                  Xex.Term[] args)
     {
-      ((MInputContext) domain.context).delete ((int) args[0].Val);
+      ((MInputContext) domain.context).delete ((int) args[0].Intval);
       return true;
     }
 
-    private static object select (MExpression[] args, MExpression.Domain domain)
+    private static Xex.Term Fselect (Xex.Domain domain, Xex.Variable vari,
+                                  Xex.Term[] args)
     {
       MInputContext ic = (MInputContext) domain.context;
-      object val = args[0].Val;
 
-      if (val is int)
-       ic.select ((int) val);
+      if (args[0].IsInt)
+       ic.select (args[0].Intval);
       else
-       ic.select ((MSymbol) val);
-      return true;
+       ic.select ((MSYmbol) ((string) args[0].Nameval));
+      return args[0];
     }
 
-    private static object show (MExpression[] args, MExpression.Domain domain)
+    private static Xex.Term Fshow (Xex.Domain domain, Xex.Variable vari,
+                                Xex.Term[] args)
     {
       ((MInputContext) domain.context).show ();
-
-      return true;
+      return Xex.Zero;
     }
 
-    private static object hide (MExpression[] args, MExpression.Domain domain)
+    private static Xex.Term Fhide (Xex.Domain domain, Xex.Variable vari,
+                                Xex.Term[] args)
     {
       ((MInputContext) domain.context).hide ();
-
-      return true;
+      return Xex.Zero;
     }
 
-    private static object move (MExpression[] args, MExpression.Domain domain)
+    private static Xex.Term Fmove (Xex.Domain domain, Xex.Variable vari,
+                                Xex.Term[] args)
     {
-      ((MInputContext) domain.context).move ((int) args[0].Val);
-
-      return true;
+      ((MInputContext) domain.context).move (args[0].Intval);
+      return args[0];
     }
 
-    private static object mark (MExpression[] args, MExpression.Domain domain)
+    private static Xex.Term Fmark (Xex.Domain domain, Xex.Variable vari,
+                                Xex.Term[] args)
     {
-      MSymbol sym = (MSymbol) args[0].Val;
-
-      ((MInputContext) domain.context).mark (sym);
-      return true;
+      ((MInputContext) domain.context).mark (args[0]);
+      return args[0];
     }
 
-    private static object keyseq (MExpression[] args, MExpression.Domain domain)
+    private static Xex.Term Fkeyseq (Xex.Domain domain, Xex.Variable vari,
+                                    Xex.Term[] args)
     {
-      MPlist p = new MPlist ();
-
-      for (int i = 0; i < args.Length; i++)
-       p.Add (MSymbol.symbol, (MSymbol) args[i].Val);
-      return new KeySeq (p);
+      return new KeySeq (args[0].Listval);
     }
 
-    private static object pushback (MExpression[] args,
-                                   MExpression.Domain domain)
+    private static Xex.Term Fpushback (Xex.Domain domain, Xex.Variable vari,
+                                      Xex[] args)
     {
       MInputContext ic = (MInputContext) domain.context;
-      object val = args[0].Val;
-
-      if (val is int)
-       ic.pushback ((int) val);
-      else if (val is MText)
-       ic.pushback (new KeySeq ((MText) val));
-      else if (val is KeySeq)
-       ic.pushback ((KeySeq) val);
+
+      if (args[0].IsInt)
+       ic.pushback (args[0].Intval);
+      else if (args[0].IsStr)
+       ic.pushback (new KeySeq (args[0].Strval));
       else
-       throw new Exception ("Invalid keyseq: " + val);
-      return true;
+       ic.pushback ((KeySeq) args[0].Objval);
+      return args[0];
     }
 
-    private static object pop (MExpression[] args, MExpression.Domain domain)
+    private static Xex.Term Fpop (Xex.Domain domain, Xex.Variable vari,
+                                 Xex.Term[] args)
     {
       ((MInputContext) domain.context).pop ();
-      return true;
+      return Xex.Zero;
     }
 
-    private static object undo (MExpression[] args, MExpression.Domain domain)
+    private static Xex.Term Fundo (Xex.Domain domain, Xex.Variable vari,
+                                  Xex.Term[] args)
     {
-      int n = args.Length == 0 ? -2 : (int) args[0].Val;
+      int n = args.Length == 0 ? -2 : args[0].Intval;
       ((MInputContext) domain.context).undo (n);
-      return true;
+      return Xex.Zero;
     }
 
-    private static object commit (MExpression[] args, MExpression.Domain domain)
+    private static Xex.Term Fcommit (Xex.Domain domain, Xex.Variable vari,
+                                    Xex.Term[] args)
     {
       ((MInputContext) domain.context).commit ();
-      return true;
+      return Xex.Zero;
     }
 
-    private static object unhandle (MExpression[] args,
-                                   MExpression.Domain domain)
+    private static Xex.Term Funhandle (Xex.Domain domain, Xex.Variable vari,
+                                      Xex.Term[] args)
     {
       ((MInputContext) domain.context).commit ();
-      return false;
+      return Xex.Zero;
     }
 
-    private static object shift (MExpression[] args, MExpression.Domain domain)
+    private static Xex.Term Fshift (Xex.Domain domain, Xex.Variable vari,
+                                   Xex.Term[] args)
     {
-      MSymbol sym = (MSymbol) args[0].Args[0].Val;
-
-      ((MInputContext) domain.context).shift (sym);
-      return true;
+      ((MInputContext) domain.context).shift (args[0].Symval);
+      return args[0];
     }
 
-    private static object call (MExpression[] args, MExpression.Domain domain)
+    private static Xex.Term Fcall (Xex.Domain domain, Xex.Variable vari, Xex.Term[] args)
     {
       MSymbol module = (MSymbol) args[0].Args[0].Val;
       MSymbol method = (MSymbol) args[1].Args[0].Val;
@@ -1571,12 +1705,12 @@ namespace M17N.Input
     internal MText following_text = new MText ();
     private bool key_unhandled;
 
-    internal MExpression.Domain domain;
+    internal Xex.Domain domain;
 
     public MInputContext (MInputMethod im)
     {
       this.im = im;
-      domain = new MExpression.Domain (im.local_domain, this);
+      domain = new Xex.Domain (im.domain, this);
       states = new Stack<MInputMethod.State> ();
       states.Push ((MInputMethod.State) im.states.val);
       keys = new MInputMethod.KeySeq ();
@@ -1619,12 +1753,12 @@ namespace M17N.Input
       adjust_markers (from, to, mt);
     }
 
-    internal void insert (object arg)
+    internal void insert (Xex.Term arg)
     {
-      if (arg is int)
-       preedit_replace (cursor_pos, cursor_pos, (int) arg);
+      if (arg.IsInt is int)
+       preedit_replace (cursor_pos, cursor_pos, arg.Intval);
       else
-       preedit_replace (cursor_pos, cursor_pos, (MText) arg);
+       preedit_replace (cursor_pos, cursor_pos, new MText (arg.Strval));
       preedit_changed = true;
       cursor_pos_changed = true;
     }
@@ -1714,6 +1848,17 @@ namespace M17N.Input
          group = new object[column];
       }
 
+      public Candidates (List<Xex.Term> list, int column)
+      {
+       int nblocks = list.Count;
+
+       blocks = new Block[nblocks];
+       for (int i = 0, start = 0; i < nblocks; i++)
+         start += (blocks[i] = new Block (index, list[i])).Count;
+       if (column > 0)
+         group = new object[column];
+      }
+
       public static void Detach (MInputContext ic)
       {
        ic.preedit.PopProp (0, ic.preedit.Length, MInputMethod.Mcandidates);
@@ -1878,7 +2023,7 @@ namespace M17N.Input
       candidate_changed = true;
     }
 
-    internal void insert_candidates (MPlist list)
+    internal void insert_candidates (Xex.Term arg)
     {
       int column = 0;
 
@@ -1888,7 +2033,7 @@ namespace M17N.Input
          if (val is int)
            column = (int) val;
        }
-      candidates = new Candidates (list, column);
+      candidates = new Candidates (arg.Listval, column);
       candidate_from = candidate_to = cursor_pos;
       update_candidate ();
     }
@@ -2145,8 +2290,8 @@ namespace M17N.Input
              if (status == null)
                status = im.title;
              status_changed = true;
-             MExpression on_entry
-               = (MExpression) state.branches.Get (MSymbol.t);
+             Xex on_entry
+               = (Xex) state.branches.Get (MSymbol.t);
              if (on_entry != null)
                on_entry.Eval (domain);
            }
@@ -2182,7 +2327,7 @@ namespace M17N.Input
       if (! result)
        return false;
       if (! arglist.IsEmpty)
-       (new MExpression (arglist, domain)).Eval (domain);
+       (new Xex (arglist, domain)).Eval (domain);
       return true;
     }
 
index 71478bd..3837632 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -6,12 +6,11 @@ RUNCS = ${CS} ${DEBUG_FLAG} -codepage:${CODEPAGE}
 
 M17N_SRC = M17N.cs
 CORE_SRC = MSymbol.cs MPlist.cs MCharTable.cs MText.cs MDatabase.cs
-EXPR_SRC = MExpression.cs
 INPUT_SRC = MInputMethod.cs
 XEX_SRC = XmlExpr.cs
-DLL = M17N.dll M17NCore.dll M17NExpr.dll M17NIM.dll XmlExpr.dll
+DLL = M17N.dll M17NCore.dll M17NIM.dll XmlExpr.dll
 EXAMPLE = symbol.exe plist.exe chartab.exe text.exe textprop.exe database.exe \
-       expr.exe
+       xex.exe
 TEST = rearsticky.exe frontsticky.exe bothsticky.exe \
        sensitive.exe frontsensitive.exe rearsensitive.exe
 
@@ -21,19 +20,16 @@ M17N.dll: ${M17N_SRC}
        $(RUNCS) -out:$@ -t:library ${M17N_SRC}
 
 M17NCore.dll: M17N.dll ${CORE_SRC}
-       $(RUNCS) -out:$@ -t:library -r:M17N.dll -r:Mvp.Xml-bin-2.0/Mvp.Xml.dll ${CORE_SRC}
+       $(RUNCS) -out:$@ -t:library -r:M17N.dll ${CORE_SRC}
 
-M17NExpr.dll: M17N.dll M17NCore.dll ${EXPR_SRC}
-       $(RUNCS) -out:$@ -t:library -r:M17N.dll -r:M17NCore.dll ${EXPR_SRC}
-
-M17NIM.dll: ${INPUT_SRC} M17N.dll M17NCore.dll M17NExpr.dll
-       $(RUNCS) -out:$@ -t:library -r:M17N.dll -r:M17NCore.dll -r:M17NExpr.dll ${INPUT_SRC}
+M17NIM.dll: ${INPUT_SRC} M17N.dll M17NCore.dll XmlExpr.dll
+       $(RUNCS) -out:$@ -t:library -r:M17N.dll -r:M17NCore.dll -r:XmlExpr.dll ${INPUT_SRC}
 
 XmlExpr.dll: ${XEX_SRC}
        $(RUNCS) -out:$@ -t:library ${XEX_SRC}
 
-input.exe: input.cs ${DLL}
-       $(RUNCS) -r:M17N.dll -r:M17NCore -r:M17NExpr -r:M17NIM.dll $<
+input.exe: input.cs M17NIM.dll
+       $(RUNCS) -r:M17N.dll -r:M17NCore -r:XmlExpr -r:M17NIM.dll $<
 
 expr.exe: expr.cs
        $(RUNCS) -r:M17N.dll -r:M17NCore -r:M17NExpr $<
index 806ccc0..f88d2e7 100644 (file)
@@ -14,7 +14,7 @@ namespace System.Xml.Expression
     {
       private static NameTable nt = new NameTable ();
 
-      private string name;
+      internal string name;
 
       public Name (string str)
        {
@@ -103,9 +103,6 @@ namespace System.Xml.Expression
     private static Name Ndescription = "description";
     private static Name Nrange = "range";
 
-    private static Name Nbreak = "break";
-    private static Name Nreturn = "return";
-
     internal abstract class Function
     {
       public Name name;
@@ -253,7 +250,7 @@ namespace System.Xml.Expression
              {
                try {
                  if (args_evalled)
-                   domain.Catch (Nreturn);
+                   domain.Catch (CatchTag.Return);
                  foreach (Term term in body)
                    {
                      result = term.Eval (domain);
@@ -276,75 +273,216 @@ namespace System.Xml.Expression
     public class Variable : Object
     {
       public readonly Name name;
+      public string desc;
+      internal Term default_val;
       internal Term val;
+      object range;
 
-      public Variable (Name name, Term term)
+      public Variable (Name name, Term value)
       {
        this.name = name;
-       val = term;
+       val = value;
+       default_val = Zero;
+      }
+
+      public virtual bool ValueP (Term val) { return true; }
+
+      public Variable Clone ()
+      {
+       Variable v = new Variable (name, val);
+       v.desc = desc;
+       v.default_val = default_val;
+       v.range = range;
+       return v;
       }
 
-      public virtual Term Value
+      public Term Value
       {
        get { return val; }
-       set
-         {
-           if (! ValueP (value))
-             throw new Exception ("Invalid value of " + name + ": " + value);
-           val = value;
-         }
+       set {
+         if (! ValueP (value))
+           throw new Exception ("Invalid value: " + value);
+         val = value;
+       }
       }
 
-      public override Term Eval (Domain domain) { return val; }
+      public Term DefaultValue
+      {
+       get { return default_val; }
+       set {
+         if (! ValueP (value))
+           throw new Exception ("Invalid value: " + value);
+         default_val = value;
+       }
+      }
 
-      public virtual bool ValueP (Term term) { return true; }
+      public virtual object Range
+      {
+       get { return range; }
+       set { range = value; }
+      }
+
+      public override Term Eval (Domain domain) { return val; }
 
       public override string ToString () { return name + "(" + val + ")"; }
 
-      internal class Int : Variable
+      public class Int : Variable
       {
-       public struct Range
-       {
-         public int from, to;
-       }
+       public int[] range;
+
+       private static bool SubsetP (int[] r1, int[] r2)
+         {
+           if (r2 == null)
+             return true;
+           for (int i = 0; i < r1.Length; i += 2)
+             {
+               int j;
+               for (j = 0; j < r2.Length; j += 2)
+                 if (r2[j] <= r1[i] && r2[j + 1] >= r1[i + 1])
+                   break;
+               if (j >= r2.Length)
+                 return false;
+             }
+           return true;
+         }
 
-       public Range[] ranges;
+       private static bool SubsetP (int val, int[] r)
+         {
+           if (r == null)
+             return true;
+           for (int i = 0; i < r.Length; i += 2)
+             if (r[i] <= val && r[i + 1] >= val)
+               return true;
+           return false;
+         }
 
-       public Int (Name name, int i) : base (name, new Term (i)) { }
+       public Int (Name name, string description, int value, int[] range)
+         : base (name, new Term (value))
+         {
+           if (! SubsetP (value, range))
+             throw new Exception ("Invalid value: " + value);
+           desc = description;
+           default_val = val;
+           this.range = range;
+         }
 
        public override bool ValueP (Term term)
        {
-         int i;
-
-         if (term.objval != null)
+         if (! term.IsInt)
            return false;
-         if (ranges == null)
-           return true;
-         i = term.intval;
-         foreach (Range r in ranges)
-           if (i >= r.from && i <= r.to)
-             return true;
-         return false;
+         return SubsetP (term.Intval, range);
+       }
+
+       public override object Range {
+         get { return range; }
+         set {
+           int[] r = (int[]) value;
+           if (! SubsetP (r, range)
+               || ! SubsetP (val.Intval, r)
+               || ! SubsetP (default_val.Intval, r))
+             throw new Exception ("Invalid range");
+           range = r;
+         }
        }
       }
 
       internal class Str : Variable
       {
-       public string[] ranges;
+       public string[] range;
+
+       private static bool SubsetP (string[] r1, string[] r2)
+         {
+           foreach (string s in r1)
+             if (! SubsetP (s, r2))
+               return false;
+           return true;
+         }
+
+       private static bool SubsetP (string str, string[] r)
+         {
+           foreach (string s in r)
+             if (str == s)
+               return true;
+           return false;
+       }
 
-       public Str (Name name, string str) : base (name, new Term (str)) { }
+       public Str (Name name, string description, string value, string[] range)
+         : base (name, new Term (value))
+         {
+           if (! SubsetP (value, range))
+             throw new Exception ("Invalid value: " + value);
+           desc = description;
+           default_val = val;
+           this.range = range;
+         }
 
        public override bool ValueP (Term term)
        {
          if (! (term.objval is string))
            return false;
-         if (ranges == null)
+         return SubsetP (term.Strval, range);
+       }
+
+       public override object Range {
+         get { return range; }
+         set {
+           string[] r = (string[]) value;
+           if (! SubsetP (r, range)
+               || ! SubsetP (val.Strval, r)
+               || ! SubsetP (default_val.Strval, r))
+             throw new Exception ("Invalid range");
+           range = r;
+         }
+       }
+      }
+
+      internal class Sym : Variable
+      {
+       public Name[] range;
+
+       private static bool SubsetP (Name[] r1, Name[] r2)
+         {
+           foreach (Name n in r1)
+             if (! SubsetP (n, r2))
+               return false;
            return true;
-         string str = (string) term.objval;
-         foreach (string s in ranges)
-           if (s == str)
-             return true;
-         return false;
+         }
+
+       private static bool SubsetP (Name name, Name[] r)
+         {
+           foreach (Name n in r)
+             if (name == n)
+               return true;
+           return false;
+       }
+
+       public Sym (Name name, string description, Name value, Name[] range)
+         : base (name, new Term (value))
+         {
+           if (! SubsetP (value, range))
+             throw new Exception ("Invalid value: " + value);
+           desc = description;
+           default_val = val;
+           this.range = range;
+         }
+
+       public override bool ValueP (Term term)
+       {
+         if (! (term.objval is Name))
+           return false;
+         return SubsetP (term.Nameval, range);
+       }
+
+       public override object Range {
+         get { return range; }
+         set {
+           Name[] r = (Name[]) value;
+           if (! SubsetP (r, range)
+               || ! SubsetP (val.Nameval, r)
+               || ! SubsetP (default_val.Nameval, r))
+             throw new Exception ("Invalid range");
+           range = r;
+         }
        }
       }
     }
@@ -400,15 +538,39 @@ namespace System.Xml.Expression
     }
 #endif
 
+    internal class CatchTag : IEquatable<CatchTag>
+    {
+      private object val;
+
+      public CatchTag (Name name) { val = name.name; }
+      private CatchTag (int i) { val = i; }
+
+      public static CatchTag Return = new CatchTag (0);
+      public static CatchTag Break = new CatchTag (1);
+
+      public static bool operator== (CatchTag t1, CatchTag t2)
+       { return t1.val == t2.val; }
+
+      public static bool operator!= (CatchTag t1, CatchTag t2)
+       { return t1.val != t2.val; }
+
+      public bool Equals (CatchTag tag) { return this.val == tag.val; }
+      public override bool Equals (object val) { return this.val == val; }
+
+      public override int GetHashCode () { return val.GetHashCode (); }
+    }
+
     public class Domain
     {
       public object context;
       public int depth = 0;
 
       internal Dictionary<Name, Function> functions;
+      internal Dictionary<Name, Dictionary<Name, Function>>
+       modules = new Dictionary<Name, Dictionary<Name, Function>> ();
       internal Dictionary<Name, Variable> variables;
       internal Bindings bindings;
-      private Stack<Name> catch_stack = new Stack<Name> ();
+      private Stack<CatchTag> catch_stack = new Stack<CatchTag> ();
       private int catch_count = 0;
 
       internal Domain ()
@@ -439,9 +601,9 @@ namespace System.Xml.Expression
          bindings = bindings.UnboundTo (boundary);
       }
 
-      internal void Catch (Name name)
+      internal void Catch (CatchTag tag)
       {
-       catch_stack.Push (name);
+       catch_stack.Push (tag);
        catch_count++;
       }
 
@@ -458,21 +620,31 @@ namespace System.Xml.Expression
 
       internal void ThrowReturn ()
       {
-       foreach (Name tag in catch_stack)
+       foreach (CatchTag tag in catch_stack)
          {
            catch_count--;
-           if (tag == Nreturn)
+           if (tag == CatchTag.Return)
              break;
          }
       }
 
       internal void ThrowBreak ()
       {
-       if (catch_stack.Peek () != Nbreak)
+       if (catch_stack.Peek () != CatchTag.Break)
          throw new Exception ("No outer loop to break");
        catch_count--;
       }
 
+      internal void ThrowTag (CatchTag tag)
+      {
+       foreach (CatchTag elt in catch_stack)
+         {
+           catch_count--;
+           if (elt == tag)
+             break;
+         }
+      }
+
       public void DefSubr (Builtin builtin, string str, bool setvar,
                           int min_arg, int max_arg, params string[] aliases)
       {
@@ -509,7 +681,7 @@ namespace System.Xml.Expression
        return lambda;
       }
 
-      internal Function Defun (XmlNode node)
+      public void Defun (XmlNode node)
       {
        Name name = node.Attributes[Nfname].Value;
        Function func;
@@ -517,17 +689,22 @@ namespace System.Xml.Expression
        if (! functions.TryGetValue (name, out func))
          func = RegisterFunction (node);
        ((Function.Lambda) func).SetBody (node, this);
-       return func;
       }
 
       public void Defvar (XmlNode node)
       {
        Name name = node.Attributes[0].Value;
+       String desc;
        Variable vari;
 
        node = node.FirstChild;
        if (node.Name == Ndescription)
-         node = node.NextSibling;
+         {
+           desc = node.InnerText;
+           node = node.NextSibling;
+         }
+       else
+         desc = null;
        if (node != null)
          {
            Name type = node.Name;
@@ -544,48 +721,110 @@ namespace System.Xml.Expression
 
            if (type == Ninteger)
              {
-               Variable.Int vi = new Variable.Int (name, parse_integer (val));
+               int intval = parse_integer (val);
+               int[] range = null;
                if (range_list != null)
                  {
-                   vi.ranges = new Variable.Int.Range[nranges];
-
+                   range = new int[nranges * 2];
                    for (int i = 0; i < nranges; i++)
                      {
                        XmlNode n = range_list[i];
-
                        if (n.Name == Nrange)
                          {
-                           vi.ranges[i].from =
-                             parse_integer (n.FirstChild.InnerText);
-                           vi.ranges[i].to =
-                             parse_integer (n.LastChild.InnerText);
+                           range[i * 2]
+                             = parse_integer (n.FirstChild.InnerText);
+                           range[i * 2 + 1]
+                             = parse_integer (n.LastChild.InnerText);
                          }
                        else
                          {
-                           int num = parse_integer (n.InnerText);
-                           vi.ranges[i].from = vi.ranges[i].to = num;
+                           range[i * 2]
+                             = range[i * 2 + 1]
+                             = parse_integer (n.InnerText);
                          }
                      }
                  }
-               vari = vi;
+
+               if (variables.TryGetValue (name, out vari))
+                 {
+                   if (! (vari is Variable.Int))
+                     throw new Exception ("Inalid value");
+                   vari = vari.Clone ();
+                   Term v = new Term (intval);
+                   vari.Value = v;
+                   vari.DefaultValue = v;
+                   if (range != null)
+                     vari.Range = range;
+                 }
+               else
+                 vari = new Variable.Int (name, desc, intval, range);
              }
            else if (type == Nstring)
              {
-               Variable.Str vs = new Variable.Str (name, val);
+               string[] range = null;
+               if (range_list != null)
+                 {
+                   range = new string[nranges];
+                   for (int i = 0; i < nranges; i++)
+                     range[i] = range_list[i].InnerText;
+                 }
+
+               if (variables.TryGetValue (name, out vari))
+                 {
+                   if (! (vari is Variable.Str))
+                     throw new Exception ("Invalid value");
+                   vari = vari.Clone ();
+                   Term v = new Term (val);
+                   vari.Value = v;
+                   vari.DefaultValue = v;
+                   if (range != null)
+                     vari.Range = range;
+                 }
+               else
+                 vari = new Variable.Str (name, desc, val, range);
+             }
+           else if (type == Nsymbol)
+             {
+               Name[] range = null;
                if (range_list != null)
-                 vs.ranges = new string[nranges];
-               for (int i = 0; i < nranges; i++)
-                 vs.ranges[i] = range_list[i].Value;
-               vari = vs;
+                 {
+                   range = new Name[nranges];
+                   for (int i = 0; i < nranges; i++)
+                     range[i] = range_list[i].InnerText;
+                 }
+
+               if (variables.TryGetValue (name, out vari))
+                 {
+                   if (! (vari is Variable.Sym))
+                     throw new Exception ("Invalid value");
+                   vari = vari.Clone ();
+                   Term v = new Term (val);
+                   vari.Value = v;
+                   vari.DefaultValue = v;
+                   if (range != null)
+                     vari.Range = range;
+                 }
+               else
+                 vari = new Variable.Sym (name, desc, val, range);
              }
            else
              throw new Exception ("Unknown type: " + type);
          }
        else
-         vari = new Variable (name, Zero);
+         {
+           if (variables.TryGetValue (name, out vari))
+             vari = vari.Clone ();
+           else
+             vari = new Variable (name, Zero);
+         }
        variables[name] = vari;
       }
 
+      public void Defvar (Variable vari)
+      {
+       variables[vari.name] = vari;
+      }
+
       internal Variable Defvar (Name name)
       {
        Variable vari = new Variable (name, Zero);
@@ -616,7 +855,7 @@ namespace System.Xml.Expression
          domain.functions[kv.Key] = kv.Value;
       }
 
-      internal Variable GetVar (Name name)
+      public Variable GetVar (Name name)
       {
        Variable vari;
 
@@ -700,6 +939,8 @@ namespace System.Xml.Expression
       basic.DefSpecial (Fforeach, "foreach", 2, -1);
       basic.DefSpecial (Fquote, "quote", 1, 1);
       basic.DefSpecial (Ftype, "type", 1, 1);
+      basic.DefSpecial (Fcatch, "catch", 2, 2);
+      basic.DefSpecial (Fthrow, "throw", 1, 2);
     }
 
     private static Term Fset (Domain domain, Variable vari, Term[] args)
@@ -1090,7 +1331,7 @@ namespace System.Xml.Expression
     {
       Term result = Zero;
       try {
-       domain.Catch (Nbreak);
+       domain.Catch (CatchTag.Break);
        while (! domain.Thrown)
          foreach (Term arg in args)
            {
@@ -1108,7 +1349,7 @@ namespace System.Xml.Expression
     {
       Term result = Zero;
       try {
-       domain.Catch (Nbreak);
+       domain.Catch (CatchTag.Break);
        while (! domain.Thrown && args[0].Eval (domain).IsTrue)
          for (int i = 1; i < args.Length; i++)
            {
@@ -1149,7 +1390,7 @@ namespace System.Xml.Expression
       Bindings current = domain.bindings;
 
       try {
-       domain.Catch (Nbreak);
+       domain.Catch (CatchTag.Break);
        foreach (Term term in list)
          {
            domain.Bind (vari, term);
@@ -1188,9 +1429,27 @@ namespace System.Xml.Expression
       return TermTerm;
     }
 
-    public abstract class Object
+    private static Term Fcatch (Domain domain, Variable vari, Term[] args)
     {
-      public abstract Term Eval (Domain domain);
+      Term result = Zero;
+      try {
+       domain.Catch (new CatchTag (args[0].Nameval));
+       result = args[1].Eval (domain);
+      } finally {
+       domain.Uncatch ();
+      }
+      return result;
+    }
+
+    private static Term Fthrow (Domain domain, Variable vari, Term[] args)
+    {
+      domain.ThrowTag (new CatchTag (args[0].Nameval));
+      return (args.Length == 1 ? Zero : args[1]);
+    }
+
+    public class Object
+    {
+      public virtual Term Eval (Domain domain) { return new Term (this); }
     }
 
     private class Funcall : Object
@@ -1199,12 +1458,34 @@ namespace System.Xml.Expression
       internal Variable vari;
       internal Term[] args;
 
-      public Funcall (Function func, Variable vari, Term[] args)
-      {
-       this.func = func;
-       this.vari = vari;
-       this.args = args;
-      }
+      public Funcall (XmlNode node, Domain domain)
+       {
+         vari = null;
+         Name name = node.Name;
+
+         if (name == Nfuncall)
+           name = node.Attributes[0].Value;
+         else if (node.Attributes[Nvname] != null)
+           vari = domain.GetVar (node.Attributes[Nvname].Value);
+         func = domain.GetFunc (name);
+         XmlNodeList nlist = node.ChildNodes;
+         int nargs = nlist.Count;
+
+         if (nargs < func.min_arg
+             || (func.max_arg >= 0 && nargs > func.max_arg))
+           throw new Exception ("Invalid number of arguments to: "
+                                + name + " " + nargs);
+         args = new Term[nargs];
+         for (int i = 0; i < nlist.Count; i++)
+           args[i] = new Term (nlist[i], domain);
+       }
+
+      public Funcall (Domain domain, Name fname, Name vname, Term[] args)
+       {
+         func = domain.GetFunc (fname);
+         vari = domain.GetVar (vname);
+         this.args = args;
+       }
 
       public override Term Eval (Domain domain)
       {
@@ -1240,7 +1521,7 @@ namespace System.Xml.Expression
       public Term (Name name) { intval = 0; objval = name; }
       public Term (string str) { intval = 0; objval = str; }
       public Term (List<Term> list) { intval = 0; objval = list; }
-      public Term (Term term) { intval = 0; objval = term; }
+      public Term (Term term) { intval = term.intval; objval = term.objval; }
       public Term (Object obj) { intval = 0; objval = obj; }
 
       public Term (XmlNode node, Domain domain)
@@ -1270,31 +1551,18 @@ namespace System.Xml.Expression
                  objval = list;
                }
              else
-               {
-                 Function func;
-                 Variable vari = null;
-                 Term[] args;
-
-                 if (name == Nfuncall)
-                   name = node.Attributes[0].Value;
-                 else if (node.Attributes[Nvname] != null)
-                   vari = domain.GetVar (node.Attributes[Nvname].Value);
-                 func = domain.GetFunc (name);
-                 XmlNodeList nlist = node.ChildNodes;
-                 int nargs = nlist.Count;
-
-                 if (nargs < func.min_arg
-                     || (func.max_arg >= 0 && nargs > func.max_arg))
-                   throw new Exception ("Invalid number of arguments to: "
-                                        + name + " " + nargs);
-                 args = new Term[nargs];
-                 for (int i = 0; i < nlist.Count; i++)
-                   args[i] = new Term (nlist[i], domain);
-                 objval = new Funcall (func, vari, args);
-               }
+               objval = new Funcall (node, domain);
            }
        }
 
+      public int Objval {
+       get {
+         if (objval == null)
+           throw new Exception ("term is an integer: " + this);
+         return objval;
+       }
+      }
+
       public int Intval {
        get {
          if (objval != null)
@@ -1311,6 +1579,14 @@ namespace System.Xml.Expression
        }
       }
 
+      public string Nameval {
+       get {
+         if (! IsName)
+           throw new Exception ("term is not symbol: " + this);
+         return (Name) objval;
+       }
+      }
+
       public List<Term> Listval {
        get {
          if (! IsList)
@@ -1333,6 +1609,12 @@ namespace System.Xml.Expression
       public bool IsName { get { return (objval is Name); } }
       public bool IsList { get { return (objval is List<Term>); } }
 
+      public bool IsType (Type type)
+      {
+       return (objval == null ? type == typeof (int)
+               : type == objval.GetType ());
+      }
+
       public Term Eval (Domain domain)
       {
        if (objval == null || objval is Name || objval is string)
@@ -1341,10 +1623,6 @@ namespace System.Xml.Expression
          return new Term ((List<Term>) objval);
        if (objval is Object)
          return ((Object) objval).Eval (domain);
-       if (objval is Variable)
-         return ((Variable) objval).val;
-       if (objval is Term)
-         return (Term) objval;
        throw new Exception ("invalid Term object: " + objval);
       }
 
@@ -1394,13 +1672,13 @@ namespace System.Xml.Expression
       }
     }
 
-    static Term Zero = new Term (0);
-    static Term One = new Term (1);
-    static Term TermInt = new Term (Ninteger);
-    static Term TermStr = new Term (Nstring);
-    static Term TermName = new Term (Nsymbol);
-    static Term TermList = new Term (Nlist);
-    static Term TermTerm = new Term ((Name) "term");
+    static private Term Zero = new Term (0);
+    static private Term One = new Term (1);
+    static private Term TermInt = new Term (Ninteger);
+    static private Term TermStr = new Term (Nstring);
+    static private Term TermName = new Term (Nsymbol);
+    static private Term TermList = new Term (Nlist);
+    static private Term TermTerm = new Term ((Name) "term");
 
     internal static int parse_integer (string str)
     {
@@ -1415,7 +1693,7 @@ namespace System.Xml.Expression
 
       if (c == '?')
        return str[1];
-      if (c == '0' && str[1] == 'x')
+      if ((c == '0' || c == '#') && str[1] == 'x')
        {
          i = 0;
          for (int idx = 2; idx < len; idx++)
@@ -1453,25 +1731,10 @@ namespace System.Xml.Expression
 
     private Term[] terms;
 
-    public Xexpression (string url, Domain domain)
+    private void parse_terms (Domain domain, XmlNode node)
     {
-      XmlDocument doc = new XmlDocument (Name.Table);
-      XmlNode node;
-
-      using (XmlTextReader reader = new XmlTextReader (url, Name.Table))
-       {
-         do {
-           reader.Read ();
-         } while (reader.NodeType != XmlNodeType.None
-                  && (reader.NodeType != XmlNodeType.Element
-                      || reader.Name != Nexpr));
-         if (reader.NodeType == XmlNodeType.None)
-           throw new Exception ("Node <expr> not found");
-         node = doc.ReadNode (reader);
-       }
-
       int nterms = 0;
-      for (XmlNode n = node.FirstChild; n != null; n = n.NextSibling)
+      for (XmlNode n = node; n != null; n = n.NextSibling)
        if (n.NodeType == XmlNodeType.Element)
          {
            if (n.Name == Ndefun)
@@ -1484,7 +1747,7 @@ namespace System.Xml.Expression
 
       terms = new Term[nterms];
       int i = 0;
-      for (XmlNode n = node.FirstChild; n != null; n = n.NextSibling)
+      for (XmlNode n = node; n != null; n = n.NextSibling)
        if (n.NodeType == XmlNodeType.Element)
          {
            if (n.Name == Ndefun)
@@ -1494,13 +1757,37 @@ namespace System.Xml.Expression
          }
     }
 
+    public Xexpression (Domain domain, XmlNode node)
+    {
+      parse_terms (domain, node);
+    }
+
+    public Xexpression (Domain domain, string url)
+    {
+      XmlDocument doc = new XmlDocument (Name.Table);
+      XmlNode node;
+
+      using (XmlTextReader reader = new XmlTextReader (url, Name.Table))
+       {
+         do {
+           reader.Read ();
+         } while (reader.NodeType != XmlNodeType.None
+                  && (reader.NodeType != XmlNodeType.Element
+                      || reader.Name != Nexpr));
+         if (reader.NodeType == XmlNodeType.None)
+           throw new Exception ("Node <expr> not found");
+         node = doc.ReadNode (reader);
+       }
+      parse_terms (domain, node.FirstChild);
+    }
+
     public Term Eval (Domain domain)
     {
       Term result = Zero;
 
       domain.depth = 0;
       try {
-       domain.Catch (Nreturn);
+       domain.Catch (CatchTag.Return);
        foreach (Term term in terms)
          {
            result = term.Eval (domain);
diff --git a/xex.cs b/xex.cs
index 1ea49e0..a6190f2 100644 (file)
--- a/xex.cs
+++ b/xex.cs
@@ -2,16 +2,17 @@ using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Xml;
-using System.Xml.Expression;
+using Xex = System.Xml.Expression.Xexpression;
 
 public class Test
 {
-  public static void Main()
+  public static void Main(params string[] args)
   {
-    Xexpression.Domain domain = new Xexpression.Domain (null);
-    Xexpression xex = new Xexpression ("xex.xml", domain);
+    Xex.Domain domain = new Xex.Domain (null);
+    Xex xex = new Xex (domain, "xex.xml");
 
-    Xexpression.debug_level = 10;
+    if (args.Length >= 2 && args[0] == "-d")
+      Xex.debug_level = int.Parse (args[1]);
     Console.WriteLine (xex);
     Console.WriteLine (xex.Eval (domain));
   }
diff --git a/xex.txt b/xex.txt
index fce2ebd..5426526 100644 (file)
--- a/xex.txt
+++ b/xex.txt
@@ -22,7 +22,7 @@ OPTIONAL =
 REST =
   '<rest>' VAR '</rest>'
 
-DEFVAR = DEFVAR-INT DEFVAR-STR
+DEFVAR = DEFVAR-INT DEFVAR-STR DEFVAR-SYM
 
 DEFVAR-INT =
   '<defvar vname="' VNAME '">'
@@ -38,6 +38,13 @@ DEFVAR-STR =
   <possible-value> STR * </possible-value>
   '</defvar>'
 
+DEFVAR-SYM =
+  '<defvar vname"' VNAME '">'
+  DESCRIPTION ?
+  SYMBOL ?
+  <possible-value> SYMBOL * </possible-value>
+  '</defvar>'
+
 DESCRIPTION =
   '<description>' [ TEXT | GETTEXT ] '</description>'
 
@@ -67,9 +74,9 @@ PREDEFINED =
   | 'lt' | 'le' | 'eq' | 'ge' | 'gt' | 'noteq'
   | 'add' | 'sub' | 'mul' | 'div' | 'mod'
   | 'logand' | 'logior' | 'logxor' | 'lsh'
-  | 'append' | 'concat' | 'nth'  | 'copy' | 'ins' | 'del'
+  | 'append' | 'concat' | 'length' | 'nth'  | 'copy' | 'ins' | 'del'
   | 'progn' | 'if' | 'when' | 'cond'
-  | 'loop' | 'break' | 'while' | 'foreach'
+  | 'loop' | 'while' | 'foreach' | 'break' | 'return'
   | 'quote' | 'eval' | 'type'
 
 ;; TERM has a value, and is evaluated to a TERM as below.
@@ -117,6 +124,7 @@ ANYTERM = TERM
 '<gt>' INTTERM INTTERM '</gt>'
 '<append>' ANYTERM + '</append>'
 '<concat>' [ INTTERM | STRTERM | LISTTERM ] + '</concat>'
+'<length>' [ STRTERM | LISTTERM ] '</length>'
 '<nth>' INTTERM [ STRTERM | LISTTERM ] '</nth>'
 '<copy>' LISTTERM '</nth>'
 '<ins vname="' VNAME '">' INTTERM [ STRTERM | LISTTERM ] '</ins>'
@@ -131,6 +139,8 @@ ANYTERM = TERM
 '<loop>' TERM + '</loop>'
 '<while>' TERM + '</while>'
 '<foreach vname="' VNAME '">' TERM + '</foreach>'
+'<break>' ANYTERM ? '</break>'
+'<return>' ANYTERM ? '</return>'
 '<quote>' TERM '</quote>'
 '<eval>' TERM '</eval>'
 '<type>' ANYTERM '</type>'
diff --git a/xex.xml b/xex.xml
index 95511b0..47115fa 100644 (file)
--- a/xex.xml
+++ b/xex.xml
   </defun>
 
   <defun fname="looptest">
-    <args><fixed vname="l"/></args>
-    <foreach vname="term"><varref vname="l"/>
-      <eval><varref vname="term"/></eval>
-    </foreach>
+    <args-unevalled><fixed vname="l"/></args-unevalled>
+    <loop><loop>
+      <foreach vname="term"><varref vname="l"/>
+       <eval><varref vname="term"/></eval>
+      </foreach>
+    </loop></loop>
+    <symbol>looptest-finished</symbol>
   </defun>
 
-    <funcall fname="looptest">
-      <list>
-       <set vname="i"><integer>0</integer></set>
-       <return><symbol>returned</symbol></return>
-       <add vname="i"><integer>1</integer></add>
-       <varref vname="i"/>
-      </list>
-    </funcall>
   <set vname="x"><integer>10</integer></set>
   <set vname="str"><string>ABC</string></set>
   <append>
+    <catch><symbol>tag</symbol>
+      <funcall fname="looptest">
+       <list>
+         <set vname="i"><integer>0</integer></set>
+         <throw><symbol>tag</symbol><symbol>returned</symbol></throw>
+         <add vname="i"><integer>1</integer></add>
+         <varref vname="i"/>
+       </list>
+      </funcall>
+    </catch>
     <funcall fname="factorial"><varref vname="x"/></funcall>
     <ins vname="str"><integer>1</integer><string>123</string></ins>
     <del vname="str"><integer>2</integer><integer>4</integer></del>
@@ -60,5 +65,7 @@
        <quote><add><varref vname="x"/><integer>1</integer></add></quote>
       </eval>
     </eval>
+    <concat><integer>?a</integer><integer>?b</integer></concat>
+    <quote><add><varref vname="x"/><integer>1</integer></add></quote>
   </append>
 </expr>