def __init__(self): # Define the representation self.Term, self.List, self.Atom, self.BitStr = self.create_representation() self.fmap = Function('fmap', IntSort(), ArraySort(self.List, self.Term)) self.arity = Function('arity', IntSort(), IntSort()) # Define the boolean values. decoder = TermDecoder(self, cenv.Env()) self.atmTrue = decoder.decodeTerm(cc.mk_atom([116,114,117,101])) self.atmFalse = decoder.decodeTerm(cc.mk_atom([102,97,108,115,101]))
def test_encoder(): erl = Erlang() T, L, A, B = erl.Term, erl.List, erl.Atom, erl.BitStr terms = [ ( # 4242424242 T.int(4242424242), cc.mk_int(4242424242) ), ( # 3.14159 T.real(3.14159), cc.mk_float(3.14159) ), ( # foo T.atm(A.acons(102,A.acons(111,A.acons(111,A.anil)))), cc.mk_atom([102,111,111]) ), ( # [42, 3.14] T.lst(L.cons(T.int(42),L.cons(T.real(3.14),L.nil))), cc.mk_list([cc.mk_int(42), cc.mk_float(3.14)]) ), ( # {foo, 42} T.tpl(L.cons(T.atm(A.acons(102,A.acons(111,A.acons(111,A.anil)))),L.cons(T.int(42),L.nil))), cc.mk_tuple([cc.mk_atom([102,111,111]), cc.mk_int(42)]) ), ( # <<5:3>> T.bin(3, B.bcons(BitVecVal(1,1),B.bcons(BitVecVal(0,1),B.bcons(BitVecVal(1,1),B.bnil)))), cc.mk_bitstring([True,False,True]) ), ( # <<5:3>> T.bin(3, B.bcons(BitVecVal(1,1),B.bcons(BitVecVal(0,1),B.bcons(BitVecVal(1,1),B.bcons(BitVecVal(1,1),B.bnil))))), cc.mk_bitstring([True,False,True]) ), ( # <<4:3>> T.bin(3, B.bcons(BitVecVal(1,1),B.bcons(BitVecVal(0,1),B.bnil))), cc.mk_bitstring([True,False,False]) ) ] for x, y in terms: z = erl.encode(x, None) assert z == y, "Encoded {} is not {} but {}".format(x, y, z)
def sample_entries(): es = [dict() for _ in range(4)] # 1st log entry. es[0]["type"] = LogEntry.OP_PARAMS es[0]["args"] = [ cc.mk_symb("0.0.0.44") , cc.mk_symb("0.0.0.45") , cc.mk_symb("0.0.0.46") ] es[0]["is_constraint"] = False es[0]["tag"] = 0 es[0]["message"] = cc.mk_log_entry(es[0]["type"], es[0]["args"]) # 2nd log entry. es[1]["type"] = LogEntry.OP_MATCH_EQUAL_FALSE es[1]["args"] = [ cc.mk_atom([110, 101, 116]) , cc.mk_symb("0.0.0.46") ] es[1]["tag"] = 50 es[1]["is_constraint"] = True es[1]["message"] = cc.mk_log_entry(es[1]["type"], es[1]["args"], es[1]["tag"], es[1]["is_constraint"]) # 3rd log entry. es[2]["type"] = LogEntry.OP_MATCH_EQUAL_TRUE es[2]["tag"] = 105 es[2]["is_constraint"] = True es[2]["args"] = [ cc.mk_atom([101, 114, 108, 97, 110, 103]) , cc.mk_symb("0.0.0.44") ] es[2]["message"] = cc.mk_log_entry(es[2]["type"], es[2]["args"], es[2]["tag"], es[2]["is_constraint"]) # 4th log entry. es[3]["type"] = LogEntry.OP_MATCH_EQUAL_FALSE es[3]["tag"] = 105 es[3]["is_constraint"] = True es[3]["args"] = [ cc.mk_atom([116, 114, 117, 101]) , cc.mk_symb("0.0.0.39316") ] es[3]["message"] = cc.mk_log_entry(es[3]["type"], es[3]["args"], es[3]["tag"], es[3]["is_constraint"]) return es
def test_decoder_simple(): erl = Erlang() env = cenv.Env() T, L, A, B = erl.Term, erl.List, erl.Atom, erl.BitStr # Create the term with shared subterms. tal = cc.mk_alias("0.0.0.42") x = cc.mk_tuple([tal, tal]) xv = x.shared["0.0.0.42"] xv.type = ErlangTerm.LIST xv.subterms.extend([cc.mk_int(1)]) terms = [ ( # 42 cc.mk_int(42), T.int(42) ), ( # 42.42 cc.mk_float(42.42), T.real(42.42) ), ( # ok cc.mk_atom([111,107]), T.atm(A.acons(111,A.acons(107,A.anil))) ), ( # [1,2] cc.mk_list([cc.mk_int(1), cc.mk_int(2)]), T.lst(L.cons(T.int(1),L.cons(T.int(2),L.nil))) ), ( # {1,2} cc.mk_tuple([cc.mk_int(1), cc.mk_int(2)]), T.tpl(L.cons(T.int(1),L.cons(T.int(2),L.nil))) ), ( # {[1],[1]} x, T.tpl (L.cons(T.lst(L.cons(T.int(1),L.nil)),L.cons(T.lst(L.cons(T.int(1),L.nil)),L.nil))) ), ( # <<1:2>> cc.mk_bitstring([False, True]), T.bin(2, B.bcons(BitVecVal(0,1),B.bcons(BitVecVal(1,1),B.bnil))) ) ] decode_and_check(erl, env, terms)
def encode(self, data, funs=[]): # TODO description if data[0] == "int": return cc.mk_int(parse_int(data[1])) elif data[0] == "real": return cc.mk_float(parse_real(data[1])) elif data[0] == "atom": node = data[1] v = [] while node != "in": v.append(parse_int(node[1])) node = node[2] return cc.mk_atom(v) elif data[0] == "list": node = data[1] v = [] while node != "tn": v.append(self.encode(node[1], funs)) node = node[2] return cc.mk_list(v) elif data[0] == "tuple": node = data[1] v = [] while node != "tn": v.append(self.encode(node[1], funs)) node = node[2] return cc.mk_tuple(v) elif data[0] == "str": node = data[1] v = [] while node != "sn": v.append(node[1] == "true") node = node[2] return cc.mk_bitstring(v) elif data[0] == "fun": # TODO function decoding and encoding assert isinstance(data, list) and len(data) == 2 fv = parse_int(data[1]) # if a cycle (a function calling itself recursively) is found, # it is obvious that the solver has selected an arbitrary term as a value if fv in funs: return cc.mk_any() funs = funs[:] funs.append(fv) # get function info from solver # TODO save function arity and entries to an array val = self.solver.get_value(["fa", data[1]], ["fm", data[1]]) assert isinstance(val, list) and len(val) == 2 assert isinstance(val[0], list) and len(val[0]) == 2 arity = parse_int(expand_lets(val[0][1])) # if arity is less than or greater than 255, we assume it is an arbitrary value selected by the solver # because there is no constraint limiting the function's arity; thus, we set it to zero if arity < 0 or arity > 255: arity = 0 assert isinstance(val[1], list) and len(val[1]) == 2 node = expand_lets(val[1][1]) entries = [] otherwise = None while node != "fn": assert isinstance(node, list) and len(node) == 4 and node[0] == "fc" x = cc.get_list_subterms(self.encode(["list", node[1]], funs)) # keep only entries with argument length equal to arity if len(x) == arity: y = self.encode(node[2], funs) if otherwise is None: otherwise = y else: entries.append(cc.mk_fun_entry(x, y)) node = node[3] if otherwise is None: otherwise = cc.mk_any() return cc.mk_fun(arity, entries, otherwise) clg.debug_info("encoding failed: " + str(data)) assert False