namespace Eva { public interface List : Term { private static Empty _empty; public static List empty { get { if(_empty == null) _empty = new Empty(); return _empty; } } public abstract bool is_empty { get; } public static List from_list(Gee.List list) { if(list.is_empty) return empty; else return new Cons(list.first(), List.from_list(list[1:list.size])); } private class Empty : Object, Term, List { internal Empty() {} public bool is_empty { get { return true; } } public string to_string() { return "[]"; } protected bool do_match(Term o, Gee.Map vars, Gee.Map aliases) { if(o is Var) { return o.do_match(this, vars, aliases); } else { return (o == this); } } internal void encode(Buffer buffer) { buffer.buffer.encode_empty_list(); } } } public class Cons : Object, Term, List { public Term head { get; construct;} public Term tail { get; construct;} public bool is_empty { get { return false; } } public Cons(Term head0, Term tail0 = empty) { Object(head: head0, tail: tail0); } protected bool do_match(Term o, Gee.Map vars, Gee.Map aliases) { if(o is Var) { return o.do_match(this, vars, aliases); } if(o is Cons) { Cons c = o as Cons; return (head.do_match(c.head, vars, aliases) && tail.do_match(c.tail, vars, aliases)); } else if(o is String) { return do_match(string_to_list((o as String).value), vars, aliases); } else { return false; } } public string to_string() { string ret = "[" + head.to_string(); unowned Term rest; for(rest = tail; rest is Cons; rest = (rest as Cons).tail) { ret += "," + (rest as Cons).head.to_string(); } if(rest != List.empty) { ret += "|" + rest.to_string(); } return ret + "]"; } internal void encode(Buffer buffer) { buffer.buffer.encode_list_header(1); head.encode(buffer); tail.encode(buffer); } } }