Exemple #1
0
 def operation_substract(self, target, operands):
     x, y = operands
     if is_number(x):
         # t := 1 - 1
         if is_number(y):
             if x - y > 0:
                 self.parse('GENERATE n', n=x - y)
             else:
                 self.parse('ZERO')
         # t := 1 - a
         # t := 1 - a[x]
         elif is_variable(y):
             self.parse('GENERATE n', n=x)
             self.parse('SUB a', a=y)
     elif is_variable(x):
         # t := a - 1
         if is_number(y):
             if y == 0:
                 self.parse('LOAD a', a=x)
             elif y == 1:
                 self.parse('LOAD a', a=x)
                 self.parse('DEC')
             else:
                 self.parse('GENERATE n', n=y)
                 self.parse('STORE a', a=Reg.r0)
                 self.parse('LOAD x', x=x)
                 self.parse('SUB a', a=Reg.r0)
         # t := a - b
         # t := a - b[x]
         elif is_variable(y):
             self.parse('LOAD a', a=x)
             self.parse('SUB a', a=y)
         else:
             raise CompilerError("Unexpected symbol")
     self.parse('STORE a', a=target)
 def check_expression(self, cmd):
     _, *expression = cmd
     if len(expression) == 1:
         [var] = expression
         if is_variable(var):
             self.check_variable(var)
             self.check_initialized(var)
     elif len(expression) == 3:
         [_, l_var, r_var] = expression
         for var in [l_var, r_var]:
             if is_variable(var):
                 self.check_variable(var)
                 self.check_initialized(var)
     else:
         raise CompilerError("Unexpected expression")
Exemple #3
0
    def comp_gt(self, cond, label):
        left, _, right = cond
        code = ""

        if is_number(left) and is_number(right):
            if left > right:
                self.parse('JUMP @label', label=label)
                return

        if is_number(left) and left == 0:
            return

        if is_number(right):
            if right == 0:
                code = """
                JZERO #FALSE
                JUMP @label
                #FALSE:
                """
                self.parse(code, label=label)
                return

        if is_number(right):
            code += """
            GENERATE r_val
            STORE right
            """
        if is_number(left):
            code += """
            GENERATE l_val
            """
        else:
            code += """
            LOAD left
            """
        code += """
        SUB right
        JZERO #FALSE
        JUMP @label
        #FALSE:
        """

        self.parse(code,
                   l_val=left,
                   r_val=right,
                   left=left if is_variable(left) else Reg.r0,
                   right=right if is_variable(right) else Reg.r1,
                   label=label)
Exemple #4
0
    def operation_add(self, target, operands):
        x, y = operands

        if is_array(x) and is_array(y):
            pass

        if is_number(x):
            if is_number(y):
                self.parse('GENERATE n', n=x + y)
                self.parse('STORE t', t=target)
                return
            else:
                x, y = y, x

        # t := a + 1
        if is_number(y):
            if y == 0:
                self.parse('LOAD x', x=x)
            elif y == 1:
                self.parse('LOAD x', x=x)
                self.parse('INC')
            else:
                self.parse('GENERATE n', n=y)
                self.parse('ADD x', x=x)
        # t := a + b
        # t := a + b[x]
        elif is_variable(y):
            self.parse('LOAD x', x=x)
            self.parse('ADD y', y=y)
        else:
            raise CompilerError("Unexpected symbol")

        self.parse('STORE a', a=target)
Exemple #5
0
    def assign_mul(self, trg_iden, left, right):
        res_reg = 4
        l_reg = self.loaddd(left, 2)
        r_reg = self.loaddd(right, 3)
        code = '''
        SUB     {res}   {res}
        JZERO   {r}     ${end}
        JODD	{l}	    ${add}
        JUMP	${half}
        ADD	    {res}	{r}
        HALF	{l}
        ADD     {r}     {r}
        JUMP	${jzero}
        '''.format(res=res_reg,
                   r=r_reg,
                   l=l_reg,
                   add=2,
                   half=2,
                   end=7,
                   jzero=(-6))
        self.push(code)

        if is_arr(trg_iden):
            self.store_arr(trg_iden, res_reg)
        elif is_variable(trg_iden):
            self.store_var(trg_iden, res_reg)
