示例#1
0
 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!")
示例#2
0
文件: typecheck.py 项目: uwplse/cozy
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
示例#3
0
 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")
示例#4
0
 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
示例#5
0
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)
示例#6
0
文件: impls.py 项目: uwplse/cozy
 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
示例#7
0
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
示例#8
0
文件: impls.py 项目: sanidhya/cozy
    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]
示例#9
0
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
示例#10
0
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
示例#11
0
    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")
示例#12
0
    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
示例#13
0
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)
    ])
示例#14
0
文件: java.py 项目: wcphkust/cozy
    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")
示例#15
0
文件: impls.py 项目: uwplse/cozy
 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
示例#16
0
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)
示例#17
0
    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()
示例#18
0
文件: cxx.py 项目: sanidhya/cozy
    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
示例#19
0
文件: impls.py 项目: sanidhya/cozy
    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)
示例#20
0
文件: cxx.py 项目: uwplse/cozy
    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")
示例#21
0
 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
示例#22
0
 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)
示例#23
0
 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)