Skip to content

Commit 5a93e4d

Browse files
committed
merge branch 'master' into destructuring
2 parents 123b28f + c1591cc commit 5a93e4d

9 files changed

Lines changed: 191 additions & 26 deletions

File tree

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,19 @@ Some planned and implemented features:
2828
./checkout-externals
2929
./make-with-jit
3030
./pixie-vm
31-
31+
32+
33+
## Running the tests
34+
35+
./pixie-vm run-tests.pxi
36+
37+
38+
## Examples
39+
40+
There are example in the /examples directory.
41+
Try out "Hello World" with:
42+
43+
./examples/hello-world.pxi
3244

3345
## FAQ
3446

pixie/stdlib.pxi

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@
3131
([result] (-persistent! result))
3232
([result item] (-conj! result item))))
3333

34+
(def disj (fn disj
35+
([] [])
36+
([result] result)
37+
([result item] (-disj result item))))
38+
39+
(def disj! (fn conj!
40+
([] (-transient []))
41+
([result] (-persistent! result))
42+
([result item] (-disj! result item))))
43+
3444
(def transient (fn [coll] (-transient coll)))
3545

3646
(def persistent! (fn [coll] (-persistent! coll)))
@@ -197,6 +207,21 @@
197207
(fn [v]
198208
(transduce ordered-hash-reducing-fn v)))
199209

210+
(extend -hash PersistentHashSet
211+
(fn [v]
212+
(transduce ordered-hash-reducing-fn v)))
213+
214+
(extend -hash PersistentHashMap
215+
(fn [v]
216+
(transduce ordered-hash-reducing-fn v)))
217+
218+
(extend -hash EmptyList (fn [v] 5555555))
219+
220+
(extend -hash Bool
221+
(fn [v]
222+
(if v
223+
1111111
224+
3333333)))
200225

