def trunc(self, term0, term1): """ Assert that: term0 is term1 truncated. """ t0 = self.decode(term0) t1 = self.decode(term1) conj = [ "and", ["or", ["is-int", t1], ["is-real", t1]], [ "=", t0, [ "ite", ["is-int", t1], t1, [ "int", [ "ite", [">=", ["rv", t1], "0.0"], ["to_int", ["rv", t1]], ["-", ["to_int", ["-", ["rv", t1]]]] ] ] ] ], ] self.commands.append( Log(comment="T0 = trunc(T1).", expr=["assert", conj]))
def erl_lambda(self, *args): """ Assert that a lambda application has succeeded. """ ret = self.decode(args[0]) fun = self.decode(args[1]) tlist = "tn" tlist_length = 0 for arg in reversed(args[2:]): tlist = ["tc", self.decode(arg), tlist] tlist_length += 1 if hasattr(self, "flist_depth"): self.flist_depth += 1 else: self.flist_depth = 0 conj = [ "and", ["is-fun", fun], ["=", ["fa", ["fv", fun]], build_int(tlist_length)], FListEquals(["fm", ["fv", fun]], tlist, ret, build_int(self.flist_depth), self), ] self.commands.append( Log(comment="Function is a closure with specific arity.", expr=["assert", conj]))
def fun_rec_flist(self, par_spec, ret_spec): if par_spec is None: arg_spec = "true" else: arg_spec = ["and"] tlist = ["fx", "f"] for param_spec in par_spec: arg_spec.append([ "and", ["is-tc", tlist], self.build_spec(param_spec, ["th", tlist]) ]) tlist = ["tt", tlist] arg_spec.append(["is-tn", tlist]) ret_spec = self.build_spec(ret_spec, ["fy", "f"]) spec_smt = serialize([arg_spec, ret_spec]) if not hasattr(self, "fun_rec_flists"): self.fun_rec_flists = {} elif spec_smt in self.fun_rec_flists: return self.fun_rec_flists[spec_smt] name = self.fun_rec_name() self.fun_rec_flists[spec_smt] = name args = [["f", "FList"]] body = [ "or", ["is-fn", "f"], ["and", ["is-fc", "f"], arg_spec, ret_spec, [name, ["ft", "f"]]], ] if self.define_funs_rec is not None: self.define_funs_rec.append((name, args, body)) else: self.commands.append( Log( # TODO(aggelos): Add a meaningful comment. expr=["define-fun-rec", name, args, "Bool", body])) return name
def guard_false(self, term): """ Assert the predicate: term == false """ t = self.decode(term) self.commands.append( Log(comment="Term is false.", expr=["assert", ["=", t, false]]))
def tuple_not_tpl(self, term, num): """ Assert that: term is not a tuple. """ t = self.decode(term) conj = ["not", ["is-tuple", t]] self.commands.append( Log(comment="Term is not a tuple.", expr=["assert", conj]))
def list_empty(self, term): """ Assert that: term is an empty list. """ t = self.decode(term) conj = ["and", ["is-list", t], ["is-tn", ["lv", t]]] self.commands.append( Log(comment="Term is an empty list.", expr=["assert", conj]))
def __init__(self, timeout): self.library = [] self.commands: List[Log] = [] self.commands.append( Log(expr=["set-option", ":produce-models", "true"])) self.commands.append( Log(comment="Erlang types.", expr=["declare-datatypes", [], datatypes])) self.commands.append( Log(comment="Function that maps funs to their arity.", expr=["declare-fun", "fa", ["Int"], "Int"])) self.commands.append( Log(comment="Function that maps funs to their definition.", expr=["declare-fun", "fm", ["Int"], "FList"])) self.setSolver = lambda: SolverZ3(timeout) self.solver = self.setSolver() self.define_funs_rec = []
def erl_lambda_reversed(self, *args): # TODO not exactly reversed """ Assert that a lambda application has failed. """ t_fun = self.decode(args[1]) self.commands.append( Log(comment="The lambda application should fail.", expr=["assert", ["not", ["is-fun", t_fun]]]))
def list_not_lst(self, term): """ Assert that: term is not list. """ t = self.decode(term) conj = ["not", ["is-list", t]] self.commands.append( Log(comment="Term is not a list.", expr=["assert", conj]))
def bogus(self, term0, term1): """ Assert that: term0 == term1 (Identity function). """ t0 = self.decode(term0) t1 = self.decode(term1) conj = ["=", t0, t1] self.commands.append( Log(comment="T0 = T1 (id).", expr=["assert", conj]))
def fix_parameter(self, p, v): """ Fix a symbolic variable to a specific value. """ p = self.decode(p) v = self.decode(v) self.solver.write( Log(comment="Fix parameter to a specific value", expr=["assert", ["=", p, v]]))
def is_number(self, term0, term1): """ Assert that: term0 == is_number(term1). """ t0 = self.decode(term0) t1 = self.decode(term1) conj = ["=", t0, BoolToAtom(["or", ["is-int", t1], ["is-real", t1]])] self.commands.append( Log(comment="T0 = is_number(T1).", expr=["assert", conj]))
def is_fun(self, term0, term1): """ Assert that: term0 == is_function(term1). """ t0 = self.decode(term0) t1 = self.decode(term1) conj = ["=", t0, BoolToAtom(["is-fun", t1])] self.commands.append( Log(comment="T0 = is_function(T1).", expr=["assert", conj]))
def is_float(self, term0, term1): """ Assert that: term1 == is_float(term2). """ t0 = self.decode(term0) t1 = self.decode(term1) conj = ["=", t0, BoolToAtom(["is-real", t1])] self.commands.append( Log(comment="T0 = is_float(T1).", expr=["assert", conj]))
def is_boolean(self, term0, term1): """ Assert that: term0 == is_boolean(term1). """ t0 = self.decode(term0) t1 = self.decode(term1) conj = ["=", t0, BoolToAtom(IsBool(t1))] self.commands.append( Log(comment="T0 = is_boolean(T1).", expr=["assert", conj]))
def match_not_equal(self, term1, term2): """ Assert the predicate: term1 != term2 """ t1 = self.decode(term1) t2 = self.decode(term2) self.commands.append( Log(comment="Two terms are not equal.", expr=["assert", ["not", ["=", t1, t2]]]))
def list_nonempty_reversed(self, term): """ Assert that: Not(term is a nonempty list). """ t = self.decode(term) conj = ["not", ["and", ["is-list", t], ["is-tc", ["lv", t]]]] self.commands.append( Log(comment="Term is not a non-empty list.", expr=["assert", conj]))
def atom_nil(self, term0, term1): """ Assert that: term0 = (term1 == ''). """ t0 = self.decode(term0) t1 = self.decode(term1) conj = ["=", t0, BoolToAtom(["=", t1, ["atom", "in"]])] self.commands.append( Log(comment="T0 = (T1 == '').", expr=["assert", conj]))
def equal(self, term0, term1, term2): """ Assert that: term0 = (term1 == term2). """ t0 = self.decode(term0) t1 = self.decode(term1) t2 = self.decode(term2) conj = ["=", t0, BoolToAtom(["=", t1, t2])] self.commands.append( Log(comment="T0 = (T1 == T2).", expr=["assert", conj]))
def times(self, term0, term1, term2): """ Assert that: term0 = term1 * term2. """ t0 = self.decode(term0) t1 = self.decode(term1) t2 = self.decode(term2) conj = NumBinOp("*", t0, t1, t2) self.commands.append( Log(comment="T0 = T1 * T2.", expr=["assert", conj]))
def bor(self, term0, term1, term2): """ Assert that: term0 = term1 | term2. """ t0 = self.decode(term0) t1 = self.decode(term1) t2 = self.decode(term2) conj = IntOr(["iv", t0], ["iv", t1], ["iv", t2], self) self.commands.append( Log(comment="T0 = T1 | T2.", expr=["assert", conj]))
def empty_bitstr(self, term): """ Assert that: term is an empty bitstring. """ t = self.decode(term) conj = [ "and", ["is-str", t], ["is-sn", ["sv", t]], ] self.commands.append( Log(comment="Term is an empty bistring.", expr=["assert", conj]))
def tcons(self, *terms): """ Assert that: a term is tuple of many terms. """ t0 = self.decode(terms[0]) tlist = "tn" for term in reversed(terms[1:]): t = self.decode(term) tlist = ["tc", t, tlist] conj = ["=", t0, ["tuple", tlist]] self.commands.append( Log(comment="T0 is a tuple of many terms.", expr=["assert", conj]))
def assert_typedef_funs(self): if len(self.define_funs_rec) > 0: [names, args, bodies] = zip(*self.define_funs_rec) n = len(names) self.commands.append( Log(comment="Type definition.", expr=[ "define-funs-rec", list(map(list, zip(names, args, ["Bool"] * n))), list(bodies) ])) self.define_funs_rec = None
def tuple_to_list(self, term0, term1): """ Assert that: term0 = tuple_to_list(term1). """ t0 = self.decode(term0) t1 = self.decode(term1) conj = [ "and", ["is-tuple", t1], ["=", t0, ["list", ["tv", t1]]], ] self.commands.append( Log(comment="T0 = tuple_to_list(T1),", expr=["assert", conj]))
def empty_bitstr_reversed(self, term): # TODO not exactly reversed """ Assert that: Not (term is an empty bitstring). """ t = self.decode(term) conj = [ "and", ["is-str", t], ["is-sc", ["sv", t]], ] self.commands.append( Log(comment="Term is not an empty bistring.", expr=["assert", conj]))
def tail(self, term0, term1): """ Assert that: term0 == tl(term1). """ t0 = self.decode(term0) t1 = self.decode(term1) conj = [ "and", ["is-list", t1], ["is-tc", ["lv", t1]], ["=", t0, ["list", ["tt", ["lv", t1]]]], ] self.commands.append(Log(comment="T0 = tl(T1).", expr=["assert", conj]))
def cons(self, term0, term1, term2): """ Assert that: term0 = [term1 | term2]. """ t0 = self.decode(term0) t1 = self.decode(term1) t2 = self.decode(term2) conj = [ "and", ["is-list", t2], ["=", t0, ["list", ["tc", t1, ["lv", t2]]]], ] self.commands.append( Log(comment="T0 = [T1 | T2].", expr=["assert", conj]))
def lt_floats(self, term0, term1, term2): """ Assert that: term0 = (term1 < term2). """ t0 = self.decode(term0) t1 = self.decode(term1) t2 = self.decode(term2) conj = [ "and", ["is-real", t1], ["is-real", t2], ["=", t0, BoolToAtom(["<", ["rv", t1], ["rv", t2]])], ] self.commands.append( Log(comment="T0 = (T1 < T2).", expr=["assert", conj]))
def fresh_closure(self, tFun, tArity): """ Assert that tFun is a closure with arity tArity. """ f = self.decode(tFun) a = self.decode(tArity) conj = [ "and", ["is-fun", f], ["is-int", a], ["=", ["fa", ["fv", f]], ["iv", a]], ] self.commands.append( Log(comment="Function is a closure with specific arity.", expr=["assert", conj]))