Allow hashing of any object

This was technically already supported, but would trigger a panic for
non-permanent objects. By allowing the hashing of any object we simplify
the API, and make it easier to hash complex objects without having to
manually implement the Hash trait for such structures.
parent 3199634c
Pipeline #106500275 passed with stages
in 16 minutes and 48 seconds
......@@ -1518,7 +1518,7 @@ module Inkoc
end
def on_raw_hasher_write(node, _)
node.arguments.fetch(1).type
node.arguments.fetch(0).type
end
def on_raw_hasher_to_hash(*)
......
......@@ -4,7 +4,6 @@
# `False`. Both are regular objects that are instances of the `Boolean` object.
import std::conditional::Conditional
import std::conversion::ToString
import std::hash::(Hasher, Hash)
impl Boolean {
# Returns the `Boolean` that is the opposite of `self`.
......@@ -41,13 +40,6 @@ impl ToString for Boolean {
}
}
impl Hash for Boolean {
def hash(hasher: Hasher) -> Nil {
hasher.write_boolean(self)
Nil
}
}
impl Conditional for False {
def if_true!(R)(block: do -> R) -> ?R {
Nil
......
......@@ -4,7 +4,6 @@
import std::conversion::(ToInteger, ToString, ToFloat)
import std::error::StandardError
import std::hash::(Hasher, Hash)
import std::numeric::Numeric
import std::operators::*
......@@ -346,13 +345,6 @@ impl ToString for Float {
}
}
impl Hash for Float {
def hash(hasher: Hasher) -> Nil {
hasher.write_float(self)
Nil
}
}
# The NAN (Not A Number) value.
let NAN = 0.0 / 0.0
......
......@@ -9,17 +9,8 @@ import std::operators::Equal
# hashed value. This approach makes it easier to hash multiple values together
# such as the bytes in a `String`.
trait Hasher {
# Writes the given `Integer` into this hasher.
def write_integer(value: Integer) -> Integer
# Writes the given `Float` into this hasher.
def write_float(value: Float) -> Float
# Writes the given `String` into this hasher.
def write_string(value: String) -> String
# Writes the given `Boolean` into this hasher.
def write_boolean(value: Boolean) -> Boolean
# Writes the given object into this hasher.
def write(value: Object) -> Self
# Returns the hash for the values written so far.
#
......
......@@ -2,7 +2,6 @@
import std::conversion::(ToInteger, ToString, ToFloat)
import std::error::StandardError
import std::hash::(Hasher, Hash)
import std::numeric::Numeric
import std::operators::*
import std::successor::Successor
......@@ -145,13 +144,6 @@ impl Numeric for Integer {
}
}
impl Hash for Integer {
def hash(hasher: Hasher) -> Nil {
hasher.write_integer(self)
Nil
}
}
impl Successor for Integer {
# Returns the successor of `self`.
#
......
......@@ -32,19 +32,7 @@ object DefaultHasher {
}
impl Hasher for DefaultHasher {
def write_integer(value: Integer) -> Integer {
_INKOC.hasher_write(self, value)
}
def write_float(value: Float) -> Float {
_INKOC.hasher_write(self, value)
}
def write_string(value: String) -> String {
_INKOC.hasher_write(self, value)
}
def write_boolean(value: Boolean) -> Boolean {
def write(value: Object) -> Self {
_INKOC.hasher_write(self, value)
}
......
......@@ -3,6 +3,7 @@
# All objects in Inko are an instance of `Object`, and thus all its methods are
# available to all objects.
import std::conditional::Conditional
import std::hash::(Hasher, Hash)
import std::operators::Equal
impl Conditional for Object {
......@@ -42,3 +43,10 @@ impl Object {
_INKOC.object_equals(nil?, False)
}
}
impl Hash for Object {
def hash(hasher: Hasher) -> Nil {
hasher.write(self)
Nil
}
}
......@@ -3,7 +3,6 @@
# Strings are UTF-8 encoded and immutable. A String must _always_ contain valid
# UTF-8.
import std::conversion::(ToFloat, ToInteger, ToString)
import std::hash::(Hasher, Hash)
import std::length::Length
import std::operators::(Equal, Add)
import std::process
......@@ -235,10 +234,3 @@ impl Add!(String) for String {
_INKOC.string_concat(self, other)
}
}
impl Hash for String {
def hash(hasher: Hasher) -> Nil {
hasher.write_string(self)
Nil
}
}
......@@ -2,67 +2,79 @@ import std::map::(self, DefaultHasher, Pair, RandomState)
import std::test
import std::test::assert
test.group('std::map::DefaultHasher.write_integer') do (g) {
object Dummy {}
test.group('std::map::DefaultHasher.write') do (g) {
g.test('Hashing an Integer') {
let hasher = DefaultHasher.new(1, 2)
hasher.write_integer(10)
hasher.write(10)
let hash1 = hasher.to_hash
hasher.reset
hasher.write_integer(10)
hasher.write(10)
let hash2 = hasher.to_hash
assert.equal(hash1, hash2)
}
}
test.group('std::map::DefaultHasher.write_float') do (g) {
g.test('Hashing an Float') {
let hasher = DefaultHasher.new(1, 2)
hasher.write_float(10.0)
hasher.write(10.0)
let hash1 = hasher.to_hash
hasher.reset
hasher.write_float(10.0)
hasher.write(10.0)
let hash2 = hasher.to_hash
assert.equal(hash1, hash2)
}
}
test.group('std::map::DefaultHasher.write_string') do (g) {
g.test('Hashing a String') {
let hasher = DefaultHasher.new(1, 2)
hasher.write_string('hello')
hasher.write('hello')
let hash1 = hasher.to_hash
hasher.reset
hasher.write_string('hello')
hasher.write('hello')
let hash2 = hasher.to_hash
assert.equal(hash1, hash2)
}
}
test.group('std::map::DefaultHasher.write_boolean') do (g) {
g.test('Hashing a Boolean') {
let hasher = DefaultHasher.new(1, 2)
hasher.write_boolean(True)
hasher.write(True)
let hash1 = hasher.to_hash
hasher.reset
hasher.write(True)
let hash2 = hasher.to_hash
assert.equal(hash1, hash2)
}
g.test('Hashing a regular object') {
let hasher = DefaultHasher.new(1, 2)
let dummy = Dummy.new
hasher.write(dummy)
let hash1 = hasher.to_hash
hasher.reset
hasher.write_boolean(True)
hasher.write(dummy)
let hash2 = hasher.to_hash
......@@ -75,7 +87,7 @@ test.group('std::map::DefaultHasher.reset') do (g) {
let hasher = DefaultHasher.new(1, 2)
let hash1 = hasher.to_hash
hasher.write_integer(10)
hasher.write(10)
hasher.reset
let hash2 = hasher.to_hash
......
......@@ -591,13 +591,7 @@ impl ObjectPointer {
hasher.write_string(val)
}
_ => {
if !self.is_permanent() {
return Err(
"the provided object can not be hashed".to_string()
);
}
hasher.write_unsigned_integer(self.raw.untagged() as usize);
hasher.write_unsigned_integer(self.raw.untagged() as usize)
}
};
}
......
......@@ -24,7 +24,7 @@ pub fn write(
) -> Result<ObjectPointer, String> {
value.hash_object(hasher.hasher_value_mut()?)?;
Ok(value)
Ok(hasher)
}
pub fn to_hash(
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment