schemify: cover all too-early variable uses

Don't defer any too-early variable checks to Chez Scheme, because the
schmeify-inserted checks use the right names and include a reference
to the enclosing module.
This commit is contained in:
Matthew Flatt 2019-01-21 11:56:09 -07:00
parent c47cbbf6c5
commit 1d7080fbb0
3 changed files with 23 additions and 10 deletions

View File

@ -56,7 +56,9 @@
(define (rewrite-format str irritants)
(cond
[(equal? str "attempt to reference undefined variable ~s")
(values "~a: undefined;\n cannot reference an identifier before its definition"
(values (string-append
"~a: undefined;\n cannot reference an identifier before its definition"
"\n alert: compiler pass failed to add more specific guard!")
irritants)]
[else
(let ([str (string-copy str)]

View File

@ -49,12 +49,13 @@
(eq? v 'too-early))
;; When referecing an exported identifier, we need to consistently go
;; through a `variable` record when it can be `set!`ed. We don't need
;; to go through a `variable` record if the identifier might simply be
;; used too early, because the host Scheme takes care of that issue.
;; through a `variable` record when it can be `set!`ed or is not yet
;; ready (as indicated by 'too-early, which is changed to 'too-eary/ready
;; as the variable becomes ready)
(define (via-variable-mutated-state? v)
(or (eq? v 'set!ed)
(eq? v 'undefined)))
(eq? v 'undefined)
(eq? v 'too-early)))
;; At the end of a linklet, known-value information is reliable unless
;; the identifier is mutated

View File

@ -44,6 +44,12 @@
;; `#%app` whenever a call might go through something other than a
;; plain function;
;;
;; - convert all `letrec` patterns that might involve `call/cc` to
;; ensure that locations are allocated at the right time;
;;
;; - explicily handle all potential too-early variable uses, so that
;; the right name and enclosing module are reported;
;;
;; - convert `make-struct-type` bindings to a pattern that Chez can
;; recognize;
;;
@ -51,6 +57,8 @@
;; important to make keyword-argument function calls work directly
;; without keywords;
;;
;; - similarly optimize away `variable-reference-from-unsafe?`;
;;
;; - simplify `define-values` and `let-values` to `define` and
;; `let`, when possible, and generally avoid `let-values`.
@ -58,10 +66,10 @@
;; called from the Racket expander, those annotation will be
;; "correlated" objects that just support source locations.
;; Returns (values schemified-linklet import-abi export-info)
;; Returns (values schemified-linklet import-abi export-info).
;; An import ABI is a list of list of booleans, parallel to the
;; linklet imports, where #t to means that a value is expected, and #f
;; means that a variable (which boxes a value) is expected
;; means that a variable (which boxes a value) is expected.
(define (schemify-linklet lk serializable? datum-intern? for-jitify? allow-set!-undefined?
unsafe-mode? no-prompt?
prim-knowns get-import-knowns import-keys)
@ -229,7 +237,7 @@
;; For the case that the right-hand side won't capture a
;; continuation or return multiple times, we can generate a
;; simple definition:
(define (finish-definition ids)
(define (finish-definition ids [accum-exprs accum-exprs] [accum-ids accum-ids])
(append
(make-expr-defns accum-exprs)
(cons
@ -305,8 +313,10 @@
(match form
[`(define-values ,ids ,_)
;; This is a rearranged `struct` form where any necessary
;; prompt is in place already
(finish-definition ids)]
;; prompt is in place already. There may be arbitrary expressions
;; for properties, though, so sync exported variables
(define set-vars (make-set-variables))
(finish-definition ids (append set-vars accum-exprs) null)]
[`,_
(cond
[(simple? #:pure? #f schemified prim-knowns knowns imports mutated)