make the teaching languages cooperate with the new undefined semantics

This commit is contained in:
Robby Findler 2014-04-17 14:04:14 -05:00
parent 0372249eba
commit a9f46ade9e
3 changed files with 14 additions and 44 deletions

View File

@ -135,6 +135,8 @@
(lambda (all) "list")) (lambda (all) "list"))
(list #rx"assignment disallowed;\n cannot set variable before its definition\n variable:" (list #rx"assignment disallowed;\n cannot set variable before its definition\n variable:"
(lambda (all) "cannot set variable before its definition:")) (lambda (all) "cannot set variable before its definition:"))
(list #rx"^(.*): undefined;\n cannot use before initialization"
(λ (all one) (format "local variable used before its definition: ~a" one)))
;; When do these show up? I see only `#<image>' errors, currently. ;; When do these show up? I see only `#<image>' errors, currently.
(list (regexp-quote "#(struct:object:image% ...)") (list (regexp-quote "#(struct:object:image% ...)")
(lambda (all) "an image")) (lambda (all) "an image"))

View File

@ -87,16 +87,6 @@
(format "~a: question result is not true or false: ~e" where b) (format "~a: question result is not true or false: ~e" where b)
(current-continuation-marks))))) (current-continuation-marks)))))
;; Wrapped around uses of local-bound variables:
(define (teach-check-not-undefined name val)
(if (eq? undefined val)
(raise
(make-exn:fail:contract:variable
(format "local variable used before its definition: ~a" name)
(current-continuation-marks)
name))
val))
(define (identifier-is-bound? id) (define (identifier-is-bound? id)
(or (identifier-binding id) (or (identifier-binding id)
;; identifier-binding returns #f for variable bound at the top-level, ;; identifier-binding returns #f for variable bound at the top-level,
@ -1144,18 +1134,6 @@
;; a good error message, we need to wait, and that's what ;; a good error message, we need to wait, and that's what
;; beginner-app-delay does. ;; beginner-app-delay does.
;; For intermediate:
;; This application form disallows rator expressions that aren't
;; top-level identifiers or of the form `(teach-check-not-undefined ...)'.
;; The latter is probably surprising. It turns out that every use of
;; a `local'-bound identifier gets converted to an undefined check,
;; and the call to `teach-check-not-undefined' can't be forged by the
;; programmer. So the pattern-match effectively recognizes uses of
;; `local'-bound identifiers, which are legal as rator
;; expressions. (`let' and `letrec' get converted to `local'.)
(define-values (beginner-app/proc intermediate-app/proc) (define-values (beginner-app/proc intermediate-app/proc)
(let ([mk-app (let ([mk-app
(lambda (lex-ok?) (lambda (lex-ok?)
@ -1163,10 +1141,6 @@
(syntax-case stx () (syntax-case stx ()
[(_ rator rand ...) [(_ rator rand ...)
(let* ([fun (syntax rator)] (let* ([fun (syntax rator)]
[undef-check? (syntax-case fun (teach-check-not-undefined)
[(teach-check-not-undefined id)
#t]
[_else #f])]
[binding (and (identifier? fun) [binding (and (identifier? fun)
(identifier-binding fun))] (identifier-binding fun))]
[lex? (eq? 'lexical binding)] [lex? (eq? 'lexical binding)]
@ -1177,7 +1151,7 @@
fun fun
"expected a function after the open parenthesis, but found ~a" "expected a function after the open parenthesis, but found ~a"
what))]) what))])
(unless (and (identifier? fun) (or lex-ok? undef-check? (not lex?))) (unless (and (identifier? fun) (or lex-ok? (not lex?)))
(bad-app (if lex? (bad-app (if lex?
"a variable" "a variable"
(something-else fun)))) (something-else fun))))
@ -1748,8 +1722,8 @@
(syntax (syntax
((define-syntaxes (def-id/prop ...) ((define-syntaxes (def-id/prop ...)
(values (values
(make-undefined-check (redirect-identifier-to
(quote-syntax teach-check-not-undefined) (quote-syntax set!)
(quote-syntax tmp-id)) (quote-syntax tmp-id))
...)) ...))
...)))]) ...)))])
@ -1817,8 +1791,8 @@
(syntax->list (syntax (rhs-expr ...))))]) (syntax->list (syntax (rhs-expr ...))))])
(quasisyntax/loc stx (quasisyntax/loc stx
(#%stratified-body (#%stratified-body
(define-syntaxes (name) (make-undefined-check (define-syntaxes (name) (redirect-identifier-to
(quote-syntax teach-check-not-undefined) (quote-syntax set!)
(quote-syntax tmp-id))) (quote-syntax tmp-id)))
... ...
(define-values (tmp-id) rhs-expr) (define-values (tmp-id) rhs-expr)
@ -1852,8 +1826,8 @@
(quasisyntax/loc stx (quasisyntax/loc stx
(let-values ([(tmp-id) rhs-expr] ...) (let-values ([(tmp-id) rhs-expr] ...)
#,(stepper-syntax-property #,(stepper-syntax-property
#`(let-syntaxes ([(name) (make-undefined-check #`(let-syntaxes ([(name) (redirect-identifier-to
(quote-syntax teach-check-not-undefined) (quote-syntax set!t)
(quote-syntax tmp-id))] (quote-syntax tmp-id))]
...) ...)
expr) expr)

View File

@ -4,11 +4,10 @@
stepper/private/syntax-property stepper/private/syntax-property
(for-template (prefix r: racket/base))) (for-template (prefix r: racket/base)))
(provide make-undefined-check (provide make-first-order-function
make-first-order-function) redirect-identifier-to)
(define (make-undefined-check check-proc tmp-id) (define (redirect-identifier-to set!-stx tmp-id)
(let ([set!-stx (datum->syntax-object check-proc 'set!)])
(make-set!-transformer (make-set!-transformer
(lambda (stx) (lambda (stx)
(syntax-case stx () (syntax-case stx ()
@ -24,15 +23,10 @@
stx)] stx)]
[id [id
(stepper-syntax-property (stepper-syntax-property
(datum->syntax-object tmp-id
check-proc
(list check-proc
(list 'quote (syntax id))
tmp-id)
stx)
'stepper-skipto 'stepper-skipto
(append skipto/cdr (append skipto/cdr
skipto/third))]))))) skipto/third))]))))
#; #;
(define (appropriate-use what) (define (appropriate-use what)
(case what (case what