Ejemplo n.º 1
0
    def _compute_remove_num_envs(self, ast, new_vars, sub_env_structure):
        from pycket import config
        if not config.prune_env:
            remove_num_envs = [0] * (len(ast.rhss) + 1)
            env_structures = [sub_env_structure.prev] * len(ast.rhss)
            env_structures.append(sub_env_structure)
            return ast, sub_env_structure, env_structures, remove_num_envs

        # find out whether a smaller environment is sufficient for the body
        free_vars_not_from_let = compute_body_frees(ast, self.free_vars_cache)
        free_vars_not_from_let = free_vars_not_from_let.without_many(
            ast.args.elems)

        # at most, we can remove all envs, apart from the one introduced by let
        curr_remove = max_depth = sub_env_structure.depth_and_size()[0] - 1
        max_needed = 0
        free_vars_not_mutated = True
        for v in free_vars_not_from_let:
            depth = sub_env_structure.depth_of_var(v)[1] - 1
            curr_remove = min(curr_remove, depth)
            max_needed = max(max_needed, depth)
            free_vars_not_mutated &= LexicalVar(v) not in new_vars

        if curr_remove == 0:
            body_env_structure = sub_env_structure
        else:
            next_structure = sub_env_structure.prev.drop_frames(curr_remove)
            body_env_structure = SymList(ast.args.elems, next_structure)

        if (free_vars_not_mutated and max_needed == curr_remove
                and max_depth > max_needed):
            before_max_needed = sub_env_structure.drop_frames(max_needed + 2)
            if before_max_needed and before_max_needed.depth_and_size()[1] > 0:
                counts, new_lhs_vars, new_rhss = self._copy_live_vars(
                    ast, free_vars_not_from_let)
                body_env_structure = SymList(new_lhs_vars)
                sub_env_structure = SymList(new_lhs_vars,
                                            sub_env_structure.prev)
                ast = Let(body_env_structure, counts, new_rhss, ast.body)
                return self._compute_remove_num_envs(ast, new_vars,
                                                     sub_env_structure)

        # The loops will modify all but the last element
        remove_num_envs = [curr_remove] * (len(ast.rhss) + 1)
        env_structures = [body_env_structure] * (len(ast.rhss) + 1)
        for i in range(len(ast.rhss) - 1, -1, -1):
            free_vars = ast.rhss[i].free_vars(self.free_vars_cache)
            for v in free_vars:
                var_depth = sub_env_structure.prev.depth_of_var(v)[1]
                curr_remove = min(curr_remove, var_depth)
            env_structures[i] = sub_env_structure.drop_frames(curr_remove + 1)
            remove_num_envs[i] = curr_remove
        return ast, sub_env_structure, env_structures, remove_num_envs
Ejemplo n.º 2
0
    def _compute_remove_num_envs(self, ast, new_vars, sub_env_structure):
        from pycket import config
        if not config.prune_env:
            remove_num_envs = [0] * (len(ast.rhss) + 1)
            env_structures = [sub_env_structure.prev] * len(ast.rhss)
            env_structures.append(sub_env_structure)
            return ast, sub_env_structure, env_structures, remove_num_envs

        # find out whether a smaller environment is sufficient for the body
        free_vars_not_from_let = compute_body_frees(ast)
        free_vars_not_from_let = free_vars_not_from_let.without_many(
                ast.args.elems)

        # at most, we can remove all envs, apart from the one introduced by let
        curr_remove = max_depth = sub_env_structure.depth_and_size()[0] - 1
        max_needed = 0
        free_vars_not_mutated = True
        for v in free_vars_not_from_let:
            depth = sub_env_structure.depth_of_var(v)[1] - 1
            curr_remove = min(curr_remove, depth)
            max_needed = max(max_needed, depth)
            free_vars_not_mutated &= LexicalVar(v) not in new_vars

        if curr_remove == 0:
            body_env_structure = sub_env_structure
        else:
            next_structure = sub_env_structure.prev.drop_frames(curr_remove)
            body_env_structure = SymList(ast.args.elems, next_structure)

        if (free_vars_not_mutated and max_needed == curr_remove and
                max_depth > max_needed):
            before_max_needed = sub_env_structure.drop_frames(max_needed + 2)
            if before_max_needed and before_max_needed.depth_and_size()[1] > 0:
                counts, new_lhs_vars, new_rhss = self._copy_live_vars(
                        ast, free_vars_not_from_let)
                body_env_structure = SymList(new_lhs_vars)
                sub_env_structure = SymList(new_lhs_vars, sub_env_structure.prev)
                ast = Let(body_env_structure, counts, new_rhss, ast.body)
                return self._compute_remove_num_envs(ast, new_vars, sub_env_structure)

        # The loops will modify all but the last element
        remove_num_envs = [curr_remove] * (len(ast.rhss) + 1)
        env_structures = [body_env_structure] * (len(ast.rhss) + 1)
        for i in range(len(ast.rhss) - 1, -1, -1):
            free_vars = ast.rhss[i].free_vars()
            for v in free_vars:
                var_depth = sub_env_structure.prev.depth_of_var(v)[1]
                curr_remove = min(curr_remove, var_depth)
            env_structures[i] = sub_env_structure.drop_frames(curr_remove + 1)
            remove_num_envs[i] = curr_remove
        return ast, sub_env_structure, env_structures, remove_num_envs
