how can I create a new language in racket?
Asked Answered
R

1

9

I would like to create a new language that has the same syntax as typed racket, but when executed will do two things:

  1. run the given program as typed racket
  2. 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.

Rozanneroze answered 5/8, 2018 at 6:21 Comment(2)
This isn't exactly what you want, but I thought it might help. github.com/shinh/elvm This is an IR (intermediate representation) language that compiles to common lisp, python and like 30 other languages (most of which are niche). And there is a C compiler to output this IR.Hoppe
Usually when creating a new language the steps are to transform the syntax to a base language supported by racket and racket will do the rest, but it does not seem like you are after creating a new language in racket so I find the question misleading. Perhaps you should study Whalesong which is more similar to your goals.Darwen
L
6

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:

  1. Print out the body of the code (as an s-expression), and

  2. 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.

Lanky answered 6/8, 2018 at 20:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.