def expose_struct2vector(struct): return values_struct.struct2vector(struct)
def equal_func_impl(a, b, info, env, cont, n): from pycket.interpreter import return_value if a.eqv(b): return return_value(values.w_true, env, cont) for_chaperone = jit.promote(info).for_chaperone if (for_chaperone >= EqualInfo.CHAPERONE and b.is_non_interposing_chaperone()): return equal_func_unroll_n(a, b.get_proxied(), info, env, cont, n) # Enter into chaperones/impersonators if we have permission to do so if ((for_chaperone == EqualInfo.CHAPERONE and a.is_chaperone()) or (for_chaperone == EqualInfo.IMPERSONATOR and a.is_impersonator())): return equal_func_unroll_n(a.get_proxied(), b, info, env, cont, n) # If we are doing a chaperone/impersonator comparison, then we do not have # a chaperone-of/impersonator-of relation if `a` is not a proxy and # `b` is a proxy. if for_chaperone != EqualInfo.BASIC and not a.is_proxy() and b.is_proxy(): return return_value(values.w_false, env, cont) if isinstance(a, values_string.W_String) and isinstance(b, values_string.W_String): is_chaperone = for_chaperone == EqualInfo.CHAPERONE if is_chaperone and (not a.immutable() or not b.immutable()): return return_value(values.w_false, env, cont) return return_value(values.W_Bool.make(a.equal(b)), env, cont) if isinstance(a, values.W_Bytes) and isinstance(b, values.W_Bytes): is_chaperone = info.for_chaperone == EqualInfo.CHAPERONE if is_chaperone and (not a.immutable() or not b.immutable()): return return_value(values.w_false, env, cont) return return_value(values.W_Bool.make(a.equal(b)), env, cont) if isinstance(a, values.W_Cons) and isinstance(b, values.W_Cons): cont = equal_car_cont(a.cdr(), b.cdr(), info, env, cont) return equal_func_unroll_n(a.car(), b.car(), info, env, cont, n) if isinstance(a, values.W_MCons) and isinstance(b, values.W_MCons): cont = equal_car_cont(a.cdr(), b.cdr(), info, env, cont) return equal_func_unroll_n(a.car(), b.car(), info, env, cont, n) if isinstance(a, values.W_Box) and isinstance(b, values.W_Box): is_chaperone = for_chaperone == EqualInfo.CHAPERONE if is_chaperone and (not a.immutable() or not b.immutable()): return return_value(values.w_false, env, cont) return a.unbox(env, equal_unbox_right_cont(b, info, env, cont)) if isinstance(a, values.W_MVector) and isinstance(b, values.W_MVector): is_chaperone = for_chaperone == EqualInfo.CHAPERONE if is_chaperone and (not a.immutable() or not b.immutable()): return return_value(values.w_false, env, cont) if a.length() != b.length(): return return_value(values.w_false, env, cont) return equal_vec_func(a, b, 0, info, env, cont) if isinstance(a, values_struct.W_RootStruct) and isinstance(b, values_struct.W_RootStruct): a_type = a.struct_type() b_type = b.struct_type() w_prop = a_type.read_prop(values_struct.w_prop_equal_hash) if w_prop: w_prop = b_type.read_prop(values_struct.w_prop_equal_hash) if w_prop: w_equal_proc, w_hash_proc, w_hash2_proc = equal_hash_args(w_prop) # FIXME: it should work with cycles properly and be an equal?-recur w_equal_recur = equalp.w_prim return w_equal_proc.call([a, b, w_equal_recur], env, cont) if not a_type.isopaque and not b_type.isopaque: # This is probably not correct even if struct2vector were done # correct, due to side effects, but it is close enough for now. # Though the racket documentation says that `equal?` can elide # impersonator/chaperone handlers. a_imm = a_type.all_fields_immutable() b_imm = b_type.all_fields_immutable() a = values_struct.struct2vector(a, immutable=a_imm) b = values_struct.struct2vector(b, immutable=b_imm) return equal_func_unroll_n(a, b, info, env, cont, n) if for_chaperone == EqualInfo.BASIC and a.is_proxy() and b.is_proxy(): return equal_func_unroll_n(a.get_proxied(), b.get_proxied(), info, env, cont, n) if a.equal(b): return return_value(values.w_true, env, cont) return return_value(values.w_false, env, cont)