summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-10-12 06:39:08 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-10-12 06:39:08 -0700
commit17cd878844f524ebae0024edb60c2f58ac56285d (patch)
treebd6d5e1a5ae99300ec186e8915830aca0686a2c3
parent389df91392be85e2b30150e20c5c2a98ec6fd05b (diff)
downloadtxr-17cd878844f524ebae0024edb60c2f58ac56285d.tar.gz
txr-17cd878844f524ebae0024edb60c2f58ac56285d.tar.bz2
txr-17cd878844f524ebae0024edb60c2f58ac56285d.zip
tprint and -t option: handle infinite list.
Test case: txr -t '(gun "foo")' must run in constant memory. * eval.c (tprint): Rewritten to iterate over lists using open loop rather than mapdo. Classification of the sequence is done using the new seq_info, as must be for all new sequence functions. * txr.c (txr_main): Implementation of -t, -p and -P captures the result of the expression in a variable whose value is zapped when it is passed to the function. A gc_hint is added so that this isn't optimized away. Thus, this code won't hold on to the original pointer to a lazy, infinite list.
-rw-r--r--eval.c43
-rw-r--r--txr.c12
2 files changed, 41 insertions, 14 deletions
diff --git a/eval.c b/eval.c
index e7ea1859..31938f56 100644
--- a/eval.c
+++ b/eval.c
@@ -5446,20 +5446,41 @@ val pprinl(val obj, val stream)
val tprint(val obj, val out)
{
- switch (type(obj)) {
- case NIL:
+ val self = lit("tprint");
+ seq_info_t si = seq_info(obj);
+
+ switch (si.kind) {
+ case SEQ_NIL:
break;
- case CONS:
- case LCONS:
- case VEC:
- mapdo(curry_12_1(func_n2(tprint), out), obj);
+ case SEQ_LISTLIKE:
+ {
+ gc_hint(si.obj);
+ gc_hint(obj);
+ for (obj = z(si.obj); !endp(obj); obj = cdr(obj))
+ tprint(car(obj), out);
+ }
break;
- case LIT:
- case STR:
- case LSTR:
- put_line(obj, out);
+ case SEQ_VECLIKE:
+ switch (si.type) {
+ case LIT:
+ case STR:
+ case LSTR:
+ put_line(obj, out);
+ break;
+ default:
+ {
+ val vec = si.obj;
+ cnum i, len = c_fixnum(length(vec), self);
+
+ for (i = 0; i < len; i++)
+ tprint(ref(vec, num_fast(i)), out);
+
+ }
+ break;
+ }
break;
- default:
+ case SEQ_NOTSEQ:
+ case SEQ_HASHLIKE:
pprinl(obj, out);
break;
}
diff --git a/txr.c b/txr.c
index cee8ac51..cd774de0 100644
--- a/txr.c
+++ b/txr.c
@@ -858,13 +858,19 @@ int txr_main(int argc, char **argv)
tprint));
val args_saved = or2(orig_args, arg_list);
val args_new;
+ val obj;
reg_varl(self_path_s, lit("cmdline-expr"));
reg_var(args_s, or2(orig_args, arg_list));
- pf(eval_intrinsic(lisp_parse(arg, std_error, colon_k,
- lit("cmdline-expr"), colon_k),
- make_env(bindings, nil, nil)), std_output);
+
+ obj = eval_intrinsic(lisp_parse(arg, std_error, colon_k,
+ lit("cmdline-expr"), colon_k),
+ make_env(bindings, nil, nil));
+ gc_hint(obj);
+ pf(z(obj), std_output);
+
evaled = t;
+
args_new = cdr(lookup_global_var(args_s));
if (args_new != args_saved) {
arg_list = args_new;