Skip to content

Commit d00f1c4

Browse files
committed
Merge pull request #251 from pixie-lang/fix-bad-loops
optimizations for lazy seqs, partial, and immutable_fields
2 parents 0078198 + cfb7379 commit d00f1c4

File tree

8 files changed

+80
-39
lines changed

8 files changed

+80
-39
lines changed

pixie/stdlib.pxi

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -231,16 +231,17 @@
231231
(seq (next coll)))
232232
init)))))
233233

234-
(def indexed-reduce (fn indexed-reduce
235-
[coll f init]
236-
(let [max (count coll)]
237-
(loop [init init
238-
i 0]
239-
(if (reduced? init)
240-
@init
241-
(if (-eq i max)
242-
init
243-
(recur (f init (nth coll i nil)) (+ i 1))))))))
234+
(def indexed-reduce
235+
(fn indexed-reduce
236+
[coll f init]
237+
(let [max (count coll)]
238+
(loop [init init
239+
i 0]
240+
(if (reduced? init)
241+
@init
242+
(if (-eq i max)
243+
init
244+
(recur (f init (nth coll i nil)) (+ i 1))))))))
244245

245246
(def rest (fn ^{:doc "Returns the elements after the first element, or () if there are no more elements."
246247
:signatures [[coll]]
@@ -2148,10 +2149,6 @@ Expands to calls to `extend-type`."
21482149
names)
21492150
result#)))
21502151

2151-
(defn partial [f & args]
2152-
(fn [& args2]
2153-
(apply f (-> args vec (into args2)))))
2154-
21552152
(defn pst
21562153
{:doc "Prints the trace of a Runtime Exception if given, or the last Runtime Exception in *e"
21572154
:signatures [[] [e]]

pixie/vm/array.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
class Array(object.Object):
1515
_type = object.Type(u"pixie.stdlib.Array")
16-
__immutable_fields__ = ["_list[*]"]
16+
_immutable_fields_ = ["_list"]
1717
def type(self):
1818
return Array._type
1919

@@ -76,7 +76,7 @@ def _seq(self):
7676

7777
class ArraySeq(object.Object):
7878
_type = object.Type(u"pixie.stdlib.ArraySeq")
79-
__immutable_fields__ = ["_idx", "_w_array"]
79+
_immutable_fields_ = ["_idx", "_w_array"]
8080

8181
def __init__(self, idx, array):
8282
self._idx = idx

pixie/vm/code.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ def slice_from_start(from_list, count, extra=r_uint(0)):
9191

9292

9393
class BaseCode(object.Object):
94+
_immutable_fields_ = ["_meta"]
9495
def __init__(self):
9596
assert isinstance(self, BaseCode)
9697
self._name = u"unknown"
@@ -213,7 +214,7 @@ def invoke_with(self, args, this_fn):
213214
class Code(BaseCode):
214215
"""Interpreted code block. Contains consts and """
215216
_type = object.Type(u"pixie.stdlib.Code")
216-
__immutable_fields__ = ["_arity", "_consts[*]", "_bytecode", "_stack_size", "_meta"]
217+
_immutable_fields_ = ["_arity", "_consts[*]", "_bytecode", "_stack_size", "_meta"]
217218

218219
def type(self):
219220
return Code._type
@@ -271,7 +272,7 @@ def get_base_code(self):
271272

272273

273274
class VariadicCode(BaseCode):
274-
__immutable_fields__ = ["_required_arity", "_code", "_meta"]
275+
_immutable_fields_ = ["_required_arity", "_code", "_meta"]
275276
_type = object.Type(u"pixie.stdlib.VariadicCode")
276277

277278
def type(self):
@@ -314,7 +315,7 @@ def invoke_with(self, args, self_fn):
314315

315316
class Closure(BaseCode):
316317
_type = object.Type(u"pixie.stdlib.Closure")
317-
__immutable_fields__ = ["_closed_overs[*]", "_code", "_meta"]
318+
_immutable_fields_ = ["_closed_overs[*]", "_code", "_meta"]
318319

319320
def type(self):
320321
return Closure._type
@@ -632,7 +633,7 @@ def invoke(self, args):
632633
class Protocol(object.Object):
633634
_type = object.Type(u"pixie.stdlib.Protocol")
634635

635-
__immutable_fields__ = ["_rev?"]
636+
_immutable_fields_ = ["_rev?"]
636637

637638
def type(self):
638639
return Protocol._type
@@ -664,7 +665,7 @@ class PolymorphicFn(BaseCode):
664665
def type(self):
665666
return PolymorphicFn._type
666667

667-
__immutable_fields__ = ["_rev?"]
668+
_immutable_fields_ = ["_rev?"]
668669

669670
def __init__(self, name, protocol):
670671
BaseCode.__init__(self)
@@ -738,7 +739,7 @@ class DoublePolymorphicFn(BaseCode):
738739
def type(self):
739740
return DefaultProtocolFn._type
740741

741-
__immutable_fields__ = ["_rev?"]
742+
_immutable_fields_ = ["_rev?"]
742743

743744
def __init__(self, name, protocol):
744745
BaseCode.__init__(self)

pixie/vm/custom_types.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import pixie.vm.rt as rt
77

88
class CustomType(Type):
9-
__immutable_fields__ = ["_slots", "_rev?"]
9+
_immutable_fields_ = ["_slots", "_rev?"]
1010
def __init__(self, name, slots):
1111
Type.__init__(self, name)
1212

@@ -36,7 +36,7 @@ def get_num_slots(self):
3636
return len(self._slots)
3737

3838
class CustomTypeInstance(Object):
39-
__immutable_fields__ = ["_type"]
39+
_immutable_fields_ = ["_type"]
4040
def __init__(self, type, fields):
4141
affirm(isinstance(type, CustomType), u"Can't create a instance of a non custom type")
4242
self._custom_type = type

pixie/vm/keyword.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
class Keyword(Object):
1212
_type = Type(u"pixie.stdlib.Keyword")
13-
__immutable_fields__ = ["_hash"]
1413
def __init__(self, name):
1514
self._str = name
1615
self._w_name = None

pixie/vm/lazy_seq.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import pixie.vm.stdlib as proto
44
from pixie.vm.code import extend, as_var
55
import pixie.vm.rt as rt
6+
import rpython.rlib.jit as jit
67

78

89
class LazySeq(object.Object):
@@ -16,6 +17,7 @@ def __init__(self, fn, meta=nil):
1617
self._meta = meta
1718
self._s = nil
1819

20+
@jit.jit_callback("lazy_seq_sval")
1921
def sval(self):
2022
if self._fn is None:
2123
return self._s
@@ -24,6 +26,21 @@ def sval(self):
2426
self._fn = None
2527
return self._s
2628

29+
@jit.dont_look_inside
30+
def lazy_seq_seq(self):
31+
self.sval()
32+
if self._s is not nil:
33+
ls = self._s
34+
while True:
35+
if isinstance(ls, LazySeq):
36+
ls = ls.sval()
37+
continue
38+
else:
39+
self._s = ls
40+
return rt.seq(self._s)
41+
else:
42+
return nil
43+
2744

2845

2946
@extend(proto._first, LazySeq)
@@ -41,18 +58,8 @@ def _next(self):
4158
@extend(proto._seq, LazySeq)
4259
def _seq(self):
4360
assert isinstance(self, LazySeq)
44-
self.sval()
45-
if self._s is not nil:
46-
ls = self._s
47-
while True:
48-
if isinstance(ls, LazySeq):
49-
ls = ls.sval()
50-
continue
51-
else:
52-
self._s = ls
53-
return rt.seq(self._s)
54-
else:
55-
return nil
61+
return self.lazy_seq_seq()
62+
5663

5764
@as_var("lazy-seq*")
5865
def lazy_seq(f):

pixie/vm/stdlib.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,44 @@ def _doc(self):
814814
return rt.wrap(self._doc)
815815

816816

817+
class PartialFunction(code.NativeFn):
818+
_immutable_fields_ = ["_partial_f", "_partial_args"]
819+
def __init__(self, f, args):
820+
code.NativeFn.__init__(self)
821+
self._partial_f = f
822+
self._partial_args = args
823+
824+
@jit.unroll_safe
825+
def invoke(self, args):
826+
new_args = [None] * (len(args) + len(self._partial_args))
827+
828+
for x in range(len(self._partial_args)):
829+
new_args[x] = self._partial_args[x]
830+
831+
plen = len(self._partial_args)
832+
833+
for x in range(len(args)):
834+
new_args[plen + x] = args[x]
835+
836+
837+
return self._partial_f.invoke(new_args)
838+
839+
840+
@as_var("partial")
841+
@jit.unroll_safe
842+
def _partial__args(args):
843+
"""(partial f & args)
844+
Creates a function that is a partial application of f. Thus ((partial + 1) 2) == 3"""
845+
846+
f = args[0]
847+
848+
new_args = [None] * (len(args) - 1)
849+
850+
for x in range(len(new_args)):
851+
new_args[x] = args[x + 1]
852+
853+
return PartialFunction(f, new_args)
854+
817855
@as_var("-get-current-var-frames")
818856
def _get_current_var_frames(self):
819857
"""(-get-current-var-frames)
@@ -826,3 +864,4 @@ def _set_current_var_frames(self, frames):
826864
Sets the current var frames. Frames should be a cons list of hashmaps containing mappings of vars to dynamic
827865
values. Setting this value to anything but this data format will cause undefined errors."""
828866
code._dynamic_vars.set_current_frames(frames)
867+

pixie/vm/symbol.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010

1111
class Symbol(object.Object):
1212
_type = object.Type(u"pixie.stdlib.Symbol")
13-
__immutable_fields__ = ["_hash"]
14-
1513
def __init__(self, s, meta=nil):
1614
#assert isinstance(s, unicode)
1715
self._str = s

0 commit comments

Comments
 (0)