add 'undefined-error-name property for letrec
bindings
This commit is contained in:
parent
13db06d5df
commit
46a66819cc
|
@ -1949,12 +1949,18 @@ distinct; later bindings shadow earlier bindings.
|
||||||
|
|
||||||
Like @racket[let], including left-to-right evaluation of the @racket[val-expr]s,
|
Like @racket[let], including left-to-right evaluation of the @racket[val-expr]s,
|
||||||
but the @tech{locations} for all @racket[id]s are
|
but the @tech{locations} for all @racket[id]s are
|
||||||
created first and filled with @|undefined-const|, all
|
created first, all
|
||||||
@racket[id]s are bound in all @racket[val-expr]s as well as the
|
@racket[id]s are bound in all @racket[val-expr]s as well as the
|
||||||
@racket[body]s, and each @racket[id] is set immediately after the
|
@racket[body]s, and each @racket[id] is initialized immediately after the
|
||||||
corresponding @racket[val-expr] is evaluated. The @racket[id]s must be distinct according to
|
corresponding @racket[val-expr] is evaluated. The @racket[id]s must be distinct according to
|
||||||
@racket[bound-identifier=?].
|
@racket[bound-identifier=?].
|
||||||
|
|
||||||
|
Referencing or assigning to an @racket[id] before its initialization
|
||||||
|
raises @racket[exn:fail:contract:variable]. If an @racket[id] has an
|
||||||
|
@indexed-racket['undefined-error-name] @tech{syntax property} whose
|
||||||
|
value is a symbol, the symbol is used as the name of the variable for
|
||||||
|
error reporting, instead of the symbolic form of @racket[id].
|
||||||
|
|
||||||
@mz-examples[
|
@mz-examples[
|
||||||
(letrec ([is-even? (lambda (n)
|
(letrec ([is-even? (lambda (n)
|
||||||
(or (zero? n)
|
(or (zero? n)
|
||||||
|
@ -1963,7 +1969,9 @@ corresponding @racket[val-expr] is evaluated. The @racket[id]s must be distinct
|
||||||
(and (not (zero? n))
|
(and (not (zero? n))
|
||||||
(is-even? (sub1 n))))])
|
(is-even? (sub1 n))))])
|
||||||
(is-odd? 11))
|
(is-odd? 11))
|
||||||
]}
|
]
|
||||||
|
|
||||||
|
@history[#:changed "6.0.1.2" @elem{Changed reference or assignment of an uninitialized @racket[id] to an error.}]}
|
||||||
|
|
||||||
@defform[(let-values ([(id ...) val-expr] ...) body ...+)]{ Like
|
@defform[(let-values ([(id ...) val-expr] ...) body ...+)]{ Like
|
||||||
@racket[let], except that each @racket[val-expr] must produce as many
|
@racket[let], except that each @racket[val-expr] must produce as many
|
||||||
|
@ -1991,8 +1999,7 @@ for each @racket[id], all of which are bound in the later
|
||||||
@defform[(letrec-values ([(id ...) val-expr] ...) body ...+)]{ Like
|
@defform[(letrec-values ([(id ...) val-expr] ...) body ...+)]{ Like
|
||||||
@racket[letrec], except that each @racket[val-expr] must produce as
|
@racket[letrec], except that each @racket[val-expr] must produce as
|
||||||
many values as corresponding @racket[id]s. A separate @tech{location} is
|
many values as corresponding @racket[id]s. A separate @tech{location} is
|
||||||
created for each @racket[id], all of which are initialized to
|
created for each @racket[id], all of which are bound in all @racket[val-expr]s
|
||||||
@|undefined-const| and bound in all @racket[val-expr]s
|
|
||||||
and in the @racket[body]s.
|
and in the @racket[body]s.
|
||||||
|
|
||||||
@mz-examples[
|
@mz-examples[
|
||||||
|
|
|
@ -108,6 +108,22 @@
|
||||||
(syntax-test #'(lambda (x . 5) x))
|
(syntax-test #'(lambda (x . 5) x))
|
||||||
(syntax-test #'(lambda (x) x . 5))
|
(syntax-test #'(lambda (x) x . 5))
|
||||||
|
|
||||||
|
(err/rt-test (letrec ([not-ready not-ready]) 5)
|
||||||
|
(lambda (exn)
|
||||||
|
(and (exn:fail:contract:variable? exn)
|
||||||
|
(eq? 'not-ready (exn:fail:contract:variable-id exn)))))
|
||||||
|
(err/rt-test (let-syntax ([m
|
||||||
|
(lambda (stx)
|
||||||
|
(with-syntax ([not-ready-id
|
||||||
|
(syntax-property #'not-ready
|
||||||
|
'undefined-error-name
|
||||||
|
'alice)])
|
||||||
|
#'(letrec ([not-ready-id not-ready]) 5)))])
|
||||||
|
(m))
|
||||||
|
(lambda (exn)
|
||||||
|
(and (exn:fail:contract:variable? exn)
|
||||||
|
(eq? 'alice (exn:fail:contract:variable-id exn)))))
|
||||||
|
|
||||||
(let ([f
|
(let ([f
|
||||||
(case-lambda
|
(case-lambda
|
||||||
[() 'zero]
|
[() 'zero]
|
||||||
|
|
|
@ -63,6 +63,8 @@ ROSYM static Scheme_Object *quote_symbol;
|
||||||
ROSYM static Scheme_Object *letrec_syntaxes_symbol;
|
ROSYM static Scheme_Object *letrec_syntaxes_symbol;
|
||||||
ROSYM static Scheme_Object *values_symbol;
|
ROSYM static Scheme_Object *values_symbol;
|
||||||
ROSYM static Scheme_Object *call_with_values_symbol;
|
ROSYM static Scheme_Object *call_with_values_symbol;
|
||||||
|
ROSYM static Scheme_Object *inferred_name_symbol;
|
||||||
|
ROSYM static Scheme_Object *undefined_error_name_symbol;
|
||||||
|
|
||||||
THREAD_LOCAL_DECL(static Scheme_Object *quick_stx);
|
THREAD_LOCAL_DECL(static Scheme_Object *quick_stx);
|
||||||
|
|
||||||
|
@ -165,6 +167,9 @@ void scheme_init_compile (Scheme_Env *env)
|
||||||
REGISTER_SO(disappeared_binding_symbol);
|
REGISTER_SO(disappeared_binding_symbol);
|
||||||
REGISTER_SO(compiler_inline_hint_symbol);
|
REGISTER_SO(compiler_inline_hint_symbol);
|
||||||
|
|
||||||
|
REGISTER_SO(inferred_name_symbol);
|
||||||
|
REGISTER_SO(undefined_error_name_symbol);
|
||||||
|
|
||||||
scheme_undefined->type = scheme_undefined_type;
|
scheme_undefined->type = scheme_undefined_type;
|
||||||
|
|
||||||
lambda_symbol = scheme_intern_symbol("lambda");
|
lambda_symbol = scheme_intern_symbol("lambda");
|
||||||
|
@ -178,6 +183,9 @@ void scheme_init_compile (Scheme_Env *env)
|
||||||
disappeared_binding_symbol = scheme_intern_symbol("disappeared-binding");
|
disappeared_binding_symbol = scheme_intern_symbol("disappeared-binding");
|
||||||
compiler_inline_hint_symbol = scheme_intern_symbol("compiler-hint:cross-module-inline");
|
compiler_inline_hint_symbol = scheme_intern_symbol("compiler-hint:cross-module-inline");
|
||||||
|
|
||||||
|
inferred_name_symbol = scheme_intern_symbol("inferred-name");
|
||||||
|
undefined_error_name_symbol = scheme_intern_symbol("undefined-error-name");
|
||||||
|
|
||||||
scheme_define_values_syntax = scheme_make_compiled_syntax(define_values_syntax,
|
scheme_define_values_syntax = scheme_make_compiled_syntax(define_values_syntax,
|
||||||
define_values_expand);
|
define_values_expand);
|
||||||
scheme_define_syntaxes_syntax = scheme_make_compiled_syntax(define_syntaxes_syntax,
|
scheme_define_syntaxes_syntax = scheme_make_compiled_syntax(define_syntaxes_syntax,
|
||||||
|
@ -367,13 +375,24 @@ Scheme_Object *scheme_check_name_property(Scheme_Object *code, Scheme_Object *cu
|
||||||
{
|
{
|
||||||
Scheme_Object *name;
|
Scheme_Object *name;
|
||||||
|
|
||||||
name = scheme_stx_property(code, scheme_inferred_name_symbol, NULL);
|
name = scheme_stx_property(code, inferred_name_symbol, NULL);
|
||||||
if (name && SCHEME_SYMBOLP(name))
|
if (name && SCHEME_SYMBOLP(name))
|
||||||
return name;
|
return name;
|
||||||
else
|
else
|
||||||
return current_val;
|
return current_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Scheme_Object *get_local_name(Scheme_Object *id)
|
||||||
|
{
|
||||||
|
Scheme_Object *name;
|
||||||
|
|
||||||
|
name = scheme_stx_property(id, undefined_error_name_symbol, NULL);
|
||||||
|
if (name && SCHEME_SYMBOLP(name))
|
||||||
|
return name;
|
||||||
|
else
|
||||||
|
return SCHEME_STX_VAL(id);
|
||||||
|
}
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
/* lambda utils */
|
/* lambda utils */
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
@ -498,7 +517,7 @@ Scheme_Object *scheme_build_closure_name(Scheme_Object *code, Scheme_Compile_Inf
|
||||||
{
|
{
|
||||||
Scheme_Object *name;
|
Scheme_Object *name;
|
||||||
|
|
||||||
name = scheme_stx_property(code, scheme_inferred_name_symbol, NULL);
|
name = scheme_stx_property(code, inferred_name_symbol, NULL);
|
||||||
if (name && SCHEME_SYMBOLP(name)) {
|
if (name && SCHEME_SYMBOLP(name)) {
|
||||||
name = combine_name_with_srcloc(name, code, 0);
|
name = combine_name_with_srcloc(name, code, 0);
|
||||||
} else if (name && SCHEME_VOIDP(name)) {
|
} else if (name && SCHEME_VOIDP(name)) {
|
||||||
|
@ -2260,7 +2279,9 @@ gen_let_syntax (Scheme_Object *form, Scheme_Comp_Env *origenv, char *formname,
|
||||||
currently. It would be ok if we record extra names, though. */
|
currently. It would be ok if we record extra names, though. */
|
||||||
clv_names = MALLOC_N(Scheme_Object*, lv->count);
|
clv_names = MALLOC_N(Scheme_Object*, lv->count);
|
||||||
for (m = pre_k; m < k; m++) {
|
for (m = pre_k; m < k; m++) {
|
||||||
clv_names[m - pre_k] = SCHEME_STX_SYM(names[m]);
|
Scheme_Object *ln;
|
||||||
|
ln = get_local_name(names[m]);
|
||||||
|
clv_names[m - pre_k] = ln;
|
||||||
}
|
}
|
||||||
lv->names = clv_names;
|
lv->names = clv_names;
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,6 @@ READ_ONLY Scheme_Object *scheme_apply_proc;
|
||||||
READ_ONLY Scheme_Object *scheme_call_with_values_proc; /* the function bound to `call-with-values' */
|
READ_ONLY Scheme_Object *scheme_call_with_values_proc; /* the function bound to `call-with-values' */
|
||||||
READ_ONLY Scheme_Object *scheme_reduced_procedure_struct;
|
READ_ONLY Scheme_Object *scheme_reduced_procedure_struct;
|
||||||
READ_ONLY Scheme_Object *scheme_tail_call_waiting;
|
READ_ONLY Scheme_Object *scheme_tail_call_waiting;
|
||||||
READ_ONLY Scheme_Object *scheme_inferred_name_symbol;
|
|
||||||
READ_ONLY Scheme_Object *scheme_default_prompt_tag;
|
READ_ONLY Scheme_Object *scheme_default_prompt_tag;
|
||||||
READ_ONLY Scheme_Object *scheme_chaperone_undefined_property;
|
READ_ONLY Scheme_Object *scheme_chaperone_undefined_property;
|
||||||
|
|
||||||
|
@ -644,12 +643,10 @@ scheme_init_fun (Scheme_Env *env)
|
||||||
none_symbol = scheme_intern_symbol("none");
|
none_symbol = scheme_intern_symbol("none");
|
||||||
|
|
||||||
REGISTER_SO(is_method_symbol);
|
REGISTER_SO(is_method_symbol);
|
||||||
REGISTER_SO(scheme_inferred_name_symbol);
|
|
||||||
REGISTER_SO(cont_key);
|
REGISTER_SO(cont_key);
|
||||||
REGISTER_SO(barrier_prompt_key);
|
REGISTER_SO(barrier_prompt_key);
|
||||||
REGISTER_SO(prompt_cc_guard_key);
|
REGISTER_SO(prompt_cc_guard_key);
|
||||||
is_method_symbol = scheme_intern_symbol("method-arity-error");
|
is_method_symbol = scheme_intern_symbol("method-arity-error");
|
||||||
scheme_inferred_name_symbol = scheme_intern_symbol("inferred-name");
|
|
||||||
cont_key = scheme_make_symbol("k"); /* uninterned */
|
cont_key = scheme_make_symbol("k"); /* uninterned */
|
||||||
barrier_prompt_key = scheme_make_symbol("bar"); /* uninterned */
|
barrier_prompt_key = scheme_make_symbol("bar"); /* uninterned */
|
||||||
prompt_cc_guard_key = scheme_make_symbol("cc"); /* uninterned */
|
prompt_cc_guard_key = scheme_make_symbol("cc"); /* uninterned */
|
||||||
|
|
|
@ -3185,7 +3185,6 @@ void scheme_ill_formed(Mz_CPort *port);
|
||||||
# define scheme_ill_formed_code(port) scheme_ill_formed(port)
|
# define scheme_ill_formed_code(port) scheme_ill_formed(port)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern Scheme_Object *scheme_inferred_name_symbol;
|
|
||||||
Scheme_Object *scheme_check_name_property(Scheme_Object *stx, Scheme_Object *current_name);
|
Scheme_Object *scheme_check_name_property(Scheme_Object *stx, Scheme_Object *current_name);
|
||||||
|
|
||||||
Scheme_Object *scheme_make_lifted_defn(Scheme_Object *sys_wraps, Scheme_Object **_id, Scheme_Object *expr, Scheme_Comp_Env *env);
|
Scheme_Object *scheme_make_lifted_defn(Scheme_Object *sys_wraps, Scheme_Object **_id, Scheme_Object *expr, Scheme_Comp_Env *env);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user