about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-10-26 23:12:57 -0700
committerKartik K. Agaram <vc@akkartik.com>2021-10-26 23:14:36 -0700
commitc7dde8d8b4338d478fc61c4a8ea5e1c84bf5513e (patch)
tree62a083cd61861ea57568986682d75f941d4972a0
parent5713eb7302a11af489faeb3172cc376398db57e0 (diff)
downloadmu-c7dde8d8b4338d478fc61c4a8ea5e1c84bf5513e.tar.gz
task: primitive statements vs function calls
-rw-r--r--mu.md8
-rw-r--r--tutorial/index.md66
-rw-r--r--tutorial/task8a.mu10
-rw-r--r--tutorial/task8b.mu8
-rw-r--r--tutorial/task8c.mu7
5 files changed, 98 insertions, 1 deletions
diff --git a/mu.md b/mu.md
index 4c2f5226..f5401f58 100644
--- a/mu.md
+++ b/mu.md
@@ -7,7 +7,7 @@ Mu programs are sequences of `fn` and `type` definitions.
 Define functions with the `fn` keyword. For example:
 
 ```
-  fn foo arg1: int, arg2: int -> result/eax: boolean
+  fn foo arg1: int, arg2: int -> _/eax: boolean
 ```
 
 Functions contain `{}` blocks, `var` declarations, primitive statements and
@@ -36,6 +36,12 @@ Primitives can often write to arbitrary output registers. User-defined
 functions, however, require rigidly specified output registers. Notice how the
 definition of `foo` above writes to `eax`.
 
+A function's header names its inouts, but not its outputs (hence the `_`
+above).
+
+All Mu programs must define at least one function: `main`. That's where they
+begin executing instructions.
+
 ## Variables, registers and memory
 
 Declare local variables in a function using the `var` keyword. As shown above,
diff --git a/tutorial/index.md b/tutorial/index.md
index 1dbc0d4b..72917533 100644
--- a/tutorial/index.md
+++ b/tutorial/index.md
@@ -288,6 +288,72 @@ var x/edx: int <- copy 0
 Run `translate` (or `translate_emulated`) as usual. Use your runbook from Task
 6 to address the errors that arise.
 
+## Task 8: primitive statements vs function calls
+
+Managing variables in memory vs register is one of two key skills to
+programming in Mu. The second key skill is calling primitives (which are
+provided by the x86 instruction set) vs functions (which are defined in terms
+of primitives).
+
+To prepare for this task, reread the very first section of the Mu reference,
+on [functions and function calls](https://github.com/akkartik/mu/blob/main/mu.md#functions).
+
+Now look at the following programs. In each case, write down whether you
+expect translation to return any errors and why.
+
+```
+fn f a: int {
+}
+
+fn main {
+  f 0
+  var r/eax: int <- copy 3
+  f r
+  var m: int
+  f m
+}
+```
+
+(When you're ready, try the above program out as `./translate tutorial/task8a.mu`.)
+
+```
+fn f -> _/eax: int {
+  var result/ecx: int <- copy 0
+  return result
+}
+
+fn main {
+  var x/eax: int <- f
+}
+```
+
+(When you're ready, try the above program out as `./translate tutorial/task8b.mu`.)
+
+
+```
+fn f -> _/eax: int {
+  return 3
+}
+
+fn main {
+  var x/ecx: int <- f
+}
+```
+
+(When you're ready, try the above program out as `./translate tutorial/task8c.mu`.)
+
+Functions have fewer restrictions than primitives on inouts, but more
+restrictions on outputs. Inouts can be registers, or memory, or even literals.
+This is why the first example above is legal. Outputs, however, _must_
+hard-code specific registers, and function calls must write their outputs to
+matching registers. This is why the third example above is illegal.
+
+One subtlety here is that we only require agreement on output registers
+between function call and function header. We don't actually have to `return`
+the precise register a function header specifies. The return value can even be
+a literal integer or in memory somewhere. The `return` is really just a `copy`
+to the appropriate register(s). This is why the second example above is legal.
+
 ## Task 9: operating with fractional numbers
 
 All our variables so far have had type `int` (integer), but there are limits
diff --git a/tutorial/task8a.mu b/tutorial/task8a.mu
new file mode 100644
index 00000000..bba989f7
--- /dev/null
+++ b/tutorial/task8a.mu
@@ -0,0 +1,10 @@
+fn f a: int {
+}
+
+fn main {
+  f 0
+  var r/eax: int <- copy 3
+  f r
+  var m: int
+  f m
+}
diff --git a/tutorial/task8b.mu b/tutorial/task8b.mu
new file mode 100644
index 00000000..888f01ec
--- /dev/null
+++ b/tutorial/task8b.mu
@@ -0,0 +1,8 @@
+fn f -> _/eax: int {
+  var result/ecx: int <- copy 0
+  return result
+}
+
+fn main {
+  var x/eax: int <- f
+}
diff --git a/tutorial/task8c.mu b/tutorial/task8c.mu
new file mode 100644
index 00000000..68d90c9a
--- /dev/null
+++ b/tutorial/task8c.mu
@@ -0,0 +1,7 @@
+fn f -> _/eax: int {
+  return 3
+}
+
+fn main {
+  var x/ecx: int <- f
+}