-
Notifications
You must be signed in to change notification settings - Fork 453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve Caml_obj equal function to support errors #6937
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -198,11 +198,7 @@ let rec compare = (a: Obj.t, b: Obj.t): int => | |
} else { | ||
let tag_a = Obj.tag(a) | ||
let tag_b = Obj.tag(b) | ||
if tag_a == 248 /* object/exception */ { | ||
Pervasives.compare((Obj.magic(Obj.field(a, 1)): int), Obj.magic(Obj.field(b, 1))) | ||
} else if tag_a == 251 /* abstract_tag */ { | ||
raise(Invalid_argument("equal: abstract value")) | ||
} else if tag_a != tag_b { | ||
if tag_a != tag_b { | ||
if tag_a < tag_b { | ||
-1 | ||
} else { | ||
|
@@ -303,53 +299,46 @@ type eq = (Obj.t, Obj.t) => bool | |
basic type is not the same, it will not equal | ||
*/ | ||
let rec equal = (a: Obj.t, b: Obj.t): bool => | ||
/* front and formoest, we do not compare function values */ | ||
if a === b { | ||
true | ||
} else { | ||
let a_type = Js.typeof(a) | ||
if ( | ||
a_type == "string" || | ||
(a_type == "number" || | ||
(a_type == "bigint" || | ||
(a_type == "boolean" || | ||
(a_type == "undefined" || a === %raw(`null`))))) | ||
) { | ||
if a_type !== "object" || a === %raw(`null`) { | ||
false | ||
} else { | ||
let b_type = Js.typeof(b) | ||
if a_type == "function" || b_type == "function" { | ||
raise(Invalid_argument("equal: functional value")) | ||
} /* first, check using reference equality */ | ||
Comment on lines
-321
to
-323
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we checked the functions using strict equal There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think according to the funciton name |
||
else if ( | ||
/* a_type = "object" || "symbol" */ | ||
b_type == "number" || (b_type == "bigint" || (b_type == "undefined" || b === %raw(`null`))) | ||
) { | ||
if b_type !== "object" || b === %raw(`null`) { | ||
Comment on lines
-325
to
+310
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A good example of forgetting checking various types |
||
false | ||
} else { | ||
/* [a] [b] could not be null, so it can not raise */ | ||
let tag_a = Obj.tag(a) | ||
let tag_b = Obj.tag(b) | ||
if tag_a == 248 /* object/exception */ { | ||
Obj.magic(Obj.field(a, 1)) === Obj.magic(Obj.field(b, 1)) | ||
} else if tag_a == 251 /* abstract_tag */ { | ||
raise(Invalid_argument("equal: abstract value")) | ||
Comment on lines
-333
to
-336
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed legacy check |
||
} else if tag_a != tag_b { | ||
if tag_a !== tag_b { | ||
false | ||
Comment on lines
+316
to
317
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure of the usefulness of the optimisation 🤔 But let's keep it. |
||
} else { | ||
} else if O.isArray(a) { | ||
let len_a = Obj.size(a) | ||
let len_b = Obj.size(b) | ||
Comment on lines
+318
to
320
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Length check makes sense only for arrays, so moved it inside of the |
||
if len_a == len_b { | ||
if O.isArray(a) { | ||
aux_equal_length((Obj.magic(a): array<Obj.t>), (Obj.magic(b): array<Obj.t>), 0, len_a) | ||
} else if %raw(`a instanceof Date && b instanceof Date`) { | ||
!(Js.unsafe_gt(a, b) || Js.unsafe_lt(a, b)) | ||
} else { | ||
aux_obj_equal(a, b) | ||
} | ||
if len_a !== len_b { | ||
false | ||
} else { | ||
aux_equal_length((Obj.magic(a): array<Obj.t>), (Obj.magic(b): array<Obj.t>), 0, len_a) | ||
} | ||
} else if %raw(`a instanceof Error`) { | ||
let a: {..} = Obj.magic(a) | ||
let b: {..} = Obj.magic(b) | ||
if %raw(`b instanceof Error`) && a["message"] === b["message"] { | ||
equal(a["clause"], b["clause"]) | ||
cknitt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} else { | ||
false | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for in doesn't work on |
||
} else if %raw(`a instanceof Date`) { | ||
if %raw(`b instanceof Date`) { | ||
Comment on lines
+334
to
+335
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Split the check so it earlier returns |
||
!(Js.unsafe_gt(a, b) || Js.unsafe_lt(a, b)) | ||
} else { | ||
false | ||
} | ||
} else { | ||
aux_obj_equal(a, b) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've taken a look at the generated code for the function, and it's not very optimised. Not the goal of the PR, so kept it as it is. |
||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same, but shorter, faster, easier to maintain, and prevents from forgetting symbol and other types.