201226
(def stacklet->lazy-seq
202227
(fn [k]
@@ -401,6 +426,20 @@
401426
[x]
402427
(- x 1))
403428

429+
(defn empty?
430+
{:doc "returns true if the collection has no items, otherwise false"
431+
:signatures [[coll]]
432+
:added "0.1"}
433+
[coll]
434+
(not (seq coll)))
435+
436+
(defn not-empty?
437+
{:doc "returns true if the collection has items, otherwise false"
438+
:signatures [[coll]]
439+
:added "0.1"}
440+
[coll]
441+
(if (seq coll) true false))
442+
404443
(defn first
405444
{:doc "Returns the first item in coll, if coll implements IIndexed nth will be used to retreive
406445
the item from the collection."
@@ -659,13 +698,13 @@
659698
(reduce get m ks))
660699
([m ks not-found]
661700
(loop [sentinel 'x
662-
mi m
701+
m m
663702
ks (seq ks)]
664703
(if ks
665-
(let [mi (get m (first ks) sentinel)]
666-
(if (identical? sentinel mi)
704+
(let [m (get m (first ks) sentinel)]
705+
(if (identical? sentinel m)
667706
not-found
668-
(recur sentinel mi (next ks))))
707+
(recur sentinel m (next ks))))
669708
m))))
670709

671710
(defn assoc-in

pixie/vm/persistent_hash_map.py

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from pixie.vm.numbers import Integer
66
import pixie.vm.stdlib as proto
77
from pixie.vm.code import extend, as_var
8-
from rpython.rlib.rarithmetic import r_uint, intmask
8+
from rpython.rlib.rarithmetic import r_int, r_uint, intmask
99
import rpython.rlib.jit as jit
1010
import pixie.vm.rt as rt
1111

@@ -108,7 +108,7 @@ def assoc_inode(self, shift, hash_val, key, val, added_leaf):
108108

109109
if key_or_null is None:
110110
assert isinstance(val_or_node, INode)
111-
n = val_or_node.assoc_inode(shift + 5, hash_val, key, val, added_leaf)
111+
n = val_or_node.assoc_inode(shift + 5, hash_val & MASK_32, key, val, added_leaf)
112112
if n is val_or_node:
113113
return self
114114
return BitmapIndexedNode(None, self._bitmap, clone_and_set(self._array, 2 * idx + 1, n))
@@ -226,17 +226,17 @@ def assoc_inode(self, shift, hash_val, key, val, added_leaf):
226226
return self
227227
return ArrayNode(None, self._cnt, clone_and_set(self._array, idx, n))
228228

229-
def without_inode(self, shift, hash, key):
230-
idx = mask(hash, shift)
229+
def without_inode(self, shift, hash_val, key):
230+
idx = r_uint(mask(hash_val, shift))
231231
node = self._array[idx]
232232
if node is None:
233233
return self
234-
n = node.without_inode(shift + 5, hash, key)
234+
n = node.without_inode(shift + 5, hash_val, key)
235235
if n is node:
236236
return self
237237
if n is None:
238238
if self._cnt <= 8: # shrink
239-
return self.pack(None, idx)
239+
return self.pack(idx)
240240
return ArrayNode(None, self._cnt - 1, clone_and_set(self._array, idx, n))
241241
else:
242242
return ArrayNode(None, self._cnt, clone_and_set(self._array, idx, n))
@@ -250,7 +250,7 @@ def pack(self, idx):
250250
while i < idx:
251251
if self._array[i] is not None:
252252
new_array[j] = self._array[i]
253-
bitmap |= 1 << i
253+
bitmap |= r_uint(1) << i
254254
j += 2
255255

256256
i += 1
@@ -259,7 +259,7 @@ def pack(self, idx):
259259
while i < len(self._array):
260260
if self._array[i] is not None:
261261
new_array[j] = self._array[i]
262-
bitmap |= 1 << i
262+
bitmap |= r_uint(1) << i
263263
j += 2
264264

265265
i += 1
@@ -291,7 +291,22 @@ def __init__(self, edit, hash, array):
291291
self._array = array
292292

293293
def assoc_inode(self, shift, hash_val, key, val, added_leaf):
294-
assert False
294+
if hash_val == self._hash:
295+
count = len(self._array)
296+
idx = self.find_index(key)
297+
if idx != -1:
298+
if self._array[idx + 1] == val:
299+
return self;
300+
return HashCollisionNode(None, hash_val, clone_and_set(self._array, r_uint(idx + 1), val))
301+
302+
new_array = [None] * (count + 2)
303+
list_copy(self._array, 0, new_array, 0, count)
304+
new_array[count] = key
305+
added_leaf._val = added_leaf
306+
new_array[count + 1] = val
307+
return HashCollisionNode(self._edit, self._hash, new_array)
308+
return BitmapIndexedNode(None, bitpos(self._hash, shift), [None, self]) \
309+
.assoc_inode(shift, hash_val, key, val, added_leaf)
295310

296311
def find(self, shift, hash_val, key, not_found):
297312
for x in range(0, len(self._array), 2):
@@ -314,29 +329,29 @@ def reduce_inode(self, f, init):
314329
return init
315330

316331
def find_index(self, key):
317-
i = 0
332+
i = r_int(0)
318333
while i < len(self._array):
319334
if rt.eq(key, self._array[i]):
320335
return i
321336

322337
i += 2
323338

324-
return -1
339+
return r_int(-1)
325340

326-
def without(self, shift, hash, key):
341+
def without_inode(self, shift, hash, key):
327342
idx = self.find_index(key)
328343
if idx == -1:
329344
return self
330345

331346
if len(self._array) == 1:
332347
return None
333348

334-
return HashCollisionNode(None, self._hash, remove_pair(self._array, idx / 2))
349+
return HashCollisionNode(None, self._hash, remove_pair(self._array, r_uint(idx) / 2))
335350

336351

337352

338353
def create_node(shift, key1, val1, key2hash, key2, val2):
339-
key1hash = rt.hash(key1)
354+
key1hash = rt.hash(key1) & MASK_32
340355
if key1hash == key2hash:
341356
return HashCollisionNode(None, key1hash, [key1, val1, key2, val2])
342357
added_leaf = Box()

pixie/vm/persistent_hash_set.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ def __init__(self, meta, m):
2323
def conj(self, v):
2424
return PersistentHashSet(self._meta, self._map.assoc(v, v))
2525

26+
def disj(self, k):
27+
return PersistentHashSet(self._meta, self._map.without(k))
28+
2629
def meta(self):
2730
return self._meta
2831

@@ -77,6 +80,11 @@ def _conj(self, v):
7780
assert isinstance(self, PersistentHashSet)
7881
return self.conj(v)
7982

83+
@extend(proto._disj, PersistentHashSet)
84+
def _disj(self, v):
85+
assert isinstance(self, PersistentHashSet)
86+
return self.disj(v)
87+
8088
@extend(proto._reduce, PersistentHashSet)
8189
def _reduce(self, f, init):
8290
assert isinstance(self, PersistentHashSet)

pixie/vm/stdlib.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
defprotocol("pixie.stdlib", "IIndexed", ["-nth"])
2121

22-
defprotocol("pixie.stdlib", "IPersistentCollection", ["-conj"])
22+
defprotocol("pixie.stdlib", "IPersistentCollection", ["-conj", "-disj"])
2323

2424
defprotocol("pixie.stdlib", "IEmpty", ["-empty"])
2525

@@ -509,6 +509,11 @@ def set_macro(f):
509509
f.set_macro()
510510
return f
511511

512+
@returns(bool)
513+
@as_var("macro?")
514+
def macro_QMARK_(f):
515+
return true if isinstance(f, BaseCode) and f.is_macro() else false
516+
512517
@returns(unicode)
513518
@as_var("name")
514519
def name(s):

pixie/vm/string.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import pixie.vm.stdlib as proto
66
import pixie.vm.numbers as numbers
77
import pixie.vm.util as util
8-
from rpython.rlib.rarithmetic import intmask
8+
from rpython.rlib.rarithmetic import intmask, r_uint
99

1010
class String(Object):
1111
_type = Type(u"pixie.stdlib.String")
@@ -85,6 +85,11 @@ def _eq(self, obj):
8585
return false
8686
return true if self.char_val() == obj.char_val() else false
8787

88+
@extend(proto._hash, Character)
89+
def _hash(self):
90+
return rt.wrap(intmask(util.hash_int(r_uint(self.char_val()))))
91+
92+
8893
@extend(proto._name, String)
8994
def _name(self):
9095
return self

tests/collections/test-sets.pxi

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,40 @@
11
(ns collections.test-sets
2-
(require pixie.test :as t))
2+
(require pixie.test :as t)
3+
(require tests.utils :as u))
4+
5+
(def worst-hashers (vec (map u/->WorstHasher)
6+
(range 100)))
37

48
(t/deftest test-count
59
(t/assert= (count (set [])) 0)
610
(t/assert= (count (set [1 2 3])) 3)
7-
(t/assert= (count (set [1 1 2 1])) 2))
11+
(t/assert= (count (set [1 1 2 1])) 2)
12+
(t/assert= (count (set worst-hashers)) 100))
813

