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