Exemple #6
0
 def gen_write(self, node):
     _, iden = node
     if is_variable(iden):
         self.write_variable(iden)
     elif is_number(iden):
         self.write_number(iden)
     elif is_arr(iden):
         self.write_arr(iden)
    def check_for_up(self, cmd):
        _, iterator, start, end, cmds = cmd

        for el in [v for v in [start, end] if is_variable(v)]:
            if is_variable(el):
                self.check_variable(el)
                self.check_initialized(el)

        self.check_iterator(iterator)
        _, iter_symbol, iter_lineno = iterator

        self.add_iterator(iter_symbol)
        self.initialized[iter_symbol] = True

        self.analyze(cmds)

        self.initialized[iter_symbol] = False
        self.remove_from_scope(iter_symbol)
Exemple #8
0
 def loadd(self, var):
     if is_number(var):
         reg = self.get_free_reg()
         self.gen_number(var, reg)
         return reg
     elif is_variable(var):
         reg = self.check_in_regs(var[1])
         if not reg:
             reg = self.load(var)
         return reg
Exemple #9
0
    def reserve_memory(self, symtab):
        for iden in symtab:
            if is_variable(iden):
                self.memory[iden[1]] = self.mem_id
                self.mem_id += 1

        for iden in symtab:
            if is_arr(iden):
                self.memory[iden[1]] = self.mem_id
                self.mem_id += iden[3] - iden[2] + 1
Exemple #10
0
 def load(self, iden):
     if is_variable(iden):
         pos_in_mem = self.memory[iden[1]]
         self.gen_number(pos_in_mem)
         dst_reg = self.get_reg(iden[1])
         self.push('LOAD reg', reg=dst_reg)
         self.regs[dst_reg] = iden[1]
         return dst_reg
     else:
         pass
Exemple #11
0
    def loaddd(self, iden, trg_reg):
        if is_number(iden):
            self.gen_number(iden, trg_reg)
            return trg_reg
        elif is_variable(iden):
            iden_reg = self.check_in_regs(iden[1])
            if not iden_reg:
                iden_mem_id = self.memory[iden[1]]
                self.gen_number(iden_mem_id)
                self.push('LOAD {}'.format(trg_reg))
            else:
                self.push('COPY {} {}'.format(trg_reg, iden_reg))
            return trg_reg
        elif is_arr(iden):
            _, name, inner, _ = iden
            if is_number(inner):
                offset = inner + self.arr_offset(iden)
                self.gen_number(offset)
                self.push('LOAD {}'.format(trg_reg))
                return trg_reg
            elif is_declared_var(inner, self.symtab):
                inner_reg = self.check_in_regs(inner)
                if not inner_reg:
                    inner_mem_id = self.memory[inner]
                    self.gen_number(inner_mem_id, 0)
                    self.push('''
                    LOAD    1
                    ''')
                    offset = self.arr_offset(iden)
                    self.gen_number(offset, 0)
                    self.push('''
                    ADD     0   1
                    LOAD    {}
                    '''.format(trg_reg))
                    return trg_reg
                else:
                    offset = self.arr_offset(iden)
                    self.gen_number(offset, 0)
                    self.push('''
                    ADD {} {}
                    LOAD {}
                    '''.format(0, inner_reg, trg_reg))
                    return trg_reg
        elif is_declared_var(iden, self.symtab):
            iden_reg = self.check_in_regs(iden)
            if not iden_reg:
                iden_mem_id = self.memory[iden]
                self.gen_number(iden_mem_id)
                self.push('LOAD {}'.format(trg_reg))
            else:
                self.push('COPY {} {}'.format(trg_reg, iden_reg))
            return trg_reg

            pass
Exemple #12
0
 def assign(self, target, expression):
     _, *value = expression
     if is_operation(value):
         self.assign_operation(target, value)
     else:
         if is_variable(value[0]):
             self.assign_variable(target, value[0])
         elif is_number(value[0]):
             self.assign_number(target, value[0])
         else:
             raise CompilerError("Unknown value type")
