From 0e12201c4d52440af01d54c11d7b5e928b905aaa Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Fri, 27 Jan 2017 09:03:11 -0700 Subject: [PATCH] fix bytecode writer for immediate compile-time values When a hash table or other special value appears immediately on the right-hand side of `define-values`, it needs to be protected by an explicit quote when writing to bytecode. Closes #1580 --- .../racket-test-core/tests/racket/module.rktl | 12 ++++++ racket/src/racket/src/marshal.c | 39 ++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/pkgs/racket-test-core/tests/racket/module.rktl b/pkgs/racket-test-core/tests/racket/module.rktl index e15c851fe4..30d5cd5a45 100644 --- a/pkgs/racket-test-core/tests/racket/module.rktl +++ b/pkgs/racket-test-core/tests/racket/module.rktl @@ -2005,6 +2005,18 @@ case of module-leve bindings; it doesn't cover local bindings. (test 'defined dynamic-require ''uses-defines-a-variable-x-in-its-body-at-phase-1 'out) +;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Make sure a hash-table constant is allowed as a compile-time RHS: + +(let () + (define o (open-output-bytes)) + (write (compile '(module m racket/base + (require (for-syntax racket/base)) + (define-syntax something #hash((1 . 2))))) + o) + (parameterize ([read-accept-compiled #t]) + (read (open-input-bytes (get-output-bytes o))))) + ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (report-errs) diff --git a/racket/src/racket/src/marshal.c b/racket/src/racket/src/marshal.c index 36f6b770e0..9047c43243 100644 --- a/racket/src/racket/src/marshal.c +++ b/racket/src/racket/src/marshal.c @@ -1352,6 +1352,40 @@ static Scheme_Object *ht_to_vector(Scheme_Object *ht, int delay) return vec; } +static Scheme_Object *protect_expr_quotes(Scheme_Object *body) +/* protect each expression in a phase-1-or-higher module-body vector */ +{ + Scheme_Object *e, *v, *v2, *body2 = NULL; + int i, j; + + for (j = SCHEME_VEC_SIZE(body); j--; ) { + v = SCHEME_VEC_ELS(body)[j]; + e = scheme_protect_quote(SCHEME_VEC_ELS(v)[1]); + if (!SAME_OBJ(e, SCHEME_VEC_ELS(v)[1])) { + i = SCHEME_VEC_SIZE(v); + v2 = scheme_make_vector(i, NULL); + while (i--) { + SCHEME_VEC_ELS(v2)[i] = SCHEME_VEC_ELS(v)[i]; + } + SCHEME_VEC_ELS(v2)[1] = e; + v = v2; + + if (!body2) { + i = SCHEME_VEC_SIZE(body); + body2 = scheme_make_vector(i, NULL); + while (--i > j) { + SCHEME_VEC_ELS(body2)[i] = SCHEME_VEC_ELS(body)[i]; + } + } + } + + if (body2) + SCHEME_VEC_ELS(body2)[j] = v; + } + + return (body2 ? body2 : body); +} + static Scheme_Object *write_module(Scheme_Object *obj) { Scheme_Module *m = (Scheme_Module *)obj; @@ -1380,7 +1414,10 @@ static Scheme_Object *write_module(Scheme_Object *obj) l = cons(m->requires, l); for (j = 0; j < m->num_phases; j++) { - l = cons(m->bodies[j], l); + v = m->bodies[j]; + if (j > 0) + v = protect_expr_quotes(v); + l = cons(v, l); } cnt = 0;