Ejemplo n.º 3
0
def test_cont_fusion():
    from pycket.env import SymList, ToplevelEnv
    from pycket.interpreter import (
        LetCont,
        BeginCont,
        FusedLet0Let0Cont,
        FusedLet0BeginCont,
    )
    from pycket.config import get_testing_config
    args = SymList([])
    counts = [1]
    rhss = 1
    letast1 = Let(args, counts, [1], [2])
    letast2 = Let(args, counts, [1], [2])
    env = ToplevelEnv(get_testing_config(**{"pycket.fuse_conts": True}))
    prev = object()
    let2 = LetCont.make([], letast2, 0, env, prev)
    let1 = LetCont.make([], letast1, 0, env, let2)
    assert isinstance(let1, FusedLet0Let0Cont)
    assert let1.prev is prev
    assert let1.env is env

    let2 = BeginCont(letast2.counting_asts[0], env, prev)
    let1 = LetCont.make([], letast1, 0, env, let2)
    assert isinstance(let1, FusedLet0BeginCont)
    assert let1.prev is prev
    assert let1.env is env
Ejemplo n.º 4
0
    def visit_let(self, ast, vars, env_structure):
        assert isinstance(ast, Let)
        sub_env_structure = SymList(ast.args.elems, env_structure)
        local_muts = self.body_muts(ast)
        new_vars = vars.copy()
        new_vars.update(local_muts)
        ast, sub_env_structure, env_structures, remove_num_envs = self._compute_remove_num_envs(
            ast, new_vars, sub_env_structure)

        new_rhss = [None] * len(ast.rhss)
        offset = 0
        variables = ast.args.elems
        need_cell_flags = [False] * len(ast.args.elems)
        for i, rhs in enumerate(ast.rhss):
            count = ast.counts[i]
            for j in range(count):
                var = variables[offset + j]
                need_cell_flags[offset + j] = LexicalVar(var) in local_muts
            new_rhss[i] = rhs.visit(self, vars, env_structures[i])
            offset += count

        body_env_structure = env_structures[-1]
        body_env_structures, body_remove_num_envs = self._visit_sequenced_body(
            ast, vars, body_env_structure)

        new_body = [
            b.visit(self, new_vars, body_env_structures[i])
            for i, b in enumerate(ast.body)
        ]
        result = Let(sub_env_structure, ast.counts, new_rhss, new_body,
                     remove_num_envs)
        result.init_body_pruning(body_env_structure, body_remove_num_envs)
        result.init_mutable_var_flags(need_cell_flags)
        return result
Ejemplo n.º 5
0
    def visit_letrec(self, ast, vars, env_structure):
        assert isinstance(ast, Letrec)
        local_muts = self.body_muts(ast)
        for b in ast.rhss:
            local_muts.update(b.mutated_vars(self.mutated_vars_cache))
        for v in ast.args.elems:
            lv = LexicalVar(v)
            local_muts[lv] = None
        new_vars = vars.copy()
        new_vars.update(local_muts)
        sub_env_structure = SymList(ast.args.elems, env_structure)
        new_rhss = [
            rhs.visit(self, new_vars, sub_env_structure) for rhs in ast.rhss
        ]

        body_env_structures, body_remove_num_envs = self._visit_sequenced_body(
            ast, new_vars, sub_env_structure)

        new_body = [
            b.visit(self, new_vars, body_env_structures[i])
            for i, b in enumerate(ast.body)
        ]
        letrec = Letrec(sub_env_structure, ast.counts, new_rhss, new_body)
        letrec.init_body_pruning(sub_env_structure, body_remove_num_envs)
        return letrec
Ejemplo n.º 6
0
def test_symlist_depth():
    from pycket.env import SymList
    s = SymList([1, 2, 3, 4], SymList([], None))
    assert s.depth_and_size() == (2, 4)
Ejemplo n.º 7
0
def test_symlist_depth():
    from pycket.env import SymList
    s = SymList([1, 2, 3, 4], SymList([], None))
    assert s.depth_and_size() == (2, 4)