def watch(self, new_target): print("watching new target...") self.backlog_counter = 0 self.target = new_target self.roots = OrderedSet() types = OrderedSet() for e in itertools.chain(all_exps(new_target), *[all_exps(h) for h in self.hints]): if isinstance(e, ELambda): continue for pool in ALL_POOLS: exp = e if pool == STATE_POOL: exp = strip_EStateVar(e) fvs = free_vars(exp) if all(v in self.legal_free_vars for v in fvs) and self.is_legal_in_pool(exp, pool): _on_exp(exp, "new root", pool_name(pool)) exp._root = True self.roots.add((exp, pool)) if pool == STATE_POOL and all(v in self.state_vars for v in fvs): self.roots.add((EStateVar(exp).with_type(exp.type), RUNTIME_POOL)) types.add(exp.type) else: _on_exp(exp, "rejected root", pool_name(pool)) for b in self.binders: types.add(b.type) for t in types: self.roots.add((construct_value(t), RUNTIME_POOL)) self.roots = list(self.roots) self.roots.sort(key = lambda tup: tup[0].size()) self._watches = group_by( enumerate_fragments2(new_target), k=lambda ctx: (ctx.pool, ctx.e.type), v=lambda ctxs: sorted(ctxs, key=lambda ctx: -ctx.e.size())) print("done!")
def retypecheck(exp, env : {str : syntax.Type} = None, fenv = None): """Add or fix the .type annotations on the given tree. Returns True or False to indicate success or failure. If it fails, it prints type errors to stdout. Unlike `typecheck`, this procedure attempts to guess the types of variables and functions in the expression using their .type annotations. The `env` dictionary overrides these guesses and forces variables to be annotated with a particular type. """ if env is None: env = { v.id:v.type for v in free_vars(exp) } if fenv is not None: fenv = { f : (tuple(ty.arg_types), ty.ret_type) for f, ty in fenv.items() } else: fenv = { } for e in all_exps(exp): if isinstance(e, syntax.EEnumEntry): env[e.name] = e.type if isinstance(e, syntax.ECall): if e.func not in fenv: fenv[e.func] = (tuple(arg.type for arg in e.args), e.type) errs = typecheck(exp, env=env, fenv=fenv) if errs: print("errors") for e in errs: print(" --> {}".format(e)) return not errs
def build(self, cache, size): for tup in self.wrapped_builder.build(cache, size): e, pool = tup if pool != STATE_POOL and not any(isinstance(x, EStateVar) for x in all_exps(e)): yield tup else: _on_exp(e, "culled state expression")
def problematic(e): for x in all_exps(e): if isinstance(x, ECall) and x.func in [q.name for q in self.query_specs]: problems = set(things_updated) & state_read_by_query[x.func] if problems: return True return False
def storage_size(e, cardinalities): sizes = [] for x in all_exps(e): if isinstance(x, EStateVar): sz_cost = sizeof(x.e, cardinalities) sizes.append(sz_cost.formula) return SymbolicCost(ESum(sizes), cardinalities)
def problematic(e): for x in all_exps(e): if isinstance(x, ECall) and x.func in [q.name for q in self.query_specs]: problems = set(things_updated) & state_read_by_query[x.func] if problems: return True return False
def retypecheck(exp, env: {str: syntax.Type} = None): """Add or fix the .type annotations on the given tree. Returns True or False to indicate success or failure. If it fails, it prints type errors to stdout. Unlike `typecheck`, this procedure attempts to guess the types of variables and functions in the expression using their .type annotations. The `env` dictionary overrides these guesses and forces variables to be annotated with a particular type. """ if env is None: env = {v.id: v.type for v in free_vars(exp)} fenv = {} for e in all_exps(exp): if isinstance(e, syntax.EEnumEntry): env[e.name] = e.type if isinstance(e, syntax.ECall): fenv[e.func] = (tuple(arg.type for arg in e.args), e.type) errs = typecheck(exp, env=env, fenv=fenv) if errs: print("errors") for e in errs: print(" --> {}".format(e)) return not errs
def cleanup(self): """ Remove unused state, queries, and updates. """ # sort of like mark-and-sweep queries_to_keep = OrderedSet(q.name for q in self.query_specs if q.visibility == Visibility.Public) state_vars_to_keep = OrderedSet() changed = True while changed: changed = False for qname in list(queries_to_keep): if qname in self.query_impls: for sv in free_vars(self.query_impls[qname]): if sv not in state_vars_to_keep: state_vars_to_keep.add(sv) changed = True for e in all_exps(self.query_impls[qname].ret): if isinstance(e, ECall): if e.func not in queries_to_keep: queries_to_keep.add(e.func) changed = True for op in self.op_specs: for ((ht, op_name), code) in self.handle_updates.items(): if op.name == op_name: for qname in _queries_used_by(code): if qname not in queries_to_keep: queries_to_keep.add(qname) changed = True for sv in state_vars_to_keep: for qname in _queries_used_by(self.updates[(sv, op.name)]): if qname not in queries_to_keep: queries_to_keep.add(qname) changed = True # remove old specs for q in list(self.query_specs): if q.name not in queries_to_keep: self.query_specs.remove(q) # remove old implementations for qname in list(self.query_impls.keys()): if qname not in queries_to_keep: del self.query_impls[qname] # remove old state vars self.concrete_state = [ v for v in self.concrete_state if any(v[0] in free_vars(q) for q in self.query_impls.values()) ] # remove old method implementations for k in list(self.updates.keys()): v, op_name = k if v not in [var for (var, exp) in self.concrete_state]: del self.updates[k]
def retypecheck(exp, env=None): from cozy.syntax_tools import free_vars if env is None: env = {v.id: v.type for v in free_vars(exp)} for e in all_exps(exp): if isinstance(e, syntax.EEnumEntry): env[e.name] = e.type errs = typecheck(exp, env=env) if errs: print("errors") for e in errs: print(" --> {}".format(e)) return not errs
def retypecheck(exp, env=None): if env is None: env = { v.id:v.type for v in free_vars(exp) } fenv = { } for e in all_exps(exp): if isinstance(e, syntax.EEnumEntry): env[e.name] = e.type if isinstance(e, syntax.ECall): fenv[e.func] = (tuple(arg.type for arg in e.args), e.type) errs = typecheck(exp, env=env, fenv=fenv) if errs: print("errors") for e in errs: print(" --> {}".format(e)) return not errs
def visit_Spec(self, spec: Spec, state_exps: {str: Exp}, sharing, abstract_state=()): self.state_exps = state_exps self.funcs = {f.name: f for f in spec.extern_funcs} self.queries = { q.name: q for q in spec.methods if isinstance(q, Query) } self.vars = set(e.id for e in all_exps(spec) if isinstance(e, EVar)) self.write("#pragma once\n") self.write("#include <algorithm>\n") self.write("#include <set>\n") self.write("#include <functional>\n") self.write("#include <vector>\n") self.write("#include <unordered_set>\n") self.write("#include <string>\n") if self.use_qhash: self.write("#include <QHash>\n") else: self.write("#include <unordered_map>\n") if spec.header: self.write("\n" + spec.header.strip() + "\n") self.write("{}\nclass {} {{\n".format( ("\n" + spec.docstring) if spec.docstring else "", spec.name)) self.write("public:\n") print("Setting up auxiliary types...") self.setup_types(spec, state_exps, sharing) with self.indented(): for t, name in self.types.items(): self.define_type(spec.name, t, name, sharing) self.begin_statement() if isinstance(t, THandle): # No overridden hash code! We use pointers instead. continue self.write("struct _Hash", name, " ") with self.block(): self.write_stmt("typedef ", spec.name, "::", name, " argument_type;") self.write_stmt("typedef std::size_t result_type;") self.begin_statement() self.write( "result_type operator()(const argument_type& x) const noexcept " ) x = EVar("x").with_type(t) if isinstance(t, TEnum): fields = [EEnumToInt(x).with_type(INT)] elif isinstance(t, TRecord): fields = [ EGetField(x, f).with_type(ft) for (f, ft) in t.fields ] elif isinstance(t, TTuple): fields = [ ETupleGet(x, n).with_type(tt) for (n, tt) in enumerate(t.ts) ] else: raise NotImplementedError(t) with self.block(): self.visit(self.compute_hash(fields)) self.end_statement() self.write(";") self.end_statement() print("Setting up member variables...") self.write("protected:\n") with self.indented(): for name, t in spec.statevars: self.statevar_name = name self.declare_field(name, t) self.write("public:\n") with self.indented(): print("Generating constructors...") # default constructor self.begin_statement() self.write("inline ", spec.name, "() ") with self.block(): for name, t in spec.statevars: initial_value = state_exps[name] fvs = free_vars(initial_value) initial_value = subst(initial_value, { v.id: evaluation.construct_value(v.type) for v in fvs }) stm = simplify_and_optimize( SAssign(EVar(name).with_type(t), initial_value)) self.visit(stm) self.end_statement() # explicit constructor if abstract_state: self.begin_statement() self.write("explicit inline ", spec.name, "(") self.visit_args(abstract_state) self.write(") ") with self.block(): for name, t in spec.statevars: initial_value = state_exps[name] self.visit( simplify_and_optimize( SAssign( EVar(name).with_type(t), initial_value))) self.end_statement() # disable copy constructor (TODO: support this in the future?) self.begin_statement() self.write(spec.name, "(const ", spec.name, "& other) = delete;") self.end_statement() # generate methods for op in spec.methods: print("Generating method {}...".format(op.name)) self.visit(op) self.write("};\n") if spec.footer: self.write("\n", spec.footer) if not spec.footer.endswith("\n"): self.write("\n")
def visit_Spec(self, spec, state_exps, sharing, abstract_state=()): self.state_exps = state_exps self.funcs = {f.name: f for f in spec.extern_funcs} self.queries = { q.name: q for q in spec.methods if isinstance(q, Query) } self.vars = set(e.id for e in all_exps(spec) if isinstance(e, EVar)) self.setup_types(spec, state_exps, sharing) s = "" if spec.header: s += spec.header.strip() + "\n\n" if spec.docstring: s += spec.docstring + "\n" s += "public class {} implements java.io.Serializable {{\n".format( spec.name) for name, t in spec.types: self.types[t] = name # member variables for name, t in spec.statevars: s += "{}protected {};\n".format(INDENT, self.visit(t, name)) # constructor s += ("{indent}public {name}() {{\n{indent2}clear();\n{indent}}}\n\n". format(indent=INDENT, indent2=INDENT + INDENT, name=spec.name)) # explicit constructor if abstract_state: s += INDENT + "public {name}({args}) {{\n".format( name=spec.name, args=", ".join(self.visit(t, v) for (v, t) in abstract_state)) for name, t in spec.statevars: initial_value = state_exps[name] setup = self.construct_concrete(t, initial_value, EVar(name).with_type(t)) s += self.visit(setup, INDENT + INDENT) s += INDENT + "}\n" # clear s += "{}public void clear() {{\n".format(INDENT, spec.name) for name, t in spec.statevars: initial_value = state_exps[name] fvs = free_vars(initial_value) initial_value = subst( initial_value, {v.id: evaluation.construct_value(v.type) for v in fvs}) setup = self.construct_concrete(t, initial_value, EVar(name).with_type(t)) s += self.visit(setup, INDENT + INDENT) s += "{}}}\n\n".format(INDENT) # methods for op in spec.methods: s += str(self.visit(op, INDENT)) # generate auxiliary types for t, name in self.types.items(): s += self.define_type(spec.name, t, name, INDENT, sharing) s += "}\n\n" s += spec.footer if not s.endswith("\n"): s += "\n" return s
def maintenance_cost(e: Exp, op: Op, freebies: [Exp] = []): """This method calulates the result over all expressions that are EStateVar """ return ESum([ _maintenance_cost(e=x.e, op=op, freebies=freebies) for x in all_exps(e) if isinstance(x, EStateVar) ])
def visit_Spec(self, spec, state_exps, sharing, abstract_state=()): self.state_exps = state_exps self.funcs = { f.name: f for f in spec.extern_funcs } self.queries = { q.name: q for q in spec.methods if isinstance(q, Query) } self.vars = set(e.id for e in all_exps(spec) if isinstance(e, EVar)) self.setup_types(spec, state_exps, sharing) if guava.value: self.write("import com.google.common.collect.TreeMultiset;\n") self.write("import com.google.common.collect.Iterators;\n") if spec.header: self.write(spec.header.strip() + "\n\n") if spec.docstring: self.write(spec.docstring + "\n") self.write("public class {} implements java.io.Serializable ".format(spec.name)) with self.block(): for name, t in spec.types: self.types[t] = name # member variables for name, t in spec.statevars: self.write("{}protected {};\n".format(INDENT, self.visit(t, name))) # constructor self.write( "{indent}public {name}() {{\n{indent2}clear();\n{indent}}}\n\n" .format(indent=INDENT, indent2=INDENT+INDENT, name=spec.name)) # explicit constructor if abstract_state: self.begin_statement() self.write("public ", spec.name, "(") self.visit_args(abstract_state) self.write(") ") with self.block(): for name, t in spec.statevars: initial_value = state_exps[name] self.visit(simplify_and_optimize(SAssign(EVar(name).with_type(t), initial_value))) self.end_statement() # clear self.begin_statement() self.write("public void clear() ") with self.block(): for name, t in spec.statevars: initial_value = state_exps[name] fvs = free_vars(initial_value) initial_value = subst(initial_value, {v.id : evaluation.construct_value(v.type) for v in fvs}) setup = simplify_and_optimize(SAssign(EVar(name).with_type(t), initial_value)) self.visit(setup) self.end_statement() # methods for op in spec.methods: self.visit(op) # generate auxiliary types for t, name in self.types.items(): self.define_type(spec.name, t, name, sharing) self.write("\n") self.write(spec.footer) if not spec.footer.endswith("\n"): self.write("\n")
def queries_used_by(self, stm): for e in all_exps(stm): if isinstance(e, ECall) and e.func in [q.name for q in self.query_specs]: yield e.func
def max_storage_size(e, freebies: [Exp] = []): sizes = OrderedSet() for x in all_exps(e): if isinstance(x, EStateVar): sizes.add(storage_size(x.e, freebies)) return max_of(*sizes, type=INT)
def next(self): target_cost = self.cost_model.cost(self.target, RUNTIME_POOL) self.ncount += 1 while True: if self.backlog is not None: if self.stop_callback(): raise StopException() (e, pool, cost) = self.backlog improvements = list(self._possible_replacements(e, pool, cost)) if self.backlog_counter < len(improvements): i = improvements[self.backlog_counter] self.backlog_counter += 1 return i else: self.backlog = None self.backlog_counter = 0 for (e, pool) in self.builder_iter: self._on_exp(e, pool) if self.stop_callback(): raise StopException() # # Stopgap measure... long story --Calvin # bad = False # for x in all_exps(e): # if isinstance(x, EStateVar): # if any(v not in self.state_vars for v in free_vars(x.e)): # bad = True # _on_exp(e, "skipping due to illegal free vars under EStateVar") # if bad: # continue new_e = self.pre_optimize(e, pool) if preopt.value else e if new_e is not e: _on_exp(e, "preoptimized", new_e) e = new_e cost = self.cost_model.cost(e, pool) if pool == RUNTIME_POOL and (self.cost_model.is_monotonic() or hyperaggressive_culling.value) and self.compare_costs(cost, target_cost) == Cost.WORSE: _on_exp(e, "too expensive", cost, target_cost) continue fp = self._fingerprint(e) prev = list(self.seen.find_all(pool, fp)) should_add = True if not prev: _on_exp(e, "new", pool_name(pool)) elif any(alpha_equivalent(e, ee) for (ee, _, _) in prev): _on_exp(e, "duplicate") should_add = False else: better_than = None worse_than = None for prev_exp, prev_size, prev_cost in prev: self._on_cost_cmp() ordering = self.compare_costs(cost, prev_cost) assert ordering in (Cost.WORSE, Cost.BETTER, Cost.UNORDERED) if enforce_strong_progress.value and ordering != Cost.WORSE: bad = find_one(all_exps(e), lambda ee: alpha_equivalent(ee, prev_exp)) if bad: _on_exp(e, "failed strong progress requirement", bad) should_add = False break _on_exp(e, ordering, pool_name(pool), prev_exp) if ordering == Cost.UNORDERED: continue elif ordering == Cost.BETTER: better_than = (prev_exp, prev_size, prev_cost) _on_exp(prev_exp, "found better alternative", e) self.cache.evict(prev_exp, size=prev_size, pool=pool) self.seen.remove(prev_exp, pool, fp) if (self.cost_model.is_monotonic() or hyperaggressive_culling.value) and hyperaggressive_eviction.value: for (cached_e, size, p) in list(self.cache): if p != pool: continue if prev_exp in all_exps(cached_e): _on_exp(cached_e, "evicted since it contains", prev_exp) self.cache.evict(cached_e, size=size, pool=pool) else: should_add = False worse_than = (prev_exp, prev_size, prev_cost) # break if worse_than and better_than: print("Uh-oh! Strange cost relationship between") print(" (1) this exp: {}".format(pprint(e))) print(" (2) prev. A: {}".format(pprint(worse_than[0]))) print(" (2) prev. B: {}".format(pprint(better_than[0]))) print("e1 = {}".format(repr(e))) print("e2 = {}".format(repr(worse_than[0]))) print("e3 = {}".format(repr(better_than[0]))) print("(1) vs (2): {}".format(cost.compare_to(worse_than[2], self.assumptions))) print("(2) vs (3): {}".format(worse_than[2].compare_to(better_than[2], self.assumptions))) print("(3) vs (1): {}".format(better_than[2].compare_to(cost, self.assumptions))) # raise Exception("insane cost model behavior") if should_add: self.cache.add(e, pool=pool, size=self.current_size) self.seen.add(e, pool, fp, self.current_size, cost) self.last_progress = self.current_size else: continue for pr in self._possible_replacements(e, pool, cost): self.backlog = (e, pool, cost) self.backlog_counter = 1 return pr if self.last_progress < (self.current_size+1) // 2: raise NoMoreImprovements("hit termination condition") self.current_size += 1 self.builder_iter = self.builder.build(self.cache, self.current_size) if self.current_size == 0: self.builder_iter = itertools.chain(self.builder_iter, list(self.roots)) for f, ct in sorted(_fates.items(), key=lambda x: x[1], reverse=True): print(" {:6} | {}".format(ct, f)) _fates.clear() self._start_minor_it()
def visit_Spec(self, spec: Spec, state_exps: {str: Exp}, sharing, abstract_state=()): self.state_exps = state_exps self.funcs = {f.name: f for f in spec.extern_funcs} self.queries = { q.name: q for q in spec.methods if isinstance(q, Query) } self.vars = set(e.id for e in all_exps(spec) if isinstance(e, EVar)) s = "#pragma once\n" s += "#include <algorithm>\n" s += "#include <vector>\n" s += "#include <unordered_set>\n" s += "#include <string>\n" if self.use_qhash: s += "#include <QHash>\n" else: s += "#include <unordered_map>\n" if spec.header: s += "\n" + spec.header.strip() + "\n" s += "{}\nclass {} {{\n".format( ("\n" + spec.docstring) if spec.docstring else "", spec.name) s += "public:\n" self.setup_types(spec, state_exps, sharing) for t, name in self.types.items(): s += self.define_type(spec.name, t, name, INDENT, sharing) s += "protected:\n" for name, t in spec.statevars: self.statevar_name = name s += self.declare_field(name, t, indent=INDENT) s += "public:\n" # default constructor s += INDENT + "inline {name}() {{\n".format(name=spec.name) for name, t in spec.statevars: initial_value = state_exps[name] fvs = free_vars(initial_value) initial_value = subst( initial_value, {v.id: evaluation.construct_value(v.type) for v in fvs}) setup = self.construct_concrete(t, initial_value, EVar(name).with_type(t)) s += self.visit(setup, INDENT + INDENT) s += INDENT + "}\n" # explicit constructor if abstract_state: s += INDENT + "inline {name}({args}) {{\n".format( name=spec.name, args=", ".join(self.visit(t, v) for (v, t) in abstract_state)) for name, t in spec.statevars: initial_value = state_exps[name] setup = self.construct_concrete(t, initial_value, EVar(name).with_type(t)) s += self.visit(setup, INDENT + INDENT) s += INDENT + "}\n" # disable copy constructor (TODO: support this in the future?) s += INDENT + "{name}(const {name}& other) = delete;\n".format( name=spec.name) # generate methods for op in spec.methods: s += self.visit(op, INDENT) s += "};\n\n" s += spec.footer if not s.endswith("\n"): s += "\n" return s
def code(self) -> Spec: state_read_by_query = { query_name: free_vars(query) for query_name, query in self.query_impls.items() } def queries_used_by(stm): for e in all_exps(stm): if isinstance(e, ECall) and e.func in [ q.name for q in self.query_specs ]: yield e.func # prevent read-after-write by lifting reads before writes. # list of SDecls temps = defaultdict(list) updates = dict(self.updates) for operator in self.op_specs: # Compute order constraints between statements: # v1 -> v2 means that the update code for v1 should (if possible) # appear before the update code for v2 # (i.e. the update code for v1 reads v2) g = igraph.Graph().as_directed() g.add_vertices(len(self.concrete_state)) for (i, (v1, _)) in enumerate(self.concrete_state): v1_update_code = self.updates[(v1, operator.name)] v1_queries = list(queries_used_by(v1_update_code)) for (j, (v2, _)) in enumerate(self.concrete_state): # if v1_update_code reads v2... if any(v2 in state_read_by_query[q] for q in v1_queries): # then v1->v2 g.add_edges([(i, j)]) # Find the minimum set of edges we need to break (see "feedback arc # set problem") edges_to_break = safe_feedback_arc_set(g, method="ip") g.delete_edges(edges_to_break) ordered_concrete_state = [ self.concrete_state[i] for i in g.topological_sorting(mode="OUT") ] # Lift auxiliary declarations as needed things_updated = [] for v, _ in ordered_concrete_state: things_updated.append(v) stm = updates[(v, operator.name)] for e in all_exps(stm): if isinstance(e, ECall) and e.func in [ q.name for q in self.query_specs ]: problems = set(things_updated) & state_read_by_query[ e.func] if problems: name = fresh_name() temps[operator.name].append(SDecl(name, e)) stm = replace(stm, e, EVar(name).with_type(e.type)) updates[(v, operator.name)] = stm # construct new op implementations new_ops = [] for op in self.op_specs: stms = [updates[(v, op.name)] for (v, _) in ordered_concrete_state] stms.extend(hup for ((t, op_name), hup) in self.handle_updates.items() if op.name == op_name) new_stms = seq(temps[op.name] + stms) new_ops.append(Op(op.name, op.args, [], new_stms, op.docstring)) # assemble final result return Spec(self.spec.name, self.spec.types, self.spec.extern_funcs, [(v.id, e.type) for (v, e) in self.concrete_state], [], list(self.query_impls.values()) + new_ops, self.spec.header, self.spec.footer, self.spec.docstring)
def visit_Spec(self, spec : Spec, state_exps : { str : Exp }, sharing, abstract_state=()): self.state_exps = state_exps self.funcs = { f.name: f for f in spec.extern_funcs } self.queries = { q.name: q for q in spec.methods if isinstance(q, Query) } self.vars = set(e.id for e in all_exps(spec) if isinstance(e, EVar)) self.write("#pragma once\n") self.write("#include <algorithm>\n") self.write("#include <set>\n") self.write("#include <functional>\n") self.write("#include <vector>\n") self.write("#include <unordered_set>\n") self.write("#include <string>\n") if self.use_qhash: self.write("#include <QHash>\n") else: self.write("#include <unordered_map>\n") if spec.header: self.write("\n" + spec.header.strip() + "\n") self.write("{}\nclass {} {{\n".format( ("\n" + spec.docstring) if spec.docstring else "", spec.name)) self.write("public:\n") print("Setting up auxiliary types...") self.setup_types(spec, state_exps, sharing) with self.indented(): for t, name in self.types.items(): self.define_type(spec.name, t, name, sharing) self.begin_statement() if isinstance(t, THandle): # No overridden hash code! We use pointers instead. continue self.write("struct _Hash", name, " ") with self.block(): self.write_stmt("typedef ", spec.name, "::", name, " argument_type;") self.write_stmt("typedef std::size_t result_type;") self.begin_statement() self.write("result_type operator()(const argument_type& x) const noexcept ") x = EVar("x").with_type(t) if isinstance(t, TEnum): fields = [EEnumToInt(x).with_type(INT)] elif isinstance(t, TRecord): fields = [EGetField(x, f).with_type(ft) for (f, ft) in t.fields] elif isinstance(t, TTuple): fields = [ETupleGet(x, n).with_type(tt) for (n, tt) in enumerate(t.ts)] else: raise NotImplementedError(t) with self.block(): self.visit(self.compute_hash(fields)) self.end_statement() self.write(";") self.end_statement() print("Setting up member variables...") self.write("protected:\n") with self.indented(): for name, t in spec.statevars: self.statevar_name = name self.declare_field(name, t) self.write("public:\n") with self.indented(): print("Generating constructors...") # default constructor self.begin_statement() self.write("inline ", spec.name, "() ") with self.block(): for name, t in spec.statevars: initial_value = state_exps[name] fvs = free_vars(initial_value) initial_value = subst(initial_value, {v.id : evaluation.construct_value(v.type) for v in fvs}) stm = simplify_and_optimize(SAssign(EVar(name).with_type(t), initial_value)) self.visit(stm) self.end_statement() # explicit constructor if abstract_state: self.begin_statement() self.write("explicit inline ", spec.name, "(") self.visit_args(abstract_state) self.write(") ") with self.block(): for name, t in spec.statevars: initial_value = state_exps[name] self.visit(simplify_and_optimize(SAssign(EVar(name).with_type(t), initial_value))) self.end_statement() # disable copy constructor (TODO: support this in the future?) self.begin_statement() self.write(spec.name, "(const ", spec.name, "& other) = delete;") self.end_statement() # generate methods for op in spec.methods: print("Generating method {}...".format(op.name)) self.visit(op) self.write("};\n") if spec.footer: self.write("\n", spec.footer) if not spec.footer.endswith("\n"): self.write("\n")
def queries_used_by(self, stm): for e in all_exps(stm): if isinstance(e, ECall) and e.func in [q.name for q in self.query_specs]: yield e.func
def test_regression04(self): e = EBinOp(ECond(EBinOp(EUnaryOp('len', EFilter(EBinOp(EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), '+', ESingleton(ETuple((EUnaryOp('len', EMap(EFilter(EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EGetField(ETupleGet(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), 1).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))), 'important').with_type(TBool()))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TInt()), EMakeRecord((('score', EVar('score').with_type(TFloat())), ('startOffset', EVar('startOffset').with_type(TNative('int /* st */'))), ('endOffset', EVar('endOffset').with_type(TNative('int /* ed */'))), ('important', EBinOp(EBinOp(EUnaryOp('empty', EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBool()), 'or', EBinOp(EVar('score').with_type(TFloat()), '>', ECall('floatZero', ()).with_type(TFloat())).with_type(TBool())).with_type(TBool()), 'and', EBinOp(EUnaryOp('len', EMap(EFilter(EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EGetField(ETupleGet(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), 1).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))), 'important').with_type(TBool()))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TInt()), '<', ECall('MAX_TOKENS', ()).with_type(TInt())).with_type(TBool())).with_type(TBool())))).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))).with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('_var71527').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EGetField(ETupleGet(EVar('_var71527').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), 1).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))), 'important').with_type(TBool()))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TInt()), '<', ECall('MAX_TOKENS', ()).with_type(TInt())).with_type(TBool()), EMap(EBinOp(EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), '+', ESingleton(ETuple((EUnaryOp('len', EMap(EFilter(EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EGetField(ETupleGet(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), 1).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))), 'important').with_type(TBool()))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TInt()), EMakeRecord((('score', EVar('score').with_type(TFloat())), ('startOffset', EVar('startOffset').with_type(TNative('int /* st */'))), ('endOffset', EVar('endOffset').with_type(TNative('int /* ed */'))), ('important', EBinOp(EBinOp(EUnaryOp('empty', EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBool()), 'or', EBinOp(EVar('score').with_type(TFloat()), '>', ECall('floatZero', ()).with_type(TFloat())).with_type(TBool())).with_type(TBool()), 'and', EBinOp(EUnaryOp('len', EMap(EFilter(EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EGetField(ETupleGet(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), 1).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))), 'important').with_type(TBool()))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TInt()), '<', ECall('MAX_TOKENS', ()).with_type(TInt())).with_type(TBool())).with_type(TBool())))).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))).with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('_var71528').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), ETuple((ENum(0).with_type(TInt()), EMakeRecord((('score', ENum(0).with_type(TFloat())), ('startOffset', ENative(ENum(0).with_type(TInt())).with_type(TNative('int /* st */'))), ('endOffset', ENative(ENum(0).with_type(TInt())).with_type(TNative('int /* ed */'))), ('important', EBool(False).with_type(TBool())))).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))).with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), EEmptyList().with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), '-', ECond(EBinOp(EUnaryOp('len', EFilter(EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('_var71527').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EGetField(ETupleGet(EVar('_var71527').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), 1).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))), 'important').with_type(TBool()))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TInt()), '<', ECall('MAX_TOKENS', ()).with_type(TInt())).with_type(TBool()), EMap(EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('_var71528').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), ETuple((ENum(0).with_type(TInt()), EMakeRecord((('score', ENum(0).with_type(TFloat())), ('startOffset', ENative(ENum(0).with_type(TInt())).with_type(TNative('int /* st */'))), ('endOffset', ENative(ENum(0).with_type(TInt())).with_type(TNative('int /* ed */'))), ('important', EBool(False).with_type(TBool())))).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))).with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), EEmptyList().with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))) for ee in sorted(list(all_exps(e)), key=lambda x: x.size()): if isinstance(ee, ELambda): continue simplify(ee, validate=True)
def test_regression04(self): e = EBinOp(ECond(EBinOp(EUnaryOp('len', EFilter(EBinOp(EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), '+', ESingleton(ETuple((EUnaryOp('len', EMap(EFilter(EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EGetField(ETupleGet(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), 1).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))), 'important').with_type(TBool()))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TInt()), EMakeRecord((('score', EVar('score').with_type(TFloat())), ('startOffset', EVar('startOffset').with_type(TNative('int /* st */'))), ('endOffset', EVar('endOffset').with_type(TNative('int /* ed */'))), ('important', EBinOp(EBinOp(EUnaryOp('empty', EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBool()), 'or', EBinOp(EVar('score').with_type(TFloat()), '>', ECall('floatZero', ()).with_type(TFloat())).with_type(TBool())).with_type(TBool()), 'and', EBinOp(EUnaryOp('len', EMap(EFilter(EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EGetField(ETupleGet(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), 1).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))), 'important').with_type(TBool()))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TInt()), '<', ECall('MAX_TOKENS', ()).with_type(TInt())).with_type(TBool())).with_type(TBool())))).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))).with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('_var71527').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EGetField(ETupleGet(EVar('_var71527').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), 1).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))), 'important').with_type(TBool()))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TInt()), '<', ECall('MAX_TOKENS', ()).with_type(TInt())).with_type(TBool()), EMap(EBinOp(EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), '+', ESingleton(ETuple((EUnaryOp('len', EMap(EFilter(EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EGetField(ETupleGet(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), 1).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))), 'important').with_type(TBool()))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TInt()), EMakeRecord((('score', EVar('score').with_type(TFloat())), ('startOffset', EVar('startOffset').with_type(TNative('int /* st */'))), ('endOffset', EVar('endOffset').with_type(TNative('int /* ed */'))), ('important', EBinOp(EBinOp(EUnaryOp('empty', EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBool()), 'or', EBinOp(EVar('score').with_type(TFloat()), '>', ECall('floatZero', ()).with_type(TFloat())).with_type(TBool())).with_type(TBool()), 'and', EBinOp(EUnaryOp('len', EMap(EFilter(EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EGetField(ETupleGet(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), 1).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))), 'important').with_type(TBool()))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EVar('t').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TInt()), '<', ECall('MAX_TOKENS', ()).with_type(TInt())).with_type(TBool())).with_type(TBool())))).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))).with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('_var71528').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), ETuple((ENum(0).with_type(TInt()), EMakeRecord((('score', ENum(0).with_type(TFloat())), ('startOffset', ENative(ENum(0).with_type(TInt())).with_type(TNative('int /* st */'))), ('endOffset', ENative(ENum(0).with_type(TInt())).with_type(TNative('int /* ed */'))), ('important', EBool(False).with_type(TBool())))).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))).with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), EEmptyList().with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), '-', ECond(EBinOp(EUnaryOp('len', EFilter(EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('_var71527').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), EGetField(ETupleGet(EVar('_var71527').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), 1).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))), 'important').with_type(TBool()))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TInt()), '<', ECall('MAX_TOKENS', ()).with_type(TInt())).with_type(TBool()), EMap(EVar('tokens').with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), ELambda(EVar('_var71528').with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))), ETuple((ENum(0).with_type(TInt()), EMakeRecord((('score', ENum(0).with_type(TFloat())), ('startOffset', ENative(ENum(0).with_type(TInt())).with_type(TNative('int /* st */'))), ('endOffset', ENative(ENum(0).with_type(TInt())).with_type(TNative('int /* ed */'))), ('important', EBool(False).with_type(TBool())))).with_type(TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))).with_type(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))), EEmptyList().with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool())))))))).with_type(TBag(TTuple((TInt(), TRecord((('score', TFloat()), ('startOffset', TNative('int /* st */')), ('endOffset', TNative('int /* ed */')), ('important', TBool()))))))) for ee in sorted(list(all_exps(e)), key=lambda x: x.size()): if isinstance(ee, ELambda): continue simplify(ee, validate=True)