Exactly what I was thinking, but couldn't find a clear way of doing it the "right" way. I'll have a read through the paper when I find the time and report back when I have found a better solution. It works for now with my fix, so it can wait as I need to finish my implementation ASAP.
Thx for the replies. Christophe On 03 Mar 2014, at 20:47, Sam Tobin-Hochstadt <sa...@cs.indiana.edu> wrote: > 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