-
Notifications
You must be signed in to change notification settings - Fork 326
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
NaN can be used as a key in Map #6301
Changes from all commits
ff88018
6302281
32d81f4
061cb79
5f35024
6963198
aebbf0b
c5b5696
3507484
cb520ed
268c5f3
7720f14
4b3baa3
55ceaba
d3b1aa7
a91e985
fc5aace
d65e5e9
6bae728
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 |
---|---|---|
@@ -1,6 +1,7 @@ | ||
package org.enso.interpreter.node.expression.builtin.meta; | ||
|
||
import com.oracle.truffle.api.dsl.Fallback; | ||
import com.oracle.truffle.api.dsl.GenerateUncached; | ||
import com.oracle.truffle.api.dsl.Specialization; | ||
import com.oracle.truffle.api.interop.InteropLibrary; | ||
import com.oracle.truffle.api.interop.UnsupportedMessageException; | ||
|
@@ -15,6 +16,7 @@ | |
name = "is_same_object", | ||
description = "Checks if the two arguments share an underlying reference.", | ||
autoRegister = false) | ||
@GenerateUncached | ||
public abstract class IsSameObjectNode extends Node { | ||
|
||
public static IsSameObjectNode build() { | ||
|
@@ -23,6 +25,15 @@ public static IsSameObjectNode build() { | |
|
||
public abstract boolean execute(@AcceptsError Object left, @AcceptsError Object right); | ||
|
||
@Specialization | ||
boolean isSameDouble(double left, double right) { | ||
if (Double.isNaN(left) && Double.isNaN(right)) { | ||
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. This is the handling of |
||
return true; | ||
} else { | ||
return left == right; | ||
} | ||
Akirathan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
@Specialization | ||
boolean isSameType(Type typeLeft, Type typeRight) { | ||
return typeLeft == typeRight; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,9 +10,22 @@ import Standard.Test.Extensions | |
polyglot java import java.nio.file.Path as JavaPath | ||
polyglot java import java.util.Map as JavaMap | ||
|
||
## Type that violates reflexivity | ||
type My_Nan | ||
Value comment:Text | ||
|
||
type My_Nan_Comparator | ||
compare _ _ = Nothing | ||
hash _ = 0 | ||
|
||
Comparable.from (_:My_Nan) = My_Nan_Comparator | ||
|
||
foreign js js_str str = """ | ||
return new String(str) | ||
|
||
foreign js js_null = """ | ||
return null | ||
|
||
foreign js js_empty_dict = """ | ||
return new Map() | ||
|
||
|
@@ -125,6 +138,18 @@ spec = | |
map.size.should_equal 1 | ||
map.get [1, "a", 2] . should_equal "Value" | ||
|
||
Test.specify "should support NaN as keys" <| | ||
Map.empty.insert Number.nan 1 . contains_key Number.nan . should_be_true | ||
Map.empty.insert Number.nan 1 . values . should_equal [1] | ||
Map.empty.insert Number.nan 1 . insert Number.nan 2 . contains_key Number.nan . should_be_true | ||
Map.empty.insert Number.nan 1 . insert Number.nan 2 . values . should_equal [2] | ||
Map.empty.insert Number.nan 1 . insert "key" 2 . insert Number.nan 3 . contains_key Number.nan . should_be_true | ||
Map.empty.insert Number.nan 1 . insert "key" 2 . insert Number.nan 3 . contains_key "key" . should_be_true | ||
Map.empty.insert Number.nan 1 . insert "key" 2 . insert Number.nan 3 . at Number.nan . should_equal 3 | ||
Map.empty.insert Number.nan 1 . insert "key" 2 . insert Number.nan 3 . at "key" . should_equal 2 | ||
Map.empty.insert Number.nan 1 . insert Number.nan Number.nan . at Number.nan . to_text . should_equal "NaN" | ||
Map.empty.insert Number.nan 1 . insert Number.nan Number.nan . remove Number.nan . size . should_equal 0 | ||
|
||
Test.specify "should support dates as keys" <| | ||
map = Map.empty.insert (Date.new 1993) 1 . insert (Date.new 1993 2 5) 2 . insert (Date_Time.new 1993 2 5 13 45) 3 | ||
map.size.should_equal 3 | ||
|
@@ -143,6 +168,33 @@ spec = | |
(map.get key_map).should_equal 23 | ||
(map.get map).should_equal Nothing | ||
|
||
Test.specify "should support another hash map with NaN keys as key" <| | ||
Map.singleton (Map.singleton Number.nan 1) 42 . size . should_equal 1 | ||
Map.singleton (Map.singleton Number.nan 1) 42 . keys . at 0 . keys . to_text . should_equal "[NaN]" | ||
Map.singleton (Map.singleton Number.nan 1) 42 . keys . at 0 . get Number.nan . should_equal 1 | ||
Map.singleton (Map.singleton Number.nan 1) 42 . at (Map.singleton Number.nan 1) . should_equal 42 | ||
|
||
Test.specify "should support atoms with custom comparators that violate reflexivity as keys" <| | ||
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. This test was copied from the issue description |
||
k = My_Nan.Value "foo" | ||
k2 = My_Nan.Value "foo" | ||
(k==k).should_be_true | ||
(k==k2).should_be_false | ||
Meta.is_same_object k k2 . should_be_false | ||
Meta.is_same_object k k . should_be_true | ||
m = Map.empty.insert k 10 | ||
m.contains_key k . should_be_true | ||
m.get k . should_equal 10 | ||
m.contains_key k2 . should_be_false | ||
|
||
m2 = m.insert k2 20 | ||
m2.get k . should_equal 10 | ||
m2.get k2 . should_equal 20 | ||
m2.size . should_equal 2 | ||
|
||
m3 = m2.insert k 30 | ||
m3.size . should_equal 2 | ||
m3.get k . should_equal 30 | ||
|
||
Test.specify "should handle keys with standard equality semantics" <| | ||
map = Map.singleton 2 "Hello" | ||
(map.get 2).should_equal "Hello" | ||
|
@@ -152,6 +204,9 @@ spec = | |
Test.specify "should handle Nothing as keys" <| | ||
Map.singleton Nothing 3 . get Nothing . should_equal 3 | ||
Map.singleton Nothing 1 . insert Nothing 2 . get Nothing . should_equal 2 | ||
Map.singleton Nothing 1 . should_equal (Map.singleton Nothing 1) | ||
Map.singleton Nothing 1 . insert Nothing 2 . at Nothing . should_equal 2 | ||
Map.singleton js_null 1 . at Nothing . should_equal 1 | ||
|
||
Test.specify "should handle incomparable values as keys" <| | ||
Map.empty.insert Number.nan 1 . insert Number.nan 2 . get Number.nan . should_equal 2 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,16 @@ type T_Comparator | |
|
||
Comparable.from (_:T) = T_Comparator | ||
|
||
## Type that violates reflexivity | ||
type My_Nan | ||
Value value | ||
|
||
type My_Nan_Comparator | ||
compare _ _ = Nothing | ||
hash _ = 0 | ||
|
||
Comparable.from (_:My_Nan) = My_Nan_Comparator | ||
|
||
type My_Error | ||
Value a | ||
|
||
|
@@ -654,8 +664,26 @@ type_spec name alter = Test.group name <| | |
alter [1, 1.0, 2, 2.0] . distinct . should_equal [1, 2] | ||
alter [] . distinct . should_equal [] | ||
|
||
Test.specify "should be able to handle distinct on different primitive values" <| | ||
alter [1, "a"] . distinct . should_equal [1, "a"] | ||
alter ["a", 1] . distinct . should_equal ["a", 1] | ||
alter [Nothing, Nothing] . distinct . should_equal [Nothing] | ||
alter [Number.nan, Number.nan] . distinct . to_text . should_equal "[NaN]" | ||
alter [Nothing, Number.nan, Nothing, Number.nan] . distinct . to_text . should_equal "[Nothing, NaN]" | ||
alter [1, Nothing] . distinct . should_equal [1, Nothing] | ||
alter [Nothing, 1, Nothing] . distinct . should_equal [Nothing, 1] | ||
alter [1, Number.nan] . distinct . to_text . should_equal "[1, NaN]" | ||
alter [Number.nan, 1, Number.nan] . distinct . to_text . should_equal "[NaN, 1]" | ||
alter [1, Number.nan, 1] . distinct . to_text . should_equal "[1, NaN]" | ||
Comment on lines
+667
to
+677
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. How does 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. Added in 6bae728 |
||
alter [Number.nan, My_Nan.Value 42, My_Nan.Value 23] . distinct . to_text . should_equal "[NaN, (My_Nan.Value 42), (My_Nan.Value 23)]" | ||
my_nan = My_Nan.Value 42 | ||
alter [my_nan, Number.nan, my_nan] . distinct . to_text . should_equal "[(My_Nan.Value 42), NaN]" | ||
|
||
Test.specify "should correctly handle distinct with types that have custom comparators" <| | ||
alter [T.Value 1 2, T.Value 3 3, T.Value 1 2] . distinct . should_equal [T.Value 1 2, T.Value 3 3] | ||
alter [T.Value 1 2, T.Value 3 3, T.Value 1 2, Nothing] . distinct . should_equal [T.Value 1 2, T.Value 3 3, Nothing] | ||
alter [Nothing, T.Value 1 2, T.Value 3 3, T.Value 1 2, Nothing] . distinct . should_equal [Nothing, T.Value 1 2, T.Value 3 3] | ||
alter [T.Value 1 2, Date.new hours=3] . distinct . should_equal [T.Value 1 2, Date.new hours=3] | ||
|
||
Test.specify "should return a vector containing only unique elements up to some criteria" <| | ||
alter [Pair.new 1 "a", Pair.new 2 "b", Pair.new 1 "c"] . distinct (on = _.first) . should_equal [Pair.new 1 "a", Pair.new 2 "b"] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -281,13 +281,18 @@ spec = | |
Meta.get_annotation value "Value" "bar" . should_equal Nothing | ||
Meta.get_annotation value "Value" "baz" . should_equal (My_Type.Value 1 2 3) | ||
|
||
Test.group "Check Nothing" <| | ||
Test.group "Check Nothing and NaN" <| | ||
Test.specify "Nothing.is_a Nothing" <| | ||
Nothing.is_a Nothing . should_be_true | ||
Meta.is_same_object Nothing Nothing . should_be_true | ||
|
||
Test.specify "type_of Nothing is Nothing" <| | ||
Meta.type_of Nothing . should_equal Nothing | ||
|
||
Test.specify "NaN and NaN should be the same object" <| | ||
Akirathan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Meta.is_same_object Number.nan Number.nan . should_be_true | ||
(Number.nan == Number.nan) . should_be_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.
|
||
|
||
Test.group "Atom with holes" <| | ||
Test.specify "construct and fill" <| | ||
pair = Meta.atom_with_hole (e -> My_Type.Value 1 e 3) | ||
|
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.
This is the fix for #6065, right?
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.
Yes, #6065 is addressed in these commits: