diff --git a/.travis.yml b/.travis.yml index 7176dc4b..77846892 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,14 +2,9 @@ sudo: false env: - JIT_OPTS='--opt=jit' TARGET_OPTS='target.py' - JIT_OPTS='' TARGET_OPTS='target.py' - #- JIT_OPTS='--opt=jit' TARGET_OPTS='target_preload.py' - #- JIT_OPTS='' TARGET_OPTS='target_preload.py' matrix: fast_finish: true - allow_failures: - - env: JIT_OPTS='--opt=jit' TARGET_OPTS='target_preload.py' - - env: JIT_OPTS='' TARGET_OPTS='target_preload.py' script: - make PYTHON=python build diff --git a/Makefile b/Makefile index 7a6848af..5979fde8 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ all: help EXTERNALS=externals -PYTHON ?= python2 +PYTHON ?= `env which -a python2 python2.7 | head -n1` PYTHONPATH=$$PYTHONPATH:$(EXTERNALS)/pypy @@ -38,12 +38,6 @@ compile_basics: @echo -e "\n\n\n\nWARNING: Compiling core libs. If you want to modify one of these files delete the .pxic files first\n\n\n\n" ./pixie-vm -c pixie/uv.pxi -c pixie/io.pxi -c pixie/stacklets.pxi -c pixie/stdlib.pxi -c pixie/repl.pxi -build_preload_with_jit: fetch_externals - $(PYTHON) $(EXTERNALS)/pypy/rpython/bin/rpython $(COMMON_BUILD_OPTS) --opt=jit target_preload.py 2>&1 >/dev/null | grep -v 'WARNING' - -build_preload_no_jit: fetch_externals - $(PYTHON) $(EXTERNALS)/pypy/rpython/bin/rpython $(COMMON_BUILD_OPTS) target_preload.py - build: fetch_externals $(PYTHON) $(EXTERNALS)/pypy/rpython/bin/rpython $(COMMON_BUILD_OPTS) $(JIT_OPTS) $(TARGET_OPTS) @@ -59,7 +53,7 @@ externals.fetched: $(EXTERNALS)/pypy: mkdir $(EXTERNALS); \ cd $(EXTERNALS); \ - curl https://bitbucket.org/pypy/pypy/get/81254.tar.bz2 > pypy.tar.bz2; \ + curl https://bitbucket.org/pypy/pypy/get/91db1a9.tar.bz2 > pypy.tar.bz2; \ mkdir pypy; \ cd pypy; \ tar -jxf ../pypy.tar.bz2 --strip-components=1 diff --git a/README.md b/README.md index d66d94d1..a290aa99 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -[![Build Status](https://travis-ci.org/pixie-lang/pixie.svg?branch=master)](https://travis-ci.org/pixie-lang/pixie)[![License: LGPL] (http://img.shields.io/badge/license-LGPL-green.svg)](http://img.shields.io/badge/license-LGPL-green.svg) +[![Build Status](https://travis-ci.org/pixie-lang/pixie.svg?branch=master)](https://travis-ci.org/pixie-lang/pixie) +[![License: LGPL](https://img.shields.io/badge/license-LGPL-green.svg)](https://img.shields.io/badge/license-LGPL-green.svg) # Pixie [![Join the chat at https://gitter.im/pixie-lang/pixie](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/pixie-lang/pixie?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) diff --git a/generate-docs.pxi b/generate-docs.pxi new file mode 100644 index 00000000..5f8abb5b --- /dev/null +++ b/generate-docs.pxi @@ -0,0 +1,54 @@ +(ns pixie.generate-docs + (:require [pixie.io :as io] + [pixie.string :as string])) + +(let [[namespace] program-arguments] + + (println "==============") + (println (name namespace)) + (println "==============") + + (load-ns (symbol namespace)) + (println) + + ;;Should be sorting the map + ;;Like so: (sort-by first map) + ;;However, I'm holding off until sort is properly supported + (doseq [[k v] (ns-map (the-ns namespace))] + (println (name k)) + (println "====================================") + (println) + + (if-let [m (meta @v)] + (do + ;(println m) + (if-let [doc (:doc m)];; + (println doc) + (println "No doc available :(")) + (println) + + (when-let (examples (:examples m)) + (println "**Examples:**") + (doseq [[code _ result] examples] + (println) + (println code) + (println) + (when (not (nil? result)) + (println "=> " result))) + (println)) + + (when-let (signatures (:signatures m)) + (println "**Signatures:**") + (println) + (doseq [sig signatures] + (println (str "- " sig))) + (println)) + + (when (and (:line-number m) (:file m)) + (let [file (str "pixie/" (last (string/split (:file m) "/")))] + (println (str "http://github.com/pixie-lang/pixie/blob/master/" + file "#L" (:line-number m)))) + (println))) + + (println "No meta data available :(")) + (println))) \ No newline at end of file diff --git a/pixie/ffi-infer.pxi b/pixie/ffi-infer.pxi index 51bfa34a..6b6920d6 100644 --- a/pixie/ffi-infer.pxi +++ b/pixie/ffi-infer.pxi @@ -104,11 +104,14 @@ return 0; (= (:type of-type) :function) (callback-type of-type in-struct?) :else 'pixie.stdlib/CVoidP)) +(def float-types {32 'pixie.stdlib/CFloat + 64 'pixie.stdlib/CDouble}) + (defmethod edn-to-ctype :float - [{:keys [size]} _] - (cond - (= size 8) 'pixie.stdlib/CDouble - :else (assert false "unknown type"))) + [{:keys [size] :as tp} _] + (let [tp-found (get float-types (* 8 size))] + (assert tp-found (str "No type found for " tp)) + tp-found)) (defmethod edn-to-ctype :void [_ _] diff --git a/pixie/fs.pxi b/pixie/fs.pxi index f3e73960..679bd5f6 100644 --- a/pixie/fs.pxi +++ b/pixie/fs.pxi @@ -109,7 +109,7 @@ (rel [this other] (if (satisfies? IFSPath other) (rel-path this other) - (throw "Second argument must satisfy IFSPath"))) + (throw [::AssertionException "Second argument must satisfy IFSPath"]))) (abs [this] (path/-abs pathz)) @@ -157,7 +157,7 @@ (rel [this other] (if (satisfies? IFSPath other) (rel-path this other) - (throw "Second argument must satisfy IFSPath"))) + (throw [::AssertionException "Second argument must satisfy IFSPath"]))) (abs [this] (path/-abs pathz)) @@ -217,7 +217,7 @@ (cond (path/-file? x) (->File x) (not (path/-exists? x)) (->File x) - :else (throw (str "A non-file object exists at path: " x))))) + :else (throw [::NotAFileException (str "A non-file object exists at path: " x)])))) (defn dir "Returns a dir if the path is a dir or does not exist. If a different filesystem object exists at the path an error will be thrown." @@ -226,7 +226,7 @@ (cond (path/-dir? x) (->Dir x) (not (path/-exists? x)) (->Dir x) - :else (throw (str "A non-dir object exists at path: " x))))) + :else (throw [::NotADirectoryException (str "A non-dir object exists at path: " x)])))) (defn fspath "Returns either a File or Dir if they exist at the path" @@ -235,6 +235,6 @@ (cond (path/-file? x) (->File x) (path/-dir? x) (->Dir x) - :else (throw (str "No file or directory at path: " x))))) + :else (throw [::FileNotFoundException (str "No file or directory at path: " x)])))) diff --git a/pixie/io.pxi b/pixie/io.pxi index 3dd8bdf2..a6ed1286 100644 --- a/pixie/io.pxi +++ b/pixie/io.pxi @@ -66,14 +66,13 @@ (str string)))))) IReduce (-reduce [this f init] - (let [rrf (preserving-reduced f)] - (loop [acc init] - (if-let [line (-read-line this)] - (let [result (rrf acc line)] - (if (not (reduced? result)) - (recur result) - @result)) - acc))))) + (loop [acc init] + (if-let [line (-read-line this)] + (let [result (f acc line)] + (if (reduced? result) + @result + (recur result))) + acc)))) (defn line-reader [input-stream] @@ -150,14 +149,13 @@ (deftype BufferedInputStream [upstream idx buffer] IReduce (-reduce [this f init] - (let [rrf (preserving-reduced f)] - (loop [acc init] - (if-let [next-byte (read-byte this)] - (let [step (rrf acc next-byte)] - (if (reduced? step) - @step - (recur step))) - acc)))) + (loop [acc init] + (if-let [next-byte (read-byte this)] + (let [result (f acc next-byte)] + (if (reduced? result) + @result + (recur result))) + acc))) IByteInputStream (read-byte [this] (when (= idx (count buffer)) diff --git a/pixie/math.pxi b/pixie/math.pxi index 15a778c4..253bc132 100644 --- a/pixie/math.pxi +++ b/pixie/math.pxi @@ -1,55 +1,101 @@ (ns pixie.math - (:require [pixie.ffi-infer :as i])) + (:require [pixie.ffi-infer :as i] + [pixie.string :as s])) (i/with-config {:library "m" :cxx-flags ["-lm"] :includes ["math.h"]} - (i/defcfn sin) - (i/defcfn cos) - (i/defcfn tan) + (i/defconst M_E) + (i/defconst M_LOG2E) + (i/defconst M_LOG10E) + (i/defconst M_LN2) + (i/defconst M_LN10) + (i/defconst M_PI) + (i/defconst M_PI_2) + (i/defconst M_PI_4) + (i/defconst M_1_PI) + (i/defconst M_2_PI) + (i/defconst M_2_SQRTPI) + (i/defconst M_SQRT2) + (i/defconst M_SQRT1_2) - (i/defcfn asin) - (i/defcfn acos) - (i/defcfn atan) - (i/defcfn atan2) ; Arc tangent function of two variables. + (i/defcfn nan) + (i/defcfn ceil) + (i/defcfn floor) + (i/defcfn nearbyint) + (i/defcfn rint) + (i/defcfn lround) + (i/defcfn llrint) + (i/defcfn llround) + (i/defcfn trunc) - (i/defcfn sinh) - (i/defcfn cosh) - (i/defcfn tanh) + (i/defcfn fmod) + (i/defcfn remainder) + (i/defcfn remquo) - (i/defcfn asinh) - (i/defcfn acosh) - (i/defcfn atanh) + (i/defcfn fdim) + (i/defcfn fmax) + (i/defcfn fmin) + + (i/defcfn fma) + + (i/defcfn fabs) + (i/defcfn sqrt) + (i/defcfn cbrt) + (i/defcfn hypot) (i/defcfn exp) - (i/defcfn ldexp) + (i/defcfn exp2) + (if-not (s/starts-with? pixie.platform/name "darwin") + (i/defcfn exp10)) + (i/defcfn expm1) (i/defcfn log) (i/defcfn log2) (i/defcfn log10) (i/defcfn log1p) + (i/defcfn logb) (i/defcfn ilogb) - ;; (i/defcfn modf) ;; Needs ffi support + (i/defcfn modf) + (i/defcfn frexp) + + (i/defcfn ldexp) + (i/defcfn scalbn) + (i/defcfn scalbln) + (i/defcfn pow) - (i/defcfn sqrt) - (i/defcfn ceil) - (i/defcfn fabs) - (i/defcfn floor) - (i/defcfn fmod) - (i/defconst M_E) ; base of natural logarithm, e - (i/defconst M_LOG2E) ; log2(e) - (i/defconst M_LOG10E) ; log10(e) - (i/defconst M_LN2) ; ln(2) - (i/defconst M_LN10) ; ln(10) - (i/defconst M_PI) ; pi - (i/defconst M_PI_2) ; pi / 2 - (i/defconst M_PI_4) ; pi / 4 - (i/defconst M_1_PI) ; 1 / pi - (i/defconst M_2_PI) ; 2 / pi - (i/defconst M_2_SQRTPI) ; 2 / sqrt(pi) - (i/defconst M_SQRT2) ; sqrt(2) - (i/defconst M_SQRT1_2)) ; sqrt(1/2) + (i/defcfn cos) + (i/defcfn sin) + (i/defcfn tan) + + (i/defcfn cosh) + (i/defcfn sinh) + (i/defcfn tanh) + + (i/defcfn acos) + (i/defcfn asin) + (i/defcfn atan) + (i/defcfn atan2) + + (i/defcfn acosh) + (i/defcfn asinh) + (i/defcfn atanh) + + (i/defcfn tgamma) + (i/defcfn lgamma) + + (i/defcfn j0) + (i/defcfn j1) + (i/defcfn jn) + (i/defcfn y0) + (i/defcfn y1) + (i/defcfn yn) + + (i/defcfn erf) + (i/defcfn erfc)) +(if (s/starts-with? pixie.platform/name "darwin") + (defn exp10 [x] (pow 10.0 x))) diff --git a/pixie/stdlib.pxi b/pixie/stdlib.pxi index 16c68916..2501e2fe 100644 --- a/pixie/stdlib.pxi +++ b/pixie/stdlib.pxi @@ -17,6 +17,10 @@ (def srand (ffi-fn libc "srand" [CInt] CInt)) (def fopen (ffi-fn libc "fopen" [CCharP CCharP] CVoidP)) (def fread (ffi-fn libc "fread" [CVoidP CInt CInt CVoidP] CInt)) +(def mkdtemp (ffi-fn libc "mkdtemp" [CCharP] CCharP)) +(def mkdir (ffi-fn libc "mkdir" [CCharP] CCharP)) +(def rmdir (ffi-fn libc "rmdir" [CCharP] CCharP)) +(def rm (ffi-fn libc "remove" [CCharP] CCharP)) (def libm (ffi-library (str "libm." pixie.platform/so-ext))) (def atan2 (ffi-fn libm "atan2" [CDouble CDouble] CDouble)) @@ -478,6 +482,19 @@ (let [nm (with-meta nm (assoc (meta nm) :private true))] (cons `defn (cons nm rest)))) +(defmacro letfn + "fnspec ==> (fname [params*] exprs) or (fname ([params*] exprs)+) + + Takes a vector of function specs and a body, and generates a set of + bindings of functions to their names. All of the names are available + in all of the definitions of the functions, as well as the body." + {:added "0.2" + :forms '[(letfn [fnspecs*] exprs*)]} + [fnspecs & body] + `(letfn* ~(vec (interleave (map first fnspecs) + (map #(cons `fn %) fnspecs))) + ~@body)) + (defn not {:doc "Inverts the input, if a truthy value is supplied, returns false, otherwise returns true." @@ -899,7 +916,7 @@ If further arguments are passed, invokes the method named by symbol, passing the (if (next coll) (recur (next coll)) (first coll)) - + (satisfies? ISeqable coll) (recur (seq coll)))) @@ -1636,21 +1653,25 @@ The new value is thus `(apply f current-value-of-atom args)`." (let [idx (if (neg? i) (+ i (count coll)) i)] (nth coll idx not-found))))) +(defn ensure-reduced [x] + (if (reduced? x) + x + (reduced x))) + (defn take {:doc "Takes n elements from the collection, or fewer, if not enough." :added "0.1"} ([n] (fn [rf] - (let [rrf (preserving-reduced rf) - seen (atom 0)] + (let [seen (atom 0)] (fn ([] (rf)) ([result] (rf result)) ([result input] (let [s (swap! seen inc)] - (if (<= s n) - (rrf result input) - (reduced result)))))))) + (cond (< s n) (rf result input) + (= s n) (ensure-reduced (rf result input)) + :else (reduced result)))))))) ([n coll] (lazy-seq (when (pos? n) @@ -1662,8 +1683,7 @@ The new value is thus `(apply f current-value-of-atom args)`." :added "0.1"} ([n] (fn [rf] - (let [rrf (preserving-reduced rf) - seen (atom 0)] + (let [seen (atom 0)] (fn ([] (rf)) ([result] @@ -1671,7 +1691,7 @@ The new value is thus `(apply f current-value-of-atom args)`." ([result input] (let [s (swap! seen inc)] (if (> s n) - (rrf result input) + (rf result input) result))))))) ([n coll] (let [s (seq coll)] @@ -1703,14 +1723,13 @@ The new value is thus `(apply f current-value-of-atom args)`." :added "0.1"} ([pred] (fn [rf] - (let [rrf (preserving-reduced rf)] - (fn - ([] (rf)) - ([result] (rf result)) - ([result input] + (fn + ([] (rf)) + ([result] (rf result)) + ([result input] (if (pred input) - (rrf result input) - (reduced result))))))) + (rf result input) + (reduced result)))))) ([pred coll] (lazy-seq (when-let [s (seq coll)] @@ -1821,13 +1840,12 @@ not enough elements were present." :signatures [[f] [f coll]]} ([f] (fn [rf] - (let [i (atom -1) - rrf (preserving-reduced rf)] + (let [i (atom -1)] (fn ([] (rf)) ([result] (rf result)) ([result input] - (rrf result (f (swap! i inc) input))))))) + (rf result (f (swap! i inc) input))))))) ([f coll] (let [mapi (fn mapi [i coll] (lazy-seq @@ -1845,8 +1863,7 @@ not enough elements were present." :added "0.1"} ([f] (fn [rf] - (let [iv (atom -1) - rrf (preserving-reduced rf)] + (let [iv (atom -1)] (fn ([] (rf)) ([result] (rf result)) @@ -1855,7 +1872,7 @@ not enough elements were present." v (f i input)] (if (nil? v) result - (rrf result v)))))))) + (rf result v)))))))) ([f coll] (let [keepi (fn keepi [i coll] (lazy-seq @@ -1884,6 +1901,35 @@ not enough elements were present." (when-let [s (seq coll)] (reductions f (f init (first s)) (rest s)))))))) +(defn completing + "Takes a reducing function f of 2 args and returns a fn suitable for + transduce by adding an arity-1 signature that calls cf (default - + identity) on the result argument." + ([f] (completing f identity)) + ([f cf] + (fn + ([] (f)) + ([x] (cf x)) + ([x y] (f x y))))) + +(deftype Eduction [xform coll] + IReduce + (-reduce [self f init] + ;; NB (completing f) isolates completion of inner rf from outer rf + (transduce xform (completing f) init coll)) + + ISeqable + (-seq [self] + (sequence xform coll))) + +(defn eduction + "Returns a reducible/iterable application of the transducers + to the items in coll. Transducers are applied in order as if + combined with comp. Note that these applications will be + performed every time reduce/iterator is called." + [& xforms] + (->Eduction (apply comp (butlast xforms)) (last xforms))) + (defn destructure [binding expr] (cond (symbol? binding) [binding expr] @@ -2073,7 +2119,7 @@ For more information, see http://clojure.org/special_forms#binding-forms"} val not-found))) ISeq - (-first [this] + (-first [this] (when (not= start stop) start)) (-next [this] @@ -2155,6 +2201,20 @@ For more information, see http://clojure.org/special_forms#binding-forms"} ([pred coll] (filter (complement pred) coll))) +(defn sequence + "Returns a lazy sequence of `data`, optionally transforming it using `xform`" + ([coll] + (if (seq? coll) coll + (or (seq coll) ()))) + ([xform coll] + (let [step (fn step [xform acc xs] + (if-let [s (seq xs)] + (let [next-acc ((xform conj) acc (first s))] + (if (= acc next-acc) (step xform next-acc (next s)) + (concat (drop (count acc) next-acc) (step xform next-acc (next s))))) + nil))] + (lazy-seq (step xform [] coll))))) + (defn distinct {:doc "Returns the distinct elements in the collection." :signatures [[] [coll]] @@ -2559,14 +2619,14 @@ Expands to calls to `extend-type`." `(loop [res# [] ~c (seq ~coll)] (if ~c - (recur (into res# - ~(gen-loop (into coll-bindings - [binding `(first ~c)]) - (nnext bindings))) - (next ~c)) + (let [~binding (first ~c)] + (recur (into res# + ~(gen-loop (into coll-bindings + [binding `(first ~c)]) + (nnext bindings))) + (next ~c))) res#))) - `(let ~coll-bindings - [~@body])))] + `[~@body]))] `(or (seq ~(gen-loop [] bindings)) '()))) (defmacro doto @@ -2693,7 +2753,7 @@ Calling this function on something that is not ISeqable returns a seq with that (= () form)) form (let [[sym & args] form - fvar (resolve sym)] + fvar (resolve-in *ns* sym)] (if (and fvar (macro? @fvar)) (apply @fvar args) form)))) @@ -3043,3 +3103,23 @@ ex: (vary-meta x assoc :foo 42)" (swap! cache assoc argsv ret) ret) val))))) + +(deftype Iterate [f x] + IReduce + (-reduce [self rf init] + (loop [next (f x) + acc (rf init x)] + (if (reduced? acc) + @acc + (recur (f next) (rf acc next))))) + ISeq + (-seq [self] + (cons x (lazy-seq* (fn [] (->Iterate f (f x))))))) + +(defn iterate + {:doc "Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of + side-effects" + :signatures [[f x]] + :added "0.1"} + [f x] + (->Iterate f x)) diff --git a/pixie/vm/array.py b/pixie/vm/array.py index 3bde8642..4ca97813 100644 --- a/pixie/vm/array.py +++ b/pixie/vm/array.py @@ -14,8 +14,6 @@ class Array(object.Object): _type = object.Type(u"pixie.stdlib.Array") _immutable_fields_ = ["_list"] - def type(self): - return Array._type def __init__(self, lst): self._list = lst @@ -28,6 +26,8 @@ def reduce_small(self, f, init): init = f.invoke([init, self._list[x]]) return init + def list(self): + return self._list def reduce_large(self, f, init): for x in range(len(self._list)): @@ -39,14 +39,14 @@ def reduce_large(self, f, init): @extend(proto._count, Array) def _count(self): assert isinstance(self, Array) - return rt.wrap(len(self._list)) + return rt.wrap(len(self.list())) @extend(proto._nth, Array) def _nth(self, idx): assert isinstance(self, Array) ival = idx.int_val() - if ival < len(self._list): - return self._list[ival] + if ival < len(self.list()): + return self.list()[ival] else: affirm(False, u"Index out of Range") @@ -54,15 +54,15 @@ def _nth(self, idx): def _nth_not_found(self, idx, not_found): assert isinstance(self, Array) ival = idx.int_val() - if ival < len(self._list): - return self._list[ival] + if ival < len(self.list()): + return self.list()[ival] else: return not_found @extend(proto._reduce, Array) def reduce(self, f, init): assert isinstance(self, Array) - if len(self._list) > UNROLL_IF_SMALLER_THAN: + if len(self.list()) > UNROLL_IF_SMALLER_THAN: return self.reduce_large(f, init) return self.reduce_small(f, init) @@ -98,9 +98,6 @@ def reduce(self, f, init): init = f.invoke([init, rt.nth(self._w_array, rt.wrap(x))]) return init - def type(self): - return self._type - @extend(proto._first, ArraySeq) def _first(self): assert isinstance(self, ArraySeq) @@ -127,34 +124,39 @@ def array(lst): @as_var("aget") def aget(self, idx): - assert isinstance(self, Array) - return self._list[idx.int_val()] + affirm(isinstance(self, Array), u"aget expects an Array as the first argument") + affirm(isinstance(idx, Integer), u"aget expects an Integer as the second argument") + return self.list()[idx.int_val()] @as_var("aset") def aset(self, idx, val): - assert isinstance(self, Array) - self._list[idx.int_val()] = val + affirm(isinstance(self, Array), u"aset expects an Array as the first argument") + affirm(isinstance(idx, Integer), u"aset expects an Integer as the second argument") + self.list()[idx.int_val()] = val return val @as_var("aslice") def aslice(self, offset): - assert isinstance(self, Array) and isinstance(offset, Integer) + affirm(isinstance(self, Array), u"aset expects an Array as the first argument") + affirm(isinstance(offset, Integer), u"aset expects an Integer as the second argument") offset = offset.int_val() if offset >= 0: - return Array(self._list[offset:]) + return Array(self.list()[offset:]) else: rt.throw(rt.wrap(u"offset must be an Integer >= 0")) @as_var("aconcat") def aconcat(self, other): - assert isinstance(self, Array) and isinstance(other, Array) - return Array(self._list + other._list) + affirm(isinstance(self, Array) and isinstance(other, Array), + u"aconcat expects 2 Arrays") + return Array(self.list() + other.list()) @as_var("alength") def alength(self): - assert isinstance(self, Array) - return rt.wrap(len(self._list)) + affirm(isinstance(self, Array), u"alength expects an Array") + + return rt.wrap(len(self.list())) @as_var("make-array") def make_array(l): @@ -174,9 +176,6 @@ def __init__(self, size): for x in range(size): self._buffer[x] = chr(0) - def type(self): - return ByteArray._type - def __del__(self): lltype.free(self._buffer, flavor="raw") diff --git a/pixie/vm/atom.py b/pixie/vm/atom.py index 77ecd50d..28254673 100644 --- a/pixie/vm/atom.py +++ b/pixie/vm/atom.py @@ -7,9 +7,6 @@ class Atom(object.Object): _type = object.Type(u"pixie.stdlib.Atom") - def type(self): - return Atom._type - def with_meta(self, meta): return Atom(self._boxed_value, meta) diff --git a/pixie/vm/c_api.py b/pixie/vm/c_api.py index 45888295..a050a070 100644 --- a/pixie/vm/c_api.py +++ b/pixie/vm/c_api.py @@ -1,10 +1,7 @@ - - -from rpython.rlib.entrypoint import entrypoint_highlevel, RPython_StartupCode +from rpython.rlib.entrypoint import entrypoint_highlevel from rpython.rtyper.lltypesystem import rffi, lltype from rpython.rtyper.lltypesystem.lloperation import llop - @entrypoint_highlevel('main', [rffi.CCHARP], c_name='pixie_init') def pypy_execute_source(ll_progname): from target import init_vm diff --git a/pixie/vm/code.py b/pixie/vm/code.py index 14883796..5a54ea25 100644 --- a/pixie/vm/code.py +++ b/pixie/vm/code.py @@ -148,9 +148,6 @@ class MultiArityFn(BaseCode): _immutable_fields_ = ["_arities[*]", "_required_arity", "_rest_fn"] - def type(self): - return MultiArityFn._type - def __init__(self, name, arities, required_arity=0, rest_fn=None, meta=nil): BaseCode.__init__(self) self._name = name @@ -199,9 +196,6 @@ class NativeFn(BaseCode): def __init__(self, doc=None): BaseCode.__init__(self) - def type(self): - return NativeFn._type - def invoke(self, args): return self.inner_invoke(args) @@ -217,9 +211,6 @@ class Code(BaseCode): _type = object.Type(u"pixie.stdlib.Code") _immutable_fields_ = ["_arity", "_consts[*]", "_bytecode", "_stack_size", "_meta", "_debug_points"] - def type(self): - return Code._type - def __init__(self, name, arity, bytecode, consts, stack_size, debug_points, meta=nil): BaseCode.__init__(self) self._arity = arity @@ -277,9 +268,6 @@ class VariadicCode(BaseCode): _immutable_fields_ = ["_required_arity", "_code", "_meta"] _type = object.Type(u"pixie.stdlib.VariadicCode") - def type(self): - return VariadicCode._type - def __init__(self, code, required_arity, meta=nil): BaseCode.__init__(self) self._required_arity = r_uint(required_arity) @@ -319,9 +307,6 @@ class Closure(BaseCode): _type = object.Type(u"pixie.stdlib.Closure") _immutable_fields_ = ["_closed_overs[*]", "_code", "_meta"] - def type(self): - return Closure._type - def __init__(self, code, closed_overs, meta=nil): BaseCode.__init__(self) affirm(isinstance(code, Code), u"Code argument to Closure must be an instance of Code") @@ -373,9 +358,6 @@ def get_debug_points(self): class Undefined(object.Object): _type = object.Type(u"pixie.stdlib.Undefined") - def type(self): - return Undefined._type - undefined = Undefined() @@ -413,9 +395,6 @@ class Var(BaseCode): _type = object.Type(u"pixie.stdlib.Var") _immutable_fields_ = ["_ns_ref"] - def type(self): - return Var._type - def __init__(self, ns_ref, ns, name): BaseCode.__init__(self) self._ns_ref = ns_ref @@ -497,9 +476,6 @@ class Namespace(object.Object): _immutable_fields_ = ["_rev?"] - def type(self): - return Namespace._type - def __init__(self, name): self._rev = 0 self._registry = {} @@ -636,9 +612,6 @@ class Protocol(object.Object): _immutable_fields_ = ["_rev?"] - def type(self): - return Protocol._type - def __init__(self, name): self._name = name self._polyfns = {} @@ -663,9 +636,6 @@ def satisfies(self, tp): class PolymorphicFn(BaseCode): _type = object.Type(u"pixie.stdlib.PolymorphicFn") - def type(self): - return PolymorphicFn._type - _immutable_fields_ = ["_rev?"] def __init__(self, name, protocol): @@ -745,9 +715,6 @@ class DoublePolymorphicFn(BaseCode): """A function that is polymorphic on the first two arguments""" _type = object.Type(u"pixie.stdlib.DoublePolymorphicFn") - def type(self): - return DefaultProtocolFn._type - _immutable_fields_ = ["_rev?"] def __init__(self, name, protocol): diff --git a/pixie/vm/compiler.py b/pixie/vm/compiler.py index 5d0f214f..60cc353a 100644 --- a/pixie/vm/compiler.py +++ b/pixie/vm/compiler.py @@ -539,8 +539,8 @@ def compile_fn_body(name, args, body, ctx): compile_form(body, new_ctx) else: while body is not nil: - if rt.next(body) is nil: - new_ctx.enable_tail_call() + #if rt.next(body) is nil: + # new_ctx.enable_tail_call() compile_form(rt.first(body), new_ctx) body = rt.next(body) if body is not nil: @@ -635,7 +635,7 @@ def compile_quote(form, ctx): def compile_recur(form, ctx): form = form.next() - #affirm(ctx.can_tail_call, u"Can't recur in non-tail position") + affirm(ctx.can_tail_call, u"Can't recur in non-tail position") ctc = ctx.can_tail_call ctx.disable_tail_call() args = 0 @@ -697,7 +697,7 @@ def compile_loop(form, ctx): bindings = rt.first(form) affirm(isinstance(bindings, PersistentVector), u"Loop bindings must be a vector") body = rt.next(form) - + ctx.enable_tail_call() ctc = ctx.can_tail_call ctx.disable_tail_call() diff --git a/pixie/vm/cons.py b/pixie/vm/cons.py index bc27357e..27fcc109 100644 --- a/pixie/vm/cons.py +++ b/pixie/vm/cons.py @@ -7,9 +7,6 @@ class Cons(object.Object): _type = object.Type(u"pixie.stdlib.Cons") - def type(self): - return Cons._type - def __init__(self, head, tail, meta=nil): self._first = head self._next = tail diff --git a/pixie/vm/custom_types.py b/pixie/vm/custom_types.py index 0cbbc4ef..d5fb3047 100644 --- a/pixie/vm/custom_types.py +++ b/pixie/vm/custom_types.py @@ -216,8 +216,6 @@ def get_field(inst, field): class AbstractMutableCell(Object): _type = Type(u"pixie.stdlib.AbstractMutableCell") - def type(self): - return self._type def set_mutable_cell_value(self, ct, fields, nm, idx, value): pass diff --git a/pixie/vm/interpreter.py b/pixie/vm/interpreter.py index d279e2fb..cb11508d 100644 --- a/pixie/vm/interpreter.py +++ b/pixie/vm/interpreter.py @@ -159,10 +159,6 @@ def __init__(self, frame, val): self._frame = frame self._val = val - def type(self): - return ShallowContinuation._type - - def is_finished(self): return self._frame.finished diff --git a/pixie/vm/lazy_seq.py b/pixie/vm/lazy_seq.py index b95c3c94..65cb744c 100644 --- a/pixie/vm/lazy_seq.py +++ b/pixie/vm/lazy_seq.py @@ -9,9 +9,6 @@ class LazySeq(object.Object): _type = object.Type(u"pixie.stdlib.LazySeq") - def type(self): - return LazySeq._type - def __init__(self, fn, meta=nil): self._fn = fn self._meta = meta diff --git a/pixie/vm/libs/env.py b/pixie/vm/libs/env.py index 25bfb7ca..39b806df 100644 --- a/pixie/vm/libs/env.py +++ b/pixie/vm/libs/env.py @@ -10,9 +10,6 @@ class Environment(Object): _type = Type(u"pixie.stdlib.Environment") - def type(self): - return Environment._type - def val_at(self, key, not_found): if not isinstance(key, String): runtime_error(u"Environment variables are strings ") diff --git a/pixie/vm/libs/ffi.py b/pixie/vm/libs/ffi.py index 193b56ce..cdd670b4 100644 --- a/pixie/vm/libs/ffi.py +++ b/pixie/vm/libs/ffi.py @@ -41,9 +41,6 @@ def __init__(self, name): class ExternalLib(object.Object): _type = object.Type(u"pixie.stdlib.ExternalLib") - def type(self): - return ExternalLib._type - def __init__(self, nm): assert isinstance(nm, unicode) self._name = nm @@ -94,9 +91,6 @@ class FFIFn(object.Object): _type = object.Type(u"pixie.stdlib.FFIFn") _immutable_fields_ = ["_name", "_f_ptr", "_c_fn_type"] - def type(self): - return FFIFn._type - def __init__(self, name, fn_ptr, c_fn_type): assert isinstance(c_fn_type, CFunctionType) self._rev = 0 @@ -219,9 +213,6 @@ class Buffer(PointerType): """ _type = object.Type(u"pixie.stdlib.Buffer") - def type(self): - return Buffer._type - def __init__(self, size): self._size = size self._used_size = 0 @@ -350,6 +341,26 @@ def ffi_type(self): return clibffi.cast_type_to_ffitype(rffi.INT) CInt() +class CFloat(CType): + def __init__(self): + CType.__init__(self, u"pixie.stdlib.CFloat") + + def ffi_get_value(self, ptr): + casted = rffi.cast(rffi.FLOATP, ptr) + return Float(rffi.cast(rffi.DOUBLE, casted[0])) + + def ffi_set_value(self, ptr, val): + val = to_float(val) + casted = rffi.cast(rffi.FLOATP, ptr) + casted[0] = rffi.cast(rffi.FLOAT, val.float_val()) + + def ffi_size(self): + return rffi.sizeof(rffi.FLOAT) + + def ffi_type(self): + return clibffi.cast_type_to_ffitype(rffi.FLOAT) +CFloat() + class CDouble(CType): def __init__(self): CType.__init__(self, u"pixie.stdlib.CDouble") @@ -482,8 +493,6 @@ def ffi_type(self): class VoidP(PointerType): _type = cvoidp - def type(self): - return VoidP._type def __init__(self, raw_data): self._raw_data = raw_data @@ -584,9 +593,6 @@ def __init__(self, cft, raw_closure, id, fn): self._is_invoked = False self._unique_id = id - def type(self): - return CCallback._type - def get_raw_closure(self): return self._raw_closure diff --git a/pixie/vm/libs/path.py b/pixie/vm/libs/path.py index 8afd0ef2..e512efe8 100644 --- a/pixie/vm/libs/path.py +++ b/pixie/vm/libs/path.py @@ -8,9 +8,6 @@ class Path(Object): _type = Type(u"pixie.path.Path") - def type(self): - return Path._type - def __init__(self, top): self._path = rt.name(top) diff --git a/pixie/vm/libs/pxic/writer.py b/pixie/vm/libs/pxic/writer.py index 7aedcb17..0d2e511a 100644 --- a/pixie/vm/libs/pxic/writer.py +++ b/pixie/vm/libs/pxic/writer.py @@ -73,8 +73,6 @@ def finish(self): class WriterBox(Object): _type = Type(u"pixie.stdlib.WriterBox") - def type(self): - return WriterBox._type def __init__(self, wtr): self._pxic_writer = wtr diff --git a/pixie/vm/map_entry.py b/pixie/vm/map_entry.py index 543fb7d3..3b14a6c4 100644 --- a/pixie/vm/map_entry.py +++ b/pixie/vm/map_entry.py @@ -6,9 +6,6 @@ class MapEntry(object.Object): _type = object.Type(u"pixie.stdlib.MapEntry") - def type(self): - return MapEntry._type - def __init__(self, key, val): self._key = key self._val = val diff --git a/pixie/vm/numbers.py b/pixie/vm/numbers.py index ab80edbe..8e637365 100644 --- a/pixie/vm/numbers.py +++ b/pixie/vm/numbers.py @@ -13,9 +13,6 @@ class Number(object.Object): _type = object.Type(u"pixie.stdlib.Number") - def type(self): - return Number._type - class Integer(Number): _type = object.Type(u"pixie.stdlib.Integer", Number._type) _immutable_fields_ = ["_int_val"] @@ -32,9 +29,6 @@ def r_uint_val(self): def promote(self): return Integer(jit.promote(self._int_val)) - def type(self): - return Integer._type - zero_int = Integer(0) one_int = Integer(1) @@ -48,9 +42,6 @@ def __init__(self, bi_val): def bigint_val(self): return self._bigint_val - def type(self): - return BigInteger._type - class Float(Number): _type = object.Type(u"pixie.stdlib.Float", Number._type) _immutable_fields_ = ["_float_val"] @@ -61,9 +52,6 @@ def __init__(self, f_val): def float_val(self): return self._float_val - def type(self): - return Float._type - class Ratio(Number): _type = object.Type(u"pixie.stdlib.Ratio", Number._type) _immutable_fields_ = ["_numerator", "_denominator"] @@ -79,9 +67,6 @@ def numerator(self): def denominator(self): return self._denominator - def type(self): - return Ratio._type - @wrap_fn def ratio_write(obj): assert isinstance(obj, Ratio) @@ -320,7 +305,7 @@ def to_float(x): return rt.wrap(float(x.int_val())) if isinstance(x, BigInteger): return rt.wrap(x.bigint_val().tofloat()) - assert False + object.runtime_error(u"Cannot convert %s to float" %x.type().name()) def to_float_conv(c): if c == Float: diff --git a/pixie/vm/object.py b/pixie/vm/object.py index ccddf276..2ef03de3 100644 --- a/pixie/vm/object.py +++ b/pixie/vm/object.py @@ -8,7 +8,6 @@ def __init__(self): self._registry = [] def register(self, o): - print "register finalizer ", o self._registry.append(o) def run_finalizers(self): @@ -26,8 +25,12 @@ class Object(object): """ _attrs_ = () + # Initialized after Type is defined. + _type = None + def type(self): - affirm(False, u".type isn't overloaded") + assert(isinstance(self.__class__._type, Type)) + return self.__class__._type @jit.unroll_safe def invoke(self, args): @@ -109,9 +112,6 @@ def __init__(self, name, parent=None, object_inited=True): def name(self): return self._name - def type(self): - return Type._type - def parent(self): return self._parent @@ -157,9 +157,6 @@ def __init__(self, msg, data): self._data = data self._trace = [] - def type(self): - return RuntimeException._type - def __repr__(self): import pixie.vm.rt as rt s = [] @@ -211,8 +208,7 @@ def safe_invoke(f, args): class ErrorInfo(Object): _type = Type(u"pixie.stdlib.ErrorInfo") - def type(self): - return ErrorInfo._type + def __init__(self): pass diff --git a/pixie/vm/persistent_hash_map.py b/pixie/vm/persistent_hash_map.py index c36dbbdc..7cab577c 100644 --- a/pixie/vm/persistent_hash_map.py +++ b/pixie/vm/persistent_hash_map.py @@ -19,9 +19,6 @@ def __init__(self): class PersistentHashMap(object.Object): _type = object.Type(u"pixie.stdlib.PersistentHashMap") - def type(self): - return PersistentHashMap._type - def __init__(self, cnt, root, meta=nil): self._cnt = cnt self._root = root @@ -62,9 +59,6 @@ def without(self, key): class INode(object.Object): _type = object.Type(u"pixie.stdlib.INode") - def type(self): - return INode._type - def assoc_inode(self, shift, hash_val, key, val, added_leaf): pass diff --git a/pixie/vm/persistent_hash_set.py b/pixie/vm/persistent_hash_set.py index 9327ea42..f2bd5d4a 100644 --- a/pixie/vm/persistent_hash_set.py +++ b/pixie/vm/persistent_hash_set.py @@ -12,9 +12,6 @@ class PersistentHashSet(object.Object): _type = object.Type(u"pixie.stdlib.PersistentHashSet") - def type(self): - return PersistentHashSet._type - def __init__(self, meta, m): self._meta = meta self._map = m diff --git a/pixie/vm/persistent_list.py b/pixie/vm/persistent_list.py index 54d6b11a..10514b43 100644 --- a/pixie/vm/persistent_list.py +++ b/pixie/vm/persistent_list.py @@ -8,9 +8,6 @@ class PersistentList(object.Object): _type = object.Type(u"pixie.stdlib.PersistentList") - def type(self): - return PersistentList._type - def __init__(self, head, tail, cnt, meta=nil): self._first = head self._next = tail @@ -100,8 +97,6 @@ def _with_meta(self, meta): class EmptyList(object.Object): _type = object.Type(u"pixie.stdlib.EmptyList") - def type(self): - return EmptyList._type def __init__(self, meta=nil): self._meta = meta diff --git a/pixie/vm/persistent_vector.py b/pixie/vm/persistent_vector.py index 202e3c72..2740caf5 100644 --- a/pixie/vm/persistent_vector.py +++ b/pixie/vm/persistent_vector.py @@ -13,9 +13,6 @@ class Node(object.Object): _type = object.Type(u"pixie.stdlib.PersistentVectorNode") - def type(self): - return Node._type - def __init__(self, edit, array=None): self._edit = edit self._array = [None] * 32 if array is None else array @@ -27,9 +24,6 @@ def __init__(self, edit, array=None): class PersistentVector(object.Object): _type = object.Type(u"pixie.stdlib.PersistentVector") - def type(self): - return PersistentVector._type - def __init__(self, meta, cnt, shift, root, tail): self._meta = meta self._cnt = cnt @@ -211,9 +205,6 @@ def new_path(edit, level, node): class TransientVector(object.Object): _type = object.Type(u"pixie.stdlib.TransientVector") - def type(self): - return TransientVector._type - def __init__(self, cnt, shift, root, tail): self._cnt = cnt self._shift = shift diff --git a/pixie/vm/primitives.py b/pixie/vm/primitives.py index 6bab30aa..5924b6a5 100644 --- a/pixie/vm/primitives.py +++ b/pixie/vm/primitives.py @@ -1,25 +1,15 @@ import pixie.vm.object as object - class Nil(object.Object): _type = object.Type(u"pixie.stdlib.Nil") def __repr__(self): return u"nil" - def type(self): - return Nil._type - - nil = Nil() - class Bool(object.Object): _type = object.Type(u"pixie.stdlib.Bool") - def type(self): - return Bool._type - - true = Bool() false = Bool() diff --git a/pixie/vm/reader.py b/pixie/vm/reader.py index 84dccfba..4a6ab292 100644 --- a/pixie/vm/reader.py +++ b/pixie/vm/reader.py @@ -10,7 +10,6 @@ from pixie.vm.keyword import keyword, Keyword import pixie.vm.rt as rt from pixie.vm.persistent_vector import EMPTY as EMPTY_VECTOR -from pixie.vm.libs.libedit import _readline from pixie.vm.string import Character from pixie.vm.code import wrap_fn from pixie.vm.persistent_hash_map import EMPTY as EMPTY_MAP @@ -43,9 +42,6 @@ class PlatformReader(object.Object): _type = object.Type(u"PlatformReader") - def type(self): - return PlatformReader._type - def read(self): assert False @@ -57,8 +53,6 @@ def reset_line(self): class StringReader(PlatformReader): _type = object.Type(u"pixie.stdlib.StringReader") - def type(self): - return StringReader._type def __init__(self, s): affirm(isinstance(s, unicode), u"StringReader requires unicode") @@ -111,8 +105,6 @@ def reader_fn(fn): class LinePromise(object.Object): _type = object.Type(u"pixie.stdlib.LinePromise") - def type(self): - return LinePromise._type def __init__(self): self._chrs = [] @@ -326,11 +318,12 @@ def fqd(self, itm): def invoke(self, rdr, ch): ch = rdr.read() if ch == u":": - itm = read_inner(rdr, True) + ch = rdr.read() + itm = read_symbol(rdr, ch, False) return self.fqd(itm) else: - rdr.unread() - itm = read_inner(rdr, True) + itm = read_symbol(rdr, ch, False) + return keyword(rt.name(itm), rt.namespace(itm)) class LiteralStringReader(ReaderHandler): @@ -746,7 +739,7 @@ def read_number(rdr, ch): return parsed return Symbol(joined) -def read_symbol(rdr, ch): +def read_symbol(rdr, ch, convert_primitives=True): acc = [ch] try: while True: @@ -759,20 +752,19 @@ def read_symbol(rdr, ch): pass sym_str = u"".join(acc) - if sym_str == u"true": - return true - if sym_str == u"false": - return false - if sym_str == u"nil": - return nil + + if convert_primitives: + if sym_str == u"true": + return true + if sym_str == u"false": + return false + if sym_str == u"nil": + return nil return symbol(sym_str) class EOF(object.Object): _type = object.Type(u"EOF") - def type(self): - return EOF._type - eof = EOF() diff --git a/pixie/vm/reduced.py b/pixie/vm/reduced.py index d1d703ea..c94739a6 100644 --- a/pixie/vm/reduced.py +++ b/pixie/vm/reduced.py @@ -6,8 +6,6 @@ class Reduced(object.Object): _type = object.Type(u"pixie.stdlib.Reduced") - def type(self): - return Reduced._type def __init__(self, boxed_value): self._boxed_value = boxed_value diff --git a/pixie/vm/stacklet.py b/pixie/vm/stacklet.py index da42cfc0..d4e8e5c4 100644 --- a/pixie/vm/stacklet.py +++ b/pixie/vm/stacklet.py @@ -25,9 +25,6 @@ def __init__(self, h): self._stacklet_handle = h self._used = False - def type(self): - return self._type - def invoke(self, args): affirm(not self._used, u"Can only call a given stacklet handle once.") affirm(len(args) == 1, u"Only one arg should be handed to a stacklet handle") @@ -53,4 +50,4 @@ def new_handler(h, _): def new_stacklet(fn): global_state._val = fn h = global_state._th.new(new_handler) - return StackletHandle(h) \ No newline at end of file + return StackletHandle(h) diff --git a/pixie/vm/stdlib.py b/pixie/vm/stdlib.py index 79a9061c..d8611d72 100644 --- a/pixie/vm/stdlib.py +++ b/pixie/vm/stdlib.py @@ -687,7 +687,8 @@ def set_macro(f): @returns(bool) @as_var("macro?") -def macro_QMARK_(f): +def macro_QMARK_(v): + f = v.deref() if isinstance(v, Var) else v return true if isinstance(f, BaseCode) and f.is_macro() else false @returns(unicode) diff --git a/pixie/vm/string.py b/pixie/vm/string.py index c9be8844..17327fa9 100644 --- a/pixie/vm/string.py +++ b/pixie/vm/string.py @@ -11,9 +11,6 @@ class String(Object): _type = Type(u"pixie.stdlib.String") - def type(self): - return String._type - def __init__(self, s): #assert isinstance(s, unicode) self._str = s @@ -76,9 +73,6 @@ class Character(Object): _type = Type(u"pixie.stdlib.Character") _immutable_fields_ = ["_char_val"] - def type(self): - return Character._type - def __init__(self, i): assert isinstance(i, int) self._char_val = i diff --git a/pixie/vm/string_builder.py b/pixie/vm/string_builder.py index d2a94296..588b00a5 100644 --- a/pixie/vm/string_builder.py +++ b/pixie/vm/string_builder.py @@ -6,9 +6,6 @@ class StringBuilder(Object): _type = Type(u"pixie.stdlib.StringBuilder") - def type(self): - return StringBuilder._type - def __init__(self): self._strs = [] @@ -34,4 +31,4 @@ def _str(self): @as_var("-string-builder") def _string_builder(): - return StringBuilder() \ No newline at end of file + return StringBuilder() diff --git a/pixie/vm/threads.py b/pixie/vm/threads.py index 5140608b..e42d7d18 100644 --- a/pixie/vm/threads.py +++ b/pixie/vm/threads.py @@ -6,8 +6,6 @@ from pixie.vm.code import as_var import pixie.vm.rt as rt -from rpython.rlib.objectmodel import invoke_around_extcall - class Bootstrapper(object): def __init__(self): self._is_inited = False @@ -15,10 +13,9 @@ def __init__(self): def init(self): if not self._is_inited: - self._is_inited = True self._lock = rthread.allocate_lock() - rgil.gil_allocate() - invoke_around_extcall(before_external_call, after_external_call) + self._is_inited = True + rgil.allocate() def aquire(self, fn): self.init() @@ -55,7 +52,7 @@ def new_thread(fn): @as_var("-yield-thread") def yield_thread(): - do_yield_thread() + rgil.yield_thread() return nil # Locks @@ -65,9 +62,6 @@ class Lock(Object): def __init__(self, ll_lock): self._ll_lock = ll_lock - def type(self): - return Lock._type - @as_var("-create-lock") def _create_lock(): @@ -89,46 +83,5 @@ def _release_lock(self): return rt.wrap(self._ll_lock.release()) - -## From PYPY - - -after_thread_switch = lambda: None # hook for signal.py - -# Fragile code below. We have to preserve the C-level errno manually... - -def before_external_call(): - # this function must not raise, in such a way that the exception - # transformer knows that it cannot raise! - rgil.gil_release() -before_external_call._gctransformer_hint_cannot_collect_ = True -before_external_call._dont_reach_me_in_del_ = True - -def after_external_call(): - rgil.gil_acquire() - rthread.gc_thread_run() - after_thread_switch() -after_external_call._gctransformer_hint_cannot_collect_ = True -after_external_call._dont_reach_me_in_del_ = True - -# The _gctransformer_hint_cannot_collect_ hack is needed for -# translations in which the *_external_call() functions are not inlined. -# They tell the gctransformer not to save and restore the local GC -# pointers in the shadow stack. This is necessary because the GIL is -# not held after the call to before_external_call() or before the call -# to after_external_call(). - -def do_yield_thread(): - # explicitly release the gil, in a way that tries to give more - # priority to other threads (as opposed to continuing to run in - # the same thread). - if rgil.gil_yield_thread(): - rthread.gc_thread_run() - after_thread_switch() -do_yield_thread._gctransformer_hint_close_stack_ = True -do_yield_thread._dont_reach_me_in_del_ = True -do_yield_thread._dont_inline_ = True - -# do_yield_thread() needs a different hint: _gctransformer_hint_close_stack_. # The *_external_call() functions are themselves called only from the rffi # module from a helper function that also has this hint. diff --git a/pixie/vm/util.py b/pixie/vm/util.py index 931ba731..cd97ed7b 100644 --- a/pixie/vm/util.py +++ b/pixie/vm/util.py @@ -78,9 +78,6 @@ def mix_coll_hash(hash, count): class HashingState(Object): _type = Type(u"pixie.stdlib.HashingState") - def type(self): - return HashingState._type - def __init__(self): self._n = r_uint(0) self._hash = r_uint(1) diff --git a/target.py b/target.py index 7eb8932c..71be1c7d 100644 --- a/target.py +++ b/target.py @@ -117,8 +117,11 @@ def __init__(self, filename): def inner_invoke(self, args): import pixie.vm.rt as rt - - rt.compile_file(rt.wrap(self._filename)) + try: + rt.compile_file(rt.wrap(self._filename)) + except WrappedException as ex: + print "Error: ", ex._ex.__repr__() + os._exit(1) class IsPreloadFlag(object): diff --git a/target_preload.py b/target_preload.py deleted file mode 100644 index 3bb0fbe8..00000000 --- a/target_preload.py +++ /dev/null @@ -1,32 +0,0 @@ -from target import entry_point, load_stdlib, init_load_path, LOAD_PATHS, load_path, BatchModeFn -from pixie.vm.atom import Atom -from pixie.vm.persistent_vector import EMPTY as EMPTY_VECTOR -from pixie.vm.symbol import symbol -from pixie.vm.code import intern_var - -import pixie.vm.rt as rt -rt.init() - -load_path.set_root(rt.wrap(u"./")) -LOAD_PATHS.set_root(Atom(EMPTY_VECTOR.conj(rt.wrap(u"./")))) -load_stdlib() - -BatchModeFn(["pixie/preload.pxi"]).invoke([]) - -def target(*args): - import pixie.vm.rt as rt - driver = args[0] - driver.exe_name = "pixie-vm" - rt.__config__ = args[0].config - - - - - - return entry_point, None - -import rpython.config.translationoption -print rpython.config.translationoption.get_combined_translation_config() - -if __name__ == "__main__": - entry_point(sys.argv) \ No newline at end of file diff --git a/tests/pixie/tests/test-arrays.pxi b/tests/pixie/tests/test-arrays.pxi index fbd55937..ecd651cb 100644 --- a/tests/pixie/tests/test-arrays.pxi +++ b/tests/pixie/tests/test-arrays.pxi @@ -8,6 +8,12 @@ (foreach [x a] (t/assert= x nil)))) +(t/deftest test-alength + (let [a (make-array 10)] + (t/assert= (alength a) 10) + (t/assert-throws? RuntimeException + (alength [])))) + (t/deftest test-aget-and-aset (let [a (make-array 10)] (dotimes [i 10] @@ -17,7 +23,13 @@ (aset a i i)) (dotimes [i 10] - (t/assert= (aget a i) i)))) + (t/assert= (aget a i) i)) + + (t/assert-throws? RuntimeException + (aget a 1.0)) + + (t/assert-throws? RuntimeException + (aset a 1.0 :foo)))) (t/deftest test-aconcat (let [a1 (make-array 10) @@ -30,7 +42,13 @@ (let [a3 (aconcat a1 a2)] (dotimes [i 20] - (t/assert= (aget a3 i) i))))) + (t/assert= (aget a3 i) i))) + + (t/assert-throws? RuntimeException + (t/aconcat a1 [])) + + (t/assert-throws? RuntimeException + (t/aconcat a1 '())))) (t/deftest test-aslice (let [a (make-array 10)] @@ -42,10 +60,19 @@ (foreach [i (range 0 7)] (t/assert= (aget a1 i) (+ i 3))) (foreach [i (range 0 3)] - (t/assert= (aget a2 i) (+ i 7)))))) + (t/assert= (aget a2 i) (+ i 7)))) + + (t/assert-throws? RuntimeException + (aslice [1 2 3 4] 0 2)) + + (t/assert-throws? RuntimeException + (aslice '() 0 2)) + + (t/assert-throws? RuntimeException + (aslice a 1.0 2)))) (t/deftest test-byte-array-creation (let [ba (byte-array 10)] (t/assert= (vec ba) [0 0 0 0 0 0 0 0 0 0]) - (t/assert= (count ba) 10))) \ No newline at end of file + (t/assert= (count ba) 10))) diff --git a/tests/pixie/tests/test-compiler.pxi b/tests/pixie/tests/test-compiler.pxi index 944343d4..751ee95e 100644 --- a/tests/pixie/tests/test-compiler.pxi +++ b/tests/pixie/tests/test-compiler.pxi @@ -35,3 +35,39 @@ (t/deftest test-deftype-mutables (mutate! (->Foo 0))) + +(t/deftest test-recur-must-tail + (t/assert-throws? + (eval + '(loop [n 0] + (inc (recur n))))) + + (t/assert-throws? + (eval + '(fn [n] + (if (zero? n) + 1 + (* n (recur (dec n))))))) + +(t/assert-throws? + (eval + '(fn [n] + (if (zero? n) + (* n (recur (dec n))) + 1)))) + + (t/assert= + (eval + '(loop [n 0] + (if (= 10 n) + n + (recur (inc n))))) + 10) + + (t/assert= + (eval + '(loop [n 0] + (if (not= 10 n) + (recur (inc n)) + n))) + 10)) diff --git a/tests/pixie/tests/test-ffi.pxi b/tests/pixie/tests/test-ffi.pxi index f2d997c7..4cc486dd 100644 --- a/tests/pixie/tests/test-ffi.pxi +++ b/tests/pixie/tests/test-ffi.pxi @@ -1,6 +1,7 @@ (ns pixie.tests.test-ffi (require pixie.test :as t) - (require pixie.math :as m)) + (require pixie.math :as m) + (require pixie.ffi-infer :as i)) @@ -36,6 +37,21 @@ (t/deftest test-ffi-infer (t/assert= 0.5 (m/asin (m/sin 0.5)))) +(t/deftest test-cdouble + (i/with-config {:library "m" + :cxx-flags ["-lm"] + :includes ["math.h"]} + (i/defcfn sinf) + (i/defcfn asinf) + (i/defcfn cosf) + (i/defcfn powf)) + (t/assert= 0.5 (asinf (sinf 0.5))) + (t/assert= 1.0 (+ (powf (sinf 0.5) 2.0) (powf (cosf 0.5) 2.0)))) + +(t/deftest test-invalid-float-argument + (t/assert-throws? (m/sin "nil")) + (t/assert-throws? (m/sin nil)) + ) (t/deftest test-ffi-callbacks (let [MAX 255 diff --git a/tests/pixie/tests/test-io.pxi b/tests/pixie/tests/test-io.pxi index 1d41c4a5..07a3606b 100644 --- a/tests/pixie/tests/test-io.pxi +++ b/tests/pixie/tests/test-io.pxi @@ -3,6 +3,7 @@ (require pixie.streams :as st :refer :all) (require pixie.streams.utf8 :as utf8 :refer :all) (require pixie.io :as io) + (require pixie.io-blocking :as blocking) (require pixie.streams.zlib :as zlib)) (t/deftest test-file-reduction @@ -10,11 +11,25 @@ (t/assert= (transduce (map identity) count-rf f) - 91))) + 91)) + (let [f (io/open-read "tests/pixie/tests/test-io.txt")] + (t/assert= (transduce (comp (map char) (take 4)) string-builder f) + "This")) + (let [f (blocking/open-read "tests/pixie/tests/test-io.txt")] + (t/assert= (transduce (map identity) + count-rf + f) + 91)) + (let [f (blocking/open-read "tests/pixie/tests/test-io.txt")] + (t/assert= (transduce (comp (map char) (take 4)) string-builder f) + "This"))) (t/deftest test-process-reduction (let [f (io/run-command "ls tests/pixie/tests/test-io.txt")] - (t/assert= f "tests/pixie/tests/test-io.txt\n"))) + (t/assert= f "tests/pixie/tests/test-io.txt\n")) + (let [pipe (blocking/popen-read "ls tests/pixie/tests/test-io.txt")] + (t/assert= (transduce (comp (map char) (take 6)) string-builder pipe) + "tests/"))) (t/deftest test-read-into-buffer (let [f (io/open-read "tests/pixie/tests/test-io.txt")] @@ -38,6 +53,14 @@ (t/assert= (io/read-line f) "Second line.") (t/assert= (io/read-line f) nil))) +(t/deftest test-line-reader + (let [lines (io/line-reader (io/open-read "tests/pixie/tests/test-io.txt"))] + (t/assert= (transduce (map count) conj [] lines) + [77 12])) + (let [lines (io/line-reader (io/open-read "tests/pixie/tests/test-io.txt"))] + (t/assert= (transduce (comp (map count) (take 1)) conj [] lines) + [77]))) + (t/deftest test-line-seq (let [f (io/buffered-input-stream (io/open-read "tests/pixie/tests/test-io.txt")) s (io/line-seq f)] @@ -58,7 +81,11 @@ (t/assert= (char (io/read-byte f)) \T) (t/assert= (char (io/read-byte f)) \h) (t/assert= (char (io/read-byte f)) \i) - (t/assert= (char (io/read-byte f)) \s))) + (t/assert= (char (io/read-byte f)) \s) + (t/assert= (transduce (comp (map char) (take 5)) string-builder f) + " is a") + (t/assert= (transduce (comp (map char) (take 5)) string-builder f) + " test"))) (t/deftest test-buffered-input-streams-throws-on-non-input-streams (let [f (io/buffered-input-stream (io/open-read "tests/pixie/tests/test-io.txt"))] diff --git a/tests/pixie/tests/test-keywords.pxi b/tests/pixie/tests/test-keywords.pxi index 06e2deb7..1094cf45 100644 --- a/tests/pixie/tests/test-keywords.pxi +++ b/tests/pixie/tests/test-keywords.pxi @@ -6,7 +6,6 @@ (t/assert= (:a m) 1) (t/assert= (:b m) 2) (t/assert= (:c m) 3) - (t/assert= (:d m) nil) (t/assert= (:d m :foo) :foo))) @@ -29,9 +28,40 @@ (t/assert= (not= :foo/bar :cat/bar) true) (t/assert= (not= :foo/cat :foo/dog) true)) +(t/deftest keyword-reader + (t/assert= (read-string ":1") :1) + (t/assert= (read-string ":1") :1) + (t/assert= (read-string ":1.0") :1.0) + (t/assert= (read-string ":foo") :foo) + (t/assert= (read-string ":1foo") :1foo) + (t/assert= (read-string ":foo/bar") :foo/bar) + (t/assert= (read-string ":1foo/1bar") :1foo/1bar) + (t/assert= (read-string ":nil") :nil) + (t/assert= (read-string ":true") :true) + (t/assert= (read-string ":false") :false) + + ;; We are reading at runtime so the namespace isn't + ;; going to be pixie.test.test-keywords. Its probably + ;; 'user but lets explicitly set it. + ;; The refer-ns is to initialize a new space + (refer-ns 'my.other.ns 'my.fake.core 'fake) + (binding [*ns* (the-ns 'my.other.ns)] + (t/assert= (read-string "::1") :my.other.ns/1) + (t/assert= (read-string "::1.0") :my.other.ns/1.0) + (t/assert= (read-string "::foo") :my.other.ns/foo) + (t/assert= (read-string "::true") :my.other.ns/true))) + (t/deftest string-to-keyword + (t/assert= (keyword "1") :1) + (t/assert= (keyword "1") :1) + (t/assert= (keyword "1.0") :1.0) (t/assert= (keyword "foo") :foo) + (t/assert= (keyword "1foo") :1foo) (t/assert= (keyword "foo/bar") :foo/bar) + (t/assert= (keyword "1foo/1bar") :1foo/1bar) + (t/assert= (keyword "nil") :nil) + (t/assert= (keyword "true") :true) + (t/assert= (keyword "false") :false) (t/assert-throws? (keyword 1)) (t/assert-throws? (keyword :a)) (t/assert-throws? (keyword 'a)) diff --git a/tests/pixie/tests/test-stdlib.pxi b/tests/pixie/tests/test-stdlib.pxi index 8e96707f..9b2174e0 100644 --- a/tests/pixie/tests/test-stdlib.pxi +++ b/tests/pixie/tests/test-stdlib.pxi @@ -28,9 +28,28 @@ (t/assert= (keep-indexed (constantly nil) []) []) (t/assert= (keep-indexed (fn [i x] [i x]) [:a :b]) [[0 :a] [1 :b]]) - (t/assert= (transduce (keep-indexed (constantly true)) conj []) []) - (t/assert= (transduce (keep-indexed (constantly nil)) conj []) []) - (t/assert= (transduce (keep-indexed (fn [i x] [i x])) conj [:a :b]) [[0 :a] [1 :b]])) + (t/assert= (transduce (keep-indexed (constantly true)) conj [:a :b]) [true true]) + (t/assert= (transduce (keep-indexed (constantly nil)) conj [:a :b]) []) + (t/assert= (transduce (keep-indexed (fn [i x] [i x])) conj [:a :b]) [[0 :a] [1 :b]]) + + (let [even-index? (fn [i x] + (when (even? i) + x))] + (t/assert= (transduce (keep-indexed even-index?) conj [:a :b :c :d]) + [:a :c]) + (t/assert= (transduce (map-indexed even-index?) conj [:a :b :c :d]) + [:a nil :c nil]) + + (t/assert= (transduce (comp (keep-indexed even-index?) + (take 3)) + conj + [:a :b :c :d :e :f]) + [:a :c :e]) + (t/assert= (transduce (comp (map-indexed even-index?) + (take 3)) + conj + [:a :b :c :d]) + [:a nil :c]))) (t/deftest test-reductions (t/assert= (reductions + nil) @@ -433,7 +452,11 @@ (t/assert= (for [x [1 2 3] y [:a :b :c]] [x y]) [[1 :a] [1 :b] [1 :c] [2 :a] [2 :b] [2 :c] - [3 :a] [3 :b] [3 :c]])) + [3 :a] [3 :b] [3 :c]]) + (t/assert= (for [x [[1 2 3]] + y x] + y) + [1 2 3])) (t/deftest test-doto (let [a (atom 0)] @@ -542,7 +565,21 @@ (t/assert= (transduce (take 0) conj [1 2 3 4]) []) (t/assert= (transduce (take 1) conj [1 2 3 4]) [1]) (t/assert= (transduce (take 2) conj [1 2 3 4]) [1 2]) - (t/assert= (transduce (take 3) conj [1 2 3 4]) [1 2 3])) + (t/assert= (transduce (take 3) conj [1 2 3 4]) [1 2 3]) + (t/assert= (transduce (take 10) conj [1 2 3 4]) [1 2 3 4]) + (t/assert= (transduce (comp (take 2) (take 1)) conj [1 2 3 4]) [1]) + (t/assert= (transduce (comp (take 1) (take 2)) conj [1 2 3 4]) [1]) + + (let [call-count (atom 0) + inc-call-count! (fn [x] + (swap! call-count inc) + x)] + (t/assert= (transduce (comp (map inc-call-count!) (take 2)) conj (range 10)) + [0 1]) + (t/assert= @call-count 2) + (t/assert= (transduce (comp (take 2) (map inc-call-count!)) conj (range 10)) + [0 1]) + (t/assert= @call-count 4))) (t/deftest test-drop (t/assert= (drop 0 [1 2 3 4]) [1 2 3 4]) @@ -552,21 +589,26 @@ (t/assert= (transduce (drop 0) conj [1 2 3 4]) [1 2 3 4]) (t/assert= (transduce (drop 1) conj [1 2 3 4]) [2 3 4]) (t/assert= (transduce (drop 2) conj [1 2 3 4]) [3 4]) - (t/assert= (transduce (drop 3) conj [1 2 3 4]) [4])) + (t/assert= (transduce (drop 3) conj [1 2 3 4]) [4]) + (t/assert= (transduce (drop 10) conj [1 2 3 4]) []) + (t/assert= (transduce (comp (drop 1) (take 2)) conj [1 2 3 4]) [2 3]) + (t/assert= (transduce (comp (take 2) (drop 1)) conj [1 2 3 4]) [2])) (t/deftest test-take-while (t/assert= (take-while pos? [1 2 3 -1]) [1 2 3]) (t/assert= (take-while pos? [-1 2]) ()) (t/assert= (transduce (take-while even?) conj [2 4 6 7 8]) [2 4 6]) (t/assert= (transduce (take-while even?) conj [0 2] [1 4 6]) [0 2]) - (t/assert= (transduce (take-while even?) conj [1 3] [2 4 6 7 8]) [1 3 2 4 6])) + (t/assert= (transduce (take-while even?) conj [1 3] [2 4 6 7 8]) [1 3 2 4 6]) + (t/assert= (transduce (comp (take-while even?) (take 2)) conj [1 3] [2 4 6 7 8]) [1 3 2 4])) (t/deftest test-drop-while (t/assert= (drop-while pos? [1 2 3 -1]) [-1]) (t/assert= (drop-while pos? [-1 2]) [-1 2]) (t/assert= (transduce (drop-while even?) conj [2 4 6 7 8]) [7 8]) (t/assert= (transduce (drop-while even?) conj [0 2] [1 4 6]) [0 2 1 4 6]) - (t/assert= (transduce (drop-while even?) conj [0 2] [2 4 6 7 8]) [0 2 7 8])) + (t/assert= (transduce (drop-while even?) conj [0 2] [2 4 6 7 8]) [0 2 7 8]) + (t/assert= (transduce (comp (drop-while even?) (take 2)) conj [0 2] [2 4 6 7 8]) [0 2 7 8])) (t/deftest test-cycle (t/assert= (cycle ()) ()) @@ -574,6 +616,29 @@ (t/assert= (take 5 (cycle '(1 2))) '(1 2 1 2 1)) (t/assert= (take 3 (cycle [nil])) '(nil nil nil))) +(t/deftest test-eduction + ;; one xform + (t/assert= [1 2 3 4 5] + (eduction (map inc) (range 5))) + ;; multiple xforms + (t/assert= ["2" "4"] + (eduction (map inc) (filter even?) (map str) (range 5))) + ;; materialize at the end + (t/assert= [1 1 2 1 2 3 1 2 3 4] + (vec (->> (range 5) + (eduction (mapcat range) (map inc))))) + (t/assert= {1 4, 2 3, 3 2, 4 1} + (->> (range 5) + (eduction (mapcat range) (map inc)) + frequencies)) + (t/assert= ["tac" "god" "hsif" "drib" "kravdraa"] + (->> ["cat" "dog" "fish" "bird" "aardvark"] + (eduction (map pixie.string/reverse)) + (seq))) + ;; expanding transducer with nils + (t/assert= '(1 2 3 nil 4 5 6 nil) + (seq (eduction cat [[1 2 3 nil] [4 5 6 nil]])))) + (t/deftest test-trace (try (/ 0 0) @@ -738,3 +803,42 @@ (t/deftest test-memoize (let [f (memoize rand)] (t/assert= (f) (f)))) + +(t/deftest test-iterate + (t/assert= (take 5 (iterate inc 5)) '(5 6 7 8 9)) + (t/assert= (reduce (fn [a v] (reduced "foo")) 0 (iterate inc 1)) "foo") + (t/assert= (reduce (fn [a v] (if (< a 10) (+ a v) (reduced a))) 0 (iterate (partial + 2) 1)) 16)) + +(t/deftest test-sequence-empty-sequences + (t/assert= '() (take 1 (sequence (map inc) '()))) + (t/assert= '() (take 1 (sequence (map inc) []))) + (t/assert= '() (take 1 (sequence (map inc) #{}))) + (t/assert= '() (take 1 (sequence (map inc) {})))) + +(t/deftest test-sequence-non-empty-sequences + (t/assert= '(1 3) (take 2 (sequence (comp + (filter even?) + (map inc)) (range 3)))) + (t/assert= '(1) (take 1 (sequence (distinct) (repeat 4 1))))) + +(t/deftest test-sequence-early-terminating-sequences + (t/assert= '() (take 5 (sequence (filter (fn [x] false)) (repeat 8 8)))) + (t/assert= '(1 2) (take 3 (sequence (map identity) [1 2]))) + (t/assert= #{[:a 1] [:b 2]} (into #{} (take 3 (sequence (filter (fn [[k v]] + (keyword? k)) {:a 1 + :b 2 + "c" 3 + "d" 4})))))) + +(t/deftest test-letfn + (letfn [(hello [] "Hello") + (adder [x y] (+ x y))] + (t/assert= "Hello" (hello)) + (dotimes [i 10] + (dotimes [j 20] + (t/assert= (+ i j) (adder i j))))) + (letfn [(f [x n] (vec (repeat n x)))] + (t/assert= (f :x 3) [:x :x :x]) + (t/assert= (f 0 20) [0 0 0 0 0 + 0 0 0 0 0 + 0 0 0 0 0])))