From 259b59ddd679f19744a03218357e51b1d1eddc5a Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Mon, 8 Apr 2019 18:04:44 -0700 Subject: repl: groundwork for recursive listener invocation. * parser.c (lino_ctx, repl_level): New static variable. (repl): Increment repl_level on entry and decrement on exit. On the initial entry, allocate the lino_t object, storing it in the new static variable. Free it on outermost exit. The number of > characters in the prompt indicates the nesting level. The function now takes an environment parameter, which is applied to the evaluation of the input form. The intent is to be able to supply symbol macros which expand to function calls implementing debugger commands. (parser_init): Register sys:repl intrinsic. * parser.h (repl): Declaration updated. * txr.c (txr_main): Pass nil environment parameter to repl --- parser.c | 24 +++++++++++++++++------- parser.h | 2 +- txr.c | 2 +- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/parser.c b/parser.c index 0d526ba5..b7713f64 100644 --- a/parser.c +++ b/parser.c @@ -72,6 +72,8 @@ val listener_hist_len_s, listener_multi_line_p_s, listener_sel_inclusive_p_s; val listener_pprint_s, listener_greedy_eval_s; val rec_source_loc_s; val intr_s; +static lino_t *lino_ctx; +static int repl_level = 0; static val stream_parser_hash, catch_all; @@ -1210,10 +1212,12 @@ static int is_balanced_line(const wchar_t *line, void *ctx) static_forward(lino_os_t linenoise_txr_binding); -val repl(val bindings, val in_stream, val out_stream) +val repl(val bindings, val in_stream, val out_stream, val env) { - lino_t *ls = lino_make(coerce(mem_t *, in_stream), - coerce(mem_t *, out_stream)); + lino_t *ls = if3(repl_level++, + lino_ctx, + lino_ctx = lino_make(coerce(mem_t *, in_stream), + coerce(mem_t *, out_stream))); wchar_t *line_w = 0; val quit_k = intern(lit("quit"), keyword_package); val read_k = intern(lit("read"), keyword_package); @@ -1225,7 +1229,7 @@ val repl(val bindings, val in_stream, val out_stream) val result_hash = make_hash(nil, nil, nil); val done = nil; val counter = one; - val home = get_home_path(); + val home = if3(repl_level == 1, get_home_path(), nil); val histfile = if2(home, format(nil, lit("~a/.txr_history"), home, nao)); const wchar_t *histfile_w = if3(home, c_str(histfile), NULL); val rcfile = if2(home, format(nil, lit("~a/.txr_profile"), home, nao)); @@ -1237,6 +1241,7 @@ val repl(val bindings, val in_stream, val out_stream) val greedy_eval = lookup_global_var(listener_greedy_eval_s); val rw_f = func_f1v(out_stream, repl_warning); val saved_dyn_env = set_dyn_env(make_env(nil, nil, dyn_env)); + val brackets = mkstring(num_fast(repl_level), chr('>')); env_vbind(dyn_env, stderr_s, out_stream); @@ -1263,7 +1268,7 @@ val repl(val bindings, val in_stream, val out_stream) lino_set_noninteractive(ls, opt_noninteractive); while (!done) { - val prompt = format(nil, lit("~d> "), counter, nao); + val prompt = format(nil, lit("~d~a "), counter, brackets,nao); val prev_counter = counter; val var_counter = mod(counter, num_fast(100)); val var_name = format(nil, lit("*~d"), var_counter, nao); @@ -1328,7 +1333,7 @@ val repl(val bindings, val in_stream, val out_stream) counter = prev_counter; } else { val value = if3(form != read_k, - eval_intrinsic(form, nil), + eval_intrinsic(form, env), read_eval_ret_last(nil, prev_counter, in_stream, out_stream)); val pprin = cdr(pprint_var); @@ -1344,6 +1349,7 @@ val repl(val bindings, val in_stream, val out_stream) while (bindable(value) || consp(value)) { value = eval_intrinsic_noerr(value, nil, &error_p); + /* env deliberately not passed to eval here */ if (error_p) break; pfun(value, out_stream); @@ -1394,7 +1400,10 @@ val repl(val bindings, val in_stream, val out_stream) } free(line_w); - lino_free(ls); + if (--repl_level == 0) { + lino_free(lino_ctx); + lino_ctx = 0; + } gc_hint(histfile); return nil; } @@ -1591,4 +1600,5 @@ void parse_init(void) reg_fun(intern(lit("get-parser"), system_package), func_n1(get_parser)); reg_fun(intern(lit("parser-errors"), system_package), func_n1(parser_errors)); reg_fun(intern(lit("parser-eof"), system_package), func_n1(parser_eof)); + reg_fun(intern(lit("repl"), system_package), func_n4(repl)); } diff --git a/parser.h b/parser.h index a0fd7e73..246832ab 100644 --- a/parser.h +++ b/parser.h @@ -124,7 +124,7 @@ val iread(val source_in, val error_stream, val error_return_val, val read_eval_stream(val self, val stream, val error_stream); val read_compiled_file(val self, val stream, val error_stream); #if HAVE_TERMIOS -val repl(val bindings, val in_stream, val out_stream); +val repl(val bindings, val in_stream, val out_stream, val env); #endif void parser_common_init(parser_t *); void parser_cleanup(parser_t *); diff --git a/txr.c b/txr.c index b6e14f24..dab0b7f5 100644 --- a/txr.c +++ b/txr.c @@ -1105,7 +1105,7 @@ repl: env_vbind(dyn_env, package_s, opt_compat && opt_compat <= 190 ? user_package : public_package); env_vbind(dyn_env, load_recursive_s, nil); - repl(bindings, std_input, std_output); + repl(bindings, std_input, std_output, nil); #endif return 0; } -- cgit v1.2.3