1
0
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:
Calvin Rose 2018-04-01 18:24:04 -04:00
parent 1110267c9d
commit 534c936e14
3 changed files with 34 additions and 18 deletions

View File

@ -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))

View File

@ -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;

View File

@ -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));