*** empty log message ***
authorhanda <handa>
Fri, 18 Sep 2009 13:07:28 +0000 (13:07 +0000)
committerhanda <handa>
Fri, 18 Sep 2009 13:07:28 +0000 (13:07 +0000)
XmlExpr.cs
xex.cs
xex.xml

index 86048c8..3c1594b 100644 (file)
@@ -104,8 +104,8 @@ namespace System.Xml.Expression
     private static Name Nrange = "range";
 
     private static Name Nprogn = "progn";
-    private static Name Nloop = "loop";
-    private static Name Nfunction = "function";
+    private static Name Nbreak = "break";
+    private static Name Nreturn = "return";
 
     internal abstract class Function
     {
@@ -145,7 +145,11 @@ namespace System.Xml.Expression
          Term[] newargs = new Term[args.Length];
 
          for (int i = 0; i < args.Length; i++)
-           newargs[i] = args[i].Eval (domain);
+           {
+             newargs[i] = args[i].Eval (domain);
+             if (domain.Catched)
+               return newargs[i];
+           }
          return builtin (domain, vari, newargs);
        }
       }
@@ -247,8 +251,19 @@ namespace System.Xml.Expression
            for (i = 0; i < min_arg; i++)
              domain.Bind (this.args[i], args[i]);
            if (body != null)
-             foreach (Term term in body)
-               result = term.Eval (domain);
+             {
+               try {
+                 domain.Catch (Nreturn);
+                 foreach (Term term in body)
+                   {
+                     result = term.Eval (domain);
+                     if (domain.Catched)
+                       return result;
+                   }
+               } finally {
+                 domain.Uncatch ();
+               }
+             }
          } finally {
            domain.UnboundTo (current);
          }
@@ -389,18 +404,6 @@ namespace System.Xml.Expression
     }
 #endif
 