914
(t/deftest test-contains
1015
(let [s #{1 2 3}
1116
c [1 2 3]
12-
n [-1 0 4]]
17+
n [-1 0 4]
18+
g (set worst-hashers)]
1319
(foreach [c c]
1420
(t/assert= (contains? s c) true))
1521
(foreach [n n]
16-
(t/assert= (contains? s n) false))))
22+
(t/assert= (contains? s n) false))
23+
(foreach [n worst-hashers]
24+
(t/assert= (contains? g n) true))))
25+
26+
(t/deftest test-conj
27+
(t/assert= (conj #{}) #{})
28+
(t/assert= (conj #{1 2} 3) #{1 2 3})
29+
(t/assert= (reduce conj #{} (range 10)) (set (vec (range 10))))
30+
(t/assert= (reduce conj #{} worst-hashers) (set worst-hashers)))
31+
32+
(t/deftest test-disj
33+
(t/assert= (disj #{}) #{})
34+
(t/assert= (disj #{1 2} 3) #{1 2})
35+
(t/assert= (disj #{1 2} 2) #{1})
36+
(t/assert= (reduce disj (set (vec (range 10))) (range 10)) #{})
37+
(t/assert= (reduce disj (set worst-hashers) worst-hashers) #{}))
1738

1839
(t/deftest test-eq
1940
(let [s #{1 2 3}]

tests/test-stdlib.pxi

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,37 @@
3939
(t/assert= (butlast l) res)
4040
(t/assert= (butlast r) res)))
4141

42+
(t/deftest test-empty?
43+
(t/assert= (empty? []) true)
44+
(t/assert= (empty? '()) true)
45+
(t/assert= (empty? (make-array 0)) true)
46+
(t/assert= (empty? {}) true)
47+
(t/assert= (empty? #{}) true)
48+
(t/assert= (empty? (range 1 5)) false)
49+
50+
(t/assert= (empty? [1 2 3]) false)
51+
(t/assert= (empty? '(1 2 3)) false)
52+
(let [a (make-array 1)]
53+
(aset a 0 1)
54+
(t/assert= (empty? a) false))
55+
(t/assert= (empty? {:a 1}) false)
56+
(t/assert= (empty? #{:a :b}) false))
57+
58+
(t/deftest test-not-empty?
59+
(t/assert= (not-empty? []) false)
60+
(t/assert= (not-empty? '()) false)
61+
(t/assert= (not-empty? (make-array 0)) false)
62+
(t/assert= (not-empty? {}) false)
63+
(t/assert= (not-empty? #{}) false)
64+
(t/assert= (not-empty? (range 1 5)) true)
65+
66+
(t/assert= (not-empty? [1 2 3]) true)
67+
(t/assert= (not-empty? '(1 2 3)) true)
68+
(let [a (make-array 1)]
69+
(aset a 0 1)
70+
(t/assert= (not-empty? a) true))
71+
(t/assert= (not-empty? {:a 1}) true)
72+
(t/assert= (not-empty? #{:a :b}) true))
4273

4374
(t/deftest test-keys
4475
(let [v {:a 1 :b 2 :c 3}]
@@ -73,6 +104,13 @@
73104
(t/assert= (vec (keep pos?) v) [true true true true true])
74105
(t/assert= (vec (keep pos? v)) (vec (keep pos?) v))))
75106

107+
(t/deftest test-get-in
108+
(let [m {:a 1 :b 2 :x {:a 2 :x [1 2 3]}}]
109+
(t/assert= (get-in m [:a]) 1)
110+
(t/assert= (get-in m [:missing]) nil)
111+
(t/assert= (get-in m [:missing] :not-found) :not-found)
112+
(t/assert= (get-in m [:x :x 0] :not-found) 1)))
113+
76114
(t/deftest test-fn?
77115
(t/assert= (fn? inc) true)
78116
(t/assert= (fn? {}) true)
@@ -81,4 +119,13 @@
81119
(t/assert= (fn? 1) false)
82120
(t/assert= (fn? and) false)
83121
(t/assert= (fn? "foo") false)
84-
(t/assert (fn? (let [x 8] (fn [y] (+ x y)))) true))
122+
(t/assert= (fn? (let [x 8] (fn [y] (+ x y)))) true))
123+
124+
(t/deftest test-macro?
125+
(t/assert= (macro? and) true)
126+
(t/assert= (macro? or) true)
127+
(t/assert= (macro? defn) true)
128+
(t/assert= (macro? inc) false)
129+
(t/assert= (macro? 1) false)
130+
(t/assert= (macro? :foo) false)
131+
(t/assert= (macro? "foo") false))

0 commit comments

Comments
 (0)