changeset 349:60292f131de9

Make map actually work right on hashmaps
author Michael Pavone <pavone@retrodev.com>
date Fri, 10 Apr 2015 01:19:10 -0700
parents a840e9a068a2
children a3b06d53bcb9
files modules/dict.tp
diffstat 1 files changed, 118 insertions(+), 114 deletions(-) [+]
line wrap: on
line diff
--- a/modules/dict.tp	Fri Apr 10 00:48:42 2015 -0700
+++ b/modules/dict.tp	Fri Apr 10 01:19:10 2015 -0700
@@ -102,6 +102,120 @@
 			= <- :other { k = other }
 		}
 	}
+	_hashWithBuckets:size:hashdiffs <- :_buckets :_size :_hashdiffs {
+		#{
+			size <- { size }
+			ifget:else <- :key ifpres :ifnot {
+				basehash <- key hash
+				notdone <- true
+				i <- 0
+				ret <- _empty
+
+				while: { if: notdone { i < (_hashdiffs length)}} do: {
+					hv <- basehash + (_hashdiffs get: i)
+					trunc <- hv % (_buckets length)
+					if: trunc < 0 { trunc <- 0 - trunc }
+					bucket <- _buckets get: trunc
+					if: (bucket empty?) {
+						notdone <- false
+					} else: {
+						if: bucket = key {
+							ret <- bucket
+							notdone <- false
+						}
+					}
+					i <- i + 1
+				}
+				if: (ret empty?) ifnot else: {
+					ifpres: (ret v)
+				}
+			}
+
+			get:else <- :key :else {
+				ifget: key :val {
+					val
+				} else: else
+			}
+
+			contains? <- :key {
+				ifget: key :_ {
+					true
+				} else: {
+					false
+				}
+			}
+
+			set <- :key val {
+				notdone <- true
+				basehash <- key hash
+				i <- 0
+				while: { if: notdone { i < (_hashdiffs length) } } do: {
+					hv <- basehash + (_hashdiffs get: i)
+					trunc <- hv % (_buckets length)
+					if: trunc < 0 { trunc <- 0 - trunc }
+					bucket <- (_buckets get: trunc)
+					if: (bucket empty?) {
+						_size <- _size + 1
+						_buckets set: trunc (_makeBucket: key val)
+						notdone <- false
+					} else: {
+						if: bucket = key {
+							bucket v!: val
+							notdone <- false
+						}
+					}
+					i <- i + 1
+				}
+				if: notdone {
+					newsize <- (_buckets length) * 3 + 1
+					lastdiff <- _hashdiffs get: ((_hashdiffs length) - 1)
+					if: lastdiff <= 0 {
+						_hashdiffs append: 0 - lastdiff + 1
+					} else: {
+						_hashdiffs append: 0 - lastdiff
+					}
+					newbucks <- #[]
+					newbucks resize: newsize
+					while: { (newbucks length) < newsize } do: {
+						newbucks append: _empty
+					}
+					oldbucks <- _buckets
+					_buckets <- newbucks
+					_size <- 0
+					foreach: oldbucks :idx el {
+						if: (not: (el empty?)) {
+							set: (el k) (el v)
+						}
+					}
+					set: key val
+				}
+				self
+			}
+
+			foreach <- :fun {
+				foreach: _buckets :idx el {
+					if: (not: (el empty?)) {
+						fun: (el k) (el v)
+					}
+				}
+			}
+			
+			map <- :fun {
+				newbucks <- _buckets map: :bucket {
+					if: (bucket empty?) {
+						bucket
+					} else: {
+						_makeBucket: (bucket k) (fun: (bucket v))
+					}
+				}
+				_hashWithBuckets: newbucks size: _size hashdiffs: (_hashdiffs map: :e { e })
+			}
+
+			jsonEncode <- {
+				_jsonEncode: self
+			}
+		}
+	}
 	#{
 		//requires only that keys support equality
 		linear <- {
@@ -110,123 +224,13 @@
 
 		//requires that keys support equality and hash
 		hash <- {
-
-			_buckets <- #[
+			_hashWithBuckets: #[
 				_empty
 				_empty
 				_empty
-				_empty]
-			_size <- 0
-			_hashdiffs <- #[0]
-			#{
-				size <- { size }
-				ifget:else <- :key ifpres :ifnot {
-					basehash <- key hash
-					notdone <- true
-					i <- 0
-					ret <- _empty
-
-					while: { if: notdone { i < (_hashdiffs length)}} do: {
-						hv <- basehash + (_hashdiffs get: i)
-						trunc <- hv % (_buckets length)
-						if: trunc < 0 { trunc <- 0 - trunc }
-						bucket <- _buckets get: trunc
-						if: (bucket empty?) {
-							notdone <- false
-						} else: {
-							if: bucket = key {
-								ret <- bucket
-								notdone <- false
-							}
-						}
-						i <- i + 1
-					}
-					if: (ret empty?) ifnot else: {
-						ifpres: (ret v)
-					}
-				}
-
-				get:else <- :key :else {
-					ifget: key :val {
-						val
-					} else: else
-				}
-
-				contains? <- :key {
-					ifget: key :_ {
-						true
-					} else: {
-						false
-					}
-				}
-
-				set <- :key val {
-					notdone <- true
-					basehash <- key hash
-					i <- 0
-					while: { if: notdone { i < (_hashdiffs length) } } do: {
-						hv <- basehash + (_hashdiffs get: i)
-						trunc <- hv % (_buckets length)
-						if: trunc < 0 { trunc <- 0 - trunc }
-						bucket <- (_buckets get: trunc)
-						if: (bucket empty?) {
-							_size <- _size + 1
-							_buckets set: trunc (_makeBucket: key val)
-							notdone <- false
-						} else: {
-							if: bucket = key {
-								bucket v!: val
-								notdone <- false
-							}
-						}
-						i <- i + 1
-					}
-					if: notdone {
-						newsize <- (_buckets length) * 3 + 1
-						lastdiff <- _hashdiffs get: ((_hashdiffs length) - 1)
-						if: lastdiff <= 0 {
-							_hashdiffs append: 0 - lastdiff + 1
-						} else: {
-							_hashdiffs append: 0 - lastdiff
-						}
-						newbucks <- #[]
-						newbucks resize: newsize
-						while: { (newbucks length) < newsize } do: {
-							newbucks append: _empty
-						}
-						oldbucks <- _buckets
-						_buckets <- newbucks
-						_size <- 0
-						foreach: oldbucks :idx el {
-							if: (not: (el empty?)) {
-								set: (el k) (el v)
-							}
-						}
-						set: key val
-					}
-					self
-				}
-
-				foreach <- :fun {
-					foreach: _buckets :idx el {
-						if: (not: (el empty?)) {
-							fun: (el k) (el v)
-						}
-					}
-				}
-				
-				map <- :fun {
-					foreach: _buckets :idx el {
-						if: (not: (el empty?)) {
-							el v!: (fun: (el v))
-						}
-					}
-				}
-
-				jsonEncode <- {
-					_jsonEncode: self
-				}
-			}
+				_empty
+			] size: 0 hashdiffs: #[0]
+			
 		}
 
 		main <- {