I'm pretty sure that this is just implementing an internal definition context inside the `METHOD` macro, and should therefore use the techniques discussed in this paper: http://www.cs.utah.edu/plt/expmodel-6/
In general, trying to traverse the body of the `METHOD` before expanding it will never actually do the right thing -- the only way to understand pre-expansion Racket forms is to expand them. Sam On Mon, Mar 3, 2014 at 2:42 PM, Matthias Felleisen <matth...@ccs.neu.edu> wrote: > > Okay, got it. > > (1) I can't see better ways to accomplish what you want, other than turning > identifiers into symbols and looking them up in a hash table (which defaults > to void). > > (2) I admit it's ugly to keep track of lexical vars like that. Chez used to > have fluid-syntax-let, and it would have helped a bit here. We don't have it, > or I am too out of it today to find something similar. > > Perhaps someone from the unstable/syntax family can help. > > -- Matthias > > > > > > > > On Mar 3, 2014, at 2:18 PM, Chrisophe Vandenberghe <chv...@gmail.com> wrote: > >> If you run the code (the last one I posted) it outputs '(1 2 #<void> >> #<void>). But, I want it to output '(1 2 1 #<void>). >> There is a (define c 1) which is not recognised in my implementation. >> >> The only solution I have found so far is to keep a list during syntax >> expansion which keeps track of local definitions and which is reset when a >> new METHOD is encountered. Below is the result code which outputs what I >> want. This allows me to do more useful stuff then to return void when the >> identifier is not found. >> >> Is it really that hard to understand? Should i re-write my code and not use >> syntax-classes? I know the example is unclear cause this syntax simply >> returns a method, but that is not the point. My entire implementation is 500 >> LOC, so I had to simplify it to post it. >> >> #lang racket >> >> (require (for-syntax syntax/parse)) >> >> (define-for-syntax (lexically-bound? stx) >> (define expanded (local-expand stx (syntax-local-context) #f)) >> (and (identifier? expanded) >> (not (eq? #f (identifier-binding expanded))))) >> >> (define-for-syntax (local-parameter? stx pars-stx) >> (ormap (lambda (par) (bound-identifier=? stx par)) (syntax-e pars-stx))) >> >> (define-syntax (CLASS stx) >> >> ;; Literal >> >> (define-syntax-class (literal) >> (pattern value:boolean) >> (pattern value:char) >> (pattern value:integer) >> (pattern value:number) >> (pattern value:str)) >> >> ;; Current local definition (used during every method expansion) >> >> (define current-local-defs '()) >> >> ;; Arg List >> >> (define-splicing-syntax-class (arg-list) >> (pattern (~seq arg:id ...) >> #:do [(set! current-local-defs '())])) >> >> ;; Class Expression (validates all expressions inside a class) >> >> (define-syntax-class (class-expr args) >> >> #:datum-literals (define) >> #:commit >> >> (pattern value:literal >> #:with <value> #'value) >> (pattern value:id >> #:with <value> (if (or (lexically-bound? #'value) >> (local-parameter? #'value args) >> (member (syntax-e #'value) >> current-local-defs)) >> #'value >> #'(void))) >> (pattern (define name:id (~var arg (class-expr args))) >> #:with <value> #'(define name arg.<value>) >> #:do [(set! current-local-defs (cons (syntax-e #'name) >> current-local-defs))]) >> (pattern (operator:id (~var arg (class-expr args)) ...) >> #:with <value> #'(operator arg.<value> ...))) >> >> ;; Method Class >> >> (define-syntax-class (class-method) >> >> #:datum-literals (METHOD) >> >> (pattern (METHOD (name:id (~var arg-list arg-list)) (~var body >> (class-expr #'arg-list)) ...) >> #:with <value> #'(define (name arg-list.arg ...) body.<value> >> ...))) >> >> ;;;;; Class Parser >> >> (syntax-parse >> stx >> >> #:datum-literals (CLASS) >> >> [(CLASS <method>:class-method) >> #'<method>.<value>])) >> >> (CLASS >> >> (METHOD (test a b) (define c 1) (list a b c d))) >> >> (test 1 2) > > > ____________________ > Racket Users list: > http://lists.racket-lang.org/users ____________________ Racket Users list: http://lists.racket-lang.org/users