def test_bag_elimination(self): spec = """ MyDataStructure: state elements : Bag<Int> query containsZero() exists [x | x <- elements, x == 0] op addElement(x : Int) elements.add(x); """ spec = parse_spec(spec) errs = typecheck(spec) assert not errs, str(errs) spec = desugar(spec) impl = construct_initial_implementation(spec) impl = improve_implementation(impl, timeout=datetime.timedelta(seconds=30)) print(pprint(impl.code)) assert len(impl.concretization_functions) == 1 (v, e), = list(impl.concretization_functions.items()) print("{} = {}".format(v, pprint(e))) assert e.type == BOOL
def debug_comparison(e1, c1, e2, c2, assumptions : Exp = T): print("-" * 20) print("comparing costs...") print(" e1 = {}".format(pprint(e1))) print(" c1 = {}".format(c1)) print(" e2 = {}".format(pprint(e2))) print(" c2 = {}".format(c2)) print(" c1 compare_to c2 = {}".format(c1.compare_to(c2, assumptions=assumptions))) print(" c2 compare_to c1 = {}".format(c2.compare_to(c1, assumptions=assumptions))) for c1, c2 in zip(c1.costs, c2.costs): if not isinstance(c1, SymbolicCost): continue print("-" * 10) print("comparing {} and {}".format(c1, c2)) print(" c1 compare_to c2 = {}".format(c1.compare_to(c2, assumptions=assumptions))) print(" c2 compare_to c1 = {}".format(c2.compare_to(c1, assumptions=assumptions))) print("variable meanings...") for e, v in itertools.chain(c1.cardinalities.items(), c2.cardinalities.items()): print(" {v} = len {e}".format(v=pprint(v), e=pprint(e))) print("joint orderings...") cards = c1.order_cardinalities(c2, assumptions=assumptions) print(" {}".format(pprint(cards))) for op in ("<=", "<", ">", ">="): print("c1 always {} c2?".format(op)) x = [] res = c1.always(op, c2, cards=cards, model_callback=lambda m: x.append(m)) if res: print(" YES") elif not x: print(" NO (no model!?)") else: print(" NO: {}".format(x[0])) print(" c1 = {}".format(eval(c1.formula, env=x[0]))) print(" c2 = {}".format(eval(c2.formula, env=x[0])))
def visit_SCall(self, call): target = self.visit(call.target) args = [self.visit(a) for a in call.args] self.begin_statement() if type(call.target.type) in (TBag, TList): if call.func == "add": self.write(target, ".push_back(", args[0], ");") elif call.func == "remove": v = self.fv(TNative("auto"), "it") self.write("auto ", v.id, "(::std::find(", target, ".begin(), ", target, ".end(), ", args[0], "));") self.end_statement() self.begin_statement() self.write("if (", v.id, " != ", target, ".end()) { ", target, ".erase(", v.id, "); }") else: raise NotImplementedError(call.func) elif isinstance(call.target.type, TSet): if call.func == "add": self.write(target, ".insert(", args[0], ");") elif call.func == "remove": self.write(target, ".erase(", target, ".find(", args[0], "));") else: raise NotImplementedError(call.func) else: raise NotImplementedError("unknown target type {} in {}".format( pprint(call.target.type), pprint(call))) self.end_statement()
def visit_EBinOp(self, e): self.visit(e.e1) self.visit(e.e2) if e.op in ["==", "===", "!=", "<", "<=", ">", ">="]: if not all(is_numeric(t) for t in [e.e1.type, e.e2.type]): self.ensure_type(e.e2, e.e1.type) e.type = BOOL elif e.op in [syntax.BOp.And, syntax.BOp.Or, "=>"]: self.ensure_type(e.e1, BOOL) self.ensure_type(e.e2, BOOL) e.type = BOOL elif e.op == syntax.BOp.In: t = self.get_collection_type(e.e2) self.ensure_type(e.e1, t) e.type = BOOL elif e.op in ["+", "-"]: if is_numeric(e.e1.type): self.ensure_numeric(e.e2) e.type = self.numeric_lub(e, e.e1.type, e.e2.type) else: t1 = self.get_collection_type(e.e1) t2 = self.get_collection_type(e.e2) if t1 != t2: self.report_err( e, "cannot concat {} and {}".format( pprint(e.e1.type), pprint(e.e2.type))) e.type = to_abstract(e.e1.type) else: raise NotImplementedError(e.op)
def visit_EBinOp(self, e): self.visit(e.e1) self.visit(e.e2) if e.op in ["==", "===", "!=", "<", "<=", ">", ">="]: self.lub(e, e.e1.type, e.e2.type, "due to comparison") e.type = BOOL elif e.op in [syntax.BOp.And, syntax.BOp.Or, "=>"]: self.ensure_type(e.e1, BOOL) self.ensure_type(e.e2, BOOL) e.type = BOOL elif e.op == syntax.BOp.In: t = self.get_collection_type(e.e2) self.ensure_type(e.e1, t) e.type = BOOL elif e.op in ["+", "-"]: if is_numeric(e.e1.type): self.ensure_numeric(e.e2) e.type = self.numeric_lub(e, e.e1.type, e.e2.type) else: t1 = self.get_collection_type(e.e1) t2 = self.get_collection_type(e.e2) if t1 != t2: self.report_err(e, "cannot concat {} and {}".format(pprint(e.e1.type), pprint(e.e2.type))) e.type = to_abstract(e.e1.type) elif e.op in ["*"]: if is_numeric(e.e1.type): e.type = self.numeric_lub(e, e.e1.type, e.e2.type) if not isinstance(e.e1, syntax.ENum) and not isinstance(e.e2, syntax.ENum): self.report_err(e, "multiplication is only legal when one operand is a constant") else: e.type = DEFAULT_TYPE self.report_err(e, "cannot multiply {} and {}".format(pprint(e.e1.type), pprint(e.e2.type))) else: raise NotImplementedError(e.op)
def debug_comparison(cm: CostModel, e1: Exp, e2: Exp, context: Context): """Print information about the cost relationship of two expressions. This procedure gives a lot of insight into the relationship between e1 and e2 under the given cost model. """ print("-" * 20) print("Comparing") print(" e1 = {}".format(pprint(e1))) print(" e2 = {}".format(pprint(e2))) print("-" * 20 + " {} examples...".format(len(cm.examples))) for f in asymptotic_runtime, max_storage_size, rt: for ename, e in [("e1", e1), ("e2", e2)]: print("{f}({e}) = {res}".format(f=f.__name__, e=ename, res=pprint(f(e)))) for x in cm.examples: print("-" * 20) print(x) print("asympto(e1) = {}".format(asymptotic_runtime(e1))) print("asympto(e2) = {}".format(asymptotic_runtime(e2))) print("storage(e1) = {}".format( eval_bulk(max_storage_size(e1), [x], use_default_values_for_undefined_vars=True)[0])) print("storage(e2) = {}".format( eval_bulk(max_storage_size(e2), [x], use_default_values_for_undefined_vars=True)[0])) print("runtime(e1) = {}".format( eval_bulk(rt(e1), [x], use_default_values_for_undefined_vars=True)[0])) print("runtime(e2) = {}".format( eval_bulk(rt(e2), [x], use_default_values_for_undefined_vars=True)[0])) print("-" * 20)
def _consider(e, context, pool): if _interesting(e, context, pool) and not verbose.value: print("considering {} in {}".format(pprint(e), context)) task_begin("considering expression", expression=pprint(e), context=context, pool=pool_name(pool), interesting=_interesting(e, context, pool))
def _evict(e, size, context, pool, better_exp, better_exp_size): """Called when an Enumerator evicts a cached expression in favor of a better one.""" if _interesting(e, size, context, pool) and not verbose.value: print("evicting {}".format(pprint(e))) elif _interesting(better_exp, better_exp_size, context, pool) and not verbose.value: print("{} caused eviction of {}".format(pprint(better_exp), pprint(e))) event("evicting {}".format(pprint(e)))
def dbg(model): print("model: {!r}".format(model)) r1 = eval(e1, model) r2 = eval(e2, model) print("e1: {}".format(pprint(e1))) print(" ---> {!r}".format(r1)) print("e2: {}".format(pprint(e2))) print(" ---> {!r}".format(r2))
def check_assignment(self, node, ltype, rtype): if ltype == rtype or ltype is DEFAULT_TYPE or rtype is DEFAULT_TYPE: return if is_collection(ltype) and is_collection(rtype): return self.report_err( node, "cannot assign {} to a {}".format(pprint(rtype), pprint(ltype)))
def numeric_lub(self, src, t1, t2): if t1 == LONG or t2 == LONG: return LONG if t1 == INT and t2 == INT: return INT if t1 == FLOAT and t2 == FLOAT: return FLOAT self.report_err(src, "cannot unify types {} and {}".format(pprint(t1), pprint(t2))) return DEFAULT_TYPE
def check_assignment(self, node, ltype, rtype): if ltype == rtype or ltype is DEFAULT_TYPE or rtype is DEFAULT_TYPE: return for ct in (syntax.TBag, syntax.TSet, syntax.TList): if isinstance(ltype, ct) and isinstance(rtype, ct): return self.report_err( node, "cannot assign {} to a {}".format(pprint(rtype), pprint(ltype)))
def test_complicated_adapt(self): e = EVar('p').with_type(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString())))) e_ctx = UnderBinder(parent=RootCtx(state_vars=OrderedSet([EVar('lineitem').with_type(TBag(TRecord((('orderkey', TInt()), ('partkey', TInt()), ('suppkey', TInt()), ('linenumber', TInt()), ('quantity', TFloat()), ('extendedprice', TFloat()), ('discount', TFloat()), ('tax', TFloat()), ('returnflag', TNative('char')), ('linestatus', TNative('char')), ('shipdate', TNative('uint64_t')), ('commitdate', TNative('uint64_t')), ('receiptdate', TNative('uint64_t')), ('shipinstruct', TString()), ('shipmode', TString()), ('comment', TString()))))), EVar('orders').with_type(TBag(TRecord((('orderkey', TInt()), ('custkey', TInt()), ('orderstatus', TNative('char')), ('totalprice', TFloat()), ('orderdate', TNative('uint64_t')), ('orderpriority', TString()), ('clerk', TString()), ('shippriority', TInt()), ('comment', TString()))))), EVar('part').with_type(TBag(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString()))))), EVar('customer').with_type(TBag(TRecord((('custkey', TInt()), ('name', TString()), ('address', TString()), ('nationkey', TInt()), ('phone', TString()), ('acctbal', TFloat()), ('mktsegment', TString()), ('comment', TString()))))), EVar('supplier').with_type(TBag(TRecord((('suppkey', TInt()), ('name', TString()), ('address', TString()), ('nationkey', TInt()), ('phone', TString()), ('acctbal', TFloat()), ('comment', TString()))))), EVar('partsupp').with_type(TBag(TRecord((('partkey', TInt()), ('suppkey', TInt()), ('availqty', TInt()), ('supplycost', TFloat()), ('comment', TString()))))), EVar('nation').with_type(TBag(TRecord((('nationkey', TInt()), ('name', TString()), ('regionkey', TInt()), ('comment', TString()))))), EVar('region').with_type(TBag(TRecord((('regionkey', TInt()), ('name', TString()), ('comment', TString())))))]), args=OrderedSet([EVar('orderkey').with_type(TInt()), EVar('partkey').with_type(TInt()), EVar('suppkey').with_type(TInt()), EVar('linenumber').with_type(TInt()), EVar('quantity').with_type(TFloat()), EVar('extendedprice').with_type(TFloat()), EVar('discount').with_type(TFloat()), EVar('tax').with_type(TFloat()), EVar('returnflag').with_type(TNative('char')), EVar('linestatus').with_type(TNative('char')), EVar('shipdate').with_type(TNative('uint64_t')), EVar('commitdate').with_type(TNative('uint64_t')), EVar('receiptdate').with_type(TNative('uint64_t')), EVar('shipinstruct').with_type(TString()), EVar('shipmode').with_type(TString()), EVar('comment').with_type(TString())]), funcs=OrderedDict([('div', TFunc((TFloat(), TFloat()), TFloat())), ('int2float', TFunc((TInt(),), TFloat())), ('brand23', TFunc((), TString())), ('medbox', TFunc((), TString()))])), v=EVar('p').with_type(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString())))), bag=EStateVar(EFilter(EFilter(EVar('part').with_type(TBag(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString()))))), ELambda(EVar('p').with_type(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString())))), EBinOp(EGetField(EVar('p').with_type(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString())))), 'brand').with_type(TString()), '==', ECall('brand23', ()).with_type(TString())).with_type(TBool()))).with_type(TBag(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString()))))), ELambda(EVar('p').with_type(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString())))), EBinOp(EGetField(EVar('p').with_type(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString())))), 'container').with_type(TString()), '==', ECall('medbox', ()).with_type(TString())).with_type(TBool()))).with_type(TBag(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString())))))).with_type(TBag(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString()))))), bag_pool=RUNTIME_POOL) dest_ctx = UnderBinder(parent=UnderBinder(parent=RootCtx(state_vars=OrderedSet([EVar('lineitem').with_type(TBag(TRecord((('orderkey', TInt()), ('partkey', TInt()), ('suppkey', TInt()), ('linenumber', TInt()), ('quantity', TFloat()), ('extendedprice', TFloat()), ('discount', TFloat()), ('tax', TFloat()), ('returnflag', TNative('char')), ('linestatus', TNative('char')), ('shipdate', TNative('uint64_t')), ('commitdate', TNative('uint64_t')), ('receiptdate', TNative('uint64_t')), ('shipinstruct', TString()), ('shipmode', TString()), ('comment', TString()))))), EVar('orders').with_type(TBag(TRecord((('orderkey', TInt()), ('custkey', TInt()), ('orderstatus', TNative('char')), ('totalprice', TFloat()), ('orderdate', TNative('uint64_t')), ('orderpriority', TString()), ('clerk', TString()), ('shippriority', TInt()), ('comment', TString()))))), EVar('part').with_type(TBag(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString()))))), EVar('customer').with_type(TBag(TRecord((('custkey', TInt()), ('name', TString()), ('address', TString()), ('nationkey', TInt()), ('phone', TString()), ('acctbal', TFloat()), ('mktsegment', TString()), ('comment', TString()))))), EVar('supplier').with_type(TBag(TRecord((('suppkey', TInt()), ('name', TString()), ('address', TString()), ('nationkey', TInt()), ('phone', TString()), ('acctbal', TFloat()), ('comment', TString()))))), EVar('partsupp').with_type(TBag(TRecord((('partkey', TInt()), ('suppkey', TInt()), ('availqty', TInt()), ('supplycost', TFloat()), ('comment', TString()))))), EVar('nation').with_type(TBag(TRecord((('nationkey', TInt()), ('name', TString()), ('regionkey', TInt()), ('comment', TString()))))), EVar('region').with_type(TBag(TRecord((('regionkey', TInt()), ('name', TString()), ('comment', TString())))))]), args=OrderedSet([EVar('orderkey').with_type(TInt()), EVar('partkey').with_type(TInt()), EVar('suppkey').with_type(TInt()), EVar('linenumber').with_type(TInt()), EVar('quantity').with_type(TFloat()), EVar('extendedprice').with_type(TFloat()), EVar('discount').with_type(TFloat()), EVar('tax').with_type(TFloat()), EVar('returnflag').with_type(TNative('char')), EVar('linestatus').with_type(TNative('char')), EVar('shipdate').with_type(TNative('uint64_t')), EVar('commitdate').with_type(TNative('uint64_t')), EVar('receiptdate').with_type(TNative('uint64_t')), EVar('shipinstruct').with_type(TString()), EVar('shipmode').with_type(TString()), EVar('comment').with_type(TString())]), funcs=OrderedDict([('div', TFunc((TFloat(), TFloat()), TFloat())), ('int2float', TFunc((TInt(),), TFloat())), ('brand23', TFunc((), TString())), ('medbox', TFunc((), TString()))])), v=EVar('l').with_type(TRecord((('orderkey', TInt()), ('partkey', TInt()), ('suppkey', TInt()), ('linenumber', TInt()), ('quantity', TFloat()), ('extendedprice', TFloat()), ('discount', TFloat()), ('tax', TFloat()), ('returnflag', TNative('char')), ('linestatus', TNative('char')), ('shipdate', TNative('uint64_t')), ('commitdate', TNative('uint64_t')), ('receiptdate', TNative('uint64_t')), ('shipinstruct', TString()), ('shipmode', TString()), ('comment', TString())))), bag=EBinOp(EStateVar(EVar('lineitem').with_type(TBag(TRecord((('orderkey', TInt()), ('partkey', TInt()), ('suppkey', TInt()), ('linenumber', TInt()), ('quantity', TFloat()), ('extendedprice', TFloat()), ('discount', TFloat()), ('tax', TFloat()), ('returnflag', TNative('char')), ('linestatus', TNative('char')), ('shipdate', TNative('uint64_t')), ('commitdate', TNative('uint64_t')), ('receiptdate', TNative('uint64_t')), ('shipinstruct', TString()), ('shipmode', TString()), ('comment', TString())))))).with_type(TBag(TRecord((('orderkey', TInt()), ('partkey', TInt()), ('suppkey', TInt()), ('linenumber', TInt()), ('quantity', TFloat()), ('extendedprice', TFloat()), ('discount', TFloat()), ('tax', TFloat()), ('returnflag', TNative('char')), ('linestatus', TNative('char')), ('shipdate', TNative('uint64_t')), ('commitdate', TNative('uint64_t')), ('receiptdate', TNative('uint64_t')), ('shipinstruct', TString()), ('shipmode', TString()), ('comment', TString()))))), '+', ESingleton(EMakeRecord((('orderkey', EVar('orderkey').with_type(TInt())), ('partkey', EVar('partkey').with_type(TInt())), ('suppkey', EVar('suppkey').with_type(TInt())), ('linenumber', EVar('linenumber').with_type(TInt())), ('quantity', EVar('quantity').with_type(TFloat())), ('extendedprice', EVar('extendedprice').with_type(TFloat())), ('discount', EVar('discount').with_type(TFloat())), ('tax', EVar('tax').with_type(TFloat())), ('returnflag', EVar('returnflag').with_type(TNative('char'))), ('linestatus', EVar('linestatus').with_type(TNative('char'))), ('shipdate', EVar('shipdate').with_type(TNative('uint64_t'))), ('commitdate', EVar('commitdate').with_type(TNative('uint64_t'))), ('receiptdate', EVar('receiptdate').with_type(TNative('uint64_t'))), ('shipinstruct', EVar('shipinstruct').with_type(TString())), ('shipmode', EVar('shipmode').with_type(TString())), ('comment', EVar('comment').with_type(TString())))).with_type(TRecord((('orderkey', TInt()), ('partkey', TInt()), ('suppkey', TInt()), ('linenumber', TInt()), ('quantity', TFloat()), ('extendedprice', TFloat()), ('discount', TFloat()), ('tax', TFloat()), ('returnflag', TNative('char')), ('linestatus', TNative('char')), ('shipdate', TNative('uint64_t')), ('commitdate', TNative('uint64_t')), ('receiptdate', TNative('uint64_t')), ('shipinstruct', TString()), ('shipmode', TString()), ('comment', TString()))))).with_type(TBag(TRecord((('orderkey', TInt()), ('partkey', TInt()), ('suppkey', TInt()), ('linenumber', TInt()), ('quantity', TFloat()), ('extendedprice', TFloat()), ('discount', TFloat()), ('tax', TFloat()), ('returnflag', TNative('char')), ('linestatus', TNative('char')), ('shipdate', TNative('uint64_t')), ('commitdate', TNative('uint64_t')), ('receiptdate', TNative('uint64_t')), ('shipinstruct', TString()), ('shipmode', TString()), ('comment', TString())))))).with_type(TBag(TRecord((('orderkey', TInt()), ('partkey', TInt()), ('suppkey', TInt()), ('linenumber', TInt()), ('quantity', TFloat()), ('extendedprice', TFloat()), ('discount', TFloat()), ('tax', TFloat()), ('returnflag', TNative('char')), ('linestatus', TNative('char')), ('shipdate', TNative('uint64_t')), ('commitdate', TNative('uint64_t')), ('receiptdate', TNative('uint64_t')), ('shipinstruct', TString()), ('shipmode', TString()), ('comment', TString()))))), bag_pool=RUNTIME_POOL), v=EVar('p').with_type(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString())))), bag=EStateVar(EFilter(EFilter(EVar('part').with_type(TBag(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString()))))), ELambda(EVar('p').with_type(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString())))), EBinOp(EGetField(EVar('p').with_type(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString())))), 'brand').with_type(TString()), '==', ECall('brand23', ()).with_type(TString())).with_type(TBool()))).with_type(TBag(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString()))))), ELambda(EVar('p').with_type(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString())))), EBinOp(EGetField(EVar('p').with_type(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString())))), 'container').with_type(TString()), '==', ECall('medbox', ()).with_type(TString())).with_type(TBool()))).with_type(TBag(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString())))))).with_type(TBag(TRecord((('partkey', TInt()), ('name', TString()), ('mfgr', TString()), ('brand', TString()), ('part_type', TString()), ('size', TInt()), ('container', TString()), ('retailprice', TFloat()), ('comment', TString()))))), bag_pool=RUNTIME_POOL) print("adapting {}".format(pprint(e))) print("in {}".format(e_ctx)) print("to {}".format(dest_ctx)) e_prime = dest_ctx.adapt(e, e_ctx) print(" ---> {}".format(pprint(e_prime)))
def test_mutate_preserves_statevar(self): x = EVar("x").with_type(INT) e = EBinOp(EStateVar(x), "+", ONE) assert retypecheck(e) s = SAssign(x, EBinOp(x, "+", ONE).with_type(INT)) e2 = inc.mutate(e, s) e2 = inc.repair_EStateVar(e2, [x]) print(pprint(e)) print(pprint(e2)) assert e2 == EBinOp(EBinOp(EStateVar(x), "+", ONE), "+", ONE)
def test_mutate_preserves_statevar(self): x = EVar("x").with_type(INT) e = EBinOp(EStateVar(x), "+", ONE) assert retypecheck(e) s = SAssign(x, EBinOp(x, "+", ONE).with_type(INT)) e2 = strip_EStateVar(inc.mutate(e, s)) e2 = repair_well_formedness(e2, context=RootCtx(state_vars=[x], args=[])) print(pprint(e)) print(pprint(e2)) assert e2 == EBinOp(EBinOp(EStateVar(x), "+", ONE), "+", ONE)
def test_regression02(self): impl = Spec('EagerMapper', [], [ExternFunc('log', [('f', TFloat())], TFloat(), 'std::log({f})')], [('_var1492', TInt()), ('_var4588', TList(TFloat())), ('_var6562', TList(TFloat()))], (), (Query('take', Visibility.Public, [], (), EVar('_var6562').with_type(TList(TFloat())), ''), Op('rm', [('index', TInt())], [], SAssign(EVar('_var6562').with_type(TList(TFloat())), EBinOp(EListSlice(EVar('_var4588').with_type(TList(TFloat())), ENum(0).with_type(TInt()), EVar('index').with_type(TInt())).with_type(TList(TFloat())), '+', EListSlice(EVar('_var4588').with_type(TList(TFloat())), EBinOp(EVar('index').with_type(TInt()), '+', ENum(1).with_type(TInt())).with_type(TInt()), EVar('_var1492').with_type(TInt())).with_type(TList(TFloat()))).with_type(TList(TFloat()))), ''), Op('restore', [], [], SAssign(EVar('_var6562').with_type(TList(TFloat())), EVar('_var4588').with_type(TList(TFloat()))), '')), '\n#include <cmath>\n', '', '') state_map = OrderedDict([('_var1492', EUnaryOp('len', EVar('xs').with_type(TList(TFloat()))).with_type(TInt())), ('_var4588', EMap(EVar('xs').with_type(TList(TFloat())), ELambda(EVar('x').with_type(TFloat()), EBinOp(ECall('log', (EBinOp(ENum(1.0).with_type(TFloat()), '+', EVar('x').with_type(TFloat())).with_type(TFloat()),)).with_type(TFloat()), '+', ECall('log', (ENum(1.5).with_type(TFloat()),)).with_type(TFloat())).with_type(TFloat()))).with_type(TList(TFloat()))), ('_var6562', ECond(EVar('isDropped').with_type(TBool()), EMap(EBinOp(EListSlice(EVar('xs').with_type(TList(TFloat())), ENum(0).with_type(TInt()), EVar('dropped').with_type(TInt())).with_type(TList(TFloat())), '+', EListSlice(EVar('xs').with_type(TList(TFloat())), EBinOp(EVar('dropped').with_type(TInt()), '+', ENum(1).with_type(TInt())).with_type(TInt()), EUnaryOp('len', EVar('xs').with_type(TList(TFloat()))).with_type(TInt())).with_type(TList(TFloat()))).with_type(TList(TFloat())), ELambda(EVar('x').with_type(TFloat()), EBinOp(ECall('log', (EBinOp(ENum(1.0).with_type(TFloat()), '+', EVar('x').with_type(TFloat())).with_type(TFloat()),)).with_type(TFloat()), '+', ECall('log', (ENum(1.5).with_type(TFloat()),)).with_type(TFloat())).with_type(TFloat()))).with_type(TList(TFloat())), EMap(EVar('xs').with_type(TList(TFloat())), ELambda(EVar('x').with_type(TFloat()), EBinOp(ECall('log', (EBinOp(ENum(1.0).with_type(TFloat()), '+', EVar('x').with_type(TFloat())).with_type(TFloat()),)).with_type(TFloat()), '+', ECall('log', (ENum(1.5).with_type(TFloat()),)).with_type(TFloat())).with_type(TFloat()))).with_type(TList(TFloat()))).with_type(TList(TFloat())))]) share_info = defaultdict(list, {}) impl = inline_calls(impl) impl, state_map = rewrite_extensions(impl, state_map) for v, e in state_map.items(): print(" - {} = {}".format(v, pprint(e))) print(pprint(impl)) for codegen in CODE_GENERATORS: self.check(impl, state_map, share_info, lambda out: codegen(out=out), target_languages=[CxxPrinter])
def test_regression04(self): impl = Spec('Basic', [], [], [('_var12', TList(TInt())), ('_var895', TMap(TInt(), TList(TInt()))), ('_var9841', TMap(TInt(), TList(TInt()))), ('_var10947', TMap(TInt(), TBool()))], [], [Query('elems', 'public', [], (), EVar('_var12').with_type(TList(TInt())), ""), Query('_name13', 'internal', [('n', TInt())], (), ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt())), ""), Query('_name14', 'internal', [('n', TInt())], (), EEmptyList().with_type(TBag(TInt())), ""), Query('_name35', 'internal', [('n', TInt())], (), EMapGet(EVar('_var895').with_type(TMap(TInt(), TList(TInt()))), EVar('n').with_type(TInt())).with_type(TList(TInt())), ""), Query('_name911', 'internal', [('_var905', TInt()), ('n', TInt())], (), ESingleton(EVar('_var905').with_type(TInt())).with_type(TBag(TInt())), ""), Query('_name912', 'internal', [('_var905', TInt()), ('n', TInt())], (), EEmptyList().with_type(TBag(TInt())), ""), Query('_name914', 'internal', [('n', TInt())], (), EFilter(ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt())), ELambda(EVar('_var1498').with_type(TInt()), EUnaryOp('not', EMapGet(EVar('_var10947').with_type(TMap(TInt(), TBool())), EVar('_var1498').with_type(TInt())).with_type(TBool())).with_type(TBool()))).with_type(TBag(TInt())), ""), Query('_name1497', 'internal', [('_var1492', TInt()), ('n', TInt())], (), EEmptyList().with_type(TBag(TInt())), ""), Query('_name1506', 'internal', [('_var1492', TInt()), ('n', TInt())], (), ESingleton(EVar('_var1492').with_type(TInt())).with_type(TBag(TInt())), ""), Query('_name1519', 'internal', [('n', TInt())], (), EMapGet(EVar('_var9841').with_type(TMap(TInt(), TList(TInt()))), EVar('n').with_type(TInt())).with_type(TList(TInt())), ""), Query('_name9848', 'internal', [('_var9842', TInt()), ('n', TInt())], (), EBinOp(ECond(EBinOp(EVar('_var9842').with_type(TInt()), 'in', EBinOp(EVar('_var12').with_type(TList(TInt())), '+', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool()), EBinOp(EFilter(EVar('_var12').with_type(TList(TInt())), ELambda(EVar('_var2515').with_type(TInt()), EUnaryOp('not', EBinOp(EVar('_var2515').with_type(TInt()), 'in', EBinOp(EBinOp(EVar('_var12').with_type(TList(TInt())), '+', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt())), '-', ESingleton(EVar('_var9842').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool())).with_type(TBool()))).with_type(TBag(TInt())), '+', EFilter(ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt())), ELambda(EVar('_var2515').with_type(TInt()), EUnaryOp('not', EBinOp(EVar('_var2515').with_type(TInt()), 'in', EBinOp(EBinOp(EVar('_var12').with_type(TList(TInt())), '+', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt())), '-', ESingleton(EVar('_var9842').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool())).with_type(TBool()))).with_type(TBag(TInt()))).with_type(TBag(TInt())), EEmptyList().with_type(TBag(TInt()))).with_type(TBag(TInt())), '-', ECond(EBinOp(EVar('_var9842').with_type(TInt()), 'in', EVar('_var12').with_type(TList(TInt()))).with_type(TBool()), EFilter(EVar('_var12').with_type(TList(TInt())), ELambda(EVar('_var2515').with_type(TInt()), EUnaryOp('not', EBinOp(EVar('_var2515').with_type(TInt()), 'in', EBinOp(EVar('_var12').with_type(TList(TInt())), '-', ESingleton(EVar('_var9842').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool())).with_type(TBool()))).with_type(TBag(TInt())), EEmptyList().with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBag(TInt())), ""), Query('_name9855', 'internal', [('_var9842', TInt()), ('n', TInt())], (), EBinOp(ECond(EBinOp(EVar('_var9842').with_type(TInt()), 'in', EVar('_var12').with_type(TList(TInt()))).with_type(TBool()), EFilter(EVar('_var12').with_type(TList(TInt())), ELambda(EVar('_var2515').with_type(TInt()), EUnaryOp('not', EBinOp(EVar('_var2515').with_type(TInt()), 'in', EBinOp(EVar('_var12').with_type(TList(TInt())), '-', ESingleton(EVar('_var9842').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool())).with_type(TBool()))).with_type(TBag(TInt())), EEmptyList().with_type(TBag(TInt()))).with_type(TBag(TInt())), '-', ECond(EBinOp(EVar('_var9842').with_type(TInt()), 'in', EBinOp(EVar('_var12').with_type(TList(TInt())), '+', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool()), EBinOp(EFilter(EVar('_var12').with_type(TList(TInt())), ELambda(EVar('_var2515').with_type(TInt()), EUnaryOp('not', EBinOp(EVar('_var2515').with_type(TInt()), 'in', EBinOp(EBinOp(EVar('_var12').with_type(TList(TInt())), '+', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt())), '-', ESingleton(EVar('_var9842').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool())).with_type(TBool()))).with_type(TBag(TInt())), '+', EFilter(ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt())), ELambda(EVar('_var2515').with_type(TInt()), EUnaryOp('not', EBinOp(EVar('_var2515').with_type(TInt()), 'in', EBinOp(EBinOp(EVar('_var12').with_type(TList(TInt())), '+', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt())), '-', ESingleton(EVar('_var9842').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool())).with_type(TBool()))).with_type(TBag(TInt()))).with_type(TBag(TInt())), EEmptyList().with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBag(TInt())), ""), Query('_name9863', 'internal', [('n', TInt())], (), EFilter(EUnaryOp('distinct', EBinOp(EUnaryOp('distinct', EVar('_var12').with_type(TList(TInt()))).with_type(TList(TInt())), '+', EUnaryOp('distinct', EBinOp(EVar('_var12').with_type(TList(TInt())), '+', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBag(TInt())), ELambda(EVar('_var9842').with_type(TInt()), EUnaryOp('not', EBinOp(ECond(EBinOp(EVar('_var9842').with_type(TInt()), 'in', EVar('_var12').with_type(TList(TInt()))).with_type(TBool()), EFilter(EVar('_var12').with_type(TList(TInt())), ELambda(EVar('_var2515').with_type(TInt()), EUnaryOp('not', EBinOp(EVar('_var2515').with_type(TInt()), 'in', EBinOp(EVar('_var12').with_type(TList(TInt())), '-', ESingleton(EVar('_var9842').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool())).with_type(TBool()))).with_type(TBag(TInt())), EEmptyList().with_type(TBag(TInt()))).with_type(TBag(TInt())), '==', ECond(EBinOp(EVar('_var9842').with_type(TInt()), 'in', EBinOp(EVar('_var12').with_type(TList(TInt())), '+', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool()), EBinOp(EFilter(EVar('_var12').with_type(TList(TInt())), ELambda(EVar('_var2515').with_type(TInt()), EUnaryOp('not', EBinOp(EVar('_var2515').with_type(TInt()), 'in', EBinOp(EBinOp(EVar('_var12').with_type(TList(TInt())), '+', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt())), '-', ESingleton(EVar('_var9842').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool())).with_type(TBool()))).with_type(TBag(TInt())), '+', EFilter(ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt())), ELambda(EVar('_var2515').with_type(TInt()), EUnaryOp('not', EBinOp(EVar('_var2515').with_type(TInt()), 'in', EBinOp(EBinOp(EVar('_var12').with_type(TList(TInt())), '+', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt())), '-', ESingleton(EVar('_var9842').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool())).with_type(TBool()))).with_type(TBag(TInt()))).with_type(TBag(TInt())), EEmptyList().with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool())).with_type(TBool()))).with_type(TBag(TInt())), ""), Query('_name16354', 'internal', [('_var16321', TInt()), ('n', TInt())], (), EBinOp(ECond(EBinOp(EVar('_var16321').with_type(TInt()), 'in', EBinOp(EVar('_var12').with_type(TList(TInt())), '-', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool()), EFilter(EBinOp(EVar('_var12').with_type(TList(TInt())), '-', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt())), ELambda(EVar('_var2515').with_type(TInt()), EUnaryOp('not', EBinOp(EVar('_var2515').with_type(TInt()), 'in', EBinOp(EBinOp(EVar('_var12').with_type(TList(TInt())), '-', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt())), '-', ESingleton(EVar('_var16321').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool())).with_type(TBool()))).with_type(TBag(TInt())), EEmptyList().with_type(TBag(TInt()))).with_type(TBag(TInt())), '-', ECond(EBinOp(EVar('_var16321').with_type(TInt()), 'in', EVar('_var12').with_type(TList(TInt()))).with_type(TBool()), EFilter(EVar('_var12').with_type(TList(TInt())), ELambda(EVar('_var2515').with_type(TInt()), EUnaryOp('not', EBinOp(EVar('_var2515').with_type(TInt()), 'in', EBinOp(EVar('_var12').with_type(TList(TInt())), '-', ESingleton(EVar('_var16321').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool())).with_type(TBool()))).with_type(TBag(TInt())), EEmptyList().with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBag(TInt())), ""), Query('_name16357', 'internal', [('_var16321', TInt()), ('n', TInt())], (), EBinOp(ECond(EBinOp(EVar('_var16321').with_type(TInt()), 'in', EVar('_var12').with_type(TList(TInt()))).with_type(TBool()), EFilter(EVar('_var12').with_type(TList(TInt())), ELambda(EVar('_var2515').with_type(TInt()), EUnaryOp('not', EBinOp(EVar('_var2515').with_type(TInt()), 'in', EBinOp(EVar('_var12').with_type(TList(TInt())), '-', ESingleton(EVar('_var16321').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool())).with_type(TBool()))).with_type(TBag(TInt())), EEmptyList().with_type(TBag(TInt()))).with_type(TBag(TInt())), '-', ECond(EBinOp(EVar('_var16321').with_type(TInt()), 'in', EBinOp(EVar('_var12').with_type(TList(TInt())), '-', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool()), EFilter(EBinOp(EVar('_var12').with_type(TList(TInt())), '-', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt())), ELambda(EVar('_var2515').with_type(TInt()), EUnaryOp('not', EBinOp(EVar('_var2515').with_type(TInt()), 'in', EBinOp(EBinOp(EVar('_var12').with_type(TList(TInt())), '-', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt())), '-', ESingleton(EVar('_var16321').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool())).with_type(TBool()))).with_type(TBag(TInt())), EEmptyList().with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBag(TInt())), ""), Query('_name24791', 'internal', [('_var24789', TInt()), ('n', TInt())], (), ECond(EBinOp(EVar('_var24789').with_type(TInt()), 'in', EBinOp(EVar('_var12').with_type(TList(TInt())), '+', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool()), EBinOp(EVar('_var24789').with_type(TInt()), 'in', EBinOp(EVar('_var12').with_type(TList(TInt())), '+', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool()), EBool(False).with_type(TBool())).with_type(TBool()), ""), Query('_name28311', 'internal', [('_var28307', TInt()), ('n', TInt())], (), ECond(EBinOp(EVar('_var28307').with_type(TInt()), 'in', EBinOp(EVar('_var12').with_type(TList(TInt())), '-', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool()), EBinOp(EVar('_var28307').with_type(TInt()), 'in', EBinOp(EVar('_var12').with_type(TList(TInt())), '-', ESingleton(EVar('n').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool()), EBool(False).with_type(TBool())).with_type(TBool()), ""), Op('add', [('n', TInt())], [], SSeq(SSeq(SSeq(SSeq(SForEach(EVar('_var15').with_type(TInt()), ECall('_name14', [EVar('n').with_type(TInt())]).with_type(TBag(TInt())), SCall(EVar('_var12').with_type(TList(TInt())), 'remove', [EVar('_var15').with_type(TInt())])), SForEach(EVar('_var15').with_type(TInt()), ECall('_name13', [EVar('n').with_type(TInt())]).with_type(TBag(TInt())), SCall(EVar('_var12').with_type(TList(TInt())), 'add', [EVar('_var15').with_type(TInt())]))), SForEach(EVar('_var905').with_type(TInt()), ECall('_name914', [EVar('n').with_type(TInt())]).with_type(TBag(TInt())), SMapUpdate(EVar('_var895').with_type(TMap(TInt(), TList(TInt()))), EVar('_var905').with_type(TInt()), EVar('_var906').with_type(TList(TInt())), SSeq(SForEach(EVar('_var913').with_type(TInt()), ECall('_name912', [EVar('_var905').with_type(TInt()), EVar('n').with_type(TInt())]).with_type(TBag(TInt())), SCall(EVar('_var906').with_type(TList(TInt())), 'remove', [EVar('_var913').with_type(TInt())])), SForEach(EVar('_var913').with_type(TInt()), ECall('_name911', [EVar('_var905').with_type(TInt()), EVar('n').with_type(TInt())]).with_type(TBag(TInt())), SCall(EVar('_var906').with_type(TList(TInt())), 'add', [EVar('_var913').with_type(TInt())])))))), SForEach(EVar('_var9842').with_type(TInt()), ECall('_name9863', [EVar('n').with_type(TInt())]).with_type(TBag(TInt())), SMapUpdate(EVar('_var9841').with_type(TMap(TInt(), TList(TInt()))), EVar('_var9842').with_type(TInt()), EVar('_var9843').with_type(TList(TInt())), SSeq(SForEach(EVar('_var9856').with_type(TInt()), ECall('_name9855', [EVar('_var9842').with_type(TInt()), EVar('n').with_type(TInt())]).with_type(TBag(TInt())), SCall(EVar('_var9843').with_type(TList(TInt())), 'remove', [EVar('_var9856').with_type(TInt())])), SForEach(EVar('_var9856').with_type(TInt()), ECall('_name9848', [EVar('_var9842').with_type(TInt()), EVar('n').with_type(TInt())]).with_type(TBag(TInt())), SCall(EVar('_var9843').with_type(TList(TInt())), 'add', [EVar('_var9856').with_type(TInt())])))))), SForEach(EVar('_var24789').with_type(TInt()), ECall('_name914', (EVar('n').with_type(TInt()),)).with_type(TBag(TInt())), SMapUpdate(EVar('_var10947').with_type(TMap(TInt(), TBool())), EVar('_var24789').with_type(TInt()), EVar('_var24790').with_type(TBool()), SAssign(EVar('_var24790').with_type(TBool()), ECall('_name24791', (EVar('_var24789').with_type(TInt()), EVar('n').with_type(TInt()))).with_type(TBool()))))), ""), Op('remove', [('n', TInt())], [], SSeq(SSeq(SSeq(SSeq(SForEach(EVar('_var36').with_type(TInt()), ECall('_name35', (EVar('n').with_type(TInt()),)).with_type(TList(TInt())), SCall(EVar('_var12').with_type(TList(TInt())), 'remove', [EVar('_var36').with_type(TInt())])), SForEach(EVar('_var36').with_type(TInt()), ECall('_name14', (EVar('n').with_type(TInt()),)).with_type(TBag(TInt())), SCall(EVar('_var12').with_type(TList(TInt())), 'add', [EVar('_var36').with_type(TInt())]))), SForEach(EVar('_var1492').with_type(TInt()), ECall('_name1519', [EVar('n').with_type(TInt())]).with_type(TList(TInt())), SMapUpdate(EVar('_var895').with_type(TMap(TInt(), TList(TInt()))), EVar('_var1492').with_type(TInt()), EVar('_var1493').with_type(TList(TInt())), SSeq(SForEach(EVar('_var1507').with_type(TInt()), ECall('_name1506', [EVar('_var1492').with_type(TInt()), EVar('n').with_type(TInt())]).with_type(TBag(TInt())), SCall(EVar('_var1493').with_type(TList(TInt())), 'remove', [EVar('_var1507').with_type(TInt())])), SForEach(EVar('_var1507').with_type(TInt()), ECall('_name1497', [EVar('_var1492').with_type(TInt()), EVar('n').with_type(TInt())]).with_type(TBag(TInt())), SCall(EVar('_var1493').with_type(TList(TInt())), 'add', [EVar('_var1507').with_type(TInt())])))))), SForEach(EVar('_var16321').with_type(TInt()), ECall('_name35', (EVar('n').with_type(TInt()),)).with_type(TList(TInt())), SMapUpdate(EVar('_var9841').with_type(TMap(TInt(), TList(TInt()))), EVar('_var16321').with_type(TInt()), EVar('_var16322').with_type(TList(TInt())), SSeq(SForEach(EVar('_var16358').with_type(TInt()), ECall('_name16357', (EVar('_var16321').with_type(TInt()), EVar('n').with_type(TInt()))).with_type(TBag(TInt())), SCall(EVar('_var16322').with_type(TList(TInt())), 'remove', [EVar('_var16358').with_type(TInt())])), SForEach(EVar('_var16358').with_type(TInt()), ECall('_name16354', (EVar('_var16321').with_type(TInt()), EVar('n').with_type(TInt()))).with_type(TBag(TInt())), SCall(EVar('_var16322').with_type(TList(TInt())), 'add', [EVar('_var16358').with_type(TInt())])))))), SForEach(EVar('_var28307').with_type(TInt()), ECall('_name1519', (EVar('n').with_type(TInt()),)).with_type(TList(TInt())), SMapUpdate(EVar('_var10947').with_type(TMap(TInt(), TBool())), EVar('_var28307').with_type(TInt()), EVar('_var28309').with_type(TBool()), SAssign(EVar('_var28309').with_type(TBool()), ECall('_name28311', (EVar('_var28307').with_type(TInt()), EVar('n').with_type(TInt()))).with_type(TBool()))))), "")], "", "", "") state_map = {'_var12': EVar('l').with_type(TBag(TInt())), '_var895': EMakeMap2(EVar('l').with_type(TBag(TInt())), ELambda(EVar('_var116').with_type(TInt()), ESingleton(EVar('_var116').with_type(TInt())).with_type(TBag(TInt())))).with_type(TMap(TInt(), TBag(TInt()))), '_var9841': EMakeMap2(EVar('l').with_type(TBag(TInt())), ELambda(EVar('_var2516').with_type(TInt()), EFilter(EVar('l').with_type(TBag(TInt())), ELambda(EVar('_var2515').with_type(TInt()), EUnaryOp('not', EBinOp(EVar('_var2515').with_type(TInt()), 'in', EBinOp(EVar('l').with_type(TBag(TInt())), '-', ESingleton(EVar('_var2516').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TBool())).with_type(TBool()))).with_type(TBag(TInt())))).with_type(TMap(TInt(), TBag(TInt()))), '_var10947': EMakeMap2(EVar('l').with_type(TBag(TInt())), ELambda(EVar('_var1498').with_type(TInt()), EBinOp(EVar('_var1498').with_type(TInt()), 'in', EVar('l').with_type(TBag(TInt()))).with_type(TBool()))).with_type(TMap(TInt(), TBool()))} impl = inline_calls(impl) impl, state_map = rewrite_extensions(impl, state_map) for v, e in state_map.items(): print(" - {} = {}".format(v, pprint(e))) print(pprint(impl)) for codegen in CODE_GENERATORS: share_info = {} self.check(impl, state_map, share_info, lambda out: codegen(out=out))
def assert_same(self, e1, e2): assert e1.type == e2.type, "{} | {}".format(pprint(e1.type), pprint(e2.type)) def dbg(model): print("model: {!r}".format(model)) r1 = eval(e1, model) r2 = eval(e2, model) print("e1: {}".format(pprint(e1))) print(" ---> {!r}".format(r1)) print("e2: {}".format(pprint(e2))) print(" ---> {!r}".format(r2)) assert satisfy(ENot(EBinOp(e1, "===", e2).with_type(BOOL)), model_callback=dbg) is None
def _consider(e, size, context, pool): """Called when an Enumerator sees an expression for the first time.""" if _interesting(e, size, context, pool) and not verbose.value: print("considering {} @ size={} in {}/{}".format( pprint(e), size, context, pool_name(pool))) task_begin("considering expression", expression=pprint(e), size=size, context=context, pool=pool_name(pool), interesting=_interesting(e, size, context, pool))
def test_heap_enumeration(self): xs = EVar("xs").with_type(INT_BAG) context = RootCtx(state_vars=[xs]) cost_model = CostModel() def not_min_or_max(e, *args, **kwargs): # forbid min/max to ensure that heap operations get cached if isinstance(e, EArgMin) or isinstance(e, EArgMax): return False return True enumerator = Enumerator(examples=[{ "xs": Bag(()) }, { "xs": Bag((1, 2)) }, { "xs": Bag((1, 1)) }], cost_model=cost_model, check_wf=not_min_or_max) with save_property(accelerate, "value"): accelerate.value = False print("-" * 20 + " Looking for xs...") found_xs = False for e in enumerator.enumerate(context, 0, STATE_POOL): print(pprint(e)) if e == xs: assert retypecheck(deep_copy(e)) found_xs = True print("^^^ FOUND") assert found_xs print("-" * 20 + " Looking for heap construction...") found_make_heap = False for e in enumerator.enumerate(context, 1, STATE_POOL): print(pprint(e)) if isinstance(e, EMakeMinHeap) or isinstance(e, EMakeMaxHeap): assert retypecheck(deep_copy(e)) found_make_heap = True print("^^^ FOUND") assert found_make_heap print("-" * 20 + " Looking for heap usage...") found_heap_peek = False for e in enumerator.enumerate(context, 2, RUNTIME_POOL): print(pprint(e)) if isinstance(e, EHeapPeek) or isinstance(e, EHeapPeek2): assert retypecheck(deep_copy(e)) found_heap_peek = True print("^^^ FOUND") assert found_heap_peek
def assert_same(self, e1, e2, assumptions : Exp = ETRUE, op = "==="): assert e1.type == e2.type, "{} | {}".format(pprint(e1.type), pprint(e2.type)) def dbg(model): print("model: {!r}".format(model)) r1 = eval(e1, model) r2 = eval(e2, model) print("e1: {}".format(pprint(e1))) print(" ---> {!r}".format(r1)) print("e2: {}".format(pprint(e2))) print(" ---> {!r}".format(r2)) assert satisfy(EAll([ assumptions, ENot(EBinOp(e1, op, e2).with_type(BOOL))]), model_callback=dbg, validate_model=True) is None
def pre_optimize(self, e, pool): """ Optimize `e` by replacing its subexpressions with the best cached versions available (or leaving them untouched if they are new). """ if not hasattr(e, "_accel"): return e top_level = e class V(BottomUpRewriter): def visit_EStateVar(_, e): return EStateVar(self.pre_optimize(e.e, STATE_POOL)).with_type(e.type) def visit_ELambda(_, e): if e.arg not in self.binders and e.arg in free_vars(e.body): # Derp! Someone made an expression that uses an illegal # binder. There is no way to compute a fingerprint for the # body, unfortunately, so we just stop here. return e return ELambda(e.arg, super().visit_ADT(e.body)) # optimize children def visit_Exp(_, e): # do not shadow `self` if e is top_level: return super().visit_ADT(e) # optimize children fp = self._fingerprint(e) prev = self.seen.find_one(pool, fp) if prev is None: return super().visit_ADT(e) # optimize children prev_exp, prev_size, prev_cost = prev if prev_exp == e: return prev_exp cost = self.cost_model.cost(e, pool) ordering = self.compare_costs(cost, prev_cost) if ordering == Cost.BETTER: return super().visit_ADT(e) # optimize children else: # NOTE: no need to optimize children; if it is cached, then # it is presumably already the best possible. # if not alpha_equivalent(e, prev_exp): # print("*** rewriting {} to {}".format(pprint(e), pprint(prev_exp)), file=sys.stderr) return prev_exp res = None try: res = V().visit(e) assert exp_wf(res, state_vars=self.state_vars, args=self.args, pool=pool, assumptions=self.assumptions) if hasattr(e, "_tag"): res._tag = e._tag return res except: traceback.print_exc(file=sys.stdout) print("FAILED TO PREOPTIMIZE {} ---> {}".format(pprint(e), pprint(res))) print(repr(e)) return e
def lub(self, src, t1, t2, explanation): if t1 == t2: return t1 if is_numeric(t1) and is_numeric(t2): return self.numeric_lub(src, t1, t2) if isinstance(t1, syntax.TList) and isinstance(t2, syntax.TList): return syntax.TList(t1.t) if is_collection(t1) and is_collection(t2): return syntax.TBag(t1.t) self.report_err( src, "cannot unify types {} and {} ({})".format(pprint(t1), pprint(t2), explanation)) return DEFAULT_TYPE
def check_ops_preserve_invariants(spec : Spec): if not invariant_preservation_check.value: return [] res = [] for m in spec.methods: if not isinstance(m, Op): continue for a in spec.assumptions: print("Checking that {} preserves {}...".format(m.name, pprint(a))) a_post_delta = mutate(a, m.body) assumptions = list(m.assumptions) + list(spec.assumptions) if not valid(EImplies(EAll(assumptions), a_post_delta)): res.append("{.name!r} may not preserve invariant {}".format(m, pprint(a))) return res
def test_heaps(self): sgs = [] s = inc.mutate_in_place( lval=EVar('_var6975').with_type(TMinHeap(THandle('ETRUE', TNative('int')), TNative('int'))), e=EMakeMinHeap(EVar('xs').with_type(TBag(THandle('ETRUE', TNative('int')))), ELambda(EVar('_var2813').with_type(THandle('ETRUE', TNative('int'))), EGetField(EVar('_var2813').with_type(THandle('ETRUE', TNative('int'))), 'val').with_type(TNative('int')))).with_type(TMinHeap(THandle('ETRUE', TNative('int')), TNative('int'))), op=SCall(EVar('xs').with_type(TBag(THandle('ETRUE', TNative('int')))), 'remove', (EVar('x').with_type(THandle('ETRUE', TNative('int'))),)), abstract_state=[EVar('xs').with_type(TBag(THandle('ETRUE', TNative('int'))))], assumptions=[EBinOp(EVar('x').with_type(THandle('ETRUE', TNative('int'))), 'in', EVar('xs').with_type(TBag(THandle('ETRUE', TNative('int'))))).with_type(TBool()), EUnaryOp('all', EMap(EBinOp(EFlatMap(EVar('xs').with_type(TBag(THandle('ETRUE', TNative('int')))), ELambda(EVar('_var12').with_type(THandle('ETRUE', TNative('int'))), ESingleton(EVar('_var12').with_type(THandle('ETRUE', TNative('int')))).with_type(TBag(THandle('ETRUE', TNative('int')))))).with_type(TBag(THandle('ETRUE', TNative('int')))), '+', ESingleton(EVar('x').with_type(THandle('ETRUE', TNative('int')))).with_type(TBag(THandle('ETRUE', TNative('int'))))).with_type(TBag(THandle('ETRUE', TNative('int')))), ELambda(EVar('_var13').with_type(THandle('ETRUE', TNative('int'))), EUnaryOp('all', EMap(EBinOp(EFlatMap(EVar('xs').with_type(TBag(THandle('ETRUE', TNative('int')))), ELambda(EVar('_var12').with_type(THandle('ETRUE', TNative('int'))), ESingleton(EVar('_var12').with_type(THandle('ETRUE', TNative('int')))).with_type(TBag(THandle('ETRUE', TNative('int')))))).with_type(TBag(THandle('ETRUE', TNative('int')))), '+', ESingleton(EVar('x').with_type(THandle('ETRUE', TNative('int')))).with_type(TBag(THandle('ETRUE', TNative('int'))))).with_type(TBag(THandle('ETRUE', TNative('int')))), ELambda(EVar('_var14').with_type(THandle('ETRUE', TNative('int'))), EBinOp(EBinOp(EVar('_var13').with_type(THandle('ETRUE', TNative('int'))), '==', EVar('_var14').with_type(THandle('ETRUE', TNative('int')))).with_type(TBool()), '=>', EBinOp(EGetField(EVar('_var13').with_type(THandle('ETRUE', TNative('int'))), 'val').with_type(TNative('int')), '==', EGetField(EVar('_var14').with_type(THandle('ETRUE', TNative('int'))), 'val').with_type(TNative('int'))).with_type(TBool())).with_type(TBool()))).with_type(TBag(TBool()))).with_type(TBool()))).with_type(TBag(TBool()))).with_type(TBool())], subgoals_out=sgs) print("---") print(pprint(s)) for g in sgs: print(pprint(g)) print("---")
def visit(self, e): if hasattr(e, "_nosimpl"): return e if isinstance(e, Exp) and not isinstance(e, ELambda): t = e.type new = super().visit(e) if isinstance(e, Exp) and not isinstance(e, ELambda): assert new.type == e.type, repr(e) if self.debug and isinstance(e, Exp) and not isinstance(e, ELambda): model = satisfy(ENot(EBinOp(e, "===", new).with_type(BOOL))) if model is not None: raise Exception( "bad simplification: {} ---> {} (under model {!r}, got {!r} and {!r})" .format(pprint(e), pprint(new), model, eval(e, model), eval(new, model))) return new
def _add_subquery(self, sub_q : Query, used_by : Stm) -> Stm: with task("adding query", query=sub_q.name): sub_q = shallow_copy(sub_q) with task("checking whether we need more handle assumptions"): new_a = implicit_handle_assumptions_for_method( reachable_handles_at_method(self.spec, sub_q), sub_q) if not valid(EImplies(EAll(sub_q.assumptions), EAll(new_a))): event("we do!") sub_q.assumptions = list(itertools.chain(sub_q.assumptions, new_a)) with task("simplifying"): orig_a = sub_q.assumptions orig_a_size = sum(a.size() for a in sub_q.assumptions) orig_ret_size = sub_q.ret.size() sub_q.assumptions = tuple(simplify_or_ignore(a) for a in sub_q.assumptions) sub_q.ret = simplify(sub_q.ret) a_size = sum(a.size() for a in sub_q.assumptions) ret_size = sub_q.ret.size() event("|assumptions|: {} -> {}".format(orig_a_size, a_size)) event("|ret|: {} -> {}".format(orig_ret_size, ret_size)) if a_size > orig_a_size: print("NO, BAD SIMPLIFICATION") print("original") for a in orig_a: print(" - {}".format(pprint(a))) print("simplified") for a in sub_q.assumptions: print(" - {}".format(pprint(a))) assert False state_vars = self.abstract_state funcs = self.extern_funcs qq = find_one(self.query_specs, lambda qq: dedup_queries.value and queries_equivalent(qq, sub_q, state_vars=state_vars, extern_funcs=funcs)) if qq is not None: event("subgoal {} is equivalent to {}".format(sub_q.name, qq.name)) arg_reorder = [[x[0] for x in sub_q.args].index(a) for (a, t) in qq.args] class Repl(BottomUpRewriter): def visit_ECall(self, e): args = tuple(self.visit(a) for a in e.args) if e.func == sub_q.name: args = tuple(args[idx] for idx in arg_reorder) return ECall(qq.name, args).with_type(e.type) else: return ECall(e.func, args).with_type(e.type) used_by = Repl().visit(used_by) else: self.add_query(sub_q) return used_by
def test_heaps(self): sgs = [] s = inc.mutate_in_place( lval=EVar('_var6975').with_type(TMinHeap(THandle('T', TNative('int')), TNative('int'))), e=EMakeMinHeap(EVar('xs').with_type(TBag(THandle('T', TNative('int')))), ELambda(EVar('_var2813').with_type(THandle('T', TNative('int'))), EGetField(EVar('_var2813').with_type(THandle('T', TNative('int'))), 'val').with_type(TNative('int')))).with_type(TMinHeap(THandle('T', TNative('int')), TNative('int'))), op=SCall(EVar('xs').with_type(TBag(THandle('T', TNative('int')))), 'remove', (EVar('x').with_type(THandle('T', TNative('int'))),)), abstract_state=[EVar('xs').with_type(TBag(THandle('T', TNative('int'))))], assumptions=[EBinOp(EVar('x').with_type(THandle('T', TNative('int'))), 'in', EVar('xs').with_type(TBag(THandle('T', TNative('int'))))).with_type(TBool()), EUnaryOp('all', EMap(EBinOp(EFlatMap(EVar('xs').with_type(TBag(THandle('T', TNative('int')))), ELambda(EVar('_var12').with_type(THandle('T', TNative('int'))), ESingleton(EVar('_var12').with_type(THandle('T', TNative('int')))).with_type(TBag(THandle('T', TNative('int')))))).with_type(TBag(THandle('T', TNative('int')))), '+', ESingleton(EVar('x').with_type(THandle('T', TNative('int')))).with_type(TBag(THandle('T', TNative('int'))))).with_type(TBag(THandle('T', TNative('int')))), ELambda(EVar('_var13').with_type(THandle('T', TNative('int'))), EUnaryOp('all', EMap(EBinOp(EFlatMap(EVar('xs').with_type(TBag(THandle('T', TNative('int')))), ELambda(EVar('_var12').with_type(THandle('T', TNative('int'))), ESingleton(EVar('_var12').with_type(THandle('T', TNative('int')))).with_type(TBag(THandle('T', TNative('int')))))).with_type(TBag(THandle('T', TNative('int')))), '+', ESingleton(EVar('x').with_type(THandle('T', TNative('int')))).with_type(TBag(THandle('T', TNative('int'))))).with_type(TBag(THandle('T', TNative('int')))), ELambda(EVar('_var14').with_type(THandle('T', TNative('int'))), EBinOp(EBinOp(EVar('_var13').with_type(THandle('T', TNative('int'))), '==', EVar('_var14').with_type(THandle('T', TNative('int')))).with_type(TBool()), '=>', EBinOp(EGetField(EVar('_var13').with_type(THandle('T', TNative('int'))), 'val').with_type(TNative('int')), '==', EGetField(EVar('_var14').with_type(THandle('T', TNative('int'))), 'val').with_type(TNative('int'))).with_type(TBool())).with_type(TBool()))).with_type(TBag(TBool()))).with_type(TBool()))).with_type(TBag(TBool()))).with_type(TBool())], subgoals_out=sgs) print("---") print(pprint(s)) for g in sgs: print(pprint(g)) print("---")
def check_ops_preserve_invariants(spec : Spec): if not invariant_preservation_check.value: return [] res = [] for m in spec.methods: if not isinstance(m, Op): continue for a in spec.assumptions: print("Checking that {} preserves {}...".format(m.name, pprint(a))) a_post_delta = mutate(a, m.body) if not alpha_equivalent(a, a_post_delta): assumptions = list(m.assumptions) + list(spec.assumptions) if not valid(EImplies(EAll(assumptions), a_post_delta)): res.append("{.name!r} may not preserve invariant {}".format(m, pprint(a))) return res
def lub(self, src, t1, t2, explanation): if t1 == t2: return t1 if is_numeric(t1) and is_numeric(t2): return self.numeric_lub(src, t1, t2) if isinstance(t1, syntax.TList) and isinstance(t2, syntax.TList) and t1.elem_type == t2.elem_type: return syntax.TList(t1.elem_type) if is_collection(t1) and is_collection(t2) and t1.elem_type == t2.elem_type: return syntax.TBag(t1.elem_type) if t1 is DEFAULT_TYPE: return t2 if t2 is DEFAULT_TYPE: return t1 self.report_err(src, "cannot unify types {} and {} ({})".format(pprint(t1), pprint(t2), explanation)) return DEFAULT_TYPE
def test_heap_enumeration(self): xs = EVar("xs").with_type(INT_BAG) context = RootCtx(state_vars=[xs]) cost_model = CostModel() def not_min_or_max(e, *args, **kwargs): # forbid min/max to ensure that heap operations get cached if isinstance(e, EArgMin) or isinstance(e, EArgMax): return False return True enumerator = Enumerator( examples=[{"xs": Bag(())}, {"xs": Bag((1,2))}, {"xs": Bag((1,1))}], cost_model=cost_model, check_wf=not_min_or_max) with save_property(accelerate, "value"): accelerate.value = False print("-" * 20 + " Looking for xs...") found_xs = False for e in enumerator.enumerate(context, 0, STATE_POOL): print(pprint(e)) if e == xs: assert retypecheck(deep_copy(e)) found_xs = True print("^^^ FOUND") assert found_xs print("-" * 20 + " Looking for heap construction...") found_make_heap = False for e in enumerator.enumerate(context, 1, STATE_POOL): print(pprint(e)) if isinstance(e, EMakeMinHeap) or isinstance(e, EMakeMaxHeap): assert retypecheck(deep_copy(e)) found_make_heap = True print("^^^ FOUND") assert found_make_heap print("-" * 20 + " Looking for heap usage...") found_heap_peek = False for e in enumerator.enumerate(context, 2, RUNTIME_POOL): print(pprint(e)) if isinstance(e, EHeapPeek) or isinstance(e, EHeapPeek2): assert retypecheck(deep_copy(e)) found_heap_peek = True print("^^^ FOUND") assert found_heap_peek
def simplify_and_optimize_lvalue(e : Exp) -> (Stm, Exp): """Helper for simplify_and_optimize. Input: e - an L-value expression to optimize Output: A pair (s, e') such that executing s and then evaluating e' is the same as evaluating the input expression. Unlike `simplify_and_optimize_expression`, this function preserves the meaning of `e` as an L-value. For instance, this function will not replace `e` with a fresh variable. """ assert is_lvalue(e), "not an L-value: {}".format(pprint(e)) if isinstance(e, EVar): return (SNoOp(), e) if isinstance(e, EGetField): if isinstance(e.e.type, THandle): setup, handle = simplify_and_optimize_expression(e.e) return (setup, EGetField(handle, e.field_name).with_type(e.type)) else: setup, lvalue = simplify_and_optimize_lvalue(e.e) return (setup, EGetField(lvalue, e.field_name).with_type(e.type)) if isinstance(e, EMapGet): mapsetup, map = simplify_and_optimize_lvalue(e.map) keysetup, key = simplify_and_optimize_expression(e.key) return (seq([mapsetup, keysetup]), EMapGet(map, key).with_type(e.type)) if isinstance(e, EListGet): listsetup, list_lvalue = simplify_and_optimize_lvalue(e.e) indexsetup, index_exp = simplify_and_optimize_expression(e.index) return (seq([listsetup, indexsetup]), EListGet(list_lvalue, index_exp).with_type(e.type)) raise NotImplementedError(repr(e))
def run(self): print("STARTING IMPROVEMENT JOB {}".format(self.q.name)) os.makedirs(log_dir.value, exist_ok=True) with open(os.path.join(log_dir.value, "{}.log".format(self.q.name)), "w", buffering=LINE_BUFFER_MODE) as f: sys.stdout = f print("STARTING IMPROVEMENT JOB {}".format(self.q.name)) print(pprint(self.q)) if nice_children.value: os.nice(20) cost_model = CostModel( funcs=self.context.funcs(), assumptions=EAll(self.assumptions), freebies=self.freebies, ops=self.ops) try: for expr in itertools.chain((self.q.ret,), core.improve( target=self.q.ret, assumptions=EAll(self.assumptions), context=self.context, hints=self.hints, stop_callback=lambda: self.stop_requested, cost_model=cost_model, ops=self.ops, improve_count=self.improve_count)): new_rep, new_ret = unpack_representation(expr) self.k(new_rep, new_ret) print("PROVED OPTIMALITY FOR {}".format(self.q.name)) except core.StopException: print("stopping synthesis of {}".format(self.q.name)) return
def __init__(self, ctx: SynthCtx, state: [EVar], assumptions: [Exp], q: Query, k, hints: [Exp] = [], freebies: [Exp] = [], ops: [Op] = [], funcs: {str: TFunc} = {}): assert all( v in state for v in free_vars(q) ), "Oops, query looks malformed due to {}:\n{}\nfree_vars({})".format( [v for v in free_vars(q) if v not in state], pprint(q), repr(q)) super().__init__() self.ctx = ctx self.state = state self.assumptions = assumptions q = shallow_copy(q) q.ret = wrap_naked_statevars(q.ret, OrderedSet(state)) self.q = q self.hints = hints self.freebies = freebies self.ops = ops self.k = k self.funcs = OrderedDict(funcs)
def test_hint_instantation(self): x = EVar("x").with_type(INT) y = EVar("y").with_type(INT) z = EVar("z").with_type(INT) hint = ECall("f", (x,)).with_type(INT) context = UnderBinder( RootCtx(args=[x]), v=y, bag=ESingleton(x).with_type(TBag(x.type)), bag_pool=RUNTIME_POOL) cost_model = CostModel() f = lambda a: a + 1 enumerator = Enumerator( examples=[{"x": 1, "f": f}, {"x": 100, "f": f}], hints=[(hint, context, RUNTIME_POOL)], cost_model=cost_model) results = [] for ctx in ( context, context.parent(), UnderBinder(context, v=z, bag=ESingleton(y).with_type(TBag(y.type)), bag_pool=RUNTIME_POOL), UnderBinder(context.parent(), v=z, bag=ESingleton(x).with_type(TBag(y.type)), bag_pool=RUNTIME_POOL), UnderBinder(context.parent(), v=y, bag=ESingleton(ONE).with_type(INT_BAG), bag_pool=RUNTIME_POOL)): print("-" * 30) found = False for e in enumerator.enumerate(ctx, 0, RUNTIME_POOL): print(" -> {}".format(pprint(e))) found = found or alpha_equivalent(e, hint) print("found? {}".format(found)) results.append(found) assert all(results)
def _print(self, m): for (k, v) in m.items(): if k == ContextMap.VALUE: yield "-> {}".format(v) else: for s in self._print(v): yield "{} {}".format(pprint(k), s)
def check_calls_wf(spec : Spec): res = [] queries = { m.name : m for m in spec.methods if isinstance(m, Query) } for ctx in enumerate_fragments(spec): e = ctx.e if isinstance(e, ECall): q = queries.get(e.func) if q is None: continue print("Checking call {}...".format(pprint(e))) a = EAll(ctx.facts) for precond in q.assumptions: precond = mutate(subst(precond, { v : val for (v, t), val in zip(q.args, e.args) }), ctx.mutations) if not valid(inline_calls(spec, EImplies(a, precond))): res.append("at {}: call may not satisfy precondition {}".format(pprint(e), pprint(precond))) return res
def _uneval(t, value): if is_numeric(t): return ENum(value).with_type(t) elif t == BOOL: return EBool(value).with_type(t) elif is_collection(t): e = EEmptyList().with_type(t) for x in value: e = EBinOp(e, "+", ESingleton(uneval(t.t, x)).with_type(t)).with_type(t) return e elif isinstance(t, TString): return EStr(value).with_type(t) elif isinstance(t, TTuple): return ETuple(tuple(uneval(tt, x) for (tt, x) in zip(t.ts, value))).with_type(t) elif isinstance(t, TRecord): return EMakeRecord( tuple((f, uneval(tt, value[f])) for (f, tt) in t.fields)).with_type(t) elif isinstance(t, TEnum): return EEnumEntry(value).with_type(t) elif isinstance(t, THandle): return EHandle( ENum(value.address).with_type(INT), uneval(t.value_type, value.value)).with_type(t) elif isinstance(t, TNative): return ENative(ENum(value[1]).with_type(INT)).with_type(t) else: raise NotImplementedError(pprint(t))
def construct_value(t : Type) -> Exp: """ Construct an arbitrary expression e of the given type. eval(construct_value(t), {}) == mkval(t) """ if is_numeric(t): e = ENum(0) elif t == BOOL: e = EFALSE elif t == STRING: e = EStr("") elif is_collection(t): e = EEmptyList() elif isinstance(t, TTuple): e = ETuple(tuple(construct_value(tt) for tt in t.ts)) elif isinstance(t, TRecord): e = EMakeRecord(tuple((f, construct_value(tt)) for (f, tt) in t.fields)) elif isinstance(t, TEnum): e = EEnumEntry(t.cases[0]) elif isinstance(t, THandle): e = EHandle(construct_value(INT), construct_value(t.value_type)) elif isinstance(t, TNative): e = ENative(construct_value(INT)) elif isinstance(t, TMap): e = EMakeMap2( EEmptyList().with_type(TBag(t.k)), ELambda(EVar("x").with_type(t.k), construct_value(t.v))) else: h = extension_handler(type(t)) if h is not None: return h.default_value(t, construct_value) raise NotImplementedError(pprint(t)) return e.with_type(t)
def mutate_in_place(self, lval, e, op, assumptions, make_subgoal): from cozy.state_maintenance import mutate old_value = e new_value = mutate(e, op) # added/removed elements t = TBag(lval.type.elem_type) old_elems = EHeapElems(old_value).with_type(t) new_elems = EHeapElems(new_value).with_type(t) initial_count = make_subgoal(ELen(old_elems)) to_add = make_subgoal(EBinOp(new_elems, "-", old_elems).with_type(t), docstring="additions to {}".format(pprint(lval))) to_del_spec = EBinOp(old_elems, "-", new_elems).with_type(t) removed_count = make_subgoal(ELen(to_del_spec)) to_del = make_subgoal(to_del_spec, docstring="deletions from {}".format(pprint(lval))) # modified elements f1 = heap_func(old_value) f2 = heap_func(new_value) v = fresh_var(t.t) old_v_key = f1.apply_to(v) new_v_key = f2.apply_to(v) mod_spec = EFilter(old_elems, ELambda(v, EAll([EIn(v, new_elems), ENot(EEq(new_v_key, old_v_key))]))).with_type(new_elems.type) modified = make_subgoal(mod_spec) return seq([ SCall(lval, "remove_all", (initial_count, to_del)), SCall(lval, "add_all", (EBinOp(initial_count, "-", removed_count).with_type(INT), to_add)), SForEach(v, modified, SCall(lval, "update", (v, make_subgoal(new_v_key, a=[EIn(v, mod_spec)]))))])
def mutate_in_place(self, lval, e, op, assumptions, invariants, make_subgoal): from cozy.state_maintenance import mutate old_value = e new_value = mutate(e, op) # added/removed elements t = TBag(lval.type.elem_type) old_elems = EHeapElems(old_value).with_type(t) new_elems = EHeapElems(new_value).with_type(t) initial_count = make_subgoal(ELen(old_elems)) to_add = make_subgoal(EBinOp(new_elems, "-", old_elems).with_type(t), docstring="additions to {}".format(pprint(lval))) to_del_spec = EBinOp(old_elems, "-", new_elems).with_type(t) removed_count = make_subgoal(ELen(to_del_spec)) to_del = make_subgoal(to_del_spec, docstring="deletions from {}".format(pprint(lval))) # modified elements f1 = heap_func(old_value) f2 = heap_func(new_value) v = fresh_var(t.elem_type) old_v_key = f1.apply_to(v) new_v_key = f2.apply_to(v) mod_spec = EFilter(old_elems, ELambda(v, EAll([EIn(v, new_elems), ENot(EEq(new_v_key, old_v_key))]))).with_type(new_elems.type) modified = make_subgoal(mod_spec) intermediate_count = make_subgoal(EBinOp(ELen(old_elems), "-", ELen(to_del_spec)).with_type(INT)) return seq([ SCall(lval, "remove_all", (initial_count, to_del)), SCall(lval, "add_all", (intermediate_count, to_add)), SForEach(v, modified, SCall(lval, "update", (v, make_subgoal(new_v_key, a=[EIn(v, mod_spec)]))))])
def construct_value(t: Type) -> Exp: """ Construct an arbitrary expression e of the given type. eval(construct_value(t), {}) == mkval(t) """ if is_numeric(t): e = ENum(0) elif t == BOOL: e = F elif t == STRING: e = EStr("") elif is_collection(t): e = EEmptyList() elif isinstance(t, TTuple): e = ETuple(tuple(construct_value(tt) for tt in t.ts)) elif isinstance(t, TRecord): e = EMakeRecord(tuple( (f, construct_value(tt)) for (f, tt) in t.fields)) elif isinstance(t, TEnum): e = EEnumEntry(t.cases[0]) elif isinstance(t, THandle): e = EHandle(construct_value(INT), construct_value(t.value_type)) elif isinstance(t, TNative): e = ENative(construct_value(INT)) elif isinstance(t, TMap): e = EMakeMap2(EEmptyList().with_type(TBag(t.k)), ELambda(EVar("x").with_type(t.k), construct_value(t.v))) else: h = extension_handler(type(t)) if h is not None: return h.default_value(t, construct_value) raise NotImplementedError(pprint(t)) return e.with_type(t)
def build(self, cache, size): for (e, pool) in self.wrapped_builder.build(cache, size): try: orig = e # print(hasattr(orig, "_tag"), file=sys.stderr) e = fixup_binders(e, self.binders_to_use) for a in ATTRS_TO_PRESERVE: if hasattr(orig, a): setattr(e, a, getattr(orig, a)) except Exception: _on_exp(e, "unable to rename binders") continue print("WARNING: skipping built expression {}".format(pprint(e)), file=sys.stderr) if reject_symmetric_binops.value and size > 1 and isinstance(e, EBinOp) and e.op in COMMUTATIVE_OPERATORS and e.e2 < e.e1: _on_exp(e, "rejecting symmetric use of commutative operator") continue try: # Acceleration rules can produce arbitrary expressions, so we # need to recursively check them. The regular grammar only # produces expressions "one level deep"---all subexpressions # have already been checked. if hasattr(e, "_accel"): exp_wf(e, self.state_vars, self.args, pool, assumptions=self.assumptions) else: exp_wf_nonrecursive(e, self.state_vars, self.args, pool, assumptions=self.assumptions) except ExpIsNotWf as exc: _on_exp(e, exc.reason, exc.offending_subexpression) continue yield (e, pool)
def visit_SCall(self, call): target = self.visit(call.target) args = [self.visit(a) for a in call.args] self.begin_statement() if type(call.target.type) in (TBag, TList): if call.func == "add": self.write(target, ".push_back(", args[0], ");") elif call.func == "remove": v = self.fv(TNative("auto"), "it") self.write("auto ", v.id, "(::std::find(", target, ".begin(), ", target, ".end(), ", args[0], "));") self.end_statement() self.begin_statement() self.write("if (", v.id, " != ", target, ".end()) { ", target, ".erase(", v.id, "); }") else: raise NotImplementedError(call.func) elif isinstance(call.target.type, TSet): if call.func == "add": self.write(target, ".insert(", args[0], ");") elif call.func == "remove": self.write(target, ".erase(", target, ".find(", args[0], "));") else: raise NotImplementedError(call.func) else: raise NotImplementedError("unknown target type {} in {}".format(pprint(call.target.type), pprint(call))) self.end_statement()
def visit_EBinOp(self, e): self.visit(e.e1) self.visit(e.e2) if e.op in ["==", "===", "!=", "<", "<=", ">", ">="]: self.lub(e, e.e1.type, e.e2.type, "due to comparison") e.type = BOOL elif e.op in [syntax.BOp.And, syntax.BOp.Or, "=>"]: self.ensure_type(e.e1, BOOL) self.ensure_type(e.e2, BOOL) e.type = BOOL elif e.op == syntax.BOp.In: t = self.get_collection_type(e.e2) self.ensure_type(e.e1, t) e.type = BOOL elif e.op in ["+", "-"]: if is_numeric(e.e1.type): self.ensure_numeric(e.e2) e.type = self.numeric_lub(e, e.e1.type, e.e2.type) else: t1 = self.get_collection_type(e.e1) t2 = self.get_collection_type(e.e2) if t1 != t2: self.report_err(e, "cannot {!r} {} and {}".format(e.op, pprint(e.e1.type), pprint(e.e2.type))) e.type = to_abstract(e.e1.type) elif e.op in ["*"]: if is_numeric(e.e1.type): e.type = self.numeric_lub(e, e.e1.type, e.e2.type) if not is_constant(e.e1) and not is_constant(e.e2): self.report_err(e, "multiplication is only legal when one operand is a constant") else: e.type = DEFAULT_TYPE self.report_err(e, "cannot multiply {} and {}".format(pprint(e.e1.type), pprint(e.e2.type))) elif e.op == "/": e.type = FLOAT if not (e.e1.type is DEFAULT_TYPE or e.e1.type == FLOAT): self.report_err(e, "division is only legal on floats; left-hand side {} has type {}".format(pprint(e.e1), pprint(e.e1.type))) if not (e.e2.type is DEFAULT_TYPE or e.e2.type == FLOAT): self.report_err(e, "division is only legal on floats; right-hand side {} has type {}".format(pprint(e.e2), pprint(e.e2.type))) self.report_err(e, "Division is currently unsupported since it is a partial function (x/0 is undefined)." + " See https://github.com/CozySynthesizer/cozy/issues/19 for more information.") else: raise NotImplementedError(e.op)
def callback(impl): if orig_callback is not None: orig_callback(impl) ast = impl.code state_map = impl.concretization_functions s = "<!DOCTYPE html>\n" s += "<html>" s += "<head><style>" s += ".kw { color: #909; font-weight: bold; }" s += ".builtin { color: #009; font-weight: bold; }" s += ".comment { color: #999; }" s += "</style></head>" s += "<body><pre>" for v, e in state_map.items(): s += "{} : {} = {}\n".format(v, syntax_tools.pprint(e.type, format="html"), syntax_tools.pprint(e, format="html")) s += "\n" s += syntax_tools.pprint(ast, format="html") s += "</pre></body></html>" state[0] = s
def check_discovery(spec, expected, state_vars=[], args=[], examples=[], assumptions=ETRUE): ctx = RootCtx(state_vars=state_vars, args=args) for r in improve(spec, assumptions=assumptions, context=ctx, examples=examples): print("GOT RESULT ==> {}".format(pprint(r))) if isinstance(expected, Exp): if alpha_equivalent(r, expected): return True elif expected(r): return True return False
def visit_ETupleGet(self, e): self.visit(e.e) t = e.e.type if isinstance(t, syntax.TTuple): if e.index >= 0 and e.index < len(t.ts): e.type = t.ts[e.index] else: self.report_err(e, "cannot get element {} from tuple of size {}".format(e.index, len(t.ts))) e.type = DEFAULT_TYPE elif t is DEFAULT_TYPE: e.type = DEFAULT_TYPE else: self.report_err(e, "cannot get element from non-tuple {}".format(pprint(t))) e.type = DEFAULT_TYPE
def test_regression01(self): impl = Spec('MaxBag', [], [], [('_var656', TInt()), ('_var753', TMap(TInt(), TBool())), ('_var1653', TBool()), ('_var2642', TMaxHeap(TInt(), TInt())), ('_var4385', TInt())], (), (Query('get_max', 'pubilc', [], (), EVar('_var656').with_type(TInt()), ''), Op('add', [('x', TInt())], [], SSeq(SSeq(SDecl(EVar('_var32322').with_type(TInt()), ECond(EVar('_var1653').with_type(TBool()), EArgMax(EBinOp(ESingleton(EVar('_var656').with_type(TInt())).with_type(TBag(TInt())), '+', ESingleton(EVar('x').with_type(TInt())).with_type(TBag(TInt()))).with_type(TBag(TInt())), ELambda(EVar('_var662').with_type(TInt()), EVar('_var662').with_type(TInt()))).with_type(TInt()), EVar('x').with_type(TInt())).with_type(TInt())), SSeq(SDecl(EVar('_var32323').with_type(TInt()), EBinOp(EVar('_var4385').with_type(TInt()), '+', ENum(1).with_type(TInt())).with_type(TInt())), SAssign(EVar('_var656').with_type(TInt()), EVar('_var32322').with_type(TInt())))), SSeq(SSeq(SAssign(EVar('_var1653').with_type(TBool()), EBool(True).with_type(TBool())), SSeq(SCall(EVar('_var2642').with_type(TMaxHeap(TInt(), TInt())), 'remove_all', (EVar('_var4385').with_type(TInt()), EEmptyList().with_type(TBag(TInt())))), SSeq(SCall(EVar('_var2642').with_type(TMaxHeap(TInt(), TInt())), 'add_all', (EVar('_var4385').with_type(TInt()), ESingleton(EVar('x').with_type(TInt())).with_type(TBag(TInt())))), SForEach(EVar('_var3970').with_type(TInt()), EEmptyList().with_type(TBag(TInt())), SCall(EVar('_var2642').with_type(TMaxHeap(TInt(), TInt())), 'update', (EVar('_var3970').with_type(TInt()), EVar('_var3970').with_type(TInt()))))))), SSeq(SAssign(EVar('_var4385').with_type(TInt()), EVar('_var32323').with_type(TInt())), SSeq(SForEach(EVar('_var1135').with_type(TInt()), EEmptyList().with_type(TBag(TInt())), SMapDel(EVar('_var753').with_type(TMap(TInt(), TBool())), EVar('_var1135').with_type(TInt()))), SForEach(EVar('_var1135').with_type(TInt()), ESingleton(EVar('x').with_type(TInt())).with_type(TBag(TInt())), SMapUpdate(EVar('_var753').with_type(TMap(TInt(), TBool())), EVar('_var1135').with_type(TInt()), EVar('_var1136').with_type(TBool()), SAssign(EVar('_var1136').with_type(TBool()), EBool(True).with_type(TBool())))))))), ''), Op('remove', [('x', TInt())], [], SSeq(SSeq(SSeq(SDecl(EVar('_var32324').with_type(TInt()), ECond(EBinOp(EVar('x').with_type(TInt()), '==', EVar('_var656').with_type(TInt())).with_type(TBool()), EHeapPeek2(EVar('_var2642').with_type(TMaxHeap(TInt(), TInt()))).with_type(TInt()), EVar('_var656').with_type(TInt())).with_type(TInt())), SDecl(EVar('_var32325').with_type(TInt()), EBinOp(EVar('_var4385').with_type(TInt()), '-', EUnaryOp('len', ECond(EHasKey(EVar('_var753').with_type(TMap(TInt(), TBool())), EVar('x').with_type(TInt())).with_type(TBool()), ESingleton(EVar('x').with_type(TInt())).with_type(TBag(TInt())), EEmptyList().with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TInt())).with_type(TInt()))), SSeq(SDecl(EVar('_var32326').with_type(TBag(TInt())), ECond(EHasKey(EVar('_var753').with_type(TMap(TInt(), TBool())), EVar('x').with_type(TInt())).with_type(TBool()), ESingleton(EVar('x').with_type(TInt())).with_type(TBag(TInt())), EEmptyList().with_type(TBag(TInt()))).with_type(TBag(TInt()))), SAssign(EVar('_var656').with_type(TInt()), EVar('_var32324').with_type(TInt())))), SSeq(SSeq(SAssign(EVar('_var1653').with_type(TBool()), EBinOp(EBinOp(EVar('_var4385').with_type(TInt()), '-', ECond(EHasKey(EVar('_var753').with_type(TMap(TInt(), TBool())), EVar('x').with_type(TInt())).with_type(TBool()), ENum(1).with_type(TInt()), ENum(0).with_type(TInt())).with_type(TInt())).with_type(TInt()), '>', ENum(0).with_type(TInt())).with_type(TBool())), SSeq(SCall(EVar('_var2642').with_type(TMaxHeap(TInt(), TInt())), 'remove_all', (EVar('_var4385').with_type(TInt()), ECond(EHasKey(EVar('_var753').with_type(TMap(TInt(), TBool())), EVar('x').with_type(TInt())).with_type(TBool()), ESingleton(EVar('x').with_type(TInt())).with_type(TBag(TInt())), EEmptyList().with_type(TBag(TInt()))).with_type(TBag(TInt())))), SSeq(SCall(EVar('_var2642').with_type(TMaxHeap(TInt(), TInt())), 'add_all', (EBinOp(EVar('_var4385').with_type(TInt()), '-', EUnaryOp('len', ECond(EHasKey(EVar('_var753').with_type(TMap(TInt(), TBool())), EVar('x').with_type(TInt())).with_type(TBool()), ESingleton(EVar('x').with_type(TInt())).with_type(TBag(TInt())), EEmptyList().with_type(TBag(TInt()))).with_type(TBag(TInt()))).with_type(TInt())).with_type(TInt()), EEmptyList().with_type(TBag(TInt())))), SForEach(EVar('_var6136').with_type(TInt()), EEmptyList().with_type(TBag(TInt())), SCall(EVar('_var2642').with_type(TMaxHeap(TInt(), TInt())), 'update', (EVar('_var6136').with_type(TInt()), EVar('_var6136').with_type(TInt()))))))), SSeq(SAssign(EVar('_var4385').with_type(TInt()), EVar('_var32325').with_type(TInt())), SSeq(SForEach(EVar('_var2481').with_type(TInt()), EVar('_var32326').with_type(TBag(TInt())), SMapDel(EVar('_var753').with_type(TMap(TInt(), TBool())), EVar('_var2481').with_type(TInt()))), SForEach(EVar('_var2481').with_type(TInt()), EEmptyList().with_type(TBag(TInt())), SMapUpdate(EVar('_var753').with_type(TMap(TInt(), TBool())), EVar('_var2481').with_type(TInt()), EVar('_var2482').with_type(TBool()), SNoOp())))))), '')), '', '', '') state_map = OrderedDict([('_var656', EArgMax(EVar('l').with_type(TBag(TInt())), ELambda(EVar('x').with_type(TInt()), EVar('x').with_type(TInt()))).with_type(TInt())), ( '_var753', EMakeMap2(EVar('l').with_type(TBag(TInt())), ELambda(EVar('_var690').with_type(TInt()), EBool(True).with_type(TBool()))).with_type( TMap(TInt(), TBool()))), ('_var1653', EUnaryOp('exists', EVar('l').with_type(TBag(TInt()))).with_type(TBool())), ('_var2642', EMakeMaxHeap(EVar('l').with_type(TBag(TInt())), ELambda(EVar('_var758').with_type(TInt()), EVar('_var758').with_type(TInt()))).with_type( TMaxHeap(TInt(), TInt()))), ('_var4385', EUnaryOp('len', EVar('l').with_type(TBag(TInt()))).with_type(TInt()))]) impl = inline_calls(impl) impl, state_map = rewrite_extensions(impl, state_map) for v, e in state_map.items(): print(" - {} = {}".format(v, pprint(e))) print(pprint(impl)) for codegen in CODE_GENERATORS: share_info = defaultdict(list, {}) self.check(impl, state_map, share_info, lambda out: codegen(out=out))
def _do_assignment(lval : syntax.Exp, new_value : syntax.Exp, e : syntax.Exp) -> syntax.Exp: """ Return the value of `e` after the assignment `lval = new_value`. """ if isinstance(lval, syntax.EVar): return lightweight_subst(e, lval, new_value) elif isinstance(lval, syntax.EGetField): if isinstance(lval.e.type, syntax.THandle): assert lval.field_name == "val" # Because any two handles might alias, we need to rewrite all # reachable handles in `e`. return replace_get_value(e, lval.e, new_value) return _do_assignment(lval.e, _replace_field(lval.e, lval.field_name, new_value), e) else: raise Exception("not an lvalue: {}".format(pprint(lval)))
def visit_EMap(self, e): self.visit(e.e) elem_type = self.get_collection_type(e.e) e.transform_function.arg.type = elem_type self.visit(e.transform_function) if isinstance(e.e.type, syntax.TSet): # Sets might not have distinct elements after the map transform. # Consider e.g. `map {\x -> 1} my_set`. e.type = syntax.TBag(e.transform_function.body.type) elif is_collection(e.e.type): e.type = type(to_abstract(e.e.type))(e.transform_function.body.type) elif e.e.type is DEFAULT_TYPE: e.type = DEFAULT_TYPE else: self.report_err(e, "cannot map over non-collection {}".format(pprint(e.e.type))) e.type = DEFAULT_TYPE
def test_estatevar_ctx(self): xs = EVar("xs").with_type(INT_BAG) x = EVar("x").with_type(INT) y = EVar("y").with_type(BOOL) e = EMap(xs, ELambda(x, EStateVar(y))) ctx = RootCtx(args=(xs,), state_vars=(y,)) assert retypecheck(e) for ee, ctx, pool in all_subexpressions_with_context_information(e, ctx): if ee == y: assert isinstance(ctx, RootCtx) e = replace( e, ctx, RUNTIME_POOL, y, ctx, STATE_POOL, ETRUE) assert e == EMap(xs, ELambda(x, EStateVar(ETRUE))), pprint(e)
def _setup_handle_updates(self): """ This method creates update code for handle objects modified by each op. Must be called once after all user-specified queries have been added. """ for op in self.op_specs: print("Setting up handle updates for {}...".format(op.name)) handles = reachable_handles_at_method(self.spec, op) # print("-"*60) for t, bag in handles.items(): # print(" {} : {}".format(pprint(t), pprint(bag))) h = fresh_var(t) lval = EGetField(h, "val").with_type(t.value_type) new_val = inc.mutate(lval, op.body) # get set of modified handles modified_handles = Query( fresh_name("modified_handles"), Visibility.Internal, [], op.assumptions, EFilter(EUnaryOp(UOp.Distinct, bag).with_type(bag.type), ELambda(h, ENot(EEq(lval, new_val)))).with_type(bag.type), "[{}] modified handles of type {}".format(op.name, pprint(t))) query_vars = [v for v in free_vars(modified_handles) if v not in self.abstract_state] modified_handles.args = [(arg.id, arg.type) for arg in query_vars] # modify each one subqueries = [] state_update_stm = inc.mutate_in_place( lval, lval, op.body, abstract_state=self.abstract_state, assumptions=list(op.assumptions) + [EDeepIn(h, bag), EIn(h, modified_handles.ret)], invariants=self.abstract_invariants, subgoals_out=subqueries) for sub_q in subqueries: sub_q.docstring = "[{}] {}".format(op.name, sub_q.docstring) state_update_stm = self._add_subquery(sub_q=sub_q, used_by=state_update_stm) if state_update_stm != SNoOp(): state_update_stm = SForEach(h, ECall(modified_handles.name, query_vars).with_type(bag.type), state_update_stm) state_update_stm = self._add_subquery(sub_q=modified_handles, used_by=state_update_stm) self.handle_updates[(t, op.name)] = state_update_stm
def eval_bulk( e : Exp, envs : [{str:object}], use_default_values_for_undefined_vars : bool = False): """Evaluate an expression in many different environments. This function accepts the same arguments as `eval`, but takes a list of environments instead of just one. The call eval_bulk(e, envs) is equivalent to [eval(e, env) for env in envs]. However, using `eval_bulk` is much faster than repeatedly calling `eval` on the same expression. """ if not envs: return [] e = purify(e) ops = [] types = { v.id : v.type for v in free_vars(e) } vars = OrderedSet(itertools.chain(types.keys(), free_funcs(e).keys())) vmap = { v : i for (i, v) in enumerate(vars) } try: envs = [ [(env.get(v, mkval(types[v])) if (use_default_values_for_undefined_vars and v in types) else env[v]) for v in vars] for env in envs ] except KeyError: import sys print("OH NO", file=sys.stderr) print("e = {}".format(pprint(e)), file=sys.stderr) print("eval_bulk({!r}, {!r}, use_default_values_for_undefined_vars={!r})".format(e, envs, use_default_values_for_undefined_vars), file=sys.stderr) raise _compile(e, vmap, ops) return [_eval_compiled(ops, env) for env in envs]
def test_pickling(self): i = parse_spec(""" Foo: type ETRUE = Native "int" extern newX(x : Int) : ETRUE = "..." extern readX(x : ETRUE) : Int = "..." state xs : Set<ETRUE> state intsA : Set<Int> state intsB : Set<Int> invariant intsA == [readX(x) - 1 | x <- xs]; invariant intsB == [readX(x) + 1 | x <- xs]; query getA() intsA query getB() intsB """) errs = typecheck(i) assert not errs, errs i = desugar(i) i1 = construct_initial_implementation(i) print(pprint(i1.code)) i2 = pickle.loads(pickle.dumps(i1)) assert i1.code == i2.code