Exemple #13
0
    def assign_minus(self, trg_iden, left, right):
        l_reg = self.loaddd(left, 2)
        r_reg = self.loaddd(right, 3)

        self.push('''
        SUB     {l}     {r}
        '''.format(l=l_reg, r=r_reg))

        if is_arr(trg_iden):
            self.store_arr(trg_iden, l_reg)
        elif is_variable(trg_iden):
            self.store_var(trg_iden, l_reg)
Exemple #14
0
    def comp_geq(self, cond, label):
        left, _, right = cond

        if is_number(right) and right == 0:
            self.parse("JUMP @label", label=label)
            return

        code = ""
        if is_number(right):
            code += """
            GENERATE r_val
            STORE right
            """

        if is_number(left):
            code += """
            GENERATE l_val
            """
        else:
            code += """
            LOAD left
            """

        code += """
        INC
        SUB right
        JZERO #FALSE
        JUMP @label
        #FALSE:
        """

        self.parse(code,
                   l_val=left,
                   r_val=right,
                   left=left if is_variable(left) else Reg.r0,
                   right=right if is_variable(right) else Reg.r1,
                   label=label)
Exemple #15
0
 def assign_mod(self, trg_iden, left, right):
     l_reg = self.loaddd(left, 2)
     r_reg = self.loaddd(right, 3)
     res_reg = 4
     divide = '''
     COPY    {res}   {l}     
     JZERO   {r}     ${end}
     COPY    1       {r}
     COPY    {res}   1
     SUB     {res}   {l}
     JZERO   {res}   ${body}
     JUMP    ${out}
     ADD     1       1
     JUMP    ${loop}
     SUB     {res}   {res}
     COPY    0       1
     SUB     0       {l}
     JZERO   0       ${add}
     ADD     {res}   {res}
     HALF    1
     JUMP    ${check}
     ADD     {res}   {res}
     INC     {res}
     SUB     {l}     1
     HALF    1
     COPY    0       {r}
     SUB     0       1
     JZERO   0       ${loop2}
     JUMP    ${out2}
     SUB     {l}     {l}
     SUB     {res}   {res}
     '''.format(res=res_reg,
                l=l_reg,
                r=r_reg,
                end=23,
                body=2,
                out=3,
                loop=-5,
                add=4,
                check=5,
                loop2=-12,
                out2=3)
     self.push(divide)
     if is_arr(trg_iden):
         self.store_arr(trg_iden, l_reg)
     elif is_variable(trg_iden):
         self.store_var(trg_iden, l_reg)
Exemple #16
0
    def parse_array(self, left, right):
        _, var, index, *_ = right
        if is_number(index):
            array = self.mem['{}#0'.format(var)]
            arr_addr = array['address']
            cell_addr = index + arr_addr
            code = '{cmd} {param}'.format(cmd=left, param=cell_addr)
            self.code.append(code)
        elif is_reg(index):
            self.code.append('{cmd}I {reg}'.format(cmd=left, reg=index[1]))
        elif is_variable(index):
            left += 'I'
            array = self.mem['{}#0'.format(var)]
            arr_start_ptr = array['start_ptr']
            if left == 'LOADI':
                self.code.append(
                    'LOAD {arr_start_ptr}'.format(arr_start_ptr=arr_start_ptr))
                code = """
                ADD x
                STORE r9
                LOADI r9
                """
                self.parse(code, x=index, r9=Reg.r9)
            elif left in ['STOREI', 'ADDI', 'SUBI']:
                self.parse("""
                STORE r8
                """,
                           r8=Reg.r8)

                self.code.append(
                    'LOAD {arr_start_ptr}'.format(arr_start_ptr=arr_start_ptr))

                code = """ADD x
                STORE r9
                LOAD r8
                {cmd} r9
                """.format(cmd=left, arr_size=arr_start_ptr)
                self.parse(code, x=index, r9=Reg.r9, r8=Reg.r8)
            else:
                raise CompilerError("Unexpected command")
