From f768c56659bbdbe4c18f09bda5c0a83f7dee3019 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 9 Jul 2010 13:44:32 +0200 Subject: Correct alias handling in pattern matching --- src/Term.vala | 109 ++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 37 deletions(-) diff --git a/src/Term.vala b/src/Term.vala index 5c27e7f..e0033d6 100644 --- a/src/Term.vala +++ b/src/Term.vala @@ -8,13 +8,23 @@ namespace Eva { public Gee.Map? match(Term o) { Gee.Map vars = new Gee.HashMap(); - if(!do_match(o, vars)) + Gee.Map aliases = new Gee.HashMap(); + if(!do_match(o, vars, aliases)) { return null; - else + } + else { + foreach(string a in aliases.keys) { + string v = Var.alias(a, aliases); + + if(v in vars) + vars[a] = vars[v]; + } + return vars; + } } - protected abstract bool do_match(Term o, Gee.Map vars); + protected abstract bool do_match(Term o, Gee.Map vars, Gee.Map aliases); public abstract void encode(Erl.Buffer buffer); @@ -122,9 +132,9 @@ namespace Eva { return value.to_string(); } - protected bool do_match(Term o, Gee.Map vars) { + protected bool do_match(Term o, Gee.Map vars, Gee.Map aliases) { if(o is Var) { - return o.do_match(this, vars); + return o.do_match(this, vars, aliases); } if(o is Int) { @@ -154,9 +164,9 @@ namespace Eva { return value.to_string(); } - protected bool do_match(Term o, Gee.Map vars) { + protected bool do_match(Term o, Gee.Map vars, Gee.Map aliases) { if(o is Var) { - return o.do_match(this, vars); + return o.do_match(this, vars, aliases); } if(o is Int) { @@ -187,9 +197,9 @@ namespace Eva { return value.to_string(); } - protected bool do_match(Term o, Gee.Map vars) { + protected bool do_match(Term o, Gee.Map vars, Gee.Map aliases) { if(o is Var) { - return o.do_match(this, vars); + return o.do_match(this, vars, aliases); } if(o is Double) { @@ -238,9 +248,9 @@ namespace Eva { } } - protected bool do_match(Term o, Gee.Map vars) { + protected bool do_match(Term o, Gee.Map vars, Gee.Map aliases) { if(o is Var) { - return o.do_match(this, vars); + return o.do_match(this, vars, aliases); } if(o is Atom) { @@ -283,9 +293,9 @@ namespace Eva { return ret + "}"; } - protected bool do_match(Term o, Gee.Map vars) { + protected bool do_match(Term o, Gee.Map vars, Gee.Map aliases) { if(o is Var) { - return o.do_match(this, vars); + return o.do_match(this, vars, aliases); } if(!(o is Tuple)) @@ -297,7 +307,7 @@ namespace Eva { return false; for(int i = 0; i < value.size; ++i) { - if(!value[i].do_match(t.value[i], vars)) + if(!value[i].do_match(t.value[i], vars, aliases)) return false; } @@ -340,9 +350,9 @@ namespace Eva { tail = null; } - protected bool do_match(Term o, Gee.Map vars) { + protected bool do_match(Term o, Gee.Map vars, Gee.Map aliases) { if(o is Var) { - return o.do_match(this, vars); + return o.do_match(this, vars, aliases); } if(o is List) { @@ -352,13 +362,13 @@ namespace Eva { return false; if((tail == null) != (l.tail == null)) return false; - if(tail != null && !tail.do_match(l.tail, vars)) + if(tail != null && !tail.do_match(l.tail, vars, aliases)) return false; Gee.Iterator lt = l.list.iterator(); lt.first(); foreach(Term t in list) { - if(!t.do_match(lt.get(), vars)) + if(!t.do_match(lt.get(), vars, aliases)) return false; lt.next(); @@ -453,16 +463,16 @@ namespace Eva { return "\"" + value.replace("\\", "\\\\").replace("\"", "\\\"") + "\""; } - protected bool do_match(Term o, Gee.Map vars) { + protected bool do_match(Term o, Gee.Map vars, Gee.Map aliases) { if(o is Var) { - return o.do_match(this, vars); + return o.do_match(this, vars, aliases); } if(o is String) { return (value == (o as String).value); } else if(o is List) { - return o.do_match(this, vars); + return o.do_match(this, vars, aliases); } else { return false; @@ -493,9 +503,9 @@ namespace Eva { return "#Bin"; } - protected bool do_match(Term o, Gee.Map vars) { + protected bool do_match(Term o, Gee.Map vars, Gee.Map aliases) { if(o is Var) { - return o.do_match(this, vars); + return o.do_match(this, vars, aliases); } if(o is Binary) { @@ -535,9 +545,9 @@ namespace Eva { return "<" + node + "." + num.to_string() + "." + serial.to_string() + ">"; } - protected bool do_match(Term o, Gee.Map vars) { + protected bool do_match(Term o, Gee.Map vars, Gee.Map aliases) { if(o is Var) { - return o.do_match(this, vars); + return o.do_match(this, vars, aliases); } if(!(o is Pid)) @@ -581,9 +591,9 @@ namespace Eva { return "#Port"; } - protected bool do_match(Term o, Gee.Map vars) { + protected bool do_match(Term o, Gee.Map vars, Gee.Map aliases) { if(o is Var) { - return o.do_match(this, vars); + return o.do_match(this, vars, aliases); } if(!(o is Port)) @@ -632,9 +642,9 @@ namespace Eva { return "#Ref"; } - protected bool do_match(Term o, Gee.Map vars) { + protected bool do_match(Term o, Gee.Map vars, Gee.Map aliases) { if(o is Var) { - return o.do_match(this, vars); + return o.do_match(this, vars, aliases); } if(!(o is Ref)) @@ -687,17 +697,42 @@ namespace Eva { return name; } - protected bool do_match(Term o, Gee.Map vars) { - if(o is Var) { - return name == (o as Var).name; - } + internal static string alias(string key, Gee.Map aliases) { + if(!(key in aliases)) + return key; + else + return alias(aliases[key], aliases); + } + + protected bool do_match(Term o, Gee.Map vars, Gee.Map aliases) { + string key = alias(name, aliases); - if(name in vars) { - return vars[name].do_match(o, vars); + if(o is Var) { + Var v = o as Var; + string vkey = alias(v.name, aliases); + + if(key == vkey) + return true; + + if(key in vars && vkey in vars) + return vars[key].do_match(vars[vkey], vars, aliases); + else if(!(vkey in vars)) { + aliases[vkey] = key; + return true; + } + else /* !(key in vars) */ { + aliases[key] = vkey; + return true; + } } else { - vars[name] = o; - return true; + if(key in vars) { + return vars[key].do_match(o, vars, aliases); + } + else { + vars[key] = o; + return true; + } } } -- cgit v1.2.3