mirror of
https://github.com/janet-lang/janet
synced 2024-11-25 01:37:19 +00:00
Fix infinite recursion on defn and derivatives on invalid
input.
This commit is contained in:
parent
1110267c9d
commit
534c936e14
@ -14,12 +14,14 @@
|
|||||||
(def defn :macro
|
(def defn :macro
|
||||||
"Define a function"
|
"Define a function"
|
||||||
(fn [name & more]
|
(fn [name & more]
|
||||||
|
(def len (length more))
|
||||||
(def fstart (fn recur [i]
|
(def fstart (fn recur [i]
|
||||||
(def ith (ast-unwrap1 (get more i)))
|
(def ith (ast-unwrap1 (get more i)))
|
||||||
(def t (type ith))
|
(def t (type ith))
|
||||||
(def tuple? (= t :tuple))
|
(def tuple? (= t :tuple))
|
||||||
(def array? (= t :array))
|
(def array? (= t :array))
|
||||||
(if (if tuple? tuple? array?) i (recur (+ i 1)))))
|
(if (if tuple? tuple? array?) i
|
||||||
|
(if (< i len) (recur (+ i 1))))))
|
||||||
(def start (fstart 0))
|
(def start (fstart 0))
|
||||||
(def fnbody (tuple-prepend (tuple-prepend (tuple-slice more start) name) 'fn))
|
(def fnbody (tuple-prepend (tuple-prepend (tuple-slice more start) name) 'fn))
|
||||||
(def formargs (array-concat @['def name] (array-slice more 0 start) @[fnbody]))
|
(def formargs (array-concat @['def name] (array-slice more 0 start) @[fnbody]))
|
||||||
@ -475,22 +477,6 @@ the predicate, and abort on first failiure."
|
|||||||
[pred ind t]
|
[pred ind t]
|
||||||
(drop-until (complement pred) ind t))
|
(drop-until (complement pred) ind t))
|
||||||
|
|
||||||
(defn zip
|
|
||||||
[& seqs]
|
|
||||||
(def lens (length seqs))
|
|
||||||
(def ret @[])
|
|
||||||
(if (= 0 lens) (error "expected at least 1 sequence"))
|
|
||||||
(var minlen (length (get seqs 0)))
|
|
||||||
(for [j 1 lens]
|
|
||||||
(def sl (length (get seqs j)))
|
|
||||||
(if (< sl minlen) (:= minlen sl)))
|
|
||||||
(for [i 0 minlen]
|
|
||||||
(def accum @[])
|
|
||||||
(for [j 0 lens]
|
|
||||||
(array-push accum (get seqs j i)))
|
|
||||||
(array-push ret (apply1 tuple accum)))
|
|
||||||
(apply1 tuple ret))
|
|
||||||
|
|
||||||
(defn juxt*
|
(defn juxt*
|
||||||
[& funs]
|
[& funs]
|
||||||
(def len (length funs))
|
(def len (length funs))
|
||||||
@ -509,6 +495,9 @@ the predicate, and abort on first failiure."
|
|||||||
(tuple 'fn (tuple '& $args) (apply1 tuple parts)))
|
(tuple 'fn (tuple '& $args) (apply1 tuple parts)))
|
||||||
|
|
||||||
(defmacro ->
|
(defmacro ->
|
||||||
|
"Threading macro. Inserts x as the second value in the first form
|
||||||
|
in form, and inserts the modified firsts form into the second form
|
||||||
|
in the same manner, and so on. Useful for expressing pipelines of data."
|
||||||
[x & forms]
|
[x & forms]
|
||||||
(defn fop [last nextform]
|
(defn fop [last nextform]
|
||||||
(def n (ast-unwrap1 nextform))
|
(def n (ast-unwrap1 nextform))
|
||||||
@ -520,6 +509,9 @@ the predicate, and abort on first failiure."
|
|||||||
(reduce fop x forms))
|
(reduce fop x forms))
|
||||||
|
|
||||||
(defmacro ->>
|
(defmacro ->>
|
||||||
|
"Threading macro. Inserts x as the last value in the first form
|
||||||
|
in form, and inserts the modified firsts form into the second form
|
||||||
|
in the same manner, and so on. Useful for expressing pipelines of data."
|
||||||
[x & forms]
|
[x & forms]
|
||||||
(defn fop [last nextform]
|
(defn fop [last nextform]
|
||||||
(def n (ast-unwrap1 nextform))
|
(def n (ast-unwrap1 nextform))
|
||||||
|
@ -830,7 +830,8 @@ recur:
|
|||||||
x = dst_resume(f, dst_tuple_length(tup) - 1, tup + 1);
|
x = dst_resume(f, dst_tuple_length(tup) - 1, tup + 1);
|
||||||
dst_gcunlock(lock);
|
dst_gcunlock(lock);
|
||||||
if (f->status == DST_FIBER_ERROR || f->status == DST_FIBER_DEBUG) {
|
if (f->status == DST_FIBER_ERROR || f->status == DST_FIBER_DEBUG) {
|
||||||
dstc_cerror(c, ast, "error in macro expansion");
|
const uint8_t *es = dst_formatc("error in macro expansion: %V", x);
|
||||||
|
dstc_error(c, ast, es);
|
||||||
}
|
}
|
||||||
/* Tail recur on the value */
|
/* Tail recur on the value */
|
||||||
goto recur;
|
goto recur;
|
||||||
|
@ -336,6 +336,25 @@ void dst_description_b(DstBuffer *buffer, Dst x) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dst_to_string_b(DstBuffer *buffer, Dst x) {
|
||||||
|
switch (dst_type(x)) {
|
||||||
|
default:
|
||||||
|
dst_description_b(buffer, x);
|
||||||
|
break;
|
||||||
|
case DST_BUFFER:
|
||||||
|
dst_buffer_push_bytes(buffer,
|
||||||
|
dst_unwrap_buffer(x)->data,
|
||||||
|
dst_unwrap_buffer(x)->count);
|
||||||
|
break;
|
||||||
|
case DST_STRING:
|
||||||
|
case DST_SYMBOL:
|
||||||
|
dst_buffer_push_bytes(buffer,
|
||||||
|
dst_unwrap_string(x),
|
||||||
|
dst_string_length(dst_unwrap_string(x)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const uint8_t *dst_description(Dst x) {
|
const uint8_t *dst_description(Dst x) {
|
||||||
switch (dst_type(x)) {
|
switch (dst_type(x)) {
|
||||||
case DST_NIL:
|
case DST_NIL:
|
||||||
@ -452,6 +471,10 @@ const uint8_t *dst_formatc(const char *format, ...) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'V':
|
case 'V':
|
||||||
|
{
|
||||||
|
dst_to_string_b(bufp, va_arg(args, Dst));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'v':
|
case 'v':
|
||||||
{
|
{
|
||||||
dst_description_b(bufp, va_arg(args, Dst));
|
dst_description_b(bufp, va_arg(args, Dst));
|
||||||
|
Loading…
Reference in New Issue
Block a user