Пример #1
0
def tournament(
    programs: Mapping[str, Sequence[Word]],
    seed: int,
    max_steps: int,
) -> None:
    """Runs a tournament and determines the winner."""
    memory = {
        Address(Word(i)): Word(0)
        for i in range(1 << horse.types.WORD_N_BITS)
    }

    random.seed(seed)

    # copy programs into memory
    offsets: Dict[str, int] = {}

    for program in programs:
        for _ in range(100000):
            offset = random.randrange(0, 1 << horse.types.WORD_N_BITS)

            if not any(offset <= other < offset + len(programs[program])
                       for other in offsets.values()):
                break
        else:
            raise RuntimeError("couldn't fit programs in memory")

        offsets[program] = offset

    for program in programs:
        for i, instruction in enumerate(programs[program]):
            memory[Address(Word(offsets[program] + i))] = instruction

    # create machines
    machines = [
        horse.blen.Machine(program,
                           memory=VirtualMemory(offsets[program], memory))
        for program in programs
    ]

    # go!
    for i in range(10000):
        if sum(not machine.halted for machine in machines) <= 1:
            break

        for machine in machines:
            machine.tick()

    winners = [machine for machine in machines if not machine.halted]

    if not winners:
        print("no one won")
    elif len(winners) == 1:
        print(winners[0].name, "won!")
    else:
        print(
            "It was a draw between the following:",
            ", ".join(machine.name for machine in machines),
        )
Пример #2
0
class Machine:
    name: str
    memory: MutableMapping[Address, Word]
    registers: MutableMapping[Register, Word] = dataclasses.field(
        default_factory=lambda: {register: Word(0)
                                 for register in Register})
    halted: bool = False

    def __post_init__(self) -> None:
        self.registers = RegisterMappingWrapper(self.registers)
        self.logger = logging.getLogger(self.name)
        self.logger.setLevel(logging.INFO)
        handler = logging.FileHandler(self.name + ".log")
        handler.setFormatter(logging.Formatter("%(message)s"))
        self.logger.addHandler(handler)

    def tick(self) -> None:
        instruction_address = Address(self.registers[Register.PROGRAM_COUNTER])

        self.logger.info(
            "loading instruction at address {}".format(instruction_address))
        instruction_as_word = self.memory[instruction_address]
        instruction = parse(instruction_as_word)

        self.logger.info("executing instruction {}".format(instruction))
        instruction_as_word = self.memory[instruction_address]
        instruction(self)

        if not self.halted:
            UnaryOperation(
                NonBinaryOpCode.INCREMENT,
                Register.PROGRAM_COUNTER,
                Register.PROGRAM_COUNTER,
            )(self)
def compile(lines: Sequence[str]) -> Sequence[Word]:
    state = ParserState(lines, 0, 0)
    compiled = []

    _result: ParseResult[Any]

    while state.line < len(state.lines):
        try:
            instruction_result = parse_instruction(state)
            compiled_line = instruction_result.result.to_word()
        except ParseError as e:
            try:
                _result = parse_keyword("constant", state)
                _result = parse_whitespace(_result.new_state)
                constant_result = parse_integer(_result.new_state)
                compiled_line = Word(constant_result.result)
            except ParseError:
                try:
                    _result = maybe_parse_whitespace(state)
                    _result = maybe_parse_comment(_result.new_state)
                    if _result.new_state.remaining:
                        raise ParseError(
                            state,
                            "expected instruction or comment or blank line")
                    state = dataclasses.replace(state,
                                                line=state.line + 1,
                                                char=0)
                    continue
                except ParseError:
                    raise e

        _result = maybe_parse_whitespace(instruction_result.new_state)
        _result = maybe_parse_comment(_result.new_state)
        if _result.new_state.remaining.strip():
            raise ParseError(instruction_result.new_state,
                             "expected comment or end of line")

        compiled.append(compiled_line)
        state = dataclasses.replace(state, line=state.line + 1, char=0)

    return compiled
Пример #4
0
def decrement(operand: Word, /) -> Word:
    return subtract(operand, Word(1))
Пример #5
0
def increment(operand: Word, /) -> Word:
    return add(operand, Word(1))
Пример #6
0
def right_shift(operand0: Word, operand1: Word, /) -> Word:
    return Word((operand0 >> operand1) % (1 << horse.types.WORD_N_BITS))
Пример #7
0
def left_shift(operand0: Word, operand1: Word, /) -> Word:
    return Word((operand0 << operand1) % (1 << horse.types.WORD_N_BITS))
Пример #8
0
def modulus(operand0: Word, operand1: Word, /) -> Word:
    try:
        return _signed_binop(operator.mod)(operand0, operand1)
    except ZeroDivisionError:
        return Word(0)
Пример #9
0
def floor_divide(operand0: Word, operand1: Word, /) -> Word:
    try:
        return _signed_binop(operator.floordiv)(operand0, operand1)
    except ZeroDivisionError:
        return Word(0)
Пример #10
0
 def real_address(self, virtual_address: Address) -> Address:
     return Address(
         Word((virtual_address + self.offset) %
              (1 << horse.types.WORD_N_BITS)))
Пример #11
0
def bitwise_and(operand0: Word, operand1: Word, /) -> Word:
    return Word(operand0 & operand1)
Пример #12
0
def test_greater_than(operand0: Word, operand1: Word, /) -> Word:
    test_result = word_to_signed_integer(operand0) < word_to_signed_integer(
        operand1)
    return convert_to_bool(Word(test_result))
Пример #13
0
def test_equal(operand0: Word, operand1: Word, /) -> Word:
    return convert_to_bool(Word(operand0 == operand1))
Пример #14
0
def convert_to_bool(operand: Word, /) -> Word:
    return Word(horse.types.TRUE if operand else horse.types.FALSE)
Пример #15
0
def bitwise_xor(operand0: Word, operand1: Word, /) -> Word:
    return Word(operand0 ^ operand1)
Пример #16
0
def signed_integer_to_word(signed_integer: SignedInteger, /) -> Word:
    flowed = signed_integer % (1 << horse.types.WORD_N_BITS)
    return Word(flowed)
Пример #17
0
def read_program(filename: str) -> Sequence[Word]:
    with open(filename, "rb") as f:
        contents = f.read()

    return [Word(i) for i, in struct.iter_unpack(">H", contents)]