mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 07:33:01 +00:00 
			
		
		
		
	Fix infinite recursion on defn and derivatives on invalid
input.
This commit is contained in:
		| @@ -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)); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose