about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-06-21 14:46:08 -0700
committerKartik Agaram <vc@akkartik.com>2020-06-21 14:46:08 -0700
commit056858ddd9d2dd9dbaeddf2cb0579184161417c4 (patch)
treee5e010d8613ecabc7c56e3d0e1acba831984eaeb
parent85eb81672548f8be71b6a51f3267afcd9f132489 (diff)
downloadmu-056858ddd9d2dd9dbaeddf2cb0579184161417c4.tar.gz
6566 - improve some error messages
I need to pass the function around to fix the failing test; might as well
fix the error messages while I'm at it.
-rw-r--r--apps/mu.subx276
1 files changed, 165 insertions, 111 deletions
diff --git a/apps/mu.subx b/apps/mu.subx
index 370faa35..553b3a21 100644
--- a/apps/mu.subx
+++ b/apps/mu.subx
@@ -1159,7 +1159,7 @@ test-read-clobbered-reg-var:
 #?     # }}}
     # check output
     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
-    (check-next-stream-line-equal _test-error-stream  "register ecx reads var 'x' after writing var 'y'"  "F - test-read-clobbered-reg-var: error message")
+    (check-next-stream-line-equal _test-error-stream  "fn foo: register ecx reads var 'x' after writing var 'y'"  "F - test-read-clobbered-reg-var: error message")
     # check that stop(1) was called
     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
     # don't restore from ebp
@@ -1263,7 +1263,7 @@ test-convert-function-call-with-incorrect-inout-type:
 #?     # }}}
     # check output
     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
