Exemple #1
0
 def write(self, ptr, instruction=None, **kwargs):
     data = cvar(dict)
     old_instruction = cvar(object)
     if STRICT and not isinstance(ptr, int):
         raise ValueError('Pointer must be an integer, not %r' % ptr)
     ptr %= self.size
     if instruction is not None:
         if not isinstance(instruction, Instruction):
             raise TypeError('The instruction parameter must be an '
                     'Instruction instance')
         if STRICT and kwargs != {}:
             raise ValueError('Cannot supply extra attribute if '
                     'instruction is given')
         with self._lock:
             old_instruction = self._memory[ptr]
             self._memory[ptr] = instruction
         for callback in self._callbacks:
             callback(ptr, old_instruction, instruction)
     else:
         for key in kwargs:
             if key not in SYNTAX.data_blocks:
                 raise ValueError('%r is not a valid data block.')
         data = self.read(ptr).as_dict
         data.update(kwargs)
         self.write(ptr, Instruction(**data))
Exemple #2
0
    def _read(self, memory, ptr):
        """Return input data of the instruction, based on modifiers.

        Data with None should _never_ be read."""
        m = cvar(str)
        A = cvar(object)
        B = cvar(object)

        m = self.modifier
        A = memory.read(memory.get_absolute_ptr(ptr, self.A))
        B = memory.read(memory.get_absolute_ptr(ptr, self.B))
        if m == 'A':
            return ((None, None, A.A, None), (None, None, B.A, None))
        elif m == 'B':
            return ((None, None, A.B, None), (None, None, B.B, None))
        elif m == 'AB':
            return ((None, None, A.A, None), (None, None, B.B, None))
        elif m == 'BA':
            return ((None, None, A.B, None), (None, None, B.A, None))
        elif m == 'F':
            return ((None, None, A.A, A.B ), (None, None, B.A, B.B ))
        elif m == 'X':
            return ((None, None, A.A, A.B ), (None, None, B.B, B.A ))
        elif m == 'I':
            return (A.as_tuple, B.as_tuple)
        else:
            assert False
Exemple #3
0
    def _math(self, A, B, function):
        "Shortcut for running math operations."
        res1 = cvar(str)
        res2 = cvar(str)

        assert None not in (A[2], B[2])
        res1 = B[2][0]+str(function(get_int(A[2]), get_int(B[2])))
        res2 = None
        if A[3] is not None:
            assert B[3] is not None
            res2 = B[3][0]+str(function(get_int(A[3]), get_int(B[3])))
        return (B[0], B[1], res1, res2)
Exemple #4
0
    def _write(self, memory, dest, inst):
        """Writes data to the memory"""
        m = cvar(str)

        m = self.modifier
        if isinstance(inst, tuple):
            if m != 'I':
                # Add an opcode if needed, so it passes sanity checks
                inst = (inst[0] or 'DAT', inst[1], inst[2], inst[3])
            inst = Instruction.from_tuple(inst)
        elif STRICT and not isinstance(inst, Instruction):
            raise ValueError('You can only write tuples and instructions, '
                    'not %r' % inst)
        if STRICT and not isinstance(dest, int):
            raise ValueError('Destination must be an int, not %r.' % dest)

        if m == 'A':
            memory.write(dest, A=inst.A)
        elif m == 'B':
            memory.write(dest, B=inst.A)
        elif m == 'AB':
            memory.write(dest, B=inst.A)
        elif m == 'BA':
            memory.write(dest, A=inst.A)
        elif m == 'F':
            memory.write(dest, A=inst.A, B=inst.B)
        elif m == 'X':
            memory.write(dest, B=inst.B, A=inst.A)
        elif m == 'I':
            memory.write(dest, instruction=inst)
        else:
            assert False
Exemple #5
0
    def _increment(self, memory, ptr, field):
        "Shortcut for incrementing fields."
        inst = cvar(object)

        inst = memory.read(ptr + get_int(field))
        if field.startswith('}'):
            inst.A = inst.A[0] + str(int(inst.A[1:])+1)
        elif field.startswith('>'):
            inst.B = inst.B[0] + str(int(inst.B[1:])+1)
Exemple #6
0
    def run(self, memory, ptr):
        oc = cvar(str)
        dest = cvar(int)
        A = cvar(object)
        B = cvar(object)
        threads = cvar(list)

        assert memory.read(ptr) == self

        # Predecrement
        for field in (self.A, self.B):
            inst = memory.read(ptr + get_int(field))
            if field.startswith('{'):
                inst.A = inst.A[0] + str(int(inst.A[1:])-1)
            elif field.startswith('<'):
                inst.B = inst.B[0] + str(int(inst.B[1:])-1)

        oc = self.opcode

        # Postincrement
        # The order matters: http://www.koth.org/info/icws94.html#5.3.5
        self._increment(memory, ptr, self.A)
        dest = memory.get_absolute_ptr(ptr, self.B)
        self._increment(memory, ptr, self.B)
        A, B = self._read(memory, ptr)

        if oc == 'DAT':
            threads = []
        elif oc == 'NOP':
            threads = [ptr+1]
        elif oc == 'MOV':
            self._write(memory, dest, A)
            threads = [ptr+1]
        elif oc == 'ADD':
            self._write(memory, dest, self._math(A, B, lambda a,b:a+b))
            threads = [ptr+1]
        elif oc == 'SUB':
            self._write(memory, dest, self._math(A, B, lambda a,b:b-a))
            threads = [ptr+1]
        elif oc == 'MUL':
            self._write(memory, dest, self._math(A, B, lambda a,b:a*b))
            threads = [ptr+1]
        elif oc == 'DIV':
            try:
                self._write(memory, dest, self._math(A, B, lambda a,b:int(b/a)))
                threads = [ptr+1]
            except ZeroDivisionError:
                threads = []
        elif oc == 'MOD':
            try:
                self._write(memory, dest, self._math(A, B, lambda a,b:b%a))
                threads = [ptr+1]
            except ZeroDivisionError:
                threads = []
        elif oc == 'JMP':
            # Note that the modifier is ignored
            threads = [memory.get_absolute_ptr(ptr, self.A)]
        elif oc == 'JMZ':
            if get_int(B[2]) == 0 and \
                    (B[3] is None or get_int(B[3]) == 0):
                threads = [memory.get_absolute_ptr(ptr, self.A)]
            else:
                threads = [ptr+1]
        elif oc == 'JMN':
            if get_int(B[2]) == 0 and \
                    (B[3] is None or get_int(B[3]) == 0):
                threads = [ptr+1]
            else:
                threads = [memory.get_absolute_ptr(ptr, self.A)]
        elif oc == 'DJN':
            self.B = self.B[0] + str(get_int(self.B)-1)
            ptrB = memory.get_absolute_ptr(ptr, self.B)
            B = self._read(memory, ptrB)[1] # Load the new pointed data

            # Jump
            if get_int(B[2]) == 0 and \
                    (B[3] is None or get_int(B[3]) == 0):
                threads = [ptr+1]
            else:
                threads = [memory.get_absolute_ptr(ptr, self.A)]
        elif oc == 'CMP' or oc == 'SEQ':
            if A == B:
                threads = [ptr+2]
            else:
                threads = [ptr+1]
        elif oc == 'SLT':
            if get_int(A[2]) < get_int(B[2]) and \
                    (A[3] is None or A[3] < B[3]):
                threads = [ptr+2]
            else:
                threads = [ptr+1]
        elif oc == 'SPL':
            threads = [ptr+1, ptr+get_int(self.A)]
        else:
            raise NotImplementedError()

        return threads