summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eval.c45
-rw-r--r--lib.c5
-rw-r--r--lib.h2
-rw-r--r--lisplib.c5
-rw-r--r--parser.c12
-rw-r--r--parser.y9
-rw-r--r--share/txr/stdlib/except.tl3
-rw-r--r--share/txr/stdlib/place.tl6
-rw-r--r--tests/011/macros-2.txr15
-rw-r--r--tests/012/ifa.tl2
-rw-r--r--tests/012/struct.tl10
-rw-r--r--txr.136
-rw-r--r--unwind.c13
13 files changed, 131 insertions, 32 deletions
diff --git a/eval.c b/eval.c
index 51fcdb4b..e4ad8859 100644
--- a/eval.c
+++ b/eval.c
@@ -211,27 +211,50 @@ val ctx_name(val obj)
return nil;
}
-noreturn val eval_error(val ctx, val fmt, ...)
+noreturn static void eval_exception(val sym, val ctx, val fmt, va_list vl)
{
uses_or2;
- va_list vl;
val form = ctx_form(ctx);
val stream = make_string_output_stream();
val loc = or2(source_loc_str(form, nil),
source_loc_str(last_form_evaled, nil));
- va_start (vl, fmt);
-
if (loc)
format(stream, lit("(~a) "), loc, nao);
(void) vformat(stream, fmt, vl);
- va_end (vl);
- uw_throw(eval_error_s, get_string_from_stream(stream));
+ uw_throw(sym, get_string_from_stream(stream));
+}
+
+noreturn val eval_error(val ctx, val fmt, ...)
+{
+ va_list vl;
+ va_start (vl, fmt);
+ eval_exception(eval_error_s, ctx, fmt, vl);
+ va_end (vl);
abort();
}
+static val eval_warn(val ctx, val fmt, ...)
+{
+ va_list vl;
+
+ uw_catch_begin (cons(continue_s, nil), exsym, exvals);
+
+ va_start (vl, fmt);
+ eval_exception(warning_s, ctx, fmt, vl);
+ va_end (vl);
+
+ uw_catch(exsym, exvals) { (void) exsym; (void) exvals; }
+
+ uw_unwind;
+
+ uw_catch_end;
+
+ return nil;
+}
+
val lookup_origin(val form)
{
return gethash(origin_hash, form);
@@ -3107,9 +3130,10 @@ static val supplement_op_syms(val ssyms, val max)
static val me_op(val form, val menv)
{
cons_bind (sym, body, form);
+ val new_menv = make_var_shadowing_env(menv, cons(rest_s, nil));
val body_ex = if3(sym == op_s,
- expand_forms_lisp1(body, menv),
- expand(body, menv));
+ expand_forms_lisp1(body, new_menv),
+ expand(body, new_menv));
val rest_gensym = gensym(lit("rest-"));
cons_bind (syms, body_trans, transform_op(body_ex, nil, rest_gensym));
val ssyms = sort(syms, func_n2(lt), car_f);
@@ -3597,6 +3621,8 @@ static val do_expand(val form, val menv)
return form;
return expand(rlcp_tree(symac, form), menv);
}
+ if (!lookup_var(menv, form))
+ eval_warn(last_form_expanded, lit("unbound variable ~s"), form, nao);
return form;
} else if (atom(form)) {
return form;
@@ -3886,7 +3912,8 @@ val expand(val form, val menv)
val ret = nil;
val lfe_save = last_form_expanded;
- last_form_expanded = form;
+ if (consp(form))
+ last_form_expanded = form;
ret = do_expand(form, menv);
last_form_expanded = lfe_save;
diff --git a/lib.c b/lib.c
index f41d1015..2b1be171 100644
--- a/lib.c
+++ b/lib.c
@@ -101,7 +101,7 @@ val eof_s, eol_s, assert_s, name_s;
val error_s, type_error_s, internal_error_s, panic_s;
val numeric_error_s, range_error_s;
val query_error_s, file_error_s, process_error_s, syntax_error_s;
-val timeout_error_s, system_error_s;
+val timeout_error_s, system_error_s, warning_s, restart_s, continue_s;
val gensym_counter_s, nullify_s, from_list_s, lambda_set_s;
val nothrow_k, args_k, colon_k, auto_k, fun_k;
@@ -9329,6 +9329,9 @@ static void obj_init(void)
system_error_s = intern(lit("system-error"), user_package);
timeout_error_s = intern(lit("timeout-error"), user_package);
assert_s = intern(lit("assert"), user_package);
+ warning_s = intern(lit("warning"), user_package);
+ restart_s = intern(lit("restart"), user_package);
+ continue_s = intern(lit("continue"), user_package);
name_s = intern(lit("name"), user_package);
nullify_s = intern(lit("nullify"), user_package);
from_list_s = intern(lit("from-list"), user_package);
diff --git a/lib.h b/lib.h
index 7f99632b..b141a28c 100644
--- a/lib.h
+++ b/lib.h
@@ -441,7 +441,7 @@ extern val eof_s, eol_s, assert_s, name_s;
extern val error_s, type_error_s, internal_error_s, panic_s;
extern val numeric_error_s, range_error_s;
extern val query_error_s, file_error_s, process_error_s, syntax_error_s;
-extern val system_error_s, timeout_error_s;
+extern val system_error_s, timeout_error_s, warning_s, restart_s, continue_s;
extern val gensym_counter_s;
#define gensym_counter (deref(lookup_var_l(nil, gensym_counter_s)))
diff --git a/lisplib.c b/lisplib.c
index d1f237c4..a7247693 100644
--- a/lisplib.c
+++ b/lisplib.c
@@ -238,7 +238,10 @@ static val hash_instantiate(val set_fun)
static val except_set_entries(val dlt, val fun)
{
- val name[] = { lit("handle"), nil };
+ val name[] = {
+ lit("handle"), lit("ignwarn"), lit("macro-time-ignwarn"),
+ nil
+ };
set_dlt_entries(dlt, name, fun);
return nil;
}
diff --git a/parser.c b/parser.c
index 681ffe75..f4f1c1ce 100644
--- a/parser.c
+++ b/parser.c
@@ -887,6 +887,12 @@ static val get_home_path(void)
return getenv_wrap(lit("HOME"));
}
+static val repl_warning(val out_stream, val exc, val arg)
+{
+ format(out_stream, lit("** warning: ~!~a\n"), arg, nao);
+ uw_throw(continue_s, nil);
+}
+
val repl(val bindings, val in_stream, val out_stream)
{
val ifd = stream_get_prop(in_stream, fd_k);
@@ -911,6 +917,7 @@ val repl(val bindings, val in_stream, val out_stream)
val hist_len_var = lookup_global_var(listener_hist_len_s);
val multi_line_var = lookup_global_var(listener_multi_line_p_s);
val sel_inclusive_var = lookup_global_var(listener_sel_inclusive_p_s);
+ val rw_f = func_f2(out_stream, repl_warning);
for (; bindings; bindings = cdr(bindings)) {
val binding = car(bindings);
@@ -937,6 +944,7 @@ val repl(val bindings, val in_stream, val out_stream)
val var_counter = mod(counter, num_fast(100));
val var_name = format(nil, lit("*~d"), var_counter, nao);
val var_sym = intern(var_name, user_package);
+ uw_frame_t uw_handler;
char *prompt_u8 = utf8_dup_to(c_str(prompt));
@@ -984,6 +992,8 @@ val repl(val bindings, val in_stream, val out_stream)
uw_catch_begin (catch_all, exsym, exvals);
+ uw_push_handler(&uw_handler, cons(warning_s, nil), rw_f);
+
{
val name = format(nil, lit("expr-~d"), prev_counter, nao);
val line = string_utf8(line_u8);
@@ -1003,6 +1013,8 @@ val repl(val bindings, val in_stream, val out_stream)
}
}
+ uw_pop_frame(&uw_handler);
+
uw_catch (exsym, exvals) {
val exinfo = cons(exsym, exvals);
reg_varl(var_sym, exinfo);
diff --git a/parser.y b/parser.y
index a6950e8f..c39b3a8f 100644
--- a/parser.y
+++ b/parser.y
@@ -1740,9 +1740,15 @@ void yybadtoken(parser_t *parser, int tok, val context)
yyerrorf(scnr, lit("unexpected character ~a"), chr(tok), nao);
}
+static val warning_continue(val exc, val arg)
+{
+ uw_throw(continue_s, nil);
+}
+
int parse_once(val stream, val name, parser_t *parser)
{
int res = 0;
+ uw_frame_t uw_handler;
#if CONFIG_DEBUG_SUPPORT
debug_state_t ds = debug_set_state(opt_dbg_expansion ? 0 : -1,
opt_dbg_expansion);
@@ -1753,6 +1759,7 @@ int parse_once(val stream, val name, parser_t *parser)
parser->stream = stream;
parser->name = name;
+ uw_push_handler(&uw_handler, cons(warning_s, nil), func_n2(warning_continue));
uw_catch_begin(cons(error_s, nil), esym, eobj);
@@ -1774,6 +1781,8 @@ int parse_once(val stream, val name, parser_t *parser)
uw_catch_end;
+ uw_pop_frame(&uw_handler);
+
return res;
}
diff --git a/share/txr/stdlib/except.tl b/share/txr/stdlib/except.tl
index ad5cb0b9..addc3a66 100644
--- a/share/txr/stdlib/except.tl
+++ b/share/txr/stdlib/except.tl
@@ -44,3 +44,6 @@
syms-fragments)))
,[mapcar car syms-fragments]
,try-form)))
+
+(defmacro ignwarn (. forms)
+ ^(handler-bind (lambda (exc-sym arg) (throw 'continue)) (warning) ,*forms))
diff --git a/share/txr/stdlib/place.tl b/share/txr/stdlib/place.tl
index 20650ad0..b18fddbf 100644
--- a/share/txr/stdlib/place.tl
+++ b/share/txr/stdlib/place.tl
@@ -183,7 +183,7 @@
(expander (get-update-expander place))
(sys:*pl-env* env)
(expansion [expander getter setter place body])
- (expansion-ex (sys:expand expansion env)))
+ (expansion-ex (ignwarn (sys:expand expansion env))))
(sys:cp-origin expansion-ex place)))
(defun call-clobber-expander (ssetter unex-place env body)
@@ -191,7 +191,7 @@
(expander (get-clobber-expander place))
(sys:*pl-env* env)
(expansion [expander ssetter place body])
- (expansion-ex (sys:expand expansion env)))
+ (expansion-ex (ignwarn (sys:expand expansion env))))
(sys:cp-origin expansion-ex place)))
(defun call-delete-expander (deleter unex-place env body)
@@ -199,7 +199,7 @@
(expander (get-delete-expander place))
(sys:*pl-env* env)
(expansion [expander deleter place body])
- (expansion-ex (sys:expand expansion env)))
+ (expansion-ex (ignwarn (sys:expand expansion env))))
(sys:cp-origin expansion-ex place))))
(defmacro with-update-expander ((getter setter) unex-place env body)
diff --git a/tests/011/macros-2.txr b/tests/011/macros-2.txr
index 96045ca4..debc6eca 100644
--- a/tests/011/macros-2.txr
+++ b/tests/011/macros-2.txr
@@ -20,13 +20,14 @@
(prinl i)))
(prinl
- (sys:expand
- '(whilst ((< i 100))
- (if (< (inc i) 20)
- continue)
- (if (> i 30)
- break)
- (prinl i))))
+ (ignwarn
+ (sys:expand
+ '(whilst ((< i 100))
+ (if (< (inc i) 20)
+ continue)
+ (if (> i 30)
+ break)
+ (prinl i)))))
(let ((i 0))
(whilst ((< i 5))
diff --git a/tests/012/ifa.tl b/tests/012/ifa.tl
index 91fa4512..d669244d 100644
--- a/tests/012/ifa.tl
+++ b/tests/012/ifa.tl
@@ -11,7 +11,7 @@
7)
;; ambiguous: is "it" x or is "it" y?
-(test (ifa (> x y) (print it)) :error)
+(test (let (x y) (ifa (> x y) (print it))) :error)
;; "it" is (+ 3 (* 2 x))
(test (let ((x 5))
diff --git a/tests/012/struct.tl b/tests/012/struct.tl
index cecdfb15..a22d32d0 100644
--- a/tests/012/struct.tl
+++ b/tests/012/struct.tl
@@ -24,7 +24,7 @@
(test s
#S(bar a 100 b 4))
-(test (sys:expand 'a.b.c.d)
+(test (ignwarn (sys:expand 'a.b.c.d))
(slot (slot (slot a 'b)
'c) 'd))
@@ -36,11 +36,11 @@
[(slot s 'a) b c])
(set *gensym-counter* 0)
-(stest (sys:expand 's.(a))
+(stest (ignwarn (sys:expand 's.(a)))
"(call (slot s 'a)\n \
\ s)")
(set *gensym-counter* 0)
-(stest (sys:expand 's.(a b c))
+(stest (ignwarn (sys:expand 's.(a b c)))
"(call (slot s 'a)\n \
\ s b c)")
(test (sys:expand 's.[a].d)
@@ -48,11 +48,11 @@
(test (sys:expand 's.[a b c].d)
(slot [(slot s 'a) b c] 'd))
(set *gensym-counter* 0)
-(stest (sys:expand 's.(a).d)
+(stest (ignwarn (sys:expand 's.(a).d))
"(slot (call (slot s 'a)\n \
\ s) 'd)")
(set *gensym-counter* 0)
-(stest (sys:expand 's.(a b c).d)
+(stest (ignwarn (sys:expand 's.(a b c).d))
"(slot (call (slot s 'a)\n \
\ s b c)\n 'd)")
diff --git a/txr.1 b/txr.1
index f01e2537..cdebfa4c 100644
--- a/txr.1
+++ b/txr.1
@@ -32183,6 +32183,42 @@ form terminates without evaluating the remaining
forms, and yields
.codn nil .
+.coNP Macro @ ignwarn
+.synb
+.mets (ignwarn << form *)
+.syne
+.desc
+The
+.code ignwarn
+macro resembles
+.codn ignerr .
+It arranges for the evaluation of each
+.meta form
+in left-to-right order. If all the forms are evaluated, then the
+value of the last one is returned. If no forms are present, then
+.code nil
+is returned.
+
+If any
+.meta form
+throws an exception of type
+.code warning
+then this exception is intercepted by a handler established by
+.codn ignwarn .
+This handler reacts by throwing an exception of type
+.codn continue .
+
+The effect is that the warning is ignored, since the handler
+doesn't issue any diagnostic, and passes control to the warning's
+continue point.
+
+Note: all sites within \*(TX which throw a
+.code warning
+also provide a nearby catch for a
+.code continue
+exception, for resuming evaluation at the point where the warning
+was issued.
+
.coNP Operator @ handler-bind
.synb
.mets (handler-bind < function-form < symbol-list << body-form *)
diff --git a/unwind.c b/unwind.c
index a79a69bd..a993e7cf 100644
--- a/unwind.c
+++ b/unwind.c
@@ -556,6 +556,13 @@ val uw_throw(val sym, val args)
abort();
}
+ if (sym == warning_s) {
+ --reentry_count;
+ format(std_error, lit("warning: ~a\n"), car(args), nao);
+ uw_throw(continue_s, nil);
+ abort();
+ }
+
{
loc pfun = lookup_var_l(nil, unhandled_hook_s);
val fun = deref(pfun);
@@ -667,10 +674,6 @@ val uw_register_subtype(val sub, val sup)
sub, sup, nao);
}
- if (uw_exception_subtype_p(sub, sup))
- uw_throwf(type_error_s, lit("~s is already an exception subtype of ~s"),
- sub, sup, nao);
-
if (uw_exception_subtype_p(sup, sub))
uw_throwf(type_error_s, lit("~s is already an exception supertype of ~s"),
sub, sup, nao);
@@ -975,4 +978,6 @@ void uw_late_init(void)
func_n2v(uw_invoke_catch));
reg_fun(sys_capture_cont_s = intern(lit("capture-cont"), system_package),
func_n3o(uw_capture_cont, 2));
+ uw_register_subtype(continue_s, restart_s);
+ uw_register_subtype(warning_s, t);
}