def _code_map(state: PushState) -> PushState: if state["exec"].is_empty() or state["code"].is_empty(): return Token.revert e = state["exec"].pop() c = state["code"].pop() if not isinstance(c, CodeBlock): c = CodeBlock(c) else: c = c.copy() l1 = [CodeBlock(JitInstructionRef("code_from_exec"), item, e) for item in c] l2 = [JitInstructionRef("code_combine") for _ in c[1:]] state["exec"].push(CodeBlock.from_list(l1 + [JitInstructionRef("code_wrap")] + l2)) return state
def _code_combine(a: Atom, b: Atom) -> Tuple[CodeBlock]: if isinstance(a, CodeBlock) and isinstance(b, CodeBlock): return CodeBlock.from_list(list(b.copy()) + list(a.copy())), elif isinstance(b, CodeBlock): result = b.copy() result.append(a) return result, elif isinstance(a, CodeBlock): result = a.copy() result.append(b) return result, else: return CodeBlock(a, b),
def _code_combine(a: Atom, b: Atom) -> Tuple[CodeBlock]: if isinstance(a, CodeBlock) and isinstance(b, CodeBlock): return CodeBlock.from_list(list(b.copy()) + list(a.copy())), elif isinstance(b, CodeBlock): result = b.copy() result.append(a) return result, elif isinstance(a, CodeBlock): result = a.copy() result.append(b) return result, else: return CodeBlock(a, b),
def _code_map(state: PushState) -> PushState: if state["exec"].is_empty() or state["code"].is_empty(): return Token.revert e = state["exec"].pop() c = state["code"].pop() if not isinstance(c, CodeBlock): c = CodeBlock(c) else: c = c.copy() l1 = [ CodeBlock(JitInstructionRef("code_from_exec"), item, e) for item in c ] l2 = [JitInstructionRef("code_combine") for _ in c[1:]] state["exec"].push( CodeBlock.from_list(l1 + [JitInstructionRef("code_wrap")] + l2)) return state
def to_code_block(self) -> CodeBlock: """Translate into nested CodeBlocks. These CodeBlocks can be considered the Push program representation of the Genome which can be executed by a PushInterpreter and evaluated by an Evaluator. """ plushy_buffer = [] for atom in self: plushy_buffer.append(atom) if isinstance(atom, Instruction) and atom.code_blocks > 0: plushy_buffer.append(Opener(atom.code_blocks)) push_buffer = [] while True: # If done with plush but unclosed opens, recur with one more close. if len(plushy_buffer) == 0 and _has_opener(push_buffer): plushy_buffer.append(Closer()) # If done with plush and all opens closed, return push. elif len(plushy_buffer) == 0: return CodeBlock.from_list(push_buffer) else: atom = plushy_buffer[0] # If next instruction is a close, and there is an open. if isinstance(atom, Closer) and _has_opener(push_buffer): ndx, opener = [(ndx, el) for ndx, el in enumerate(push_buffer) if isinstance(el, Opener)][-1] post_open = push_buffer[ndx + 1:] pre_open = push_buffer[:ndx] if opener.count == 1: push_buffer = pre_open + [post_open] else: opener.dec() push_buffer = pre_open + [post_open, opener] # If next instruction is a close, and there is no open. elif not isinstance(atom, Closer): push_buffer.append(atom) del plushy_buffer[0]
def to_code_block(self) -> CodeBlock: """Translate into nested CodeBlocks. These CodeBlocks can be considered the Push program representation of the Genome which can be executed by a PushInterpreter and evaluated by an Evaluator. """ plushy_buffer = [] for atom in self: plushy_buffer.append(atom) if isinstance(atom, Instruction) and atom.code_blocks > 0: plushy_buffer.append(Opener(atom.code_blocks)) push_buffer = [] while True: # If done with plush but unclosed opens, recur with one more close. if len(plushy_buffer) == 0 and _has_opener(push_buffer): plushy_buffer.append(Closer()) # If done with plush and all opens closed, return push. elif len(plushy_buffer) == 0: return CodeBlock.from_list(push_buffer) else: atom = plushy_buffer[0] # If next instruction is a close, and there is an open. if isinstance(atom, Closer) and _has_opener(push_buffer): ndx, opener = [(ndx, el) for ndx, el in enumerate(push_buffer) if isinstance(el, Opener)][-1] post_open = push_buffer[ndx + 1:] pre_open = push_buffer[:ndx] if opener.count == 1: push_buffer = pre_open + [post_open] else: opener.dec() push_buffer = pre_open + [post_open, opener] # If next instruction is a close, and there is no open. elif not isinstance(atom, Closer): push_buffer.append(atom) del plushy_buffer[0]
def test_load_program(self, state: PushState, atoms): prog = CodeBlock.from_list([atoms["5"], atoms["5"], atoms["add"]]) state.load_program(prog) assert state.size() == 1 assert len(state["exec"].top()) == 3
def test_genome_bad_init(self, atoms): with pytest.raises(ValueError): Genome(CodeBlock.from_list([atoms["5"], [atoms["5"], atoms["add"]]]))
def test_set_program(self, unevaluated_individual): with pytest.raises(AttributeError): unevaluated_individual.program = CodeBlock.from_list([])
def _code_but_last(x) -> Tuple[Atom]: if isinstance(x, CodeBlock) and len(x) > 1: return CodeBlock.from_list(x[:-1]), return Token.revert
def simple_program(atoms): return CodeBlock.from_list([atoms["5"], atoms["5"], atoms["add"]])
def _code_but_last(x) -> Tuple[Atom]: if isinstance(x, CodeBlock) and len(x) > 1: return CodeBlock.from_list(x[:-1]), return Token.revert
def _code_reverse(code): if not isinstance(code, CodeBlock): return code, return CodeBlock.from_list(list(code[::-1])),
def test_genome_bad_init(self, atoms): with pytest.raises(ValueError): Genome( CodeBlock.from_list([atoms["5"], [atoms["5"], atoms["add"]]]))
def _code_reverse(code): if not isinstance(code, CodeBlock): return code, return CodeBlock.from_list(list(code[::-1])),
def test_load_program(self, state: PushState, atoms): prog = CodeBlock.from_list([atoms["5"], atoms["5"], atoms["add"]]) state.load_program(prog) assert state.size() == 1 assert len(state["exec"].top()) == 3
def test_set_program(self, unevaluated_individual): with pytest.raises(AttributeError): unevaluated_individual.program = CodeBlock.from_list([])