diff --git a/src/mzscheme/src/eval.c b/src/mzscheme/src/eval.c index ae28334044..b48d0d04b1 100644 --- a/src/mzscheme/src/eval.c +++ b/src/mzscheme/src/eval.c @@ -1304,6 +1304,11 @@ static void set_app2_eval_type(Scheme_App2_Rec *app) SCHEME_APPN_FLAGS(app) = et; } +void scheme_reset_app2_eval_type(Scheme_App2_Rec *app) +{ + set_app2_eval_type(app); +} + static Scheme_Object *resolve_application2(Scheme_Object *o, Resolve_Info *orig_info, int already_resolved_arg_count) { Resolve_Info *info; diff --git a/src/mzscheme/src/schpriv.h b/src/mzscheme/src/schpriv.h index 4f44f2e5af..fe4b8f9660 100644 --- a/src/mzscheme/src/schpriv.h +++ b/src/mzscheme/src/schpriv.h @@ -2122,6 +2122,8 @@ Scheme_Closure *scheme_malloc_empty_closure(void); Scheme_Object *scheme_make_native_closure(Scheme_Native_Closure_Data *code); Scheme_Object *scheme_make_native_case_closure(Scheme_Native_Closure_Data *code); +void scheme_reset_app2_eval_type(Scheme_App2_Rec *app); + Scheme_Native_Closure_Data *scheme_generate_case_lambda(Scheme_Case_Lambda *cl); void scheme_delay_load_closure(Scheme_Closure_Data *data); diff --git a/src/mzscheme/src/syntax.c b/src/mzscheme/src/syntax.c index 837b08d7de..c2147ea69d 100644 --- a/src/mzscheme/src/syntax.c +++ b/src/mzscheme/src/syntax.c @@ -3786,6 +3786,38 @@ scheme_resolve_lets(Scheme_Object *form, Resolve_Info *info) if (info->max_let_depth < max_let_depth) info->max_let_depth = max_let_depth; + /* Check for (let ([x ]) ( x)) at end, and change to + ( ). This is easy because the local-variable + offsets in do not change (as long as doesn't + access the stack). */ + last_body = NULL; + body = first; + while (1) { + if (!SAME_TYPE(SCHEME_TYPE(body), scheme_let_one_type)) + break; + if (!SAME_TYPE(SCHEME_TYPE(((Scheme_Let_One *)body)->body), scheme_let_one_type)) + break; + last_body = body; + body = ((Scheme_Let_One *)body)->body; + } + if (SAME_TYPE(SCHEME_TYPE(body), scheme_let_one_type)) { + if (SAME_TYPE(SCHEME_TYPE(((Scheme_Let_One *)body)->body), scheme_application2_type)) { + Scheme_App2_Rec *app = (Scheme_App2_Rec *)((Scheme_Let_One *)body)->body; + if (SAME_TYPE(SCHEME_TYPE(app->rand), scheme_local_type) + && (SCHEME_LOCAL_POS(app->rand) == 1)) { + if (SCHEME_TYPE(app->rator) > _scheme_values_types_) { + /* Move to app, and drop let-one: */ + app->rand = ((Scheme_Let_One *)body)->value; + scheme_reset_app2_eval_type(app); + if (last_body) + ((Scheme_Let_One *)last_body)->body = (Scheme_Object *)app; + else + first = (Scheme_Object *)app; + } + } + } + } + return first; } else { /* Maybe some multi-binding lets, but all of them are unused