From 074ad834c10410f54297f726a668d4403f92f8ec Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 9 Jul 2010 09:28:27 +0200 Subject: Implemented pattern matching --- src/Term.vala | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 105 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/Term.vala b/src/Term.vala index 46c03b3..5c27e7f 100644 --- a/src/Term.vala +++ b/src/Term.vala @@ -1,7 +1,20 @@ namespace Eva { public interface Term : Object { public abstract string to_string(); - public abstract bool equals(Term o); + + public bool equals(Term o) { + return (match(o) != null); + } + + public Gee.Map? match(Term o) { + Gee.Map vars = new Gee.HashMap(); + if(!do_match(o, vars)) + return null; + else + return vars; + } + + protected abstract bool do_match(Term o, Gee.Map vars); public abstract void encode(Erl.Buffer buffer); @@ -109,7 +122,11 @@ namespace Eva { return value.to_string(); } - public bool equals(Term o) { + protected bool do_match(Term o, Gee.Map vars) { + if(o is Var) { + return o.do_match(this, vars); + } + if(o is Int) { return value == (o as Int).value; } @@ -137,7 +154,11 @@ namespace Eva { return value.to_string(); } - public bool equals(Term o) { + protected bool do_match(Term o, Gee.Map vars) { + if(o is Var) { + return o.do_match(this, vars); + } + if(o is Int) { return value == (o as Int).value; } @@ -166,7 +187,11 @@ namespace Eva { return value.to_string(); } - public bool equals(Term o) { + protected bool do_match(Term o, Gee.Map vars) { + if(o is Var) { + return o.do_match(this, vars); + } + if(o is Double) { return value == (o as Double).value; } @@ -213,7 +238,11 @@ namespace Eva { } } - public bool equals(Term o) { + protected bool do_match(Term o, Gee.Map vars) { + if(o is Var) { + return o.do_match(this, vars); + } + if(o is Atom) { return value == (o as Atom).value; } @@ -254,7 +283,11 @@ namespace Eva { return ret + "}"; } - public bool equals(Term o) { + protected bool do_match(Term o, Gee.Map vars) { + if(o is Var) { + return o.do_match(this, vars); + } + if(!(o is Tuple)) return false; @@ -264,7 +297,7 @@ namespace Eva { return false; for(int i = 0; i < value.size; ++i) { - if(!value[i].equals(t.value[i])) + if(!value[i].do_match(t.value[i], vars)) return false; } @@ -307,7 +340,11 @@ namespace Eva { tail = null; } - public bool equals(Term o) { + protected bool do_match(Term o, Gee.Map vars) { + if(o is Var) { + return o.do_match(this, vars); + } + if(o is List) { List l = o as List; @@ -315,13 +352,13 @@ namespace Eva { return false; if((tail == null) != (l.tail == null)) return false; - if(tail != null && !tail.equals(l.tail)) + if(tail != null && !tail.do_match(l.tail, vars)) return false; Gee.Iterator lt = l.list.iterator(); lt.first(); foreach(Term t in list) { - if(!t.equals(lt.get())) + if(!t.do_match(lt.get(), vars)) return false; lt.next(); @@ -416,12 +453,16 @@ namespace Eva { return "\"" + value.replace("\\", "\\\\").replace("\"", "\\\"") + "\""; } - public bool equals(Term o) { + protected bool do_match(Term o, Gee.Map vars) { + if(o is Var) { + return o.do_match(this, vars); + } + if(o is String) { return (value == (o as String).value); } else if(o is List) { - return o.equals(this); + return o.do_match(this, vars); } else { return false; @@ -452,7 +493,11 @@ namespace Eva { return "#Bin"; } - public bool equals(Term o) { + protected bool do_match(Term o, Gee.Map vars) { + if(o is Var) { + return o.do_match(this, vars); + } + if(o is Binary) { Binary b = o as Binary; @@ -490,7 +535,11 @@ namespace Eva { return "<" + node + "." + num.to_string() + "." + serial.to_string() + ">"; } - public bool equals(Term o) { + protected bool do_match(Term o, Gee.Map vars) { + if(o is Var) { + return o.do_match(this, vars); + } + if(!(o is Pid)) return false; @@ -532,7 +581,11 @@ namespace Eva { return "#Port"; } - public bool equals(Term o) { + protected bool do_match(Term o, Gee.Map vars) { + if(o is Var) { + return o.do_match(this, vars); + } + if(!(o is Port)) return false; @@ -579,7 +632,11 @@ namespace Eva { return "#Ref"; } - public bool equals(Term o) { + protected bool do_match(Term o, Gee.Map vars) { + if(o is Var) { + return o.do_match(this, vars); + } + if(!(o is Ref)) return false; @@ -616,4 +673,36 @@ namespace Eva { buffer.encode_ref(reference); } } + + public class Var : Term, Object { + public string name {get; construct;} + + public Var(string name0) { + assert(name0.get_char() == '_' || name0.get_char().isupper()); + + Object(name: name0); + } + + public string to_string() { + return name; + } + + protected bool do_match(Term o, Gee.Map vars) { + if(o is Var) { + return name == (o as Var).name; + } + + if(name in vars) { + return vars[name].do_match(o, vars); + } + else { + vars[name] = o; + return true; + } + } + + public void encode(Erl.Buffer buffer) { + assert_not_reached(); + } + } } -- cgit v1.2.3