about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Readme.md67
-rw-r--r--example1.mu4
-rw-r--r--factorial.mu7
-rw-r--r--html/example1.pngbin0 -> 9364 bytes
-rw-r--r--html/f2c-1.pngbin0 -> 23711 bytes
-rw-r--r--html/f2c-2.pngbin0 -> 25218 bytes
-rw-r--r--tangle.mu7
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 [