I'm learning racket and as a way to consolidate my knowledge I'm trying to build a library for parser expression grammars (PEG). My intention is to build a language to express PEGs and the module should export a function parser that receives a string and tries to parse it using the grammar defined in the language. However, I'm struggling with building this module using the following read function:
(define (peg-read-syntax path port)
(define grammar (parse port))
(datum->syntax
#f
`(module peg-mod racket
(provide parser
pretty
(all-from-out "tree.rkt"))
(define (parser s)
(peg-parse ,grammar s))
(define (pretty t)
(peg-pretty ,grammar t))))))
and racket returns the following error whenever I try to process a program in #lang peg language:
default-load-handler: expected a `module' declaration, but found something else
Can someone help me with this mistake? The complete project is at the following github repo:
https://github.com/lives-group/peg-parsing
Related
I want a language like scribble/text but with some additional functions offered. This is what I've tried:
#lang racket/base
(require scribble/text)
(provide (all-from-out scribble/text)
hello)
(define (hello name)
(format "Hello ~a!" name))
When I try to run a module written in this language, I get a message saying that there is no #%module-begin binding in the module's language.
I assume that scribble/text has a binding for #%module-begin, else how does it work when I use it as a #lang?
Maybe scribble/text knows that I am importing it using 'require' rather than as a #lang, and so I don't automatically get the #% macros? If that's the case, then how would I get them and re-export them?
Or is something else happening here?
The language for #lang scribble/text and the library for (require scribble/text) are different modules. The library version doesn't provide #%module-begin or the other bindings from racket:
When scribble/text is used via require instead of #lang, then .... it does not include the bindings of racket/base ....
The module-language #lang scribble/text actually uses is scribble/text/lang. So you can fix your module-language like this:
#lang racket/base
(require scribble/text/lang)
(provide (all-from-out scribble/text/lang)
hello)
(define (hello name)
(format "Hello ~a!" name))
However, the module scribble/text/lang is undocumented, so use at your own risk.
I would like to create a new language that has the same syntax as typed racket, but when executed will do two things:
run the given program as typed racket
if type checks, then translates the input into another language (say python). I am planning to write a translator from typed racket forms to python syntax.
Any suggestions on how to start or pointers to some skeleton code? I have read this tutorial but it mostly talks about creating new syntax which I don't need in my case.
I understand how I can write racket code to translate from one language to another, what I don't get is how I can do both of the above, i.e., first run it as another language, and then do something else with the same input.
It sounds like you want to make a language with a new #%module-begin form. This form is either inserted by the reader (when you do a #lang .... line at the top of your file, or by the language if you wrote the module out by hand. Either way, its generally associated with your language definition. This macro has full access to the entire module's unexpanded syntax. So for example, a macro like this:
(provide (rename-out [-module-begin #%module-begin]))
(define-simple-macro (-module-begin body ...)
(#%module-begin
(writeln '(body ...))
body ...))
Would create a language that does two things:
Print out the body of the code (as an s-expression), and
Run the body with the #%module-begin that the language definition was written in.
You can see how you can use this technique to grab the body of your program twice, and do two different things with it. So let's try running this example. First, lets take the sample from above, and put it in a file "mylang.rkt":
#lang racket
(provide (rename-out [-module-begin #%module-begin])
(except-out (all-from-out racket) #%module-begin))
(require syntax/parse/define)
(define-simple-macro (-module-begin body ...)
(#%module-begin
(writeln '(body ...))
body ...))
And now we can write a program in mylang like this:
#lang s-exp "mylang.rkt"
(+ 1 2)
And when you run it, you'll get something like this:
((+ 1 2))
3
First its printing out the program text, then running it.
You can read more about this process in a paper I wrote discussing this aspect of the Video language. You might also find the book Beautiful Racket to have some examples you might find useful.
I would like to write code that is correct for both untyped Racket and typed/racket...
For now, I've come up with the following not-so-satisfying principle: I insert a dummy syntax definition for ':' at the beginning of the file, so that the annotations are skipped when using untyped racket. And I comment this definition when using typed/racket.
E.g:
#lang racket
; comment the following line for typed/racket
(define-syntax : (syntax-rules () ((_ id type) (void))))
(: fact (-> Integer Integer))
; the rest of the file is common to both racket and typed/racket
(define (fact n) (if (zero? n) 1 (* n (fact (sub1 n)))))
and
#lang typed/racket
; comment the following line for typed/racket
;(define-syntax : (syntax-rules () ((_ id type) (void))))
(: fact (-> Integer Integer))
; the rest of the file is common to both racket and typed/racket
(define (fact n) (if (zero? n) 1 (* n (fact (sub1 n)))))
This way I just need to remove/insert a ';' to switch between racket and typed/racket...
But is there a way to have a code that doesn't need any change to run in racket and typed/racket? I didn't find how to programmatically detect if I'm in racket or typed/racket... Then I guess I would also have to find a way to conditionally define ':' at the top-level... All this doesn't seem the way to go, so, is there a better way ?
Generally, if you want code to work with both #lang racket and #lang typed/racket, just write your code in #lang typed/racket. When you require a module written in #lang typed/racket from a module written in #lang racket, contracts will automatically be inserted between the two modules to enforce the types. You don’t have to do anything special to require a typed module from an untyped one, so from the user’s perspective, they don’t have to care.
The one area where you might need to worry about being in a typed or untyped context is when writing macros. Often, you can expand to the same code in both situations, but sometimes, you have to do things differently depending on whether or not the target code is typed. For that, you can use define-typed/untyped-identifier, which allows specifying two different forms to be used in different contexts.
If you really need to detect whether or not the current expansion context is typed, you can use the large hammer syntax-local-typed-context?. However, the documentation itself recommends avoiding its use:
This is the nuclear option, provided because it is sometimes, but rarely, useful. Avoid.
I have sample code like this:
#!/usr/bin/guile -s
!#
(define (process body)
(list 'list (map (lambda (lst)
(list 'quote (car lst)))
body)))
(defmacro macro (body)
(list 'quote (process body)))
(display (macro ((foo bar) (bar baz))))
(newline)
it run but I've got error from compiler
ERROR: Unbound variable: process
functions inside macros should be allowed, why I got this error?
Functions inside macros are allowed in Guile and in most other Scheme dialects.
However, the crucial question is: Which functions are available for a macro to call out during the expansion process?
Think of it this way: When the compiler is processing your code, it is first focused on turning your source code into something that can be run at some point in the future. But the compiler might not necessarily be able to execute those same functions right now while it is compiling them, at the same time that your macro is running and expanding the source code in general.
Why wouldn't such a function be available? Well, one example would be: What if the function's body used the macro you are in the midst of defining? Then you would have a little chicken/egg problem. The function would need to run the macro to be compiled (since the macro use in the body needs to be expanded, at compile-time) ... But the macro would need the compiled function available in order to even run!
(Furthermore, there might be some functions that you only want to be available at compile-time, as a helper for your macros, but that you do not want to be available at run-time, so that it will not be included in your program executable when you deploy it, as that would waste space in the deployed binary.)
One of my favorite papers describing this problem, and the particular solution adopted by MzScheme (now known as Racket), is the "You Want It When" paper by Matthew Flatt.
So, this is a problem that any Scheme dialect with a procedural macro system has to deal with in some way, and Guile is no exception.
In Guile's case, one fix that is directly documented in the Guile manual is to use the eval-when special form, which allows you to specify at what phases a particular definition is meant to be available.
(The "You Want It When" paper referenced above describes some problems with eval-when, but since it is what the Guile manual documents, I'm going to stick with it for now. I do recommend that after you understand eval-when, that you then look into Racket's solution, and see if Guile offers anything similar.)
So in your case, since you want the process function to be available at compile-time (for use in the macro definition), you could write:
#!/usr/bin/guile -s
!#
(eval-when (expand)
(define (process body)
(list 'list (map (lambda (lst)
(list 'quote (car lst)))
body))))
(defmacro macro (body)
(list 'quote (process body)))
(display (macro ((foo bar) (bar baz))))
(newline)
I'm writing an ADT in r5rs and I'm using DrRacket. I put #lang r5rs at the top of my file and chose Determine Language from Source from DrRacket, but it tells me my ADT is undefined. I'm using DrRacket version 6.0. It's the first time I've had this and can't understand what I'm doing wrong.
My ADT
#lang r5rs
(#%require "queue.rkt") ;A required file
(#%provide (all-defined))
(define (my-ADT)
(let ((val1 '())
(val2 '()))
(define (foo) ...)
(define (bar) ...)
(define (dispatch msg)
(case msg
((foo) foo)
((bar) bar)
(else "Unknown message")))
dispatch))
When I try to create an instance of my-ADT I get the following output: my-ADT: undefined; cannot reference an identifier before its definition
When I remove #lang r5rs from the top and choose R5RS as language in DrRacket, it seems to work. But then my queue.rkt file still has #lang r5rs at the top and Determine Language from Source. When I remote #lang r5rs and choose R5RS as language in that file also, I get the following in the my-ADT file:
default-load-handler: expected a `module' declaration
found: something else
in: #<path:/Users/path/path/path/queue.rkt>
The error
my-ADT: undefined; cannot reference an identifier before its definition
normally indicates that the function my-ADT was used before it was defined.
That is, one must place all definitions on top of the file and place the expressions below.
Your example above has no uses of my-ADT so if you get this error, the problem might be in "queue.rkt". Can you run "queue.rkt" without errors?