## Grammar
-The grammar of Thun is very simple. A Thun expression is zero or more Thun
-terms separated by blanks. Terms can be integers in decimal notation,
-Booleans `true` and `false`, lists enclosed by square brackets `[` and `]`,
-or symbols (names of functions.)
+The grammar of Thun is very simple. A Thun expression is zero or more
+Thun terms separated by blanks. Terms can be integers in decimal
+notation, Booleans `true` and `false`, lists enclosed by square brackets
+`[` and `]`, or symbols (names of functions.)
joy ::= term*
term ::= integer | bool | '[' joy ']' | symbol
- integer ::= [ '-' ] ('0'...'9')+
+ integer ::= 0 | [ '-' ] ('1'...'9') ('0'...'9')*
bool ::= 'true' | 'false'
That's it. That's the whole of the grammar.
+![Thun Grammar Railroad Diagram](https://git.sr.ht/~sforman/Thun/blob/trunk/docs/html/images/grammar.png)
+
+
## Types
The original Joy has several datatypes (such as strings and sets)
## Literals, Functions, Combinators
-Terms in Thun can be categorized into literal, simple functions that
-operate on the stack only, and combinators that can prepend quoted
-programs onto the pending expression ("continuation").
+Terms in Thun can be categorized into **literals**, simple **functions**
+that operate on the stack only, and **combinators** that can prepend
+quoted programs onto the pending expression ("continuation").
### Literals
Literal values (integers, Booleans, lists) are put onto the stack.
+Literals can be thought of as functions that put accept a stack and
+return it with the value they denote on top, if you like.
### Functions
-Functions take values from the stack and push results onto it.
+Functions take values from the stack and push results onto it. There are
+a few kinds of functions: math, comparison, list and stack manipulation.
### Combinators
__Combinators__ are functions which accept quoted programs on the stack
-and run them in various ways. These combinators reify specific
-control-flow patterns (such as `ifte` which is like `if.. then.. else..`
-in other languages.) Combinators receive the current expession in
-addition to the stack and return the next expression. They work by
-changing the pending expression the interpreter is about to execute.
+and run them in various ways by prepending them (or not) to the pending
+expression. These combinators reify specific control-flow patterns (such
+as `ifte` which is like `if.. then.. else..` in other languages.)
+Combinators receive the current expession in addition to the stack and
+return the next expression. They work by changing the pending expression
+the interpreter is about to execute.
### Basis Functions
derivation seems to lead to bug-free code, which is the kinda the point.)
+### Variations between Interpreters
+
+There are several small choices to be made when implementing a Thun
+interpreter (TODO: make a comprehensive list), for example, the Python
+interpreter keeps all of its functions in one dictionary but most of the
+other interpreters have a `case` or `switch` statement for the built-in
+functions and a separate hash table for definitions. Additionally, of
+the interpreters that have hash tables most of them check the hash table
+after the `case` statement. This means that one cannot "shadow" built-in
+functions is some interpreters. You can `inscribe` them, but the
+interpreter will not look for them.
+
+I haven't yet formally made a decision for how Thun *shall* work.
+Letting built-ins be shadowed is fun and useful for exploration, and
+letting them be inviolate is useful for unsurprising behaviour.
+
+Another choice is how to handle duplicate definitions in general. Should
+you be able to reuse a name? Or should `inscribe` throw some sort of
+error if you try?
+
+
+
--------------------------------------------------
Copyright © 2014 - 2023 Simon Forman