mirror of
https://github.com/janet-lang/janet
synced 2024-12-01 04:19:55 +00:00
Remove duplicate code in loop macro.
Also evaluate for loop and range step exactly once. Multiple evaluations can be inefficent and make infinite loop detection impossible.
This commit is contained in:
parent
e548e1f6e0
commit
97c64f27ff
@ -379,26 +379,23 @@
|
|||||||
,(apply defer [(or dtor :close) binding] [truthy])
|
,(apply defer [(or dtor :close) binding] [truthy])
|
||||||
,falsey))
|
,falsey))
|
||||||
|
|
||||||
(defn- for-template
|
|
||||||
[binding start stop step comparison delta body]
|
|
||||||
(with-syms [i s]
|
|
||||||
~(do
|
|
||||||
(var ,i ,start)
|
|
||||||
(def ,s ,stop)
|
|
||||||
(while (,comparison ,i ,s)
|
|
||||||
(def ,binding ,i)
|
|
||||||
,;body
|
|
||||||
(set ,i (,delta ,i ,step))))))
|
|
||||||
|
|
||||||
(defn- for-var-template
|
(defn- for-var-template
|
||||||
[i start stop step comparison delta body]
|
[i start stop step comparison delta body]
|
||||||
(with-syms [s]
|
(with-syms [s]
|
||||||
|
(def st (if (idempotent? step) step (gensym)))
|
||||||
~(do
|
~(do
|
||||||
(var ,i ,start)
|
(var ,i ,start)
|
||||||
(def ,s ,stop)
|
(def ,s ,stop)
|
||||||
|
,;(if (= st step) [] [~(def ,st ,step)])
|
||||||
(while (,comparison ,i ,s)
|
(while (,comparison ,i ,s)
|
||||||
,;body
|
,;body
|
||||||
(set ,i (,delta ,i ,step))))))
|
(set ,i (,delta ,i ,st))))))
|
||||||
|
|
||||||
|
(defn- for-template
|
||||||
|
[binding start stop step comparison delta body]
|
||||||
|
(def i (gensym))
|
||||||
|
(for-var-template i start stop step comparison delta
|
||||||
|
[~(def ,binding ,i) ;body]))
|
||||||
|
|
||||||
(defn- check-indexed [x]
|
(defn- check-indexed [x]
|
||||||
(if (indexed? x)
|
(if (indexed? x)
|
||||||
@ -411,26 +408,18 @@
|
|||||||
(for-template binding start stop (or step 1) comparison op [rest])))
|
(for-template binding start stop (or step 1) comparison op [rest])))
|
||||||
|
|
||||||
(defn- each-template
|
(defn- each-template
|
||||||
[binding inx body]
|
[binding inx kind body]
|
||||||
(with-syms [k]
|
(with-syms [k]
|
||||||
(def ds (if (idempotent? inx) inx (gensym)))
|
(def ds (if (idempotent? inx) inx (gensym)))
|
||||||
~(do
|
~(do
|
||||||
,(unless (= ds inx) ~(def ,ds ,inx))
|
,(unless (= ds inx) ~(def ,ds ,inx))
|
||||||
(var ,k (,next ,ds nil))
|
(var ,k (,next ,ds nil))
|
||||||
(while (,not= nil ,k)
|
(while (,not= nil ,k)
|
||||||
(def ,binding (,in ,ds ,k))
|
(def ,binding
|
||||||
,;body
|
,(case kind
|
||||||
(set ,k (,next ,ds ,k))))))
|
:each ~(,in ,ds ,k)
|
||||||
|
:keys k
|
||||||
(defn- keys-template
|
:pairs ~(,tuple ,k (,in ,ds ,k))))
|
||||||
[binding in pair? body]
|
|
||||||
(with-syms [k]
|
|
||||||
(def ds (if (idempotent? in) in (gensym)))
|
|
||||||
~(do
|
|
||||||
,(unless (= ds in) ~(def ,ds ,in))
|
|
||||||
(var ,k (,next ,ds nil))
|
|
||||||
(while (,not= nil ,k)
|
|
||||||
(def ,binding ,(if pair? ~(tuple ,k (in ,ds ,k)) k))
|
|
||||||
,;body
|
,;body
|
||||||
(set ,k (,next ,ds ,k))))))
|
(set ,k (,next ,ds ,k))))))
|
||||||
|
|
||||||
@ -487,9 +476,9 @@
|
|||||||
:range-to (range-template binding object rest + <=)
|
:range-to (range-template binding object rest + <=)
|
||||||
:down (range-template binding object rest - >)
|
:down (range-template binding object rest - >)
|
||||||
:down-to (range-template binding object rest - >=)
|
:down-to (range-template binding object rest - >=)
|
||||||
:keys (keys-template binding object false [rest])
|
:keys (each-template binding object :keys [rest])
|
||||||
:pairs (keys-template binding object true [rest])
|
:pairs (each-template binding object :pairs [rest])
|
||||||
:in (each-template binding object [rest])
|
:in (each-template binding object :each [rest])
|
||||||
:iterate (iterate-template binding object rest)
|
:iterate (iterate-template binding object rest)
|
||||||
:generate (loop-fiber-template binding object [rest])
|
:generate (loop-fiber-template binding object [rest])
|
||||||
(error (string "unexpected loop verb " verb)))))
|
(error (string "unexpected loop verb " verb)))))
|
||||||
@ -508,12 +497,12 @@
|
|||||||
(defmacro eachk
|
(defmacro eachk
|
||||||
"Loop over each key in ds. Returns nil."
|
"Loop over each key in ds. Returns nil."
|
||||||
[x ds & body]
|
[x ds & body]
|
||||||
(keys-template x ds false body))
|
(each-template x ds :each body))
|
||||||
|
|
||||||
(defmacro eachp
|
(defmacro eachp
|
||||||
"Loop over each (key, value) pair in ds. Returns nil."
|
"Loop over each (key, value) pair in ds. Returns nil."
|
||||||
[x ds & body]
|
[x ds & body]
|
||||||
(keys-template x ds true body))
|
(each-template x ds :pairs body))
|
||||||
|
|
||||||
(defmacro eachy
|
(defmacro eachy
|
||||||
"Resume a fiber in a loop until it has errored or died. Evaluate the body
|
"Resume a fiber in a loop until it has errored or died. Evaluate the body
|
||||||
@ -530,7 +519,7 @@
|
|||||||
(defmacro each
|
(defmacro each
|
||||||
"Loop over each value in ds. Returns nil."
|
"Loop over each value in ds. Returns nil."
|
||||||
[x ds & body]
|
[x ds & body]
|
||||||
(each-template x ds body))
|
(each-template x ds :each body))
|
||||||
|
|
||||||
(defmacro loop
|
(defmacro loop
|
||||||
"A general purpose loop macro. This macro is similar to the Common Lisp
|
"A general purpose loop macro. This macro is similar to the Common Lisp
|
||||||
@ -575,7 +564,6 @@
|
|||||||
(put _env 'for-var-template nil)
|
(put _env 'for-var-template nil)
|
||||||
(put _env 'iterate-template nil)
|
(put _env 'iterate-template nil)
|
||||||
(put _env 'each-template nil)
|
(put _env 'each-template nil)
|
||||||
(put _env 'keys-template nil)
|
|
||||||
(put _env 'range-template nil)
|
(put _env 'range-template nil)
|
||||||
(put _env 'loop-fiber-template nil)
|
(put _env 'loop-fiber-template nil)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user