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)
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)
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)
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)