-    internal struct CatchTag
-    {
-      public readonly Name name;
-      public readonly int count;
-
-      public CatchTag (Name name, int count)
-       {
-         this.name = name;
-         this.count = count;
-       }
-    }
-
     public class Domain
     {
       public object context;
@@ -409,8 +412,8 @@ namespace System.Xml.Expression
       internal Dictionary<Name, Function> functions;
       internal Dictionary<Name, Variable> variables;
       internal Bindings bindings;
-      internal Stack<CatchTag> catch_list = new Stack<CatchTag> ();
-      private int catch_count = 0;
+      private Stack<Name> catch_stack = new Stack<Name> ();
+      private int catch_count = -1;
 
       internal Domain ()
       {
@@ -442,32 +445,43 @@ namespace System.Xml.Expression
 
       internal void Catch (Name name)
       {
-       catch_list.Push (new CatchTag (name, catchcount++));
+       catch_stack.Push (name);
+       catch_count++;
+       Console.WriteLine ("catch {0}", catch_count);
       }
 
       internal bool Catched {
-       get { return catch_list.Peek ().count == catchcount; }
+       get {
+         Console.WriteLine ("catched {0} {1}",
+                            catch_stack.Count,
+                            catch_count);
+         return catch_stack.Count == catch_count; }
       }
 
       internal void ThrowReturn ()
       {
-       CatchTag tag = catch_list.Peek ();
-       while (tag.name != Nreturn)
+       Name tag = catch_stack.Peek ();
+       while (tag != Nreturn)
          {
-           catch_list.Pop ();
-           tag = catch_list.Peek ();
+           catch_stack.Pop ();
+           tag = catch_stack.Peek ();
          }
-       catchcount = tag.count;
+       catch_count = catch_stack.Count - 1;
       }
 
       internal void ThrowBreak ()
       {
-       catch_list.Peek ().count = catchcount;
+       Name tag = catch_stack.Peek ();
+       if (tag != Nbreak)
+         throw new Exception ("No outer loop to break");
+       catch_count = catch_stack.Count - 1;
       }
 
       internal void Uncatch ()
       {
-       catch_list.Pop ();
+       catch_stack.Pop ();
+       catch_count = catch_stack.Count;
+       Console.WriteLine ("uncatch {0}", catch_count);
       }
 
       public void DefSubr (Builtin builtin, string str, bool setvar,
@@ -1075,39 +1089,23 @@ namespace System.Xml.Expression
       return result;
     }
 
-    private static Term break_clause (Domain domain, Variable vari, Term[] args)
+    private static Term return_clause (Domain domain, Variable vari, Term[] args)
     {
-      Stack<CatchTag> clist = domain.catch_list;
-      if (clist.Count == 0)
-       throw new Exception ("No outer loop to break");
-      CatchTag tag = clist.Peek ();
-      if (tag.name != Nloop)
-       throw new Exception ("No outer loop to break");
-      domain.depth = tag.depth;
+      domain.ThrowReturn ();
       return args.Length == 0 ? Zero : args[0];
     }    
 
-    private static Term return_clause (Domain domain, Variable vari, Term[] args)
+    private static Term break_clause (Domain domain, Variable vari, Term[] args)
     {
-      Stack<CatchTag> clist = domain.catch_list;
-
-      while (clist.Count > 0)
-       {
-         CatchTag tag = clist.Pop ();
-         if (tag.name == Nfunction)
-           {
-             domain.depth = tag.depth;
-             return = args.Length == 0 ? Zero : args[0];
-           }
-       }
+      domain.ThrowBreak ();
       return args.Length == 0 ? Zero : args[0];
     }    
 
     private static Term loop_clause (Domain domain, Variable vari, Term[] args)
     {
-      domain.Catch (Nloop);
       Term result = Zero;
       try {
+       domain.Catch (Nbreak);
        while (! domain.Catched)
          foreach (Term arg in args)
            {
@@ -1123,10 +1121,20 @@ namespace System.Xml.Expression
 
     private static Term while_clause (Domain domain, Variable vari, Term[] args)
     {
-      while (args[0].Eval (domain).IsTrue)
-       for (int i = 1; i < args.Length; i++)
-         args[i].Eval (domain);
-      return Zero;
+      Term result = Zero;
+      try {
+       domain.Catch (Nbreak);
+       while (! domain.Catched && args[0].Eval (domain).IsTrue)
+         for (int i = 1; i < args.Length; i++)
+           {
+             result = args[i].Eval (domain);
+             if (domain.Catched)
+               break;
+           }
+      } finally {
+       domain.Uncatch ();
+      }
+      return result;
     }
 
     private static Term cond_clause (Domain domain, Variable vari, Term[] args)
@@ -1149,20 +1157,32 @@ namespace System.Xml.Expression
     private static Term foreach_clause (Domain domain, Variable vari,
                                        Term[] args)
     {
-      List<Term> list = args[0].Listval;
+      List<Term> list = args[0].Eval (domain).Listval;
       Bindings current = domain.bindings;
+      Term result = Zero;
 
-      foreach (Term term in list)
-       {
-         domain.Bind (vari, term);
-         try {
-           for (int i = 1; i < args.Length; i++)
-             args[i].Eval (domain);
-         } finally {
-           domain.UnboundTo (current);
+      try {
+       domain.Catch (Nbreak);
+       foreach (Term term in list)
+         {
+           domain.Bind (vari, term);
+           try {
+             for (int i = 1; i < args.Length; i++)
+               {
+                 result = args[i].Eval (domain);
+                 if (domain.Catched)
+                   break;
+               }
+           } finally {
+             domain.UnboundTo (current);
+           }
+           if (domain.Catched)
+             break;
          }
-       }
-      return Zero;
+      } finally {
+       domain.Uncatch ();
+      }
+      return result;
     }
 
     private static Term quote_clause (Domain domain, Variable vari, Term[] args)
@@ -1486,8 +1506,17 @@ namespace System.Xml.Expression
       Term result = Zero;
 
       domain.depth = 0;
-      foreach (Term term in terms)
-       result = term.Eval (domain);
+      try {
+       domain.Catch (Nreturn);
+       foreach (Term term in terms)
+         {
+           result = term.Eval (domain);
+           if (domain.Catched)
+             break;
+         }
+      } finally {
+       domain.Uncatch ();
+      }
       return result;
     }
 
diff --git a/xex.cs b/xex.cs
index 09f5669..1ea49e0 100644 (file)
--- a/xex.cs
+++ b/xex.cs
@@ -11,7 +11,7 @@ public class Test
     Xexpression.Domain domain = new Xexpression.Domain (null);
     Xexpression xex = new Xexpression ("xex.xml", domain);
 
-    Xexpression.debug_level = 0;
+    Xexpression.debug_level = 10;
     Console.WriteLine (xex);
     Console.WriteLine (xex.Eval (domain));
   }
diff --git a/xex.xml b/xex.xml
index 6f24c55..95511b0 100644 (file)
--- a/xex.xml
+++ b/xex.xml
     <eval><varref vname="x"/></eval>
   </defun>
 
+  <defun fname="looptest">
+    <args><fixed vname="l"/></args>
+    <foreach vname="term"><varref vname="l"/>
+      <eval><varref vname="term"/></eval>
+    </foreach>
+  </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>