1

Since Racket is well-known for his ability to create new programming language, the following shouldn't be too difficult.

I would like to create a subset of Racket (let's name it min) for an educational purpose renaming some function (tail instead of cdr) and ignoring others (such as string=? and = to just have equal?).

The first step I made is to start my min files with #lang s-exp "min.rkt" but I am stuck at the expander stage.

  • Slightly related: https://stackoverflow.com/questions/73074984/defining-a-purely-functional-r5rs-env-in-racket – Felipe Jul 29 '22 at 21:34

1 Answers1

2

The following module is an example of a minimal subset of Racket that allows top-level definitions, constants, and arithmetic using + and *:

;; min.rkt
#lang racket/base
(provide #%module-begin #%top-interaction
         #%app #%datum #%top
         define + *)

Here's what the provides mean:

  • #%module-begin must be provided by a module for that module to be considered a "language"; it determines what a module body means. You can just reuse Racket's module-begin macro. (The #%module-begin export gives you a hook to implement non-local constraints or transformations. For example, if you wanted to add a typechecker or check that variables are defined in alphabetical order, you could do that in the module-begin hook.)
  • #%top-level is necessary for interactive languages. If you leave it out, you can't use a REPL for your language (eg, with racket -t "min.rkt" -i).
  • #%app and #%datum make function application and self-evaluating constants (like numbers and booleans) work.
  • #%top makes forward references work at the REPL, like in mutually-recursive functions. You still must define a name before you evaluate a reference to it, of course.
  • The rest of the exports are the special forms and functions you want to include in your language.

Here's a program in this "min.rkt" language:

#lang s-exp "min.rkt"
(define x 2)
(define y (+ x 5))
(* y 7)
(define (f x) (+ x x 1))
(f 8)

Note that since the language includes Racket's define, it allows function definition, even though the language doesn't include lambda. If you wanted a restricted version of define, you would have to define your own macro and provide it as your language's define, like (provide (rename-out [my-define define])).

You can also use rename-out to provide Racket's cdr as tail, but the procedure would still print as #<procedure:cdr> and if it raised an error the error message would still say cdr. To change that, you'd need to define your own wrapper function that does its own error checking.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Ryan Culpepper
  • 10,495
  • 4
  • 31
  • 30