Exemple #17
0
    def comp_neq(self, cond, label):
        left, _, right = cond

        if is_number(left) and is_number(right):
            if left == right:
                return
            else:
                self.parse('JUMP @label', label=label)
                return

        if is_number(right):
            right, left = left, right

        if is_number(left) and left == 0:
            code = """
            LOAD a
            JZERO #FALSE
            JUMP @label
            #FALSE:
            """
            self.parse(code, a=right, label=label)
            return

        if is_number(left) and left == 1:
            code = """
            LOAD a
            JZERO @label
            DEC
            JZERO #FALSE
            JUMP @label
            #FALSE:
            """
            self.parse(code, a=right, label=label)
            return

        code = ""

        if is_number(left):
            code += """
               GENERATE l_val
               STORE left
               """

        if is_number(right):
            code += """
               GENERATE r_val
               STORE right
               """

        code += """
            LOAD left
            SUB right
            JZERO #FALSE1
            JUMP @label
            #FALSE1:
            LOAD right
            SUB left
            JZERO #FALSE
            JUMP @label
            #FALSE:
            """

        self.parse(code,
                   l_val=left,
                   r_val=right,
                   left=left if is_variable(left) else Reg.r0,
                   right=right if is_variable(right) else Reg.r1,
                   label=label)
Exemple #18
0
 def read(self, target):
     if is_variable(target):
         self.read_variable(target)
     else:
         raise CompilerError("Cannot READ non-variable")
Exemple #19
0
 def write(self, value):
     if is_variable(value):
         self.write_variable(value)
     else:
         self.write_number(value)
