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
{
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);
}
}
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);
}
}
#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;
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 ()
{
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,
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)
{
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)
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)
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;
}