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
|
||||
"Define a function"
|
||||
(fn [name & more]
|
||||
(def len (length more))
|
||||
(def fstart (fn recur [i]
|
||||
(def ith (ast-unwrap1 (get more i)))
|
||||
(def t (type ith))
|
||||
(def tuple? (= t :tuple))
|
||||
(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 fnbody (tuple-prepend (tuple-prepend (tuple-slice more start) name) 'fn))
|
||||
(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]
|
||||
(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*
|
||||
[& funs]
|
||||
(def len (length funs))
|
||||
@ -509,6 +495,9 @@ the predicate, and abort on first failiure."
|
||||
(tuple 'fn (tuple '& $args) (apply1 tuple parts)))
|
||||
|
||||
(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]
|
||||
(defn fop [last nextform]
|
||||
(def n (ast-unwrap1 nextform))
|
||||
@ -520,6 +509,9 @@ the predicate, and abort on first failiure."
|
||||
(reduce fop x forms))
|
||||
|
||||
(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]
|
||||
(defn fop [last nextform]
|
||||
(def n (ast-unwrap1 nextform))
|
||||
|
@ -830,7 +830,8 @@ recur:
|
||||
x = dst_resume(f, dst_tuple_length(tup) - 1, tup + 1);
|
||||
dst_gcunlock(lock);
|
||||
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 */
|
||||
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) {
|
||||
switch (dst_type(x)) {
|
||||
case DST_NIL:
|
||||
@ -452,6 +471,10 @@ const uint8_t *dst_formatc(const char *format, ...) {
|
||||
break;
|
||||
}
|
||||
case 'V':
|
||||
{
|
||||
dst_to_string_b(bufp, va_arg(args, Dst));
|
||||
break;
|
||||
}
|
||||
case 'v':
|
||||
{
|
||||
dst_description_b(bufp, va_arg(args, Dst));
|
||||
|
Loading…
Reference in New Issue
Block a user