Exemple #20
0
    def operation_divmod(self, target, operands, division=True):
        [left, right] = operands

        if is_number(left) and is_number(right):
            if division:
                self.parse('GENERATE n', n=0 if right == 0 else left // right)
            else:
                self.parse('GENERATE n', n=0 if right == 0 else left % right)
            self.parse('STORE t', t=target)
            return

        # TODO: mul two times ?

        # 0 -> r2
        code = """
               ZERO
               STORE r2
               """
        # x -> r0
        code += """
               GENERATE l_val
               """ if is_number(left) else """
               LOAD left
               """
        code += """
               STORE r0
               JZERO #END
               """
        # y -> r1, r3
        code += """
               GENERATE r_val
               """ if is_number(right) else """
               LOAD right
               """
        code += """
               JZERO #END
               STORE r1
               """
        code += """
               STORE r3
               """ if is_number(right) else ""
        code += """
               JUMP #FIRST_SHIFT
               #SHIFT:
               LOAD r1
               #FIRST_SHIFT:
               SHL
               STORE r1
               SHL
               DEC
               SUB r0
               JZERO #SHIFT
               LOAD r1
               """

        code += """
               #LOOP:
               INC
               SUB {const_addr}
               JZERO #END
               """.format(const_addr='r3' if is_number(right) else 'right')

        code += """
               LOAD r1
               SUB r0
               JZERO #ADD

               #NO_ADD:
               LOAD r2
               SHL
               STORE r2
               LOAD r1
               SHR
               STORE r1
               JUMP #LOOP

               #ADD:
               LOAD r2
               SHL
               INC
               STORE r2
               LOAD r0
               SUB r1
               STORE r0
               LOAD r1
               SHR
               STORE r1
               JUMP #LOOP

               #END:
               LOAD {target_reg}
               STORE target
               """.format(target_reg='r2' if division else 'r0')

        self.parse(code,
                   l_val=left,
                   r_val=right,
                   left=left if is_variable(left) else Reg.r4,
                   right=right if is_variable(right) else Reg.r5,
                   target=target,
                   r0=Reg.r0,
                   r1=Reg.r1,
                   r2=Reg.r2,
                   r3=Reg.r3)
Exemple #21
0
    def operation_modulo(self, target, operands):
        [left, right] = operands

        if is_number(left) and is_number(right):
            self.parse('GENERATE n', n=0 if right == 0 else left % right)
            self.parse('STORE t', t=target)
            return

        code = ''

        # 0 -> r2
        code += """
                       ZERO
                       STORE r2
                       """
        # x -> r0
        code += """
                       GENERATE l_val
                       """ if is_number(left) else """
                       LOAD left
                       """
        code += """
                       STORE r0
                       JZERO #END
                       """
        # y -> r1, r3
        code += """
                       GENERATE r_val
                       """ if is_number(right) else ''
        code += """
                       LOAD right
                """ if not is_number(right) and right != left else ''

        code += """
                       JZERO #END_RIGHT
                       STORE r1
                       """
        code += """
                       STORE r3
                       """ if is_number(right) else ""
        code += """
                       JUMP #FIRST_SHIFT
                       #SHIFT:
                       LOAD r1
                       #FIRST_SHIFT:
                       SHL
                       STORE r1
                       SHL
                       DEC
                       SUB r0
                       JZERO #SHIFT
                       LOAD r1
                       """

        code += """
                       #LOOP:
                       INC
                       SUB {const_addr}
                       JZERO #END
                       """.format(
            const_addr='r3' if is_number(right) else 'right')

        code += """
                       LOAD r1
                       SUB r0
                       JZERO #ADD

                       #NO_ADD:
                       LOAD r2
                       SHL
                       STORE r2
                       LOAD r1
                       SHR
                       STORE r1
                       JUMP #LOOP

                       #ADD:
                       LOAD r2
                       SHL
                       INC
                       STORE r2
                       LOAD r0
                       SUB r1
                       STORE r0
                       LOAD r1
                       SHR
                       STORE r1
                       JUMP #LOOP
                       
                       #END_RIGHT:
                       ZERO
                       STORE target
                       JUMP #FINISH
                       
                       #END:
                       LOAD {target_reg}
                       STORE target
                       #FINISH:
                       """.format(target_reg='r0')

        self.parse(code,
                   l_val=left,
                   r_val=right,
                   left=left if is_variable(left) else Reg.r4,
                   right=right if is_variable(right) else Reg.r5,
                   target=target,
                   r0=Reg.r0,
                   r1=Reg.r1,
                   r2=Reg.r2,
                   r3=Reg.r3)
Exemple #22
0
    def operation_multiply(self, target, operands):
        [left, right] = operands

        if is_number(right):
            left, right = right, left

        if is_number(left) and is_number(right):
            self.parse('GENERATE n', n=left * right)
            self.parse('STORE t', t=target)
            return

        if is_number(left):
            if left % 2 == 0 and float(int(log(left, 2))) == log(left, 2):
                count = int(sqrt(left))
                code = """
                LOAD right
                """
                for _ in range(count):
                    code += """
                    SHL
                    """
                code += """
                STORE target
                """
                self.parse(code, right=right, target=target)
                return
            elif left == 1 and target != left:
                code = """
                LOAD right
                STORE target
                """
                self.parse(code, right=right, target=target)
                return
            elif target == right and left == 1:
                return

        code = ""

        if is_number(left) and is_number(right):
            if right > left:
                left, right = right, left

        if is_number(left):
            code += """
                   GENERATE l_val
                   STORE left
                   """

        if is_number(right):
            code += """
                   GENERATE r_val
                   STORE right
                   """

        code += """
            ZERO
            STORE r2
            """
        code += """ 
            LOAD left
            SUB right
            JZERO #RIGHT_BIGGER

            #LEFT_BIGGER:
            LOAD left
            STORE r0
            LOAD right
            STORE r1
            JUMP #START
    
            #RIGHT_BIGGER:""" if left != right and not (
            is_number(left) and is_number(right)) else ''

        code += """
            LOAD right
            STORE r0
            LOAD left
            STORE r1

            #START:
            JZERO #END
            JODD #IS_ODD
            JUMP #NOT_ODD

            #IS_ODD:
            LOAD r2
            ADD r0
            STORE r2

            #NOT_ODD:
            LOAD r0
            SHL
            STORE r0
            
            LOAD r1
            SHR
            STORE r1
            
            JUMP #START

            #END:
            LOAD r2
            STORE target
            """

        self.parse(code,
                   l_val=left,
                   r_val=right,
                   r0=Reg.r0,
                   r1=Reg.r1,
                   r2=Reg.r2,
                   left=left if is_variable(left) else Reg.r4,
                   right=right if is_variable(right) else Reg.r5,
                   target=target)
 def check_condition(self, condition):
     *_, left_op, right_op = condition
     for operand in [left_op, right_op]:
         if is_variable(operand):
             self.check_variable(operand)
             self.check_initialized(operand)
Exemple #24
0
 def gen_read(self, node):
     _, iden = node
     if is_variable(iden):
         self.read_variable(iden)
     elif is_arr(iden):
         self.read_array(iden)
 def check_write(self, cmd):
     _, operand = cmd
     if is_variable(operand):
         self.check_variable(operand)
         self.check_initialized(operand)