Skip to content
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
12 changes: 12 additions & 0 deletions pixie/test.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,22 @@
yr# ~y]
(assert (= xr# yr#) (str (show '~x xr#) " != " (show '~y yr#)))))

(defmacro assert-throws? [klass msg body]
`(try
~body
(assert false (str "Expected a " ~klass " exception: " ~msg))
(catch e#
(assert (= (type e#) ~klass)
(str "Expected exception of class " ~klass " but got " (type e#)))
(assert (= (ex-msg e#) ~msg)
(str "Expected message: " ~msg " but got " (ex-msg e#))))))

(defmacro assert [x]
`(let [x# ~x]
(assert x# (str '~x " is " x#))))



(defn show
([orig res]
(if (= orig res)
Expand Down
31 changes: 25 additions & 6 deletions pixie/vm/code.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
py_object = object
import pixie.vm.object as object
from pixie.vm.object import affirm
from pixie.vm.object import affirm, runtime_error
from pixie.vm.primitives import nil, false
from rpython.rlib.rarithmetic import r_uint
from rpython.rlib.jit import elidable_promote, promote
Expand Down Expand Up @@ -101,6 +101,9 @@ def meta(self):
def with_meta(self, meta):
assert false, "not implemented"

def name(self):
return self._name

def set_macro(self):
self._is_macro = True

Expand Down Expand Up @@ -130,15 +133,16 @@ class MultiArityFn(BaseCode):
def type(self):
return MultiArityFn._type

def __init__(self, arities, required_arity=0, rest_fn=None, meta=nil):
def __init__(self, name, arities, required_arity=0, rest_fn=None, meta=nil):
BaseCode.__init__(self)
self._name = name
self._arities = arities
self._required_arity = required_arity
self._rest_fn = rest_fn
self._meta = meta

def with_meta(self, meta):
return MultiArityFn(self._arities, self._required_arity, self._rest_fn, meta)
return MultiArityFn(self._name, self._arities, self._required_arity, self._rest_fn, meta)

@elidable_promote()
def get_fn(self, arity):
Expand All @@ -153,9 +157,9 @@ def get_fn(self, arity):
acc.append(unicode(str(x)))

if self._rest_fn:
acc.append(u" or more")
acc.append(unicode(str(self._rest_fn.required_arity())) + u" or more")

affirm(False, u"Wrong number of args to fn: got " + unicode(str(arity)) + u" expected " + u",".join(acc))
runtime_error(u"Wrong number of arguments " + unicode(str(arity)) + u" for function '" + unicode(self._name) + u"'. Expected " + u",".join(acc))

def invoke(self, args):
return self.invoke_with(args, self)
Expand Down Expand Up @@ -209,7 +213,12 @@ def get_debug_points(self):
return self._debug_points

def invoke(self, args):
return self.invoke_with(args, self)
if len(args) == self.get_arity():
return self.invoke_with(args, self)
else:
runtime_error(u"Invalid number of arguments " + unicode(str(len(args)))
+ u" for function '" + unicode(str(self._name)) + u"'. Expected "
+ unicode(str(self.get_arity())))

def invoke_with(self, args, this_fn):
try:
Expand Down Expand Up @@ -254,6 +263,12 @@ def __init__(self, code, required_arity, meta=nil):

def with_meta(self, meta):
return VariadicCode(self._code, self._required_arity, meta)

def name(self):
return None

def required_arity(self):
return self._required_arity

def invoke(self, args):
return self.invoke_with(args, self)
Expand Down Expand Up @@ -292,6 +307,10 @@ def __init__(self, code, closed_overs, meta=nil):
def with_meta(self, meta):
return Closure(self._code, self._closed_overs, meta)


def name(self):
return None

def invoke(self, args):
return self.invoke_with(args, self)

Expand Down
2 changes: 1 addition & 1 deletion pixie/vm/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def gensym2(prefix):
return rt.symbol(rt.str(prefix, i))

gensym = code.intern_var(u"pixie.stdlib", u"gensym")
gensym.set_root(code.MultiArityFn({0: code.wrap_fn(gensym1), 1: code.wrap_fn(gensym2)}))
gensym.set_root(code.MultiArityFn(u"gensym", {0: code.wrap_fn(gensym1), 1: code.wrap_fn(gensym2)}))

class with_ns(object):
def __init__(self, nm, include_stdlib=False):
Expand Down
13 changes: 5 additions & 8 deletions pixie/vm/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,8 @@ def push_nth(self, delta):
self.push(self.nth(delta))

def push_arg(self, idx):
if not 0 <= idx < len(self.args):
runtime_error(u"Invalid number of arguments " + unicode(str(idx))
+ u" for function '" + unicode(str(self.code_obj._name)) + u"'. Expected "
+ unicode(str(self.code_obj.get_arity())))

self.push(self.args[r_uint(idx)])
if 0 <= idx < len(self.args):
self.push(self.args[r_uint(idx)])

@unroll_safe
def push_n(self, args, argc):
Expand Down Expand Up @@ -140,6 +136,7 @@ def make_multi_arity(frame, argc):
d = {}
required_arity = 0
rest_fn = None
fn_name = None
for i in range(argc):
a = frame.get_inst()
if a & 256:
Expand All @@ -148,9 +145,9 @@ def make_multi_arity(frame, argc):
rest_fn = frame.pop()
else:
fn = frame.pop()
fn_name = fn.name()
d[a] = fn

return code.MultiArityFn(d, required_arity, rest_fn)
return code.MultiArityFn(fn_name, d, required_arity, rest_fn)

class ShallowContinuation(Object):
_type = Type(u"pixie.stdlib.ShallowContinuation")
Expand Down
4 changes: 2 additions & 2 deletions pixie/vm/libs/string.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def index_of4(a, sep, start, end):
runtime_error(u"Third and fourth argument must be non-negative integers")

index_of = intern_var(u"pixie.string.internal", u"index-of")
index_of.set_root(MultiArityFn({2: wrap_fn(index_of2), 3: wrap_fn(index_of3), 4: wrap_fn(index_of4)},
index_of.set_root(MultiArityFn(u"index-of", {2: wrap_fn(index_of2), 3: wrap_fn(index_of3), 4: wrap_fn(index_of4)},
required_arity = 2))

def substring2(a, start):
Expand All @@ -64,7 +64,7 @@ def substring3(a, start, end):
runtime_error(u"Second and third argument must be non-negative integers")

substring = intern_var(u"pixie.string.internal", u"substring")
substring.set_root(MultiArityFn({2: wrap_fn(substring2), 3: wrap_fn(substring3)},
substring.set_root(MultiArityFn(u"substring", {2: wrap_fn(substring2), 3: wrap_fn(substring3)},
required_arity = 2))

@as_var("pixie.string.internal", "upper-case")
Expand Down
75 changes: 38 additions & 37 deletions tests/pixie/tests/test-fns.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -18,40 +18,41 @@
(t/deftest test-code-arity-errors
(let [arity-0 (fn arity-0 [])
arity-1 (fn arity-1 [a])
arity-2 (fn arity-2 [a b])]
(try
(arity-0 :foo)
(catch e
(t/assert=
(ex-msg e)
"Invalid number of arguments 1 for function 'arity-0'. Expected 0")))
(try
(arity-0 :foo :bar)
(catch e
(t/assert=
(ex-msg e)
"Invalid number of arguments 2 for function 'arity-0'. Expected 0")))
(try
(arity-1)
(catch e
(t/assert=
(ex-msg e)
"Invalid number of arguments 0 for function 'arity-1'. Expected 1")))
(try
(arity-1 :foo :bar)
(catch e
(t/assert=
(ex-msg e)
"Invalid number of arguments 2 for function 'arity-1'. Expected 1")))
(try
(arity-2)
(catch e
(t/assert=
(ex-msg e)
"Invalid number of arguments 0 for function 'arity-2'. Expected 2")))
(try
(arity-2 :foo)
(catch e
(t/assert=
(ex-msg e)
"Invalid number of arguments 1 for function 'arity-2'. Expected 2")))))
arity-2 (fn arity-2 [a b])
arity-0-or-1 (fn arity-0-or-1 ([]) ([a]))
arity-1-or-3 (fn arity-1-or-3 ([a]) ([a b c]))
arity-0-or-1-or-3-or-more
(fn arity-0-or-1-or-3-or-more ([]) ([a]) ([a b c & more]))]
(t/assert-throws? RuntimeException
"Invalid number of arguments 1 for function 'arity-0'. Expected 0"
(arity-0 :foo))
(t/assert-throws? RuntimeException
"Invalid number of arguments 2 for function 'arity-0'. Expected 0"
(arity-0 :foo :bar))
(t/assert-throws? RuntimeException
"Invalid number of arguments 0 for function 'arity-1'. Expected 1"
(arity-1))
(t/assert-throws? RuntimeException
"Invalid number of arguments 2 for function 'arity-1'. Expected 1"
(arity-1 :foo :bar))
(t/assert-throws? RuntimeException
"Invalid number of arguments 0 for function 'arity-2'. Expected 2"
(arity-2))
(t/assert-throws? RuntimeException
"Invalid number of arguments 1 for function 'arity-2'. Expected 2"
(arity-2 :foo))
(t/assert-throws? RuntimeException
"Wrong number of arguments 2 for function 'arity-0-or-1'. Expected 1,0"
(arity-0-or-1 :foo :bar))
(t/assert-throws? RuntimeException
"Wrong number of arguments 3 for function 'arity-0-or-1'. Expected 1,0"
(arity-0-or-1 :foo :bar :baz))
(t/assert-throws? RuntimeException
"Wrong number of arguments 2 for function 'arity-1-or-3'. Expected 3,1"
(arity-1-or-3 :foo :bar))
(t/assert-throws? RuntimeException
"Wrong number of arguments 0 for function 'arity-1-or-3'. Expected 3,1"
(arity-1-or-3))
(t/assert-throws? RuntimeException
"Wrong number of arguments 2 for function 'arity-0-or-1-or-3-or-more'. Expected 1,0,3 or more"
(arity-0-or-1-or-3-or-more :foo :bar))))
11 changes: 5 additions & 6 deletions tests/pixie/tests/test-stdlib.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,9 @@
(t/assert= (merge-with identity {} {:a 1, :b 2}) {:a 1, :b 2})
(t/assert= (merge-with identity {:a 1} {:b 2}) {:a 1, :b 2})

(t/assert= (merge-with #(identity %1) {:a 1} {:a 2}) {:a 1})
(t/assert= (merge-with #(identity %1) {:a 1} {:a 2} {:a 3}) {:a 1})
(t/assert= (merge-with #(identity %2) {:a 1} {:a 2}) {:a 2})
(t/assert= (merge-with (fn [a b] a) {:a 1} {:a 2}) {:a 1})
(t/assert= (merge-with (fn [a b] a) {:a 1} {:a 2} {:a 3}) {:a 1})
(t/assert= (merge-with (fn [a b] b) {:a 1} {:a 2}) {:a 2})

(t/assert= (merge-with + {:a 21} {:a 21}) {:a 42})
(t/assert= (merge-with + {:a 21} {:a 21, :b 1}) {:a 42, :b 1}))
Expand All @@ -333,9 +333,8 @@

(t/deftest test-range
(t/assert= (= (-seq (range 10))
(-seq (-iterator (range 10))
(reduce conj nil (range 10))
'(0 1 2 3 4 5 6 7 8 9)))
(-seq (-iterator (range 10)))
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops, a missing )!

'(0 1 2 3 4 5 6 7 8 9))
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having fixed the missing bracket, this test fails because reducing on a list build a list in reverse (9 8 7 ...). So I've removed it. My bad.

true))

(t/deftest test-ns
Expand Down