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) (define (rewrite-format str irritants)
(cond (cond
[(equal? str "attempt to reference undefined variable ~s") [(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)] irritants)]
[else [else
(let ([str (string-copy str)] (let ([str (string-copy str)]

View File

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

View File

@ -44,6 +44,12 @@
;; `#%app` whenever a call might go through something other than a ;; `#%app` whenever a call might go through something other than a
;; plain function; ;; 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 ;; - convert `make-struct-type` bindings to a pattern that Chez can
;; recognize; ;; recognize;
;; ;;
@ -51,6 +57,8 @@
;; important to make keyword-argument function calls work directly ;; important to make keyword-argument function calls work directly
;; without keywords; ;; without keywords;
;; ;;
;; - similarly optimize away `variable-reference-from-unsafe?`;
;;
;; - simplify `define-values` and `let-values` to `define` and ;; - simplify `define-values` and `let-values` to `define` and
;; `let`, when possible, and generally avoid `let-values`. ;; `let`, when possible, and generally avoid `let-values`.
@ -58,10 +66,10 @@
;; called from the Racket expander, those annotation will be ;; called from the Racket expander, those annotation will be
;; "correlated" objects that just support source locations. ;; "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 ;; 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 ;; 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? (define (schemify-linklet lk serializable? datum-intern? for-jitify? allow-set!-undefined?
unsafe-mode? no-prompt? unsafe-mode? no-prompt?
prim-knowns get-import-knowns import-keys) prim-knowns get-import-knowns import-keys)
@ -229,7 +237,7 @@
;; For the case that the right-hand side won't capture a ;; For the case that the right-hand side won't capture a
;; continuation or return multiple times, we can generate a ;; continuation or return multiple times, we can generate a
;; simple definition: ;; simple definition:
(define (finish-definition ids) (define (finish-definition ids [accum-exprs accum-exprs] [accum-ids accum-ids])
(append (append
(make-expr-defns accum-exprs) (make-expr-defns accum-exprs)
(cons (cons
@ -305,8 +313,10 @@
(match form (match form
[`(define-values ,ids ,_) [`(define-values ,ids ,_)
;; This is a rearranged `struct` form where any necessary ;; This is a rearranged `struct` form where any necessary
;; prompt is in place already ;; prompt is in place already. There may be arbitrary expressions
(finish-definition ids)] ;; for properties, though, so sync exported variables
(define set-vars (make-set-variables))
(finish-definition ids (append set-vars accum-exprs) null)]
[`,_ [`,_
(cond (cond
[(simple? #:pure? #f schemified prim-knowns knowns imports mutated) [(simple? #:pure? #f schemified prim-knowns knowns imports mutated)