*** empty log message ***
authorhanda <handa>
Tue, 27 Oct 2009 09:12:13 +0000 (09:12 +0000)
committerhanda <handa>
Tue, 27 Oct 2009 09:12:13 +0000 (09:12 +0000)
MInputMethod.cs
XmlExpr.cs
input.cs
input.txt
xex.cs
xex.txt
xex.xml

index 0a41c18..ff6a974 100644 (file)
@@ -411,6 +411,25 @@ namespace M17N.Input
                   : new KeySeq (term.Listval));
         }
 
+       public override bool Equals (object obj)
+       {
+        KeySeq ks = obj as KeySeq;
+        if (ks == null || ks.keyseq.Count != keyseq.Count)
+          return false;
+        for (int i = 0; i < keyseq.Count; i++)
+          if (keyseq[i] != ks.keyseq[i])
+            return false;
+        return true;
+       }
+
+       public override int GetHashCode ()
+       {
+        int code = 0;
+        for (int i = 0; i < keyseq.Count; i++)
+          code ^= keyseq[i].GetHashCode ();
+        return code;
+       }
+
        public override string ToString ()
        {
         MText mt;
@@ -581,6 +600,15 @@ namespace M17N.Input
         return Get ((MSymbol) node.InnerText);
        }
 
+       
+       public override bool Equals (object obj)
+       {
+        Marker m = obj as Marker;
+        return (m != null && m.mname == mname);
+       }
+
+       public override int GetHashCode () { return mname.GetHashCode (); }
+
        public class Named : Marker
        {
         public Named (MSymbol mname) : base (mname) { }
@@ -1035,6 +1063,19 @@ namespace M17N.Input
          throw new Exception ("Invalid selector name: " + name);
        return selector;
       }
+
+      public override bool Equals (object obj)
+      {
+       Selector s = obj as Selector;
+       return (s != null && s.tag == tag);
+      }
+
+      public override int GetHashCode () { return (int) tag; }
+
+      public override string ToString ()
+      {
+       return "<selector>@" + tag + "</selector>";
+      }
     }
 
     internal class Map
@@ -1065,6 +1106,31 @@ namespace M17N.Input
       }
     }
 
