def assert_emit_binary_op(self, op: str, dest: Value, left: Value, right: Value, expected: str) -> None: # TODO: merge this if op in c_binary_ops: c_ops = c_binary_ops[op] for c_desc in c_ops: if (is_subtype(left.type, c_desc.arg_types[0]) and is_subtype(right.type, c_desc.arg_types[1])): args = [left, right] if c_desc.ordering is not None: args = [args[i] for i in c_desc.ordering] self.assert_emit(CallC(c_desc.c_function_name, args, c_desc.return_type, c_desc.steals, c_desc.error_kind, 55), expected) return ops = binary_ops[op] for desc in ops: if (is_subtype(left.type, desc.arg_types[0]) and is_subtype(right.type, desc.arg_types[1])): self.assert_emit(PrimitiveOp([left, right], desc, 55), expected) break else: assert False, 'Could not find matching op'
def assert_emit_binary_op(self, op: str, dest: Value, left: Value, right: Value, expected: str) -> None: ops = binary_ops[op] for desc in ops: if (is_subtype(left.type, desc.arg_types[0]) and is_subtype(right.type, desc.arg_types[1])): self.assert_emit(PrimitiveOp([left, right], desc, 55), expected) break else: assert False, 'Could not find matching op'
def matching_primitive_op(self, candidates: List[OpDescription], args: List[Value], line: int, result_type: Optional[RType] = None) -> Optional[Value]: # Find the highest-priority primitive op that matches. matching = None # type: Optional[OpDescription] for desc in candidates: if len(desc.arg_types) != len(args): continue if all(is_subtype(actual.type, formal) for actual, formal in zip(args, desc.arg_types)): if matching: assert matching.priority != desc.priority, 'Ambiguous:\n1) %s\n2) %s' % ( matching, desc) if desc.priority > matching.priority: matching = desc else: matching = desc if matching: target = self.primitive_op(matching, args, line) if result_type and not is_runtime_subtype(target.type, result_type): if is_none_rprimitive(result_type): # Special case None return. The actual result may actually be a bool # and so we can't just coerce it. target = self.none() else: target = self.coerce(target, result_type, line) return target return None
def coerce(self, src: Value, target_type: RType, line: int, force: bool = False) -> Value: """Generate a coercion/cast from one type to other (only if needed). For example, int -> object boxes the source int; int -> int emits nothing; object -> int unboxes the object. All conversions preserve object value. If force is true, always generate an op (even if it is just an assignment) so that the result will have exactly target_type as the type. Returns the register with the converted value (may be same as src). """ if src.type.is_unboxed and not target_type.is_unboxed: return self.box(src) if ((src.type.is_unboxed and target_type.is_unboxed) and not is_runtime_subtype(src.type, target_type)): # To go from one unboxed type to another, we go through a boxed # in-between value, for simplicity. tmp = self.box(src) return self.unbox_or_cast(tmp, target_type, line) if ((not src.type.is_unboxed and target_type.is_unboxed) or not is_subtype(src.type, target_type)): return self.unbox_or_cast(src, target_type, line) elif force: tmp = self.alloc_temp(target_type) self.add(Assign(tmp, src)) return tmp return src
def matching_call_c( self, candidates: List[CFunctionDescription], args: List[Value], line: int, result_type: Optional[RType] = None) -> Optional[Value]: # TODO: this function is very similar to matching_primitive_op # we should remove the old one or refactor both them into only as we move forward matching = None # type: Optional[CFunctionDescription] for desc in candidates: if len(desc.arg_types) != len(args): continue if all( is_subtype(actual.type, formal) for actual, formal in zip(args, desc.arg_types)): if matching: assert matching.priority != desc.priority, 'Ambiguous:\n1) %s\n2) %s' % ( matching, desc) if desc.priority > matching.priority: matching = desc else: matching = desc if matching: target = self.call_c(matching, args, line, result_type) return target return None
def assert_emit_binary_op(self, op: str, dest: Value, left: Value, right: Value, expected: str) -> None: if op in binary_ops: ops = binary_ops[op] for desc in ops: if (is_subtype(left.type, desc.arg_types[0]) and is_subtype(right.type, desc.arg_types[1])): args = [left, right] if desc.ordering is not None: args = [args[i] for i in desc.ordering] self.assert_emit( CallC(desc.c_function_name, args, desc.return_type, desc.steals, desc.is_borrowed, desc.error_kind, 55), expected) return else: assert False, 'Could not find matching op'
def visit_runion(self, left: RUnion) -> bool: return is_subtype(left, self.right)
def visit_rinstance(self, left: RInstance) -> bool: return is_subtype(left, self.right)
def test_bool(self) -> None: assert not is_subtype(bool_rprimitive, bit_rprimitive) assert is_subtype(bool_rprimitive, int_rprimitive)