Does anyone have any simple examples of #langs
that are structured well? Or at least typically? Hard to know what is standard, and which of the various options (like the reader lang ones) are often used, and to what end; the descriptions can be rather vague for someone completely new to the art. I don’t believe there’s actually anything in the racket guide about language.rkt
but it seems to be a necessary file.
@sydney.lambda The book Beautiful Racket has many good examples https://beautifulracket.com/
Thank you, I remember learning quite a bit from your minipascal before when implementing types but it slipped my mind. Hmm. Am I on the right track in saying that the lexer/parser turn the source into syntax objects of certain classes, which are then parsed in a higher level way by the macros using the pattern-matching of syntax-parse?
I initially got the impression the idea was to just wrap everything in syntax that resembled AST nodes like (do this)
and (number that)
but from what I can see it looks like the syntax is matched against in patterns via macros.
sorry if that doesn’t make much sense, I’ve only been doing this for 2 days and I’m finding it hard to get my head around haha.
The original idea was to implement a macro for each terminal that the parser produces.
It worked quite well, but then I ran into some problem which I at the time couldn’t figure out how to solve (I think I could solve now), so I changed tactics.
In compiler-simple.rkt you can see a compile-program that is defined as:
(define (compile-program stx)
(syntax-parse stx
[({~datum program} "program" program-name ";" block ".")
(compile-block #'block)]))
(define (compile-block stx)
(syntax-parse stx
[(_ constant-definition-part
type-definition-part
variable-declaration-part
procedure-and-function-declaration-part
statement-part)
(syntax/loc stx
(let () ; new scope
constant-definition-part
type-definition-part
variable-declaration-part
procedure-and-function-declaration-part
statement-part))]
[_ (error 'compile-block "internal error")]))
Seems like a very similar thing is happening at multiple stages. From lex->parse and parse->compile, you’re building up bigger concepts from the parts you assembled in the prior step.
Yes.
If we compare the compiler with the grammar: program : "program" IDENTIFIER ";" block "."
block : constant-definition-part
type-definition-part
variable-declaration-part
procedure-and-function-declaration-part
statement-part
The original compiler defined a macro for each terminal program
, block
etc. And then the parser simply outputs a program consisting of calls to the macros (see dyoo brainf**k example).
I ran into some issue, so I changed tactics to use an explicit compile stage.
Yes! That’s exactly what I thought I should be doing at first, until I started to see more examples like yours that looked a bit more robust.
For simpler compilers the “let the parser output macro calls” is quite elegant.
All I’m doing is a concatenative/stack language, with the whole thing wrapped in (compose (reverse stx))
with all the macro functions being stack -> stack
so in honesty I could probably get away with keeping it simple I guess.
Sounds like it.
Thanks a lot for taking the time to clarify, pretty sure I understand it better now :)
Oh, the only other thing that I couldn’t work out for the life of me, is the signifance of “language.rkt”. Few languages seem to have one, but I seem to get errors without one, as if racket expects one whenever I use #lang mylang
. Any idea why that is?
I need to see the exact error, but I my guess is that the expander calls lang-error
which is defined in “language.rkt”. Did you save the error?
open-input-file: cannot open module file
module path: stack/language
path: /home/syd/proj/racket/stack/language.rkt
that’s what happens when I delete the dummy language.rkt file I have.
Is your module called “language” ?
The #lang is called stack. I set it up by cd-ing to the folder called stack that the files are in and doing raco pkg install
The closest I could get to a planet package (when following the brainf*dge tutorial) as planet doesn’t seem to like sending emails.
I think one of your tools (perhaps ragg or brag) is using #lang reader
.
Hmm, strange. I’m only using megaparsack. The only language other than racket (and #lang stack in test.rkt) is #lang s-exp syntax/module-reader
so I guess it must be the latter somehow. I’ve come across a few projects using that though and none of them seem to have language.rkt files either. Weird.
Pretty daft of me to not just provide it instead of explaining it badly: https://github.com/dys-bigwig/stacklang that’s my project, sans language.rkt. Works fine with if a dummy language.rkt is added but fails with that error otherwise. I sense it’s probably something obvious and embarrasing, but it’d be nice to not have to have the file there.
The second line in https://github.com/dys-bigwig/stacklang/blob/master/lang/reader.rkt is stack/language
So I think that’s why it is looking for language.rkt
wow, please excuse me whilst I defenstrate myself. puts on dunce hat
sorry.
no worries
thanks again for all your help. I really appreciate it :)
Looking forward to seeing the end result!