Beispiel #1
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)
Beispiel #2
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)
Beispiel #3
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
Beispiel #4
0
    def less_eq(self, left, right, label):
        if is_number(left) and is_number(right):
            if left <= right:
                self.push('JUMP lbl'.format(lbl=label))
                return

        l_reg = self.loaddd(left, 2)
        r_reg = self.loaddd(right, 3)

        self.push('SUB {l} {r}'.format(l=l_reg, r=r_reg))
        self.push('JZERO {l} {lb}'.format(l=l_reg, lb=label))
 def check_scope(self, operand):
     if is_number(operand):
         pass
     elif is_int(operand):
         if operand[1] not in self.scope:
             raise_error(msg="Undeclared variable {}".format(operand[1]),
                         lineno=operand[2])
     elif is_array(operand):
         if is_number(operand[2]):
             self.check_inttab(operand)
     else:
         raise CompilerError("Unexpected operand")
Beispiel #6
0
    def flow_if_then(self, cmd):
        _, cond, if_true = cmd
        _, cond_symb, left, right = cond

        if is_number(left) and is_number(right):
            if not self.eval_cond(cond_symb, left, right):
                return

        label_false = self.next_label()
        self.flow += self.add_goto_if(self.neg(cond), label_false)
        self.generate(if_true)
        self.flow += ('label', label_false),
Beispiel #7
0
    def flow_while(self, cmd):
        _, cond, body = cmd
        _, cond_symb, left, right = cond

        if is_number(left) and is_number(right):
            if not self.eval_cond(cond_symb, left, right):
                return

        label_start, label_end = self.next_label(2)
        self.flow += self.add_label(label_start)
        self.flow += self.add_goto_if(self.neg(cond), label_end)
        self.generate(body)
        self.flow += self.add_goto(label_start)
        self.flow += self.add_label(label_end)
Beispiel #8
0
 def store_arr(self, iden_arr, val_reg):
     _, name, inner, _ = iden_arr
     if is_number(inner):
         offset = inner + self.arr_offset(iden_arr)
         self.gen_number(offset)
         self.push('STORE {}'.format(val_reg))
         return
     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_arr)
             self.gen_number(offset, 0)
             self.push('''
             ADD     0   1
             STORE   {}
             '''.format(val_reg))
             return
         else:
             offset = self.arr_offset(iden_arr)
             self.gen_number(offset, 0)
             self.push('''
                     ADD     {}  {}
                     STORE   {}
                     '''.format(0, inner_reg, val_reg))
             return
Beispiel #9
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)
Beispiel #10
0
    def flow_if_else(self, cmd):
        _, cond, if_true, if_false = cmd

        _, cond_symb, left, right = cond

        label_false, label_end = self.next_label(), self.next_label()

        if is_number(left) and is_number(right):
            if not self.eval_cond(cond_symb, left, right):
                self.generate(if_false)
                return

        self.flow += self.add_goto_if(self.neg(cond), label_false)
        self.generate(if_true)
        self.flow += self.add_goto(label_end)
        self.flow += self.add_label(label_false)
        self.generate(if_false)
        self.flow += self.add_label(label_end)
Beispiel #11
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
Beispiel #12
0
    def eq(self, left, right, label):
        if is_number(left) and is_number(right):
            if left == right:
                self.push('JUMP     {}'.format(label))
            else:
                return

        l_reg = self.loaddd(left, 2)
        r_reg = self.loaddd(right, 3)

        self.push('''
        COPY    0   {l}
        COPY    1   {r}
        SUB     0   {r}
        JZERO   0   ${sub}
        JUMP    ${end}
        SUB     1   {l}
        JZERO   1   {lbl}
        '''.format(l=l_reg, r=r_reg, lbl=label, end=3, sub=2))
Beispiel #13
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")
Beispiel #14
0
    def flow_for_down(self, cmd):
        _, iterator, start, end, body = cmd

        if is_number(start) and is_number(end):
            if start < end:
                return

        limit = (iterator[0], '#' + iterator[1], iterator[2])
        label_start, label_end = self.next_label(2)

        self.flow += ('assign', iterator, ('expression', start)),
        self.flow += ('assign', limit, ('expression', end)),
        self.flow += self.add_goto_if((iterator, '<', limit), label_end)

        self.flow += self.add_label(label_start)

        self.generate(body)
        self.flow += self.add_goto_if((iterator, '<=', limit), label_end)
        self.flow += ('assign', iterator, ('expression', '-', iterator, 1)),
        self.flow += self.add_goto(label_start)
        self.flow += self.add_label(label_end)
    def check_inttab(self, variable):
        _, symbol, index, lineno = variable

        arr_start = '#'.join([symbol, '0'])

        if arr_start not in self.scope:
            raise_error("Usage of undeclared array {}".format(symbol), lineno)
        if is_number(index):
            self.check_inttab_index(variable)
        elif is_int(index):
            self.check_variable(index)
        else:
            raise CompilerError("Unexpected array index")
Beispiel #16
0
 def read_array(self, iden):
     _, name, sub_iden, _ = iden
     if is_number(sub_iden):
         offset = sub_iden + self.arr_offset(iden)
         self.gen_number(offset)
         self.push('''
         GET     {}
         STORE   {}
         '''.format(1, 1))
     elif is_declared_var(sub_iden, self.symtab):
         offset = self.arr_offset(iden)
         self.gen_number(offset, 2)
         inner_reg = self.loaddd(sub_iden, 3)
         self.push('''
         SUB     0   0
         ADD     0   2
         ADD     0   3
         GET     1
         STORE   1
         ''')
Beispiel #17
0
 def write_arr(self, iden):
     _, name, inner, _ = iden
     if is_number(inner):
         offset = inner + self.arr_offset(iden)
         self.gen_number(offset)
         self.push('''
                 LOAD {}
                 PUT {}
                 '''.format(1, 1))
         return
     elif is_declared_var(inner, self.symtab):
         self.loaddd(inner, 2)
         offset = self.arr_offset(iden)
         self.gen_number(offset, 3)
         self.push('''
         SUB     0   0
         ADD     0   2
         ADD     0   3
         LOAD    1
         PUT     1
         ''')
Beispiel #18
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")
Beispiel #19
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)
Beispiel #20
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)
Beispiel #21
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)