Hi,

I found a solution to the first problem where the parameter of the method are 
now recognised as "lexically bound". However, it seems like a dirty hack as i 
have to pass the arg list explicitly when checking the body expressions. 
Furthermore, this does not solve the issue when methods contain id bindings in 
the body. Any suggestions? I could keep a list during syntax parsing and 
whenever a define is found it adds to that list and then simply check if the id 
is in that list, but again that seems a very dirty hack.

#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))
  
  ;; Arg List
    
  (define-splicing-syntax-class (arg-list)
    (pattern (~seq arg:id ...)))
  
  ;; 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> (begin ;(display #'value) (newline)
                                   ;(display (lexically-bound? #'value)) 
(newline)
                                   ;(display (local-parameter? #'value args)) 
(newline)
                                   (if (or (lexically-bound? #'value)
                                           (local-parameter? #'value args))
                                           #'value 
                                           #'(void))))
    (pattern (define name:id (~var arg (class-expr args)))
             #:with <value> #'(define name arg.<value>))
    (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)

On 25 Feb 2014, at 15:54, Chrisophe Vandenberghe <chv...@gmail.com> wrote:

> Hey guys,
> 
> (first time poster)
> 
> I have been learning how the Racket Syntax Framework works and trying to make 
> a custom language. What I am currently trying to make is a small Object 
> Oriented language which has classes and so on. I don't want to use the 
> built-in classes as I want to alter the OO meaning once I got my language 
> going … Anyway, the goal would be to have something similar to this:
> 
> (CLASS
>       (FIELD x 1)
>       (FIELD y 1)
>       (METHOD (x?) x)
>       (METHOD (x! new) (set! x new)))
> 
> Both fields and methods are kept in a hash table for lookup. So what I would 
> want is that in the above method "x?" the identifier x is recognised as not 
> "lexically bound" and thus refers to the field x. So during syntax 
> transformation I can take some action to fetch the value of that field in the 
> field lookup table. However, I can't seem to make the test for "lexically 
> bound" work. It always returns false. So take for example the method "x!", in 
> that case it would fail to recognise that the value of the identifier "new" 
> is given by the local parameter and would also try to lookup new in the field 
> lookup table of the object. However, it should only try to lookup x.
> 
> I guess it's hard to grasp what I mean, so I have made a simplified version 
> of what I have. Remember that I have stripped down most to make it more 
> understandable, so this code does not create classes in any way but it is 
> structured exactly like my original code. I might therefore seem weird to use 
> so many syntax-classes as they are superfluous here, but in my implementation 
> there is a lot more stuff going on which require them.
> 
> 
> #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-syntax (CLASS stx)
> 
>  ;; Literal
> 
>  (define-syntax-class (literal)
>    (pattern value:boolean)
>    (pattern value:char)
>    (pattern value:integer)
>    (pattern value:number)
>    (pattern value:str))
> 
>  ;; Object Expression (validates all expressions inside a class)
> 
>  (define-syntax-class (class-expr)
> 
>    #:datum-literals (define)
>    #:commit
> 
>    (pattern value:literal
>             #:with <value> #'value)
>    (pattern value:id
>             #:with <value> (begin (display #'value) (newline)
>                                   (display (lexically-bound? #'value)) 
> (newline)
>                                   (if (lexically-bound? #'value) #'value 
> #'(void))))
>    (pattern (define name:id arg:class-expr)
>             #:with <value> #'(define name arg.<value>))
>    (pattern (operator:id arg:class-expr ...)
>             #:with <value> #'(operator arg.<value> ...)))
> 
>  ;; Method Class
> 
>  (define-syntax-class (class-method)
> 
>      #:datum-literals (METHOD)
> 
>      (pattern (METHOD (name:id arg:id ...) body:class-expr ...)
>               #:with <value> #'(define (name arg ...) body.<value> ...)))
> 
>  ;;;;; Class Parser
> 
>  (syntax-parse 
>   stx
> 
>   #:datum-literals (CLASS)
> 
>   [(CLASS <method>:class-method)
>    #'<method>.<value>]))
> 
> 
> 
> ;; Example Case
> 
> (CLASS
> (METHOD (test a b) (define c 1) a b c d))
> 
> 
> In the example above, what I want is that a, b and c are recognised as 
> "lexically bound" and d is not. Then I can transform d to something that 
> fetches the "d" entry in the fields hash map of the object. However, when 
> this code is run all 4 are returned as unbound.
> 
> If I would add:
> 
> (define a 1)
> (define b 1)
> (define c 1)
> (define d 1)
> 
> before the CLASS definition then it works, so the check to see if they are 
> lexically bound should be correct. Therefore, I am thinking that I am 
> approaching my problem incorrectly.
> 
> 
> Thanks for any response,
> 
> Christophe
> 
> 
> p.s. If I make incorrect use of syntax-classes feel free to let me know.


____________________
  Racket Users list:
  http://lists.racket-lang.org/users

Reply via email to