#lang magic
# display tga bitmap image information
0 name tga-image
>2 byte <34 Targa image data
0 name test-scope
>2 byte <34 Test Scope
>0 use tga-image
(module magic-mod magic/expander
(magic
#f
#f
(named-query
(name-line (offset 0) (name-type "name") "tga-image")
(level)
(line (offset 2) (type (numeric "byte")) (test (numtest "<" 34)) (message "Targa image data")))
(named-query
(name-line (offset 0) (name-type "name") "test-scope")
(level)
(line (offset 2) (type (numeric "byte")) (test (numtest "<" 34)) (message "Test Scope"))
(level)
(line (offset 0) (type (use "use")) (test (use-name "tga-image"))))))
--
You received this message because you are subscribed to the Google Groups "Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/ee664882-1dec-4bb8-b66b-bd6ee80316dc%40googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to racket...@googlegroups.com.
I changed the lines in named-query from[name (datum->syntax stx (string->symbol (syntax->datum #'magic-name)))to(format-id stx "~a" (syntax-e #'magic-name))
To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/94501425-0fae-4cea-86b0-1aaa1ac574cc%40googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/94501425-0fae-4cea-86b0-1aaa1ac574cc%40googlegroups.com.
On 13 Aug 19, at 7:03 PM, Jonathan Simpson <jjsi...@gmail.com> wrote:In the following magic code, a new function(called a named query in magic) tga-image is defined and later used inside the definition of the function test-scope. The issue is that tga-image is an unbound identifier in test-scope. If tga-image is used outside of a function there isn't a problem because the syntax object passed to use has the binding. What I would like to do is define tga-image at the top level.
Surely defining a recursive function with a macro is a fairly common occurrence. It is the expansion of the query macro within the function that appears to be the problem. The syntax object passed to query has its own lexical environment that doesn't include the containing function. This is the point of hygiene I guess. I'm not exactly sure how to use it, but would local-expand be a method to expand query in it's surrounding lexical environment?
It is, and normally it’s not a problem because people generally write macros hygienically. However, in your case, several macros are written in defmacro
-style (syntax->datum
the whole syntax object to S-expression, and then manipulate the S-expression instead). That is usually the cause of problems.
Here’s an example of how to write module-begin
hygienically without using syntax->datum
:
......
;; my own macro implementations to demonstrate that it works
(define-syntax (named-query stx)
(syntax-parse stx
;; make definition
[(_ ({~datum name} name) e) #'(define (name) e)]))
(define-syntax (query stx)
(syntax-parse stx
[(_ e) #'e]))
(define-syntax (line stx)
(syntax-parse stx
[(_ e) #'e]))
(define-syntax (use-name stx)
(syntax-parse stx
;; add application
[(_ e) #'(e)]))
;; end my own macro implementations
(define-syntax (wrap-with-delimiter-print stx)
(syntax-parse stx
[(_ expr) #'(when* expr (printf "*** "))]))
(define-syntax (magic-module-begin stx)
(define (query? expr)
(syntax-parse expr
[({~literal query} . _) #t]
[_ #f]))
(define (named-query? expr)
(syntax-parse expr
[({~literal named-query} . _) #t]
[_ #f]))
(syntax-parse stx
[(_ ({~datum magic} exprs ...))
#:with (queries ...) (filter query? (attribute exprs))
#:with (named-queries ...) (filter named-query? (attribute exprs))
#'(#%module-begin
named-queries ...
(define (magic-query) (or queries ...))
(define (magic-query-run-all)
; any-true? creates a binding for last-level-offset which we probably don't want here. investigate.
(any-true? (wrap-with-delimiter-print queries) ...))
(provide magic-query magic-query-run-all))]))
(provide
(except-out (all-from-out racket/base) #%module-begin)
(rename-out [magic-module-begin #%module-begin])
use-name query named-query line)
Then this code works correctly:
#lang racket
(module magic-mod magic/expander
(magic
(named-query (name tga-image) (line 1))
(named-query (name test-scope) (line (use-name tga-image)))
(query (use-name test-scope))))
For your code, the next thing I would suggest looking into is to avoid using syntax->datum
in the query
macro (and also the whole S-expression mangling in expander-utils
) and use syntax-parse
on the syntax object instead. As a bonus, syntax-parse
would let you avoid things like cadddadr
.
-- Jon
On Wednesday, August 14, 2019 at 10:49:35 PM UTC-4, Jonathan Simpson wrote:I will take a look at this as well. It may be a few days before I have time to devote to this again, but I appreciate everyone's help so far.-- Jonathan
On Wednesday, August 14, 2019 at 1:00:54 AM UTC-4, Matthew Butterick wrote:On 13 Aug 19, at 7:03 PM, Jonathan Simpson <jjsi...@gmail.com> wrote:In the following magic code, a new function(called a named query in magic) tga-image is defined and later used inside the definition of the function test-scope. The issue is that tga-image is an unbound identifier in test-scope. If tga-image is used outside of a function there isn't a problem because the syntax object passed to use has the binding. What I would like to do is define tga-image at the top level.You might consider the technique described here, including the `find-unique-var-ids` function:Since you're using `brag`, you can wrap your future identifiers in, say, an `id` rule that you splice away in the grammar. So your parse tree ends up the same, but now that `id` rule leaves a residue as a syntax property.Then, as part of your `#%module-begin` prep work, you can use this property to pull out the identifiers and write them into the top level of your new module as `define` expressions (with dummy values, that would get replaced later with `set!`).There may be a way of accomplishing the same thing more elegantly with syntax lifts and captures. Like the lost city of El Dorado, I searched for this beauty, but expired on the jungle floor before discovering it. Since then, however, many people smarter than me have seen that page, so by Cunningham's Law, if there were a better method, I probably would've been told by now.
--
You received this message because you are subscribed to the Google Groups "Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/cef06a2b-0d07-462d-806f-1d9804fca973%40googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to racket...@googlegroups.com.