diff --git a/eval.c b/eval.c index 67b177e6..d4be08f6 100644 --- a/eval.c +++ b/eval.c @@ -591,16 +591,17 @@ sexp sexp_syntactic_closure_expr_op (sexp ctx, sexp self, sexp_sint_t n, sexp x) return (sexp_synclop(x) ? sexp_synclo_expr(x) : x); } -sexp sexp_strip_synclos (sexp ctx, sexp self, sexp_sint_t n, sexp x) { +sexp sexp_strip_synclos_bound (sexp ctx, sexp x, int depth) { sexp_gc_var3(res, kar, kdr); + if (depth <= 0) return x; sexp_gc_preserve3(ctx, res, kar, kdr); loop: if (sexp_synclop(x)) { x = sexp_synclo_expr(x); goto loop; } else if (sexp_pairp(x) && sexp_truep(sexp_length(ctx, x))) { - kar = sexp_strip_synclos(ctx, self, n, sexp_car(x)); - kdr = sexp_strip_synclos(ctx, self, n, sexp_cdr(x)); + kar = sexp_strip_synclos_bound(ctx, sexp_car(x), depth-1); + kdr = sexp_strip_synclos_bound(ctx, sexp_cdr(x), depth-1); res = sexp_cons(ctx, kar, kdr); sexp_pair_source(res) = sexp_pair_source(x); sexp_immutablep(res) = 1; @@ -611,6 +612,10 @@ sexp sexp_strip_synclos (sexp ctx, sexp self, sexp_sint_t n, sexp x) { return res; } +sexp sexp_strip_synclos (sexp ctx, sexp self, sexp_sint_t n, sexp x) { + return sexp_strip_synclos_bound(ctx, x, SEXP_STRIP_SYNCLOS_BOUND); +} + sexp sexp_identifier_eq_op (sexp ctx, sexp self, sexp_sint_t n, sexp e1, sexp id1, sexp e2, sexp id2) { sexp cell1, cell2; cell1 = sexp_env_cell(ctx, e1, id1, 0); diff --git a/include/chibi/features.h b/include/chibi/features.h index 35fa236a..223c9a50 100644 --- a/include/chibi/features.h +++ b/include/chibi/features.h @@ -684,6 +684,10 @@ #define SEXP_DEFAULT_EQUAL_BOUND 100000000 #endif +#ifndef SEXP_STRIP_SYNCLOS_BOUND +#define SEXP_STRIP_SYNCLOS_BOUND 10000 +#endif + #ifndef SEXP_POLL_SLEEP_TIME #define SEXP_POLL_SLEEP_TIME 5000 #endif diff --git a/sexp.c b/sexp.c index 14954ed5..daf2a0d7 100644 --- a/sexp.c +++ b/sexp.c @@ -2627,6 +2627,8 @@ static int sexp_peek_char(sexp ctx, sexp in) { return c; } +sexp sexp_read_one (sexp ctx, sexp in, sexp *shares); + sexp sexp_read_raw (sexp ctx, sexp in, sexp *shares) { char *str; int c1, c2, line; @@ -2653,23 +2655,23 @@ sexp sexp_read_raw (sexp ctx, sexp in, sexp *shares) { case '\r': goto scan_loop; case '\'': - res = sexp_read(ctx, in); + res = sexp_read_one(ctx, in, shares); if (! sexp_exceptionp(res)) res = sexp_list2(ctx, sexp_global(ctx, SEXP_G_QUOTE_SYMBOL), res); break; case '`': - res = sexp_read(ctx, in); + res = sexp_read_one(ctx, in, shares); if (! sexp_exceptionp(res)) res = sexp_list2(ctx, sexp_global(ctx, SEXP_G_QUASIQUOTE_SYMBOL), res); break; case ',': if ((c1 = sexp_read_char(ctx, in)) == '@') { - res = sexp_read(ctx, in); + res = sexp_read_one(ctx, in, shares); if (! sexp_exceptionp(res)) res = sexp_list2(ctx, sexp_global(ctx, SEXP_G_UNQUOTE_SPLICING_SYMBOL), res); } else { sexp_push_char(ctx, c1, in); - res = sexp_read(ctx, in); + res = sexp_read_one(ctx, in, shares); if (! sexp_exceptionp(res)) res = sexp_list2(ctx, sexp_global(ctx, SEXP_G_UNQUOTE_SYMBOL), res); } @@ -2740,7 +2742,7 @@ sexp sexp_read_raw (sexp ctx, sexp in, sexp *shares) { for (c1=' '; isspace(c1); c1=sexp_read_char(ctx, in)) ; if (c1=='#') { - tmp = sexp_read(ctx, in); + tmp = sexp_read_one(ctx, in, shares); if (sexp_symbolp(tmp) && tmp == sexp_intern(ctx, "t", 1)) tmp = SEXP_TRUE; else if (!sexp_fixnump(tmp)) @@ -2840,7 +2842,7 @@ sexp sexp_read_raw (sexp ctx, sexp in, sexp *shares) { /* ... FALLTHROUGH ... */ case 'u': case 'U': if ((c1 = sexp_read_char(ctx, in)) == '8') { - tmp = sexp_read(ctx, in); + tmp = sexp_read_one(ctx, in, shares); if (!sexp_listp(ctx, tmp)) { res = sexp_exceptionp(tmp) ? tmp : sexp_read_error(ctx, "invalid syntax object after #u8", tmp, in); @@ -2873,8 +2875,9 @@ sexp sexp_read_raw (sexp ctx, sexp in, sexp *shares) { if (c1 == '#') { if (!sexp_vectorp(*shares) || tmp > sexp_vector_data(*shares)[sexp_vector_length(*shares)-1] || - sexp_vector_data(*shares)[c2] == SEXP_VOID) + sexp_vector_data(*shares)[c2] == SEXP_VOID) { res = sexp_read_error(ctx, "unknown reader label", tmp, in); + } else res = sexp_vector_data(*shares)[c2]; } else if (c1 == '=') { @@ -2895,7 +2898,7 @@ sexp sexp_read_raw (sexp ctx, sexp in, sexp *shares) { sexp_vector_data(*shares)[c2] = sexp_make_reader_label(c2); if (tmp > sexp_vector_data(*shares)[sexp_vector_length(*shares)-1]) sexp_vector_data(*shares)[sexp_vector_length(*shares)-1] = tmp; - res = sexp_read_raw(ctx, in, shares); + res = sexp_read_one(ctx, in, shares); sexp_vector_data(*shares)[c2] = res; if (sexp_reader_labelp(res)) res = sexp_read_error(ctx, "self reader label reference", tmp, in); @@ -2908,7 +2911,7 @@ sexp sexp_read_raw (sexp ctx, sexp in, sexp *shares) { break; #endif case ';': - tmp = sexp_read_raw(ctx, in, shares); /* discard */ + tmp = sexp_read_one(ctx, in, shares); /* discard */ if (sexp_exceptionp(tmp)) res = tmp; else @@ -3002,7 +3005,7 @@ sexp sexp_read_raw (sexp ctx, sexp in, sexp *shares) { break; case '(': sexp_push_char(ctx, c1, in); - res = sexp_read(ctx, in); + res = sexp_read_one(ctx, in, shares); if (sexp_not(sexp_listp(ctx, res))) { if (! sexp_exceptionp(res)) { res = sexp_read_error(ctx, "dotted list not allowed in vector syntax", @@ -3143,13 +3146,8 @@ sexp sexp_read_raw (sexp ctx, sexp in, sexp *shares) { return res; } -sexp sexp_read_op (sexp ctx, sexp self, sexp_sint_t n, sexp in) { - sexp res; - sexp_gc_var1(shares); - sexp_assert_type(ctx, sexp_iportp, SEXP_IPORT, in); - sexp_check_block_port(ctx, in, 0); - sexp_gc_preserve1(ctx, shares); - res = sexp_read_raw(ctx, in, &shares); +sexp sexp_read_one (sexp ctx, sexp in, sexp *shares) { + sexp res = sexp_read_raw(ctx, in, shares); if (res == SEXP_CLOSE) res = sexp_read_error(ctx, "too many ')'s", SEXP_NULL, in); #if SEXP_USE_OBJECT_BRACE_LITERALS @@ -3158,8 +3156,18 @@ sexp sexp_read_op (sexp ctx, sexp self, sexp_sint_t n, sexp in) { #endif else if (res == SEXP_RAWDOT) res = sexp_read_error(ctx, "unexpected '.'", SEXP_NULL, in); + return res; +} + +sexp sexp_read_op (sexp ctx, sexp self, sexp_sint_t n, sexp in) { + sexp res; + sexp_gc_var1(shares); + sexp_assert_type(ctx, sexp_iportp, SEXP_IPORT, in); + sexp_check_block_port(ctx, in, 0); + sexp_gc_preserve1(ctx, shares); + res = sexp_read_one(ctx, in, &shares); #if SEXP_USE_READER_LABELS - else if (!sexp_exceptionp(res) && sexp_vectorp(shares)) { + if (!sexp_exceptionp(res) && sexp_vectorp(shares)) { res = sexp_fill_reader_labels(ctx, res, shares, 1); /* mark=1 */ res = sexp_fill_reader_labels(ctx, res, shares, 0); /* mark=0 */ }