I am feeling physically bad and the game jam sold out so I'm listening to techno and turning my experimental LISP ( https://mastodon.social/@mcc/114308850669653826 ) into an assembly language
I had this thought. Imagine you have three steps in your LISP
- Reader
- Macro expansion
- Evaluator
The output of the reader and macro expansion steps are data structures. In a previous language, I swapped out the evaluator for a compiler, operating on that data structure.
What if you could swap the evaluator for "anything"?
The reason I started writing my experimental LISP was I tried TCL and wanted a "more TCL-like" LISP. One reason I was captivated by TCL was you could, in principle ( https://mastodon.social/@mcc/114004547252159909 ) use it as a text templating language, to generate some entirely non-TCL type of text (HTML, verilog, idk). So this feels like the completion of that thought: Since this is an array manipulation language rather than a text manipulation language, output arrays of symbols, and those get consumed by "something"
I was aiming this way from the start, because a thing that captivated me about TCL is you can sorta use it as a template language ( https://mastodon.social/@mcc/114004547252159909 ) to generate other text (HTML,Verilog,idk). This is the (obvious in retrospect?) completion of that thought: I made a LISP, so a *list* processor not a text processor, so obviously the output gets fed to things (like an assembler?) that consumes lists (in this case, lines of an assembly language (for which my LISP becomes a macro language)).
I have a rule my LISP has "no special forms", so to make any of this work I'm borrowing a Rustism and saying in my language
(function! x y z)
invokes a macro named "function" with arguments x y z passed to it as un-evaluated symbol trees.
Paired with this, !varname or !(expression here) are symbols/code evaluated at "compile time".
This feels clean enough, though it introduces the oddness there are *separate* runtime and compile-time scopes, and it will get VERY weird once I introduce types.
@mcc I'm confused because what you describe is *exactly*, **precisely** the way that special forms are implemented in Common Lisp?!
@krans This is *very* interesting to learn and my thoughts are
1. "No special forms, unless the form name is explicitly delineated with !" is a great rule, as far as I'm concerned.
2. I have a mode where you can turn off the macros, so a "no special forms" mode persists
@mcc Is the “!” a compile time operator, or part of the transformer's name?
@mcc I.e. can I call the transformers as regular functions without the “!”?
@krans 1. The `!` is a compile time directive to the reader, producing a special Macro() node in the AST, which is removed in a particular compile phase.
2. The ! functions are pulled from a special compile-time scope, so yes, although in the final form of the language you may have to import them from `langtools.macro` or something.