|
@@ -0,0 +1,91 @@
|
|
|
|
+**Matzo** is my first attempt at a language designed for creating random text fragments, now reimplemented in Rust.
|
|
|
|
+
|
|
|
|
+(The earlier versions were Haskell and JavaScript, and both have bit-rotted rather badly: I'm hoping that this version is both cleaner—on account of my writing it a decade later—and also that this version is easier to modify and will be more resilient to bit-rot.)
|
|
|
|
+
|
|
|
|
+## Matzo basics
|
|
|
|
+
|
|
|
|
+There are two basic kinds of statements: assignment and printing. Assignment is usually done with `:=`. All statements are terminated with a semicolon (although the REPL will usually tolerate you leaving it off.)
|
|
|
|
+
|
|
|
|
+```
|
|
|
|
+greeting := "hello";
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+Printing statements are written with `puts`.
|
|
|
|
+
|
|
|
|
+```
|
|
|
|
+puts greeting; (* prints "hello" *)
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+The two most common operations are catenation and choice. Catenation is indicated by simply putting expressions next to each other:
|
|
|
|
+
|
|
|
|
+```
|
|
|
|
+puts "Hello" " " "world!";
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+Choice is indicated by putting vertical bars between various choices.
|
|
|
|
+
|
|
|
|
+```
|
|
|
|
+puts "Hello!" | "Hey!" | "Yo!";
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+Catenation binds more tightly than choice, but parentheses can explicitly group operations.
|
|
|
|
+
|
|
|
|
+```
|
|
|
|
+puts ("Bonjour" | "Buenos dias") ", world!";
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+Choices can also be weighted by using a number and `:`. In the following example, there's a 1/6 chance of getting `"tails"`, and a 5/6 chance of getting `"heads"`:
|
|
|
|
+
|
|
|
|
+```
|
|
|
|
+puts 5: "heads" | "tails";
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+Since it's quite common to want to choose from some basic string literals, there's a special case for that: the `::=` operator allows you to list zero or more space-separated identifiers, and then it will treat them as strings and choose between them with equal weight.
|
|
|
|
+
|
|
|
|
+```
|
|
|
|
+suits ::= hearts diamonds clubs spades;
|
|
|
|
+(* this is equivalent to writing
|
|
|
|
+ suits := "hearts" | "diamonds" | "clubs" | "spades";
|
|
|
|
+*)
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+Importantly, definitions in Matzo are _lazy_: if something is defined as a choice between alternatives, then every use of that thing has a chance of choosing a different alternative.
|
|
|
|
+
|
|
|
|
+```
|
|
|
|
+letter ::= a b;
|
|
|
|
+(* this might print any of aa, ab, ba, bb *)
|
|
|
|
+puts letter letter;
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+Matzo also allows you to _fix_ definitions, which will evaluate them once and use that version for every subsequent reference. There are two ways of doing this: one is to prefix the assignment with the `fix` keyword:
|
|
|
|
+
|
|
|
|
+```
|
|
|
|
+fix letter ::= a b;
|
|
|
|
+(* this can only print aa or bb *)
|
|
|
|
+puts letter letter;
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+The other is to use `fix` as a standalone statement, which modifies a definition in-scope by fixing it.
|
|
|
|
+
|
|
|
|
+```
|
|
|
|
+letter ::= a b;
|
|
|
|
+puts letter letter; (* aa, ab, ba, or bb *)
|
|
|
|
+fix letter;
|
|
|
|
+puts letter letter; (* aa or bb *)
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+## Fancier Matzo
|
|
|
|
+
|
|
|
|
+- Data types (atoms, tuples)
|
|
|
|
+- Functions
|
|
|
|
+- Pattern-matching
|
|
|
|
+
|
|
|
|
+## Implementation notes
|
|
|
|
+
|
|
|
|
+## Todo
|
|
|
|
+
|
|
|
|
+- [ ] Pattern matching
|
|
|
|
+- [ ] Closures
|
|
|
|
+- [ ] Expand the stdlib
|
|
|
|
+- [ ] Switch to packed expr representation for easier sharing
|
|
|
|
+- [ ] Think about how to express GC
|