On this page:
1 Topics Covered
2 Extending Embedded Languages
7.8.0.8

Postlude

The focus of these notes is to learn how to program languages the Racket LOP way.

1 Topics Covered

LOP is a range of ideas, all of which build on one central mechanism in Racket:

language extension via define-syntax

We covered this idea for three sessions: Language Extensions.

With language extension, we can then realize a number of things:

kind of language

     

when covered

module-level languages

     

Module Languages

fine-grained embedded languages

     

Embedded Languages

extensible embedded languages

     

see below

To get you started, we presented you with a rough model of macro expansion (A Simple Model):
  • reading (turning char sequences into syntax trees)

  • hooking functions-at-syntax-time into the expander

  • expanding a syntax tree until no nodes refer to macros

From then on, we focused on the language extension and language building:
  • techniques for writing new macros:

  • techniques for raising the level of abstraction:

    • various flavors of syntax classes

  • lexical scope and preserving it by default:

    • lexical scope of the underlying language

    • lexical scope as the default for macros (textual substitution breaks all of this)

    • breaking lexical scope with datum->syntax

  • different lexical scope with parameters

  • building a module-level language in Racket

    • modules can export and import macros

    • the language is the first import and it provides the meaning for everything in foo for (module name language-name foo)

    • in particular, the language must define #%module-begin, which determines the meaning of the rest of the module

    • there are more interposition points: #%app, #%top, #%datum

  • with #lang languages we can build languages from scratch, restrict existing languages, extend one, and do all of the above.

  • build typed module languages

  • build simple expression-level embedded languages.

2 Extending Embedded Languages

At this point, you might think that Racket has solved all problems of language-oriented programming but this is not the case. Much remains to be done.

Over the years, we have time and again encountered situations where embedded languages, such as the one you worked on this morning, themselves call for syntactic extensibility. We constructed those capabilities on an ad hoc basis:

  • On Monday morning, we briefly showed our way of extending the language of match patterns. See Extending match.

  • Matthew used a good bit of the embedded language of providing and requiring across module boundaries. See provide Macros and require Macros for the documentation on how to extend those languages.

  • As you may know, Racket comes with a web server that has an embedded language for dispatching from requests to places in the web server’s world. See Extending web-server/dispatch for ways of extending this DSL.

Turnstile in some ways fits this pattern, too, but it also differs from the above.

Then again, you have seen embedded languages or even built some that you might wish to extend syntactically and you can’t:

Building syntactic extensibility into an embedded domain-specific language is non-trivial. We can do it but our tools for doing so are not ready for prime time. In a year from now or so, they will be. And then you will be more than welcome to attend a RacketSchool again and learn all about.