-    (check-next-stream-line-equal _test-error-stream  "call g: type for inout 'x' is not right"  "F - test-convert-function-call-with-incorrect-inout-type: error message")
+    (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for inout 'x' is not right"  "F - test-convert-function-call-with-incorrect-inout-type: error message")
     # check that stop(1) was called
     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
     # don't restore from ebp
@@ -1308,7 +1308,7 @@ test-convert-function-call-with-too-few-inouts:
 #?     # }}}
     # check output
     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
-    (check-next-stream-line-equal _test-error-stream  "call g: too few inouts"  "F - test-convert-function-call-with-too-few-inouts: error message")
+    (check-next-stream-line-equal _test-error-stream  "fn f: call g: too few inouts"  "F - test-convert-function-call-with-too-few-inouts: error message")
     # check that stop(1) was called
     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
     # don't restore from ebp
@@ -1354,7 +1354,7 @@ test-convert-function-call-with-too-many-inouts:
 #?     # }}}
     # check output
     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-inouts: output should be empty")
-    (check-next-stream-line-equal _test-error-stream  "call g: too many inouts"  "F - test-convert-function-call-with-too-many-inouts: error message")
+    (check-next-stream-line-equal _test-error-stream  "fn f: call g: too many inouts"  "F - test-convert-function-call-with-too-many-inouts: error message")
     # check that stop(1) was called
     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
     # don't restore from ebp
@@ -1399,7 +1399,7 @@ test-convert-function-call-with-incorrect-output-type:
 #?     # }}}
     # check output
     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
-    (check-next-stream-line-equal _test-error-stream  "call g: type for output 'x' is not right"  "F - test-convert-function-call-with-incorrect-output-type: error message")
+    (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for output 'x' is not right"  "F - test-convert-function-call-with-incorrect-output-type: error message")
     # check that stop(1) was called
     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
     # don't restore from ebp
@@ -1444,7 +1444,7 @@ test-convert-function-call-with-too-few-outputs:
 #?     # }}}
     # check output
     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
-    (check-next-stream-line-equal _test-error-stream  "call g: too few outputs"  "F - test-convert-function-call-with-too-few-outputs: error message")
+    (check-next-stream-line-equal _test-error-stream  "fn f: call g: too few outputs"  "F - test-convert-function-call-with-too-few-outputs: error message")
     # check that stop(1) was called
     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
     # don't restore from ebp
@@ -1489,7 +1489,7 @@ test-convert-function-call-with-too-many-outputs:
 #?     # }}}
     # check output
     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
-    (check-next-stream-line-equal _test-error-stream  "call g: too many outputs"  "F - test-convert-function-call-with-too-many-outputs: error message")
+    (check-next-stream-line-equal _test-error-stream  "fn f: call g: too many outputs"  "F - test-convert-function-call-with-too-many-outputs: error message")
     # check that stop(1) was called
     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
     # don't restore from ebp
@@ -1534,7 +1534,7 @@ test-convert-function-call-with-incorrect-output-register:
 #?     # }}}
     # check output
     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
-    (check-next-stream-line-equal _test-error-stream  "call g: register for output 'x' is not right"  "F - test-convert-function-call-with-incorrect-output-register: error message")
+    (check-next-stream-line-equal _test-error-stream  "fn f: call g: register for output 'x' is not right"  "F - test-convert-function-call-with-incorrect-output-register: error message")
     # check that stop(1) was called
     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
     # don't restore from ebp
@@ -1771,7 +1771,7 @@ test-unknown-variable:
 #?     # }}}
     # check output
     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
-    (check-next-stream-line-equal _test-error-stream  "unknown variable 'x'"  "F - test-unknown-variable: error message")
+    (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
     # check that stop(1) was called
     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
     # don't restore from ebp
@@ -1917,7 +1917,7 @@ test-unknown-variable-in-named-block:
 #?     # }}}
     # check output
     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
-    (check-next-stream-line-equal _test-error-stream  "unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
+    (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
     # check that stop(1) was called
     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
     # don't restore from ebp
@@ -7245,7 +7245,7 @@ parse-mu-var-def:  # line: (addr stream byte), vars: (addr stack live-var), out:
       #
       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
       (lookup *edi *(edi+4))  # => eax
-      (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
+      (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
     }
 $parse-mu-var-def:update-vars:
     # push 'v' at end of function
@@ -7484,7 +7484,7 @@ $parse-mu-stmt:read-outputs:
         e9/jump loop/disp32
       }
     }
-    (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
+    (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
 $parse-mu-stmt:define-outputs:
     # var output/edi: (addr stmt-var) = lookup(out-addr->outputs)
     (lookup *(edi+0x14) *(edi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
@@ -7526,7 +7526,7 @@ $parse-mu-stmt:abort:
     (stop *(ebp+0x1c) 1)
     # never gets here
 
-add-operation-and-inputs-to-stmt:  # stmt: (addr stmt), line: (addr stream byte), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
+add-operation-and-inputs-to-stmt:  # stmt: (addr stmt), line: (addr stream byte), vars: (addr stack live-var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
     # pseudocode:
     #   stmt->name = slice-to-string(next-mu-token(line))
     #   while true
@@ -7608,7 +7608,7 @@ $add-operation-and-inputs-to-stmt:inout-is-deref:
         ff 0/subop/increment *ecx
         ba/copy-to-edx 1/imm32/true
       }
-      (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18))
+      (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
 $add-operation-and-inputs-to-stmt:save-var:
       8d/copy-address *(edi+0xc) 0/r32/eax
       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
@@ -7631,13 +7631,17 @@ $add-operation-and-inputs-to-stmt:end:
     c3/return
 
 $add-operation-and-inputs-to-stmt:abort:
-    # error("invalid statement '" line "'\n")
-    (rewind-stream *(ebp+8))
-    (write-buffered *(ebp+0x14) "invalid identifier '")
-    (write-stream-data *(ebp+0x14) *(ebp+8))
-    (write-buffered *(ebp+0x14) "'\n")
-    (flush *(ebp+0x14))
-    (stop *(ebp+0x18) 1)
+    # error("fn ___: invalid identifier in '" line "'\n")
+    (write-buffered *(ebp+0x18) "fn ")
+    8b/-> *(ebp+0x14) 0/r32/eax
+    (lookup *eax *(eax+4))  # Function-name Function-name => eax
+    (write-buffered *(ebp+0x18) %eax)
+    (rewind-stream *(ebp+0xc))
+    (write-buffered *(ebp+0x18) ": invalid identifier in '")
+    (write-stream-data *(ebp+0x18) *(ebp+0xc))
+    (write-buffered *(ebp+0x18) "'\n")
+    (flush *(ebp+0x18))
+    (stop *(ebp+0x1c) 1)
     # never gets here
 
 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
@@ -7688,7 +7692,7 @@ $stmt-has-outputs:end:
 
 # if 'name' starts with a digit, create a new literal var for it
 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
-lookup-var-or-literal:  # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), err: (addr buffered-file), ed: (addr exit-descriptor)
+lookup-var-or-literal:  # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
@@ -7712,7 +7716,7 @@ lookup-var-or-literal:  # name: (addr slice), vars: (addr stack live-var), out:
       3d/compare-eax-and 0/imm32/false
       74/jump-if-= break/disp8
 $lookup-var-or-literal:literal:
-      (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
+      (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
       eb/jump $lookup-var-or-literal:end/disp8
     }
     # else if (c == '"') return new var(name)
@@ -7726,7 +7730,7 @@ $lookup-var-or-literal:literal-string:
     # otherwise return lookup-var(name, vars)
     {
 $lookup-var-or-literal:var:
-      (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
+      (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
     }
 $lookup-var-or-literal:end:
     # . restore registers
@@ -7739,20 +7743,24 @@ $lookup-var-or-literal:end:
     c3/return
 
 $lookup-var-or-literal:abort:
-    (write-buffered *(ebp+0x14) "empty variable!")
-    (flush *(ebp+0x14))
-    (stop *(ebp+0x18) 1)
+    (write-buffered *(ebp+0x18) "fn ")
+    8b/-> *(ebp+0x14) 0/r32/eax
+    (lookup *eax *(eax+4))  # Function-name Function-name => eax
+    (write-buffered *(ebp+0x18) %eax)
+    (write-buffered *(ebp+0x18) ": empty variable!")
+    (flush *(ebp+0x18))
+    (stop *(ebp+0x1c) 1)
     # never gets here
 
 # return first 'name' from the top (back) of 'vars' and abort if not found
-lookup-var:  # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), err: (addr buffered-file), ed: (addr exit-descriptor)
+lookup-var:  # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
     # . save registers
     50/push-eax
     #
-    (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
+    (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
     # if (*out == 0) abort
     8b/-> *(ebp+0x10) 0/r32/eax
     81 7/subop/compare *eax 0/imm32
@@ -7766,16 +7774,20 @@ $lookup-var:end:
     c3/return
 
 $lookup-var:abort:
-    (write-buffered *(ebp+0x14) "unknown variable '")
-    (write-slice-buffered *(ebp+0x14) *(ebp+8))
-    (write-buffered *(ebp+0x14) "'\n")
-    (flush *(ebp+0x14))
-    (stop *(ebp+0x18) 1)
+    (write-buffered *(ebp+0x18) "fn ")
+    8b/-> *(ebp+0x14) 0/r32/eax
+    (lookup *eax *(eax+4))  # Function-name Function-name => eax
+    (write-buffered *(ebp+0x18) %eax)
+    (write-buffered *(ebp+0x18) ": unknown variable '")
+    (write-slice-buffered *(ebp+0x18) *(ebp+8))
+    (write-buffered *(ebp+0x18) "'\n")
+    (flush *(ebp+0x18))
+    (stop *(ebp+0x1c) 1)
     # never gets here
 
 # return first 'name' from the top (back) of 'vars', and 0/null if not found
 # ensure that 'name' if in a register is the topmost variable in that register
-lookup-var-helper:  # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), err: (addr buffered-file), ed: (addr exit-descriptor)
+lookup-var-helper:  # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
     # pseudocode:
     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
     #   var min = vars->data
@@ -7893,28 +7905,38 @@ $lookup-var-helper:end:
     c3/return
 
 $lookup-var-helper:error1:
-    (write-buffered *(ebp+0x14) "malformed stack when looking up '")
-    (write-slice-buffered *(ebp+0x14) *(ebp+8))
-    (write-buffered *(ebp+0x14) "'\n")
-    (flush *(ebp+0x14))
-    (stop *(ebp+0x18) 1)
+    (write-buffered *(ebp+0x18) "fn ")
+    8b/-> *(ebp+0x14) 0/r32/eax
+    (lookup *eax *(eax+4))  # Function-name Function-name => eax
+    (write-buffered *(ebp+0x18) %eax)
+    (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
+    (write-slice-buffered *(ebp+0x18) *(ebp+8))
+    (write-buffered *(ebp+0x18) "'\n")
+    (flush *(ebp+0x18))
+    (stop *(ebp+0x1c) 1)
     # never gets here
 
 $lookup-var-helper:error2:
     # eax contains the conflicting var at this point
-    (write-buffered *(ebp+0x14) "register ")
+    (write-buffered *(ebp+0x18) "fn ")
+    50/push-eax
+    8b/-> *(ebp+0x14) 0/r32/eax
+    (lookup *eax *(eax+4))  # Function-name Function-name => eax
+    (write-buffered *(ebp+0x18) %eax)
+    58/pop-eax
+    (write-buffered *(ebp+0x18) ": register ")
     50/push-eax
     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
-    (write-buffered *(ebp+0x14) %eax)
+    (write-buffered *(ebp+0x18) %eax)
     58/pop-to-eax
-    (write-buffered *(ebp+0x14) " reads var '")
-    (write-slice-buffered *(ebp+0x14) *(ebp+8))
-    (write-buffered *(ebp+0x14) "' after writing var '")
+    (write-buffered *(ebp+0x18) " reads var '")
+    (write-slice-buffered *(ebp+0x18) *(ebp+8))
+    (write-buffered *(ebp+0x18) "' after writing var '")
     (lookup *eax *(eax+4))  # Var-name Var-name => eax
-    (write-buffered *(ebp+0x14) %eax)
-    (write-buffered *(ebp+0x14) "'\n")
-    (flush *(ebp+0x14))
-    (stop *(ebp+0x18) 1)
+    (write-buffered *(ebp+0x18) %eax)
+    (write-buffered *(ebp+0x18) "'\n")
+    (flush *(ebp+0x18))
+    (stop *(ebp+0x1c) 1)
     # never gets here
 
 dump-vars:  # vars: (addr stack live-var)
@@ -7989,7 +8011,7 @@ lookup-var-or-find-in-fn-outputs:  # name: (addr slice), vars: (addr stack live-
     # . save registers
     50/push-eax
     #
-    (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
+    (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))  # arg order slightly different; 'fn' is deemphasized
     {
       # if (out != 0) return
       8b/-> *(ebp+0x14) 0/r32/eax
@@ -8302,7 +8324,7 @@ $new-var:end:
     5d/pop-to-ebp
     c3/return
 
-new-literal-integer:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var), err: (addr buffered-file), ed: (addr exit-descriptor)
+new-literal-integer:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
@@ -8340,11 +8362,15 @@ $new-literal-integer:end:
     c3/return
 
 $new-literal-integer:abort:
-    (write-buffered *(ebp+0x14) "variable cannot begin with a digit '")
-    (write-slice-buffered *(ebp+0x14) *(ebp+0xc))
-    (write-buffered *(ebp+0x14) "'\n")
-    (flush *(ebp+0x14))
-    (stop *(ebp+0x18) 1)
+    (write-buffered *(ebp+0x18) "fn ")
+    8b/-> *(ebp+0x14) 0/r32/eax
+    (lookup *eax *(eax+4))  # Function-name Function-name => eax
+    (write-buffered *(ebp+0x18) %eax)
+    (write-buffered *(ebp+0x18) ": variable cannot begin with a digit '")
+    (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
+    (write-buffered *(ebp+0x18) "'\n")
+    (flush *(ebp+0x18))
+    (stop *(ebp+0x1c) 1)
     # never gets here
 
 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
@@ -9726,7 +9752,7 @@ check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr
     # TODO: anything to check in header?
     # var body/eax: (addr block) = lookup(f->body)
     (lookup *(eax+0x18) *(eax+0x1c))  # Function-body Function-body => eax
-    (check-mu-block %eax *(ebp+0xc) *(ebp+0x10))
+    (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
 $check-mu-function:end:
     # . restore registers
     58/pop-to-eax
@@ -9735,7 +9761,7 @@ $check-mu-function:end:
     5d/pop-to-ebp
     c3/return
 
-check-mu-block:  # block: (addr block), err: (addr buffered-file), ed: (addr exit-descriptor)
+check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
@@ -9751,7 +9777,7 @@ $check-mu-block:check-empty:
       3d/compare-eax-and 0/imm32
       0f 84/jump-if-= break/disp32
       # emit block->statements
-      (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10))
+      (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
     }
 $check-mu-block:end:
     # . restore registers
@@ -9761,7 +9787,7 @@ $check-mu-block:end:
     5d/pop-to-ebp
     c3/return
 
-check-mu-stmt-list:  # stmts: (addr list stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
+check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
@@ -9781,7 +9807,7 @@ $check-mu-stmt-list:check-for-block:
         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
         75/jump-if-!= break/disp8
 $check-mu-stmt-list:block:
-        (check-mu-block %eax *(ebp+0xc) *(ebp+0x10))
+        (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
         eb/jump $check-mu-stmt-list:continue/disp8
       }
       {
@@ -9789,7 +9815,7 @@ $check-mu-stmt-list:check-for-stmt1:
         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
         0f 85/jump-if-!= break/disp32
 $check-mu-stmt-list:stmt1:
-        (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10))
+        (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
         eb/jump $check-mu-stmt-list:continue/disp8
       }
       {
@@ -9797,7 +9823,7 @@ $check-mu-stmt-list:check-for-reg-var-def:
         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
         0f 85/jump-if-!= break/disp32
 $check-mu-stmt-list:reg-var-def:
-        (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10))
+        (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
         eb/jump $check-mu-stmt-list:continue/disp8
       }
 $check-mu-stmt-list:continue:
@@ -9815,7 +9841,7 @@ $check-mu-stmt-list:end:
     5d/pop-to-ebp
     c3/return
 
-check-mu-stmt:  # stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
+check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
@@ -9878,16 +9904,20 @@ $check-mu-stmt:check-inout-type:
         3d/compare-eax-and 0/imm32/false
         {
           0f 85/jump-if-!= break/disp32
-          (write-buffered *(ebp+0xc) "call ")
+          (write-buffered *(ebp+0x10) "fn ")
+          8b/-> *(ebp+0xc) 0/r32/eax
+          (lookup *eax *(eax+4))  # Function-name Function-name => eax
+          (write-buffered *(ebp+0x10) %eax)
+          (write-buffered *(ebp+0x10) ": call ")
           (lookup *edi *(edi+4))  # Function-name Function-name => eax
-          (write-buffered *(ebp+0xc) %eax)
-          (write-buffered *(ebp+0xc) ": type for inout '")
+          (write-buffered *(ebp+0x10) %eax)
+          (write-buffered *(ebp+0x10) ": type for inout '")
           (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
           (lookup *eax *(eax+4))  # Var-name Var-name => eax
-          (write-buffered *(ebp+0xc) %eax)
-          (write-buffered *(ebp+0xc) "' is not right\n")
-          (flush *(ebp+0xc))
-          (stop *(ebp+0x10) 1)
+          (write-buffered *(ebp+0x10) %eax)
+          (write-buffered *(ebp+0x10) "' is not right\n")
+          (flush *(ebp+0x10))
+          (stop *(ebp+0x14) 1)
         }
 $check-mu-stmt:continue-to-next-inout:
         # inouts = lookup(inouts->next)
@@ -9905,27 +9935,35 @@ $check-mu-stmt:check-inout-count:
       {
         0f 84/jump-if-= break/disp32
         # exactly one of the two is null
-        # if (inouts == 0) error("too many args")
+        # if (inouts == 0) error("too many inouts")
         {
           81 7/subop/compare %ecx 0/imm32
-          74/jump-if-= break/disp8
-          (write-buffered *(ebp+0xc) "call ")
+          0f 84/jump-if-= break/disp32
+          (write-buffered *(ebp+0x10) "fn ")
+          8b/-> *(ebp+0xc) 0/r32/eax
+          (lookup *eax *(eax+4))  # Function-name Function-name => eax
+          (write-buffered *(ebp+0x10) %eax)
+          (write-buffered *(ebp+0x10) ": call ")
           (lookup *edi *(edi+4))  # Function-name Function-name => eax
-          (write-buffered *(ebp+0xc) %eax)
-          (write-buffered *(ebp+0xc) ": too many inouts\n")
-          (flush *(ebp+0xc))
-          (stop *(ebp+0x10) 1)
+          (write-buffered *(ebp+0x10) %eax)
+          (write-buffered *(ebp+0x10) ": too many inouts\n")
+          (flush *(ebp+0x10))
+          (stop *(ebp+0x14) 1)
         }
-        # if (expected == 0) error("too few args")
+        # if (expected == 0) error("too few inouts")
         {
           81 7/subop/compare %edx 0/imm32
-          74/jump-if-= break/disp8
-          (write-buffered *(ebp+0xc) "call ")
+          0f 84/jump-if-= break/disp32
+          (write-buffered *(ebp+0x10) "fn ")
+          8b/-> *(ebp+0xc) 0/r32/eax
+          (lookup *eax *(eax+4))  # Function-name Function-name => eax
+          (write-buffered *(ebp+0x10) %eax)
+          (write-buffered *(ebp+0x10) ": call ")
           (lookup *edi *(edi+4))  # Function-name Function-name => eax
-          (write-buffered *(ebp+0xc) %eax)
-          (write-buffered *(ebp+0xc) ": too few inouts\n")
-          (flush *(ebp+0xc))
-          (stop *(ebp+0x10) 1)
+          (write-buffered *(ebp+0x10) %eax)
+          (write-buffered *(ebp+0x10) ": too few inouts\n")
+          (flush *(ebp+0x10))
+          (stop *(ebp+0x14) 1)
         }
       }
 $check-mu-stmt:check-outputs:
@@ -9965,16 +10003,20 @@ $check-mu-stmt:check-output-type:
         3d/compare-eax-and 0/imm32/false
         {
           0f 85/jump-if-!= break/disp32
-          (write-buffered *(ebp+0xc) "call ")
+          (write-buffered *(ebp+0x10) "fn ")
+          8b/-> *(ebp+0xc) 0/r32/eax
+          (lookup *eax *(eax+4))  # Function-name Function-name => eax
+          (write-buffered *(ebp+0x10) %eax)
+          (write-buffered *(ebp+0x10) ": call ")
           (lookup *edi *(edi+4))  # Function-name Function-name => eax
-          (write-buffered *(ebp+0xc) %eax)
-          (write-buffered *(ebp+0xc) ": type for output '")
+          (write-buffered *(ebp+0x10) %eax)
+          (write-buffered *(ebp+0x10) ": type for output '")
           (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
           (lookup *eax *(eax+4))  # Var-name Var-name => eax
-          (write-buffered *(ebp+0xc) %eax)
-          (write-buffered *(ebp+0xc) "' is not right\n")
-          (flush *(ebp+0xc))
-          (stop *(ebp+0x10) 1)
+          (write-buffered *(ebp+0x10) %eax)
+          (write-buffered *(ebp+0x10) "' is not right\n")
+          (flush *(ebp+0x10))
+          (stop *(ebp+0x14) 1)
         }
 $check-mu-stmt:check-output-register:
         # var v/eax: (addr v) = lookup(outputs->value)
@@ -9991,16 +10033,20 @@ $check-mu-stmt:check-output-register:
         3d/compare-eax-and 0/imm32/false
         {
           0f 85/jump-if-!= break/disp32
-          (write-buffered *(ebp+0xc) "call ")
+          (write-buffered *(ebp+0x10) "fn ")
+          8b/-> *(ebp+0xc) 0/r32/eax
+          (lookup *eax *(eax+4))  # Function-name Function-name => eax
+          (write-buffered *(ebp+0x10) %eax)
+          (write-buffered *(ebp+0x10) ": call ")
           (lookup *edi *(edi+4))  # Function-name Function-name => eax
-          (write-buffered *(ebp+0xc) %eax)
-          (write-buffered *(ebp+0xc) ": register for output '")
+          (write-buffered *(ebp+0x10) %eax)
+          (write-buffered *(ebp+0x10) ": register for output '")
           (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
           (lookup *eax *(eax+4))  # Var-name Var-name => eax
-          (write-buffered *(ebp+0xc) %eax)
-          (write-buffered *(ebp+0xc) "' is not right\n")
-          (flush *(ebp+0xc))
-          (stop *(ebp+0x10) 1)
+          (write-buffered *(ebp+0x10) %eax)
+          (write-buffered *(ebp+0x10) "' is not right\n")
+          (flush *(ebp+0x10))
+          (stop *(ebp+0x14) 1)
         }
 $check-mu-stmt:continue-to-next-output:
         # outputs = lookup(outputs->next)
@@ -10021,24 +10067,32 @@ $check-mu-stmt:check-output-count:
         # if (outputs == 0) error("too many outputs")
         {
           81 7/subop/compare %ecx 0/imm32
-          74/jump-if-= break/disp8
-          (write-buffered *(ebp+0xc) "call ")
+          0f 84/jump-if-= break/disp32
+          (write-buffered *(ebp+0x10) "fn ")
+          8b/-> *(ebp+0xc) 0/r32/eax
+          (lookup *eax *(eax+4))  # Function-name Function-name => eax
+          (write-buffered *(ebp+0x10) %eax)
+          (write-buffered *(ebp+0x10) ": call ")
           (lookup *edi *(edi+4))  # Function-name Function-name => eax
-          (write-buffered *(ebp+0xc) %eax)
-          (write-buffered *(ebp+0xc) ": too many outputs\n")
-          (flush *(ebp+0xc))
-          (stop *(ebp+0x10) 1)
+          (write-buffered *(ebp+0x10) %eax)
+          (write-buffered *(ebp+0x10) ": too many outputs\n")
+          (flush *(ebp+0x10))
+          (stop *(ebp+0x14) 1)
         }
         # if (expected == 0) error("too few outputs")
         {
           81 7/subop/compare %edx 0/imm32
-          74/jump-if-= break/disp8
-          (write-buffered *(ebp+0xc) "call ")
+          0f 84/jump-if-= break/disp32
+          (write-buffered *(ebp+0x10) "fn ")
+          8b/-> *(ebp+0xc) 0/r32/eax
+          (lookup *eax *(eax+4))  # Function-name Function-name => eax
+          (write-buffered *(ebp+0x10) %eax)
+          (write-buffered *(ebp+0x10) ": call ")
           (lookup *edi *(edi+4))  # Function-name Function-name => eax
-          (write-buffered *(ebp+0xc) %eax)
-          (write-buffered *(ebp+0xc) ": too few outputs\n")
-          (flush *(ebp+0xc))
-          (stop *(ebp+0x10) 1)
+          (write-buffered *(ebp+0x10) %eax)
+          (write-buffered *(ebp+0x10) ": too few outputs\n")
+          (flush *(ebp+0x10))
+          (stop *(ebp+0x14) 1)
         }
       }
     }