+    protected class Action
+    {
+      private Xex.Term action;
+
+      public Action (Xex.Domain domain, Xex.Term[] terms)
+      {
+       Xex.Term[] args = new Xex.Term[terms.Length];
+       args[0] = Tcatch_tag;
+       for (int i = 0; i < terms.Length; i++)
+         args[i + 1] = terms[i];
+       action = new Xex.Term (domain, Qcatch, args);
+      }
+
+      public bool Run (Xex.Domain domain)
+      {
+       Xex.Term result = action.Eval (domain);
+       if (result.IsError)
+         {
+           ((Context) domain.context).Error = result.ToString ();
+           return false;
+         }
+       return (result != Tcatch_tag);
+      }
+    }
+
     internal class Keymap
     {
       public Dictionary<Key, Keymap> submaps;
@@ -2269,9 +2335,7 @@ namespace M17N.Input
                                       Xex.Term[] args)
     {
       ((Context) domain.context).commit ();
-      args = new Xex.Term[2];
-      args[0] = args[1] = Tcatch_tag;
-      return Xex.Fthrow (domain, vari, args);
+      return Xex.Fthrow (domain, vari, new Xex.Term[1] { Tcatch_tag });
     }
 
     private static Xex.Term Fshift (Xex.Domain domain, Xex.Variable vari,
@@ -2388,6 +2452,12 @@ namespace M17N.Input
 
       internal ChangedStatus changed;
 
+      private string error_message;
+      public string Error {
+       get { return error_message; }
+       set { error_message = value; }
+      }
+
       private void set_cursor (string prefix, int pos)
       {
        cursor_pos = pos;
index 2bcf476..9952974 100644 (file)
@@ -9,11 +9,11 @@ namespace System.Xml
 {
   public class Xexpression
   {
-    private static int debug_depth = 0;
+    private static int trace_depth = 0;
 
-    public static int DebugDepth {
-      get { return debug_depth; }
-      set { debug_depth = value; }
+    public static int TraceDepth {
+      get { return trace_depth; }
+      set { trace_depth = value; }
     }
 
     public struct Symbol : IEquatable<Symbol>
@@ -68,7 +68,9 @@ namespace System.Xml
 
       public override bool Equals (object obj)
       {
-       return Object.ReferenceEquals (this.name, obj);
+       return (obj is Symbol ? this == (Symbol) obj
+               : obj is string ? this.name == (string) obj
+               : false);
       }
 
       public override int GetHashCode ()
@@ -103,18 +105,42 @@ namespace System.Xml
     private static Symbol Qdescription = "description";
     private static Symbol Qrange = "range";
 
+    private static Symbol Qename = "ename";
+
+    public static partial class Error
+    {
+      // Load time errors.
+      public static Symbol UnknownFunction = "unknown function";
+      public static Symbol InvalidArgumentNumber = "invalid argument number";
+      public static Symbol VariableNotAcceptable = "variable not acceptable";
+    }
+
+    public static partial class Error
+    {
+      // Run time errors.
+      public static Symbol ArithmeticError = "arithmetic error";
+      public static Symbol InvalidArgumentType = "invalid argument type";
+      public static Symbol NoVariable = "no-variable";
+      public static Symbol InvalidVariableType = "invalid variable type";
+      public static Symbol NoOuterLoop = "no outer loop";
+      public static Symbol UnknownError = "unknown error";
+    }
+
+
     public abstract class Function
     {
       public Symbol name;
       public int min_arg, max_arg;
+      public bool setvar;
 
       public Function () { }
 
-      public Function (Symbol name, int min_arg, int max_arg)
+      public Function (Symbol name, int min_arg, int max_arg, bool setvar)
       {
        this.name = name;
        this.min_arg = min_arg;
        this.max_arg = max_arg;
+       this.setvar = setvar;
       }
 
       public abstract Term Call (Domain domain, Variable vari, Term[] args);
@@ -127,19 +153,17 @@ namespace System.Xml
       internal class Subroutine : Function
       {
        public Builtin builtin;
-       public bool setvar;
 
        public Subroutine (Builtin builtin, Symbol name, bool setvar,
                           int min_arg, int max_arg)
-         : base (name, min_arg, max_arg)
+         : base (name, min_arg, max_arg, setvar)
          {
            this.builtin = builtin;
-           this.setvar = setvar;
          }
 
        public override Term Call (Domain domain, Variable vari, Term[] args)
        {
-         if (args != null)
+         if (args.Length > 0)
            {
              args = (Term[]) args.Clone ();
              for (int i = 0; i < args.Length; i++)
@@ -157,9 +181,9 @@ namespace System.Xml
       {
        public Builtin builtin;
 
-       public SpecialForm (Builtin builtin, Symbol name,
+       public SpecialForm (Builtin builtin, Symbol name, bool setvar,
                            int min_arg, int max_arg)
-         : base (name, min_arg, max_arg)
+         : base (name, min_arg, max_arg, setvar)
          {
            this.builtin = builtin;
          }
@@ -187,9 +211,9 @@ namespace System.Xml
            for (n = node.FirstChild; n != null; n = n.NextSibling)
              {
                if (n.Name == Qfixed)
-                 nfixed++;
+                 nfixed += n.ChildNodes.Count;
                else if (n.Name == Qoptional)
-                 noptional++;
+                 noptional += n.ChildNodes.Count;
                else if (n.Name == Qrest)
                  nrest++;
                else
@@ -200,14 +224,17 @@ namespace System.Xml
            args = new Variable[max_arg];
            n = node.FirstChild;
            for (int i = 0; i < max_arg; n = n.NextSibling)
-             args[i++] = domain.Defvar ((Symbol) n.Attributes[0].Value);
+             {
+               for (XmlNode nn = n.FirstChild; nn != null; nn = nn.NextSibling)
+                 args[i++] = domain.Defvar ((Symbol) nn.Attributes[0].Value);
+             }
            if (nrest == 1)
              max_arg = - max_arg;
          }
        else
          {
            min_arg = max_arg = 0;
-           args = null;
+           args = new Variable[0];
          }
       }
 
@@ -240,6 +267,7 @@ namespace System.Xml
          {
            parse_head (domain, node, out name, out min_arg, out max_arg,
                        out args);
+           setvar = false;
          }
 
        public void SetBody (Domain domain, XmlNode node)
@@ -285,6 +313,7 @@ namespace System.Xml
          {
            parse_head (domain, node, out name, out min_arg, out max_arg,
                        out args);
+           setvar = false;
          }
 
        public Lambda (Domain domain, Symbol name, Symbol[] args)
@@ -294,7 +323,7 @@ namespace System.Xml
            int nrest = 0;
 
            this.name = name;
-           if (args != null)
+           if (args.Length > 0)
              {
                int i = 0;
                for (i = 0; i < args.Length; i++, nfixed++)
@@ -323,6 +352,7 @@ namespace System.Xml
              {
                min_arg = max_arg = 0;
              }
+           setvar = false;
          }
 
        public void SetBody (Domain domain, XmlNode node)
@@ -342,7 +372,7 @@ namespace System.Xml
 
          try {
            int i;
-           if (args != null)
+           if (args.Length > 0)
              {
                Term[] newargs = new Term[args.Length];
                for (i = 0; i < min_arg; i++)
@@ -629,36 +659,24 @@ namespace System.Xml
       }
     }
 
-    private static void throw_exception (string msg)
-    {
-      throw new Exception (msg);
-    }
-
     private static void throw_exception (string fmt, params object[] args)
     {
       throw new Exception (String.Format (fmt, args));
     }
 
-    internal class CatchTag : IEquatable<CatchTag>
+    internal struct CatchTag
     {
-      private object val;
+      private Term tag;
+
+      public CatchTag (Symbol sym) { tag = new Term (sym); }
+      public CatchTag (Symbol sym, string msg) { tag = new Term (sym, msg); }
+      public CatchTag (ErrorTerm e) { tag = new Term (e); }
+      private CatchTag (int i) { tag = new Term (i); }
 
-      public CatchTag (Symbol sym) { val = (string) sym; }
-      private CatchTag (int i) { val = i; }
+      public Term Tag { get { return tag; } }
 
       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
@@ -666,6 +684,7 @@ namespace System.Xml
       public Symbol name;
       public object context;
       public int depth = 0;
+      private Stack<Term> call_stack = new Stack<Term> ();
 
       internal Dictionary<Symbol, MethodInfo> termtypes
        = new Dictionary<Symbol, MethodInfo> ();
@@ -690,6 +709,16 @@ namespace System.Xml
        this.context = context;
       }
 
+      internal void PushTerm (Term term)
+      {
+       call_stack.Push (term);
+      }
+
+      internal void PopTerm ()
+      {
+       call_stack.Pop ();
+      }
+
       internal void Bind (Variable vari, Term value)
       {
        bindings = Bindings.Bind (bindings, vari, value);
@@ -714,37 +743,51 @@ namespace System.Xml
          catch_count--;
       }
 
-      public bool Thrown {
-       get { return catch_count < catch_stack.Count; }
-      }
+      public bool Thrown { get { return catch_count < catch_stack.Count; } }
 
       internal void ThrowReturn ()
       {
-       foreach (CatchTag tag in catch_stack)
+       foreach (CatchTag elt in catch_stack)
          {
            catch_count--;
-           if (tag == CatchTag.Return)
+           if (elt.Tag == CatchTag.Return.Tag)
              break;
          }
       }
 
-      internal void ThrowBreak ()
+      internal bool ThrowBreak ()
       {
-       if (catch_stack.Peek () != CatchTag.Break)
-         throw_exception ("No outer loop to break");
+       if (catch_stack.Peek ().Tag != CatchTag.Break.Tag)
+         return false;
        catch_count--;
+       return true;
       }
 
-      internal void ThrowTag (CatchTag tag)
+      internal void ThrowSymbol (Term tag)
       {
        foreach (CatchTag elt in catch_stack)
          {
            catch_count--;
-           if (elt == tag)
+           if (elt.Tag.Matches (tag))
              break;
          }
       }
 
+      internal Term ThrowError (Term tag)
+      {
+       tag = tag.Clone ();
+       ErrorTerm e = tag.objval as ErrorTerm;
+       e.CallStack = call_stack.ToArray ();
+
+       foreach (CatchTag elt in catch_stack)
+         {
+           catch_count--;
+           if (elt.Tag.Matches (tag))
+             break;
+         }
+       return tag;
+      }
+
       public void DefType (Type type)
       {
        if (! type.IsSubclassOf (typeof (TermValue)))
@@ -777,14 +820,14 @@ namespace System.Xml
          functions[(Symbol) a] = func;
       }
 
-      public void DefSpecial (Builtin builtin, string str,
+      public void DefSpecial (Builtin builtin, string str, bool setvar,
                              int min_arg, int max_arg,
                              params string[] aliases)
       {
        Symbol name = str;
        if (termtypes.ContainsKey (name))
          throw new Exception ("already defined as termtype: " + name);
-       Function func = new Function.SpecialForm (builtin, name,
+       Function func = new Function.SpecialForm (builtin, name, setvar,
                                                  min_arg, max_arg);
        functions[name] = func;
        foreach (string a in aliases)
@@ -1087,9 +1130,9 @@ namespace System.Xml
        return str;
       }
 
-      internal void DebugWrite (string fmt, params string[] arg)
+      internal void TraceWrite (string fmt, params string[] arg)
       {
-       if (debug_depth > depth)
+       if (trace_depth > depth)
          {
            for (int i = 0; i < depth; i++)
              Console.Write ("  ");
@@ -1122,6 +1165,7 @@ namespace System.Xml
     {
       basic.DefType (typeof (Varref));
       basic.DefType (typeof (Funcall));
+      basic.DefType (typeof (ErrorTerm));
 
       basic.DefSubr (Fset, "set", true, 1, 1, "=");
       basic.DefSubr (Fnot, "not", false, 1, 1, "!");
@@ -1149,24 +1193,26 @@ namespace System.Xml
       basic.DefSubr (Feval, "eval", false, 1, 1);
       basic.DefSubr (Fbreak, "break", false, 0, 1);
       basic.DefSubr (Freturn, "return", false, 0, 1);
-
-      basic.DefSpecial (Fand, "and", 1, -1, "&&");
-      basic.DefSpecial (For, "or", 1, -1, "||");
-      basic.DefSpecial (Fprogn, "progn", 0, -1, "expr");
-      basic.DefSpecial (Fif, "if", 2, 3);
-      basic.DefSpecial (Fwhen, "when", 1, -1);
-      basic.DefSpecial (Floop, "loop", 1, -1);
-      basic.DefSpecial (Fwhile, "while", 1, -1);
-      basic.DefSpecial (Fcond, "cond", 1, -1);
-      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);
+      basic.DefSubr (Fthrow, "throw", false, 1, 2);
+
+      basic.DefSpecial (Fand, "and", false, 1, -1, "&&");
+      basic.DefSpecial (For, "or", false, 1, -1, "||");
+      basic.DefSpecial (Fprogn, "progn", false, 0, -1, "expr");
+      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);
     }
 
     private static Term Fset (Domain domain, Variable vari, Term[] args)
     {
+      if (vari == null)
+       return new Term (new ErrorTerm (Error.NoVariable, ""));
       vari.Value = args[0];
       return args[0];
     }
@@ -1527,7 +1573,8 @@ namespace System.Xml
 
     private static Term Fbreak (Domain domain, Variable vari, Term[] args)
     {
-      domain.ThrowBreak ();
+      if (! domain.ThrowBreak ())
+       return domain.ThrowError (new Term (Error.NoOuterLoop, null));
       return args.Length == 0 ? Zero : args[0];
     }    
 
@@ -1590,8 +1637,7 @@ namespace System.Xml
       return Zero;
     }
 
-    private static Term Fforeach (Domain domain, Variable vari,
-                                       Term[] args)
+    private static Term Fforeach (Domain domain, Variable vari, Term[] args)
     {
       Term result = args[0].Eval (domain);
       if (domain.Thrown)
@@ -1623,7 +1669,7 @@ namespace System.Xml
 
     private static Term Fquote (Domain domain, Variable vari, Term[] args)
     {
-      return new Term (args[0]);
+      return args[0];
     }
 
     private static Term Ftype (Domain domain, Variable vari, Term[] args)
@@ -1642,9 +1688,15 @@ namespace System.Xml
     public static Term Fcatch (Domain domain, Variable vari, Term[] args)
     {
       Term result = Zero;
+
       try {
        domain.Catch (new CatchTag (args[0].Symval));
-       result = args[1].Eval (domain);
+       for (int i = 1; i < args.Length; i++)
+         {
+           result = args[i].Eval (domain);
+           if (domain.Thrown)
+             return result;
+         }
       } finally {
        domain.Uncatch ();
       }
@@ -1653,16 +1705,26 @@ namespace System.Xml
 
     public static Term Fthrow (Domain domain, Variable vari, Term[] args)
     {
-      domain.ThrowTag (new CatchTag (args[0].Symval));
-      return (args.Length == 1 ? Zero : args[1]);
+      if (args[0].IsSymbol)
+       {
+         domain.ThrowSymbol (args[0]);
+         return (args[args.Length - 1]);
+       }
+      if (args[0].IsError)
+       return domain.ThrowError (args[0]);
+      return domain.ThrowError (new Term (Error.InvalidArgumentType,
+                                         args[0].ToString ()));
     }
 
-    public delegate TermValue TermParser (Domain domain, XmlNode node);
-
     public abstract class TermValue
     {
       public virtual Term Eval (Domain domain) { return new Term (this); }
       public virtual TermValue Clone () { return this; }
+      public virtual bool IsTrue { get { return true; } }
+      public virtual bool Matches (TermValue other) { return Equals (other); }
+      public override abstract bool Equals (object obj);
+      public override abstract int GetHashCode ();
+      public abstract string ToString (bool detail);
     }
 
     private class Varref : TermValue
@@ -1687,7 +1749,20 @@ namespace System.Xml
        return new Varref ((Symbol) node.Attributes[Qvname].Value);
       }
 
-      public override string ToString ()
+      public override bool Equals (object obj)
+      {
+       Varref varref = obj as Varref;
+       return (varref != null && varref.vari.name == vari.name);
+      }
+
+      public override int GetHashCode ()
+      {
+       return vari.name.GetHashCode ();
+      }        
+
+      public override string ToString () { return ToString (true); }
+
+      public override string ToString (bool detail)
       {
        return "<varref vname=\"" + vname + "\"/>";
       }
@@ -1696,7 +1771,6 @@ namespace System.Xml
     private class Funcall : TermValue
     {
       private static Symbol name = "funcall";
-
       public static Symbol Name { get { return name; } }
 
       internal Function func;
@@ -1705,14 +1779,14 @@ namespace System.Xml
 
       public Funcall (Function func, Variable vari, Term[] args)
        {
-         if (args != null)
-           {
-             int nargs = args.Length;
-             if (nargs < func.min_arg
-                 || (func.max_arg >= 0 && nargs > func.max_arg))
-               throw_exception ("Invalid number of arguments to {0}: ",
-                                func.name, nargs);
-           }
+         int nargs = args.Length;
+
+         if (nargs < func.min_arg
+             || (func.max_arg >= 0 && nargs > func.max_arg))
+           throw_exception ("Invalid number of arguments to {0}: ",
+                            func.name, nargs);
+         if (! func.setvar && vari != null)
+           throw_exception ("vname attribute not acceptable: ", func.name);
          this.func = func;
          this.vari = vari;
          this.args = args;
@@ -1739,11 +1813,11 @@ namespace System.Xml
 
       public override Term Eval (Domain domain)
       {
-       domain.DebugWrite (ToString ());
+       domain.TraceWrite (ToString ());
        domain.depth++;
        Term result = func.Call (domain, vari, args);
        domain.depth--;
-       domain.DebugWrite ("=> {0}", result.ToString ());
+       domain.TraceWrite ("=> {0}", result.ToString ());
        return result;
       }
 
@@ -1752,12 +1826,28 @@ namespace System.Xml
        return new Funcall (func, vari, args);
       }
 
-      public override string ToString ()
+      public override bool Equals (object obj)
+      {
+       Funcall funcall = obj as Funcall;
+       return (obj != null
+               && funcall.func == func
+               && funcall.vari == vari
+               && funcall.args.Length == args.Length);
+      }
+
+      public override int GetHashCode ()
+      {
+       return func.GetHashCode () ^ args.Length;
+      }
+
+      public override string ToString () { return ToString (true); }
+
+      public override string ToString (bool detail)
       {
        string str = "<" + func.name;
        if (vari != null)
          str += " vname=\"" + vari.name + "\"";
-       if (args == null)
+       if (args.Length == 0 || ! detail)
          return str + "/>";
        str += ">";
        if (func is Function.SpecialForm)
@@ -1772,6 +1862,75 @@ namespace System.Xml
       }
     }
 
+    internal class ErrorTerm : TermValue
+    {
+      private static Symbol name = "error";
+      public static Symbol Name { get { return name; } }
+      
+      private readonly Symbol ename;
+      private string message;
+      private Term[] stack;
+
+      public ErrorTerm (Symbol ename, string message)
+       {
+         this.ename = ename;
+         this.message = message;
+       }
+
+      public static TermValue Parser (Domain domain, XmlNode node)
+      {
+       XmlAttribute attr = node.Attributes[Qename];
+       Symbol ename = attr == null ? Qnull : (Symbol) attr.Value;
+       string message = node.InnerText;
+       return new ErrorTerm (ename, message);
+      }
+
+      public Term[] CallStack {        get { return stack; } set { stack = value; } }
+
+      public override TermValue Clone ()
+      {
+       return new ErrorTerm (ename, message);
+      }
+
+      public override bool Equals (object obj)
+      {
+       ErrorTerm e = obj as ErrorTerm;
+       if (e == null || e.ename != ename || e.message != message
+           || (e.stack == null ? stack != null
+               : (stack == null || e.stack.Length != stack.Length)))
+         return false;
+       if (stack != null)
+         for (int i = 0; i < stack.Length; i++)
+           if (! stack[i].Equals (e.stack[i]))
+           return false;
+       return true;
+      }
+
+      public override int GetHashCode ()
+      {
+       return ename.GetHashCode ();
+      }
+
+      public override bool Matches (TermValue term)
+      {
+       ErrorTerm e = term as ErrorTerm;
+       return (e != null && (ename == Qnull || e.ename == ename));
+      }
+
+      public override string ToString () { return ToString (true); }
+
+      public override string ToString (bool detail)
+       {
+         string str = "<error type=\"" + ename + "\">";
+         if (message != null)
+           str += message;
+         if (stack != null)
+           for (int i = 0; i < stack.Length; i++)
+             str += stack[i].ToString (false);
+         return str + "</error>";
+       }
+    }
+
     public struct Term
     {
       public int intval;
@@ -1785,8 +1944,13 @@ namespace System.Xml
       public Term (string str) { intval = 0; objval = str; }
       // <list>...</list>
       public Term (List<Term> list) { intval = 0; objval = list; }
+      // <error ename="ERROR-NAME">ERROR-MESSASGE</error>
+      public Term (Symbol name, string message)
+       {
+         intval = 0;
+         objval = new ErrorTerm (name, message);
+       }
 
-      public Term (Term term) { intval = term.intval; objval = term.objval; }
       public Term (TermValue obj) { intval = 0; objval = obj; }
 
       public Term (Domain domain, XmlNode node)
@@ -1883,7 +2047,7 @@ namespace System.Xml
       public string Strval {
        get {
          if (! IsStr)
-           throw new Exception ("term is not string: " + this);
+           throw new Exception ("term is not a string: " + this);
          return (string) objval;
        }
       }
@@ -1891,7 +2055,7 @@ namespace System.Xml
       public string Symval {
        get {
          if (! IsSymbol)
-           throw new Exception ("term is not symbol: " + this);
+           throw new Exception ("term is not a symbol: " + this);
          return (Symbol) objval;
        }
       }
@@ -1899,7 +2063,7 @@ namespace System.Xml
       public List<Term> Listval {
        get {
          if (! IsList)
-           throw new Exception ("term is not list: " + this);
+           throw new Exception ("term is not a list: " + this);
          return (List<Term>) objval;
        }
       }
@@ -1910,27 +2074,29 @@ namespace System.Xml
                  ? (intval != 0)
                  : objval is List<Term>
                  ? (((List<Term>) objval).Count != 0)
+                 : objval is TermValue
+                 ? ((TermValue) objval).IsTrue
                  : true);
        }
       }
+
       public bool IsInt { get { return (objval == null); } }
       public bool IsStr { get { return (objval is string); } }
       public bool IsSymbol { get { return (objval is Symbol); } }
       public bool IsList { get { return (objval is List<Term>); } }
-
-      public bool IsType (Type type)
-      {
-       return (objval == null ? type == typeof (int)
-               : type == objval.GetType ());
-      }
+      public bool IsError { get { return (objval is ErrorTerm); } }
 
       public Term Eval (Domain domain)
       {
-       if (objval == null || objval is Symbol || objval is string)
-         return this;
-       if (objval is List<Term>)
-         return new Term ((List<Term>) objval);
-       return ((TermValue) objval).Eval (domain);
+       try {
+         domain.PushTerm (this);
+         if (objval == null || objval is Symbol || objval is string
+             || objval is List<Term>)
+           return this;
+         return ((TermValue) objval).Eval (domain);
+       } finally {
+         domain.PopTerm ();
+       }
       }
 
       public Term Clone ()
@@ -1946,7 +2112,60 @@ namespace System.Xml
        return new Term (((TermValue) objval).Clone ());
       }
 
-      public override string ToString ()
+      public static bool operator== (Term t1, Term t2)
+       {
+         return t1.Equals (t2);
+       }
+
+      public static bool operator!= (Term t1, Term t2) { return ! (t1 == t2); }
+
+      public override bool Equals (object obj)
+      {
+       if (! (obj is Term))
+         return false;
+       Term term = (Term) obj;
+       if (IsInt)
+         return term.IsInt && term.Intval == Intval;
+       if (IsStr)
+         return term.IsStr && term.Strval == Strval;
+       if (IsSymbol)
+         return term.IsSymbol && term.Symval == Symval;
+       if (IsList)
+         {
+           if (! term.IsList)
+             return false;
+           List<Term> l1 = objval as List<Term>;
+           List<Term> l2 = term.objval as List<Term>;
+
+           if (l1.Count != l2.Count)
+             return false;
+           for (int i = 0; i < l1.Count; i++)
+             if (! l1[i].Equals (l2[i]))
+               return false;
+           return true;
+         }
+       return ((TermValue) objval).Equals (obj);
+      }
+
+      public override int GetHashCode () { return intval; }
+
+      public bool Matches (Term term)
+      {
+       if (IsInt)
+         return term.IsInt && term.Intval == Intval;
+       if (IsStr)
+         return term.IsStr && term.Strval == Strval;
+       if (IsSymbol)
+         return term.IsSymbol && term.Symval == Symval;
+       if (IsList)
+         return (((List<Term>) objval).Count > 0
+                 && ((List<Term>) objval)[0].Matches (term));
+       return ((TermValue) objval).Matches ((TermValue) term.objval);
+      }
+
+      public override string ToString () { return ToString (true); }
+
+      public string ToString (bool detail)
       {
        string str;
 
@@ -1958,15 +2177,20 @@ namespace System.Xml
          str = "<string>" + objval + "</string>";
        else if (objval is List<Term>)
          {
-           str = "<list>";
-           foreach (Term e in (List<Term>) objval)
-             str += e;
-           str += "</list>";
+           if (detail)
+             {
+               str = "<list>";
+               foreach (Term e in (List<Term>) objval)
+                 str += e;
+               str += "</list>";
+             }
+           else
+             str = "<list/>";
          }
        else if (objval is Term)
          str = "<quote>" + objval + "</quote>";
        else if (objval is TermValue)
-         str = ((TermValue) objval).ToString ();
+         str = ((TermValue) objval).ToString (detail);
        else
          throw new Exception ("invalid Term object: " + objval);
        return str;
index 6eb133f..18e513d 100644 (file)
--- a/input.cs
+++ b/input.cs
@@ -29,12 +29,12 @@ public class Test
     // M17n.debug = true;
     int argc = 0;
     string appdir = "/usr/local/share/m17n";
-    int debug_depth = 0;
+    int trace_depth = 0;
 
     while (argc < args.Length && args[argc][0] == '-')
       {
-       if (args[argc] == "-debug")
-         debug_depth = 10;
+       if (args[argc] == "-trace")
+         trace_depth = 10;
        else if (args[argc] == "-xml")
          appdir = "/usr/local/share/m17n-xml";
        argc++;
@@ -42,11 +42,11 @@ public class Test
     if (argc + 2 >= args.Length)
       {
        Console.WriteLine ("Usage: mono [--debug] input.exe"
-                          + " [-debug] [-xml] LANG NAME KEY-SEQUECE");
+                          + " [-trace] [-xml] LANG NAME KEY-SEQUECE");
        return;
       }
 
-    Xex.DebugDepth = debug_depth;
+    Xex.TraceDepth = trace_depth;
     MDatabase.ApplicationDir = appdir;
     MInputMethod im = MInputMethod.Find (args[argc], args[argc + 1]);
     MText mt = new MText ();
index 538f1a2..6537e65 100644 (file)
--- a/input.txt
+++ b/input.txt
@@ -86,8 +86,9 @@ SHIFT = '<shift>' SYMTERM '</shift>'
 SHIFTBACK = '<shiftback/>'
 CHAR-AT = '<char-at>' MARKERTERM '</char-at>'
   => <integer>C</integer>, where C is the character in the preedit text
-     at the postion of MARKERTERM
+     or the surrounding text at the postion specified by MARKERTERM.
 KEY-COUNT = '<key-count/>'
   => <integer>N</integer>, where N is the number of currently handled keys
 SURROUNDING-TEXT-FLAG = '<surrounding-text-flag/>'
-  => <integer>1</integer> or <integer>0</integer>
+  => <integer>1</integer> if surrounding text handling is supported
+     or <integer>0</integer> if not.
diff --git a/xex.cs b/xex.cs
index 741e4f2..6bbf112 100644 (file)
--- a/xex.cs
+++ b/xex.cs
@@ -8,12 +8,12 @@ public class Test
 {
   public static void Main(params string[] args)
   {
-    Xex.DebugDepth = 10;
+    Xex.TraceDepth = 10;
     Xex.Domain domain = new Xex.Domain ("test", null);
     Xex xex = new Xex (domain, "xex.xml");
 
     if (args.Length >= 2 && args[0] == "-d")
-      Xex.DebugDepth = int.Parse (args[1]);
+      Xex.TraceDepth = int.Parse (args[1]);
     Console.WriteLine (xex);
     Console.WriteLine (xex.Eval (domain));
   }
diff --git a/xex.txt b/xex.txt
index f09c047..337f0b6 100644 (file)
--- a/xex.txt
+++ b/xex.txt
@@ -1,7 +1,7 @@
 EXPR =
   '<expr>' [ DEFUN | DEFMACRO | DEFVAR | TERM ] * '</expr>'
 
-TERM = [ INT | STRING | SYMBOL | LIST | VAR | FUNCALL ]
+TERM = [ INT | STRING | SYMBOL | LIST | ERROR | VAR | FUNCALL ]
 
 DEFUN =
   '<defun fname="' FNAME ? ">'
@@ -16,16 +16,16 @@ DEFMACRO =
   '</defmacro>'
 
 ARGS =
-  '<args>' FIXED ? OPTIONAL ? REST ? '</args>'
+  '<args>' FIXED * OPTIONAL * REST ? '</args>'
 
 FIXED =
-  '<fixed> VAR + '</fixed>'
+  '<fixed vname="' VNAME '">'
 
 OPTIONAL =
-  '<optional>' VAR + '<optional>'
+  '<optional vname="' VNAME '">'
 
 REST =
-  '<rest>' VAR '</rest>'
+  '<rest vname="' VNAME '">'
 
 DEFVAR = DEFVAR-INT DEFVAR-STR DEFVAR-SYM
 
@@ -69,9 +69,11 @@ STR =
 SYMBOL =
   '<symbol>' NAME '</symbol>'
 LIST =
-  '<list>' TERM * '</list>' | <list/>
+  '<list>' TERM * '</list>'
+ERROR =
+  [ '<error>' | '<error ename="' ENAME '">"' ] STRING '</error>'
 
-VAR =
+VARREF =
   '<varref vname="' VNAME '"/>'
 
 FUNCALL =
@@ -86,7 +88,7 @@ PREDEFINED =
   | LOGAND | LOGIOR | LOGXOR | LSH
   | APPEND | CONCAT | LENGTH | NTH  | COPY | INS | DEL
   | PROGN | IF | WHEN | COND
-  | LOOP | WHILE | FOREACH | BREAK | RETURN
+  | LOOP | WHILE | FOREACH | BREAK | RETURN | CATCH | THROW
   | QUOTE | EVAL | TYPE
 
 ;; TERM has a value, and is evaluated to a TERM as below.
@@ -94,20 +96,22 @@ PREDEFINED =
 ;; STRING has a string value, and is evaluated to itself.
 ;; SYMBOL has a symbol value, and is evaluated to itself.
 ;; LIST has a list value and, is evaluated to itself.
-;; VAR has a value of TERM that is assigned to the variable,
-;;   and is evalued to that TERM.
-;; FUNCALL has a value of TERM that is returned by that function,
-;;   and is evalued to that TERM.
+;; VARREF has a variable, and is evalued to the value of that variable.
+;; FUNCALL has a function and arguments to it, and is evalued to the
+;; value of function called with those arguments.
 
 INTTERM = INT | VAR (value is INT) | FUNCALL (return INT)
 STRTERM = STR | VAR (value is STR) | FUNCALL (return STR)
 SYMTERM = SYMBOL | VAR (value is SYMBOL) | FUNCALL (return SYMBOL)
 LISTTERM = LIST | VAR (value is LIST) | FUNCALL (return LIST)
+ANYTERM = TERM
 
-;; Here after, when an argument is TERM, it is given to a function
-;; without being evaluted.  Otherwise, an evaluated term is given.
+;; Here after, when an argument written as TERM, it is given to a
+;; function without being evaluted.  Otherwise, an evaluated term is
+;; given.  "the value is NUM" means "the value is
+;; <integer>NUM</integer>".
 
-SET = '<set vname="' VNAME '">' TERM '</set>'
+SET = '<set vname="' VNAME '">' ANYTERM '</set>'
 ADD = '<add>' INTTERM + '</add>'
       | '<add vname="' VNAME '">' INTTERM + '</add>'
 SUB = '<sub>' INTTERM + '</sub>'
@@ -154,5 +158,20 @@ FOREACH = '<foreach vname="' VNAME '">' TERM + '</foreach>'
 BREAK = '<break>' TERM ? '</break>'
 RETURN = '<return>' TERM ? '</return>'
 QUOTE = '<quote>' TERM '</quote>'
+
+CATCH = '<catch>' [ SYMBOL | ERROR ] TERM + '</catch>'
+        | '<catch vname="' VNAME '">' [ SYMBOL | ERROR ] TERM + '</catch>'
+
+;; Evaluate TERMs one by one until the specified SYMBOL or ERROR is
+;; thrown by <throw/>.  If thrown, the value is 1, otherwise the value
+;; is 0.  If VNAME is specified it is set to the last evaluated term.
+;; It is the value of <throw/> if thrown.
+
+THROW = '<throw>' SYMBOL ANYTERM ? '</throw>'
+        | '<throw>' ERROR '</throw>'
+
+;; Throw to the catch for SYMBOL or ERROR.  The value is ANYTERM (if
+;; any) or SYMBOL in the first form, and ERROR in the second form.
+
 EVAL = '<eval>' TERM '</eval>'
 TYPE = '<type>' TERM '</type>'
diff --git a/xex.xml b/xex.xml
index 3566ba7..90d0430 100644 (file)
--- a/xex.xml
+++ b/xex.xml
@@ -1,7 +1,7 @@
 <?xml version='1.0'?>
 <expr xmlns="http://www.m17n.org/MIM">
   <defun fname="factorial">
-    <args><fixed vname="x"/></args>
+    <args><fixed><varref vname="x"/></fixed></args>
     <if><lt><varref vname="x"/><integer>2</integer></lt>
       <varref vname="x"/>
       <mul>
@@ -14,8 +14,9 @@
   </defun>
 
   <defun fname="looptest">
-    <args><fixed vname="l"/></args>
+    <args><fixed><varref vname="l"/></fixed></args>
     <loop><loop>
+      <throw><error ename="xxx">XXX</error></throw>
       <foreach vname="term"><varref vname="l"/>
        <eval><varref vname="term"/></eval>
       </foreach>
@@ -24,7 +25,7 @@
   </defun>
 
   <defmacro fname="temp">
-    <args><fixed vname="x"/></args>
+    <args><fixed><varref vname="x"/></fixed></args>
     <if>
       <lt><eval><varref vname="x"/></eval><integer>10</integer></lt>
       <varref vname="x"/>
@@ -69,4 +70,5 @@
     <integer>100</integer>
     <temp><add vname="y"><integer>5</integer></add></temp>
   </append>
+  <break/>
 </expr>