mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2026-02-05 07:00:36 -08:00
bytecmp: ensure that we close around referenced local macros
This is necessary to recompile bytecodes when they contain macro expansions.
This commit is contained in:
parent
c9c5323578
commit
77fe30efdd
1 changed files with 45 additions and 8 deletions
|
|
@ -643,6 +643,24 @@ c_restore_env(cl_env_ptr the_env, cl_compiler_env_ptr new_c_env, cl_compiler_env
|
|||
referenced across the function boundary are captured. We capture the entry
|
||||
verbatim and we don't bind any objects at runtime -- these objects are
|
||||
supplied to enable recompilation by CCMP and BCMP. */
|
||||
|
||||
static void
|
||||
close_around_macros(cl_env_ptr env, cl_object mfun)
|
||||
{
|
||||
cl_object lex = mfun->bclosure.lex, record;
|
||||
cl_object *lex_vec = lex->vector.self.t;
|
||||
for (cl_index i = 0; i < lex->vector.dim; i++) {
|
||||
cl_object reg = lex_vec[i]; /* INV see interpreter.d for lexenv structure */
|
||||
cl_object type = CAR(reg); /* lexenv tag */
|
||||
cl_object name = CDDR(reg); /* macro name */
|
||||
if (type == @'si::macro') {
|
||||
c_mac_ref(env, name);
|
||||
} else if (type == @'si::symbol_macro') {
|
||||
c_sym_ref(env, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
c_sym_ref(cl_env_ptr env, cl_object name)
|
||||
{
|
||||
|
|
@ -659,9 +677,17 @@ c_sym_ref(cl_env_ptr env, cl_object name)
|
|||
type = pop(®);
|
||||
other = pop(®);
|
||||
if (type == name) {
|
||||
if (other == @'si::symbol-macro' && function_boundary_crossed) {
|
||||
c_env->function_boundary_crossed = 1;
|
||||
c_register_captured(env, record);
|
||||
if (other == @'si::symbol-macro') {
|
||||
if (function_boundary_crossed) {
|
||||
c_env->function_boundary_crossed = 1;
|
||||
c_register_captured(env, record);
|
||||
} else {
|
||||
cl_object mfun = ECL_CONS_CAR(reg);
|
||||
if (ecl_t_of(mfun) == t_bclosure) {
|
||||
c_env->function_boundary_crossed = 1;
|
||||
close_around_macros(env, mfun);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -691,6 +717,12 @@ c_mac_ref(cl_env_ptr env, cl_object name)
|
|||
if (function_boundary_crossed) {
|
||||
c_env->function_boundary_crossed = 1;
|
||||
c_register_captured(env, record);
|
||||
} else {
|
||||
cl_object mfun = ECL_CONS_CAR(reg);
|
||||
if (ecl_t_of(mfun) == t_bclosure) {
|
||||
c_env->function_boundary_crossed = 1;
|
||||
close_around_macros(env, mfun);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -729,7 +761,7 @@ c_any_ref(cl_env_ptr env, cl_object entry)
|
|||
output.entry = record;
|
||||
return output;
|
||||
}
|
||||
if (type == @':block' || type == @':function'||type == @':tag'
|
||||
if (type == @':block' || type == @':function'|| type == @':tag'
|
||||
|| Null(other)) {
|
||||
n++;
|
||||
}
|
||||
|
|
@ -3454,14 +3486,19 @@ c_default(cl_env_ptr env, cl_object var, cl_object stmt, cl_object flag, cl_obje
|
|||
}
|
||||
|
||||
static cl_object
|
||||
fix_macro_to_lexenv(cl_object record) {
|
||||
fix_macro_to_lexenv(cl_env_ptr env, cl_object record) {
|
||||
cl_object arg1 = pop(&record);
|
||||
cl_object arg2 = pop(&record);
|
||||
cl_object arg3 = pop(&record);
|
||||
if (arg2 == @'si::macro' || arg2 == @'si::symbol-macro')
|
||||
if (arg2 == @'si::macro') {
|
||||
c_mac_ref(env, arg1);
|
||||
return CONS(arg2, CONS(arg3, arg1));
|
||||
else
|
||||
} else if (arg2 == @'si::symbol-macro') {
|
||||
c_sym_ref(env, arg1);
|
||||
return CONS(arg2, CONS(arg3, arg1));
|
||||
} else {
|
||||
return ECL_NIL;
|
||||
}
|
||||
}
|
||||
|
||||
cl_object
|
||||
|
|
@ -3594,7 +3631,7 @@ ecl_make_lambda(cl_env_ptr env, cl_object name, cl_object lambda) {
|
|||
for (i = 0; i < n; i++) {
|
||||
entry = p->vector.self.t[i];
|
||||
p->vector.self.t[i] = ECL_NIL;
|
||||
macro_entry = fix_macro_to_lexenv(entry);
|
||||
macro_entry = fix_macro_to_lexenv(env, entry);
|
||||
if(!Null(macro_entry)) {
|
||||
flex->vector.self.t[i] = macro_entry;
|
||||
continue;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue