Skip to content
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

Make digestof and hash() return USize instead of U64 and add hash64() #2615

Merged
merged 1 commit into from
Apr 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ All notable changes to the Pony compiler and standard library will be documented
- Support OpenSSL 1.1.0 ([PR #2415](https://github.com/ponylang/ponyc/pull/2415))
- Add U64 type to `cli` package. ([PR #2488](https://github.com/ponylang/ponyc/pull/2488))
- Allow customisation of `Env.input` and `Env.exitcode` in artificial environments
- `hash64()` function and related helper types in `collections` for 64-bit hashes ([PR #2615](https://github.com/ponylang/ponyc/pull/2615))

### Changed

Expand All @@ -53,6 +54,7 @@ All notable changes to the Pony compiler and standard library will be documented
- Fix and re-enable dynamic scheduler scaling ([PR #2483](https://github.com/ponylang/ponyc/pull/2483))
- Expose OutStream rather than StdStream in Env ([PR #2463](https://github.com/ponylang/ponyc/pull/2463))
- Rename StdinNotify to InputNotify
- `digestof` and `hash()` now return USize instead of U64 ([PR #2615](https://github.com/ponylang/ponyc/pull/2615))

## [0.21.3] - 2018-01-14

Expand Down
6 changes: 4 additions & 2 deletions packages/builtin/float.pony
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ primitive F32 is FloatingPoint[F32]

fun copysign(sign: F32): F32 => @"llvm.copysign.f32"[F32](this, sign)

fun hash(): U64 => bits().hash()
fun hash(): USize => bits().hash()
fun hash64(): U64 => bits().hash64()

fun i128(): I128 => f64().i128()
fun u128(): U128 => f64().u128()
Expand Down Expand Up @@ -359,7 +360,8 @@ primitive F64 is FloatingPoint[F64]

fun copysign(sign: F64): F64 => @"llvm.copysign.f64"[F64](this, sign)

fun hash(): U64 => bits().hash()
fun hash(): USize => bits().hash()
fun hash64(): U64 => bits().hash64()

fun i128(): I128 =>
if this > I128.max_value().f64() then
Expand Down
8 changes: 7 additions & 1 deletion packages/builtin/pointer.pony
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,14 @@ struct Pointer[A]
fun tag ge(that: Pointer[A] tag): Bool => not lt(that)
fun tag gt(that: Pointer[A] tag): Bool => not le(that)

fun tag hash(): U64 =>
fun tag hash(): USize =>
"""
Returns a hash of the address.
"""
usize().hash()

fun tag hash64(): U64 =>
"""
Returns a 64-bit hash of the address.
"""
usize().hash64()
20 changes: 19 additions & 1 deletion packages/builtin/real.pony
Original file line number Diff line number Diff line change
Expand Up @@ -156,15 +156,33 @@ trait val Real[A: Real[A] val] is
fun min(y: A): A
fun max(y: A): A

fun hash(): U64 =>
fun hash(): USize =>
var x = usize()

ifdef ilp32 then
x = (not x) + (x << 15)
x = x xor (x >> 12)
x = x + (x << 2)
x = x xor (x >> 4)
x = (x + (x << 3)) + (x << 11)
x = x xor (x >> 16)

x
else
hash64().usize()
end

fun hash64(): U64 =>
var x = u64()

x = (not x) + (x << 21)
x = x xor (x >> 24)
x = (x + (x << 3)) + (x << 8)
x = x xor (x >> 14)
x = (x + (x << 2)) + (x << 4)
x = x xor (x >> 28)
x = x + (x << 31)

x

fun _value(): A => compile_intrinsic
Expand Down
5 changes: 4 additions & 1 deletion packages/builtin/signed.pony
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ primitive I64 is _SignedInteger[I64, U64]

fun min(y: I64): I64 => if this < y then this else y end
fun max(y: I64): I64 => if this > y then this else y end
fun hash(): USize => u64().hash()

fun addc(y: I64): (I64, Bool) =>
@"llvm.sadd.with.overflow.i64"[(I64, Bool)](this, y)
Expand Down Expand Up @@ -227,6 +228,7 @@ primitive ILong is _SignedInteger[ILong, ULong]
fun bitwidth(): ULong => ifdef ilp32 or llp64 then 32 else 64 end
fun min(y: ILong): ILong => if this < y then this else y end
fun max(y: ILong): ILong => if this > y then this else y end
fun hash(): USize => ulong().hash()

fun addc(y: ILong): (ILong, Bool) =>
ifdef ilp32 or llp64 then
Expand Down Expand Up @@ -366,7 +368,8 @@ primitive I128 is _SignedInteger[I128, U128]
fun bitwidth(): U128 => 128
fun min(y: I128): I128 => if this < y then this else y end
fun max(y: I128): I128 => if this > y then this else y end
fun hash(): U64 => ((this.u128() >> 64).u64() xor this.u64()).hash()
fun hash(): USize => u128().hash()
fun hash64(): U64 => u128().hash64()

fun string(): String iso^ =>
_ToString._u128(abs().u128(), this < 0)
Expand Down
7 changes: 5 additions & 2 deletions packages/builtin/string.pony
Original file line number Diff line number Diff line change
Expand Up @@ -1480,8 +1480,11 @@ actor Main
F64(0)
end

fun hash(): U64 =>
@ponyint_hash_block[U64](_ptr, _size)
fun hash(): USize =>
@ponyint_hash_block[USize](_ptr, _size)

fun hash64(): U64 =>
@ponyint_hash_block64[U64](_ptr, _size)

fun string(): String iso^ =>
clone()
Expand Down
28 changes: 27 additions & 1 deletion packages/builtin/unsigned.pony
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,13 @@ primitive U64 is _UnsignedInteger[U64]
fun min(y: U64): U64 => if this < y then this else y end
fun max(y: U64): U64 => if this > y then this else y end

fun hash(): USize =>
ifdef ilp32 then
((this >> 32).u32() xor this.u32()).hash()
else
usize().hash()
end

fun addc(y: U64): (U64, Bool) =>
@"llvm.uadd.with.overflow.i64"[(U64, Bool)](this, y)

Expand Down Expand Up @@ -247,6 +254,13 @@ primitive ULong is _UnsignedInteger[ULong]
fun min(y: ULong): ULong => if this < y then this else y end
fun max(y: ULong): ULong => if this > y then this else y end

fun hash(): USize =>
ifdef ilp32 or llp64 then
u32().hash()
else
u64().hash()
end

fun addc(y: ULong): (ULong, Bool) =>
ifdef ilp32 or llp64 then
@"llvm.uadd.with.overflow.i32"[(ULong, Bool)](this, y)
Expand Down Expand Up @@ -396,7 +410,19 @@ primitive U128 is _UnsignedInteger[U128]
fun bitwidth(): U128 => 128
fun min(y: U128): U128 => if this < y then this else y end
fun max(y: U128): U128 => if this > y then this else y end
fun hash(): U64 => ((this >> 64).u64() xor this.u64()).hash()

fun hash(): USize =>
ifdef ilp32 then
((this >> 96).u32() xor
(this >> 64).u32() xor
(this >> 32).u32() xor
this.u32()).hash()
else
((this >> 64).u64() xor this.u64()).hash()
end

fun hash64(): U64 =>
((this >> 64).u64() xor this.u64()).hash64()

fun string(): String iso^ =>
_ToString._u128(this, false)
Expand Down
68 changes: 60 additions & 8 deletions packages/collections/hashable.pony
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ interface Hashable
"""
Anything with a hash method is hashable.
"""
fun hash(): U64
fun hash(): USize

interface Hashable64
"""
A version of Hashable that returns 64-bit hashes on every platform.
"""
fun hash64(): U64

interface val HashFunction[A]
"""
Expand All @@ -13,7 +19,29 @@ interface val HashFunction[A]
Data structures create instances internally. Use a primitive if possible.
"""

fun hash(x: box->A!): U64
fun hash(x: box->A!): USize
"""
Calculate the hash of some type. This is an alias of the type parameter to
allow data structures to hash things without consuming them.
"""

fun eq(x: box->A!, y: box->A!): Bool
"""
Determine equality between two keys with the same hash. This is done with
viewpoint adapted aliases to allow data structures to determine equality
in a box fun without consuming keys.
"""

interface val HashFunction64[A]
"""
A pluggable hash function with 64-bit hashes.
"""
new val create()
"""
Data structures create instances internally. Use a primitive if possible.
"""

fun hash64(x: box->A!): U64
"""
Calculate the hash of some type. This is an alias of the type parameter to
allow data structures to hash things without consuming them.
Expand All @@ -27,7 +55,7 @@ interface val HashFunction[A]
"""

primitive HashEq[A: (Hashable #read & Equatable[A] #read)] is HashFunction[A]
fun hash(x: box->A): U64 =>
fun hash(x: box->A): USize =>
"""
Use the hash function from the type parameter.
"""
Expand All @@ -39,25 +67,49 @@ primitive HashEq[A: (Hashable #read & Equatable[A] #read)] is HashFunction[A]
"""
x == y

primitive HashIs[A] is HashFunction[A]
fun hash(x: box->A!): U64 =>
primitive HashEq64[A: (Hashable64 #read & Equatable[A] #read)] is
HashFunction64[A]
fun hash64(x: box->A): U64 =>
"""
Use the hash function from the type parameter.
"""
x.hash64()

fun eq(x: box->A, y: box->A): Bool =>
"""
Use the structural equality function from the type parameter.
"""
x == y

primitive HashIs[A] is (HashFunction[A] & HashFunction64[A])
fun hash(x: box->A!): USize =>
"""
Hash the identity rather than the contents.
"""
(digestof x).hash()

fun hash64(x: box->A!): U64 =>
"""
Hash the identity rather than the contents.
"""
(digestof x).hash64()

fun eq(x: box->A!, y: box->A!): Bool =>
"""
Determine equality by identity rather than structurally.
"""
x is y

primitive HashByteSeq
primitive HashByteSeq is
(HashFunction[ByteSeq box] & HashFunction64[ByteSeq box])
"""
Hash and equality functions for arbitrary ByteSeq.
"""
fun hash(x: ByteSeq box): U64 =>
@ponyint_hash_block[U64](x.cpointer(), x.size())
fun hash(x: ByteSeq box): USize =>
@ponyint_hash_block[USize](x.cpointer(), x.size())

fun hash64(x: ByteSeq box): U64 =>
@ponyint_hash_block64[U64](x.cpointer(), x.size())

fun eq(x: ByteSeq box, y: ByteSeq box): Bool =>
if x.size() == y.size() then
Expand Down
2 changes: 1 addition & 1 deletion packages/net/http/_host_service.pony
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class val _HostService is (Hashable & Equatable[_HostService])
host = host'
service = service'

fun hash(): U64 =>
fun hash(): USize =>
scheme.hash() xor host.hash() xor service.hash()

fun eq(that: _HostService box): Bool =>
Expand Down
2 changes: 1 addition & 1 deletion src/libponyc/ast/stringtab.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ typedef struct stringtab_entry_t

static size_t stringtab_hash(stringtab_entry_t* a)
{
return (size_t)ponyint_hash_block(a->str, a->len);
return ponyint_hash_block(a->str, a->len);
}

static bool stringtab_cmp(stringtab_entry_t* a, stringtab_entry_t* b)
Expand Down
Loading