Ejemplo n.º 1
0
    def make_il(self, il_code, symbol_table, c):
        """Make code for this node."""

        left = self.left.make_il(il_code, symbol_table, c)
        right = self.right.make_il(il_code, symbol_table, c)

        if self._check_type(left, right):
            left, right = arith_convert(left, right, il_code)

            if left.literal and right.literal:
                # If NotImplementedError is raised, continue with execution.
                try:
                    val = self._arith_const(
                        shift_into_range(left.literal.val, left.ctype),
                        shift_into_range(right.literal.val, right.ctype),
                        left.ctype)
                    out = ILValue(left.ctype)
                    il_code.register_literal_var(out, val)
                    return out

                except NotImplementedError:
                    pass

            return self._arith(left, right, il_code)

        else:
            return self._nonarith(left, right, il_code)
Ejemplo n.º 2
0
    def make_il(self, il_code, symbol_table, c):
        """Make code for this node."""

        left = self.left.make_il(il_code, symbol_table, c)
        right = self.right.make_il(il_code, symbol_table, c)

        if self._check_type(left, right):
            left, right = arith_convert(left, right, il_code)

            if left.literal and right.literal:
                # If NotImplementedError is raised, continue with execution.
                try:
                    val = self._arith_const(
                        shift_into_range(left.literal.val, left.ctype),
                        shift_into_range(right.literal.val, right.ctype),
                        left.ctype)
                    out = ILValue(left.ctype)
                    il_code.register_literal_var(out, val)
                    return out

                except NotImplementedError:
                    pass

            return self._arith(left, right, il_code)

        else:
            return self._nonarith(left, right, il_code)
Ejemplo n.º 3
0
    def make_il(self, il_code, symbol_table, c):
        """Make code for this node."""

        left = self.left.make_il(il_code, symbol_table, c)
        right = self.right.make_il(il_code, symbol_table, c)

        if left.ctype.is_arith() and right.ctype.is_arith():
            left, right = arith_convert(left, right, il_code)
            return self._arith(left, right, il_code)
        else:
            return self._nonarith(left, right, il_code)
Ejemplo n.º 4
0
    def make_il(self, il_code, symbol_table, c):
        """Make code for this node."""
        right = self.right.make_il(il_code, symbol_table, c)
        lvalue = self.left.lvalue(il_code, symbol_table, c)
        if not lvalue or not lvalue.modable():
            err = "expression on left of '{}' is not assignable"
            raise CompilerError(err.format(str(self.op)), self.left.r)

        if (lvalue.ctype().is_pointer()
            and right.ctype.is_integral()
             and self.accept_pointer):

            if not lvalue.ctype().arg.is_complete():
                err = "invalid arithmetic on pointer to incomplete type"
                raise CompilerError(err, self.op.r)

            # Because of caching requirement of make_il and lvalue functions,
            # we know this call won't regenerate code for the left expression
            # beyond just what's needed to get the value stored at the lvalue.
            # This is important in cases like ``*func() += 10`` where func()
            # may have side effects if called twice.
            left = self.left.make_il(il_code, symbol_table, c)

            out = ILValue(left.ctype)
            shift = get_size(left.ctype.arg, right, il_code)

            il_code.add(self.command(out, left, shift))
            lvalue.set_to(out, il_code, self.op.r)
            return out

        elif lvalue.ctype().is_arith() and right.ctype.is_arith():
            left = self.left.make_il(il_code, symbol_table, c)
            out = ILValue(left.ctype)

            left, right = arith_convert(left, right, il_code)
            il_code.add(self.command(out, left, right))
            lvalue.set_to(out, il_code, self.op.r)
            return out

        else:
            err = "invalid types for '{}' operator".format(str(self.op))
            raise CompilerError(err, self.op.r)
Ejemplo n.º 5
0
    def make_il(self, il_code, symbol_table, c):
        """Make code for this node."""
        right = self.right.make_il(il_code, symbol_table, c)
        lvalue = self.left.lvalue(il_code, symbol_table, c)
        if not lvalue or not lvalue.modable():
            err = f"expression on left of '{str(self.op)}' is not assignable"
            raise CompilerError(err, self.left.r)

        if (lvalue.ctype().is_pointer()
            and right.ctype.is_integral()
             and self.accept_pointer):

            if not lvalue.ctype().arg.is_complete():
                err = "invalid arithmetic on pointer to incomplete type"
                raise CompilerError(err, self.op.r)

            # Because of caching requirement of make_il and lvalue functions,
            # we know this call won't regenerate code for the left expression
            # beyond just what's needed to get the value stored at the lvalue.
            # This is important in cases like ``*func() += 10`` where func()
            # may have side effects if called twice.
            left = self.left.make_il(il_code, symbol_table, c)

            out = ILValue(left.ctype)
            shift = get_size(left.ctype.arg, right, il_code)

            il_code.add(self.command(out, left, shift))
            lvalue.set_to(out, il_code, self.op.r)
            return out

        elif lvalue.ctype().is_arith() and right.ctype.is_arith():
            left = self.left.make_il(il_code, symbol_table, c)
            out = ILValue(left.ctype)

            left, right = arith_convert(left, right, il_code)
            il_code.add(self.command(out, left, right))
            lvalue.set_to(out, il_code, self.op.r)
            return out

        else:
            err = f"invalid types for '{str(self.op)}' operator"
            raise CompilerError(err, self.op.r)