diff options
-rw-r--r-- | Readme.md | 67 | ||||
-rw-r--r-- | example1.mu | 4 | ||||
-rw-r--r-- | factorial.mu | 7 | ||||
-rw-r--r-- | html/example1.png | bin | 0 -> 9364 bytes | |||
-rw-r--r-- | html/f2c-1.png | bin | 0 -> 23711 bytes | |||
-rw-r--r-- | html/f2c-2.png | bin | 0 -> 25218 bytes | |||
-rw-r--r-- | tangle.mu | 7 |
7 files changed, 72 insertions, 13 deletions
diff --git a/Readme.md b/Readme.md index 112d9ebe..9eb5761f 100644 --- a/Readme.md +++ b/Readme.md @@ -75,9 +75,18 @@ Running Mu will always recompile it if necessary: $ ./mu ``` -As a sneak peek, here's how you compute factorial in Mu: +As a sneak peek, here's how you perform some simple arithmetic: -<img alt='code example' src='html/factorial.png' width='330px'> + ```nim + recipe example1 [ + a:number <- add 2, 2 + a <- multiply a, 3 + ] + ``` + +But it's easier to read in color: + +<img alt='code example' src='html/example1.png' width='188px'> Mu functions or 'recipes' are lists of instructions, one to a line. Each instruction operates on some *ingredients* and returns some *products*. @@ -96,15 +105,63 @@ you can perform integer division as follows: Each reagent can provide a name as well as its type separated by a colon. You only have to specify the type the first time you mention a name, but you can -be more explicit if you choose. Types can be multiple words, like: +be more explicit if you choose. Types can be multiple words and even arbitrary +trees, like: ```nim x:array:number:3 # x is an array of 3 numbers y:list:number # y is a list of numbers + # without syntactic sugar + {z: (map (address array character) (list number))} # map from string to list of numbers + ``` + +Try out the program now: + + ```shell + $ ./mu example1.mu + $ ``` -Recipes load their ingredients from their caller using the *next-ingredient* -instruction, and return products using *reply*. +Not much to see yet, since it doesn't print anything. To print the result, try +adding the instruction `$print a` to the recipe. + +--- + +Here's a second example, of a recipe that can take ingredients: + +<img alt='fahrenheit to celsius' src='html/f2c-1.png' width='426px'> + +Recipes can specify headers showing their expected ingredients and products, +separated by '->' (unlike the '<-' in *calls*). + +Since mu is a low-level VM language, it provides extra control at the cost of +verbosity. You have explicit control over stack frames to isolate your recipes +(in a type-safe manner; more on that below), but you have to explicitly +`load-ingredients` after you set up the stack. + +An alternative syntax is what the above example is converted to internally: + +<img alt='fahrenheit to celsius desugared' src='html/f2c-2.png' width='426px'> + +The header gets dropped after checking types at call-sites, and after +replacing `load-ingredients` with explicit instructions to load each +ingredient separately, and to explicitly return products to the caller. After +this translation recipes are once again just lists of instructions. + +This alternative syntax isn't just an implementation detail. I've actually +found it easier to teach functions to non-programmers by starting with this +syntax, so that they can see the names of variables gradually transition from +caller to callee. + +--- + +A third example, this time illustrating conditionals: + +<img alt='factorial example' src='html/factorial.png' width='330px'> + +In spite of how it looks, this is still just a list of instructions. +Internally, the instructions `break` and `loop` get converted to `jump` +instructions to after the enclosing `}` or `{`, respectively. Try out the factorial program now: diff --git a/example1.mu b/example1.mu new file mode 100644 index 00000000..42401e3a --- /dev/null +++ b/example1.mu @@ -0,0 +1,4 @@ +recipe example1 [ + a:number <- add 2, 2 + a <- multiply a, 3 +] diff --git a/factorial.mu b/factorial.mu index 31b2f63c..02a4e2b0 100644 --- a/factorial.mu +++ b/factorial.mu @@ -7,9 +7,9 @@ recipe main [ ] ] -recipe factorial [ +recipe factorial n:number -> result:number [ local-scope - n:number <- next-ingredient + load-ingredients { # if n=0 return 1 zero?:boolean <- equal n, 0 @@ -19,8 +19,7 @@ recipe factorial [ # return n * factorial(n-1) x:number <- subtract n, 1 subresult:number <- factorial x - result:number <- multiply subresult, n - reply result + result <- multiply subresult, n ] # unit test diff --git a/html/example1.png b/html/example1.png new file mode 100644 index 00000000..980d4a08 --- /dev/null +++ b/html/example1.png Binary files differdiff --git a/html/f2c-1.png b/html/f2c-1.png new file mode 100644 index 00000000..745eb0f3 --- /dev/null +++ b/html/f2c-1.png Binary files differdiff --git a/html/f2c-2.png b/html/f2c-2.png new file mode 100644 index 00000000..250d6158 --- /dev/null +++ b/html/f2c-2.png Binary files differdiff --git a/tangle.mu b/tangle.mu index 88722185..8b989957 100644 --- a/tangle.mu +++ b/tangle.mu @@ -6,9 +6,9 @@ # This isn't a very tasteful example, just a simple demonstration of # possibilities. -recipe factorial [ +recipe factorial n:number -> result:number [ local-scope - n:number <- next-ingredient + load-ingredients { <base-case> } @@ -26,8 +26,7 @@ after <recursive-case> [ # return n * factorial(n - 1) x:number <- subtract n, 1 subresult:number <- factorial x - result:number <- multiply subresult, n - reply result + result <- multiply subresult, n ] recipe main [ |