about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-06-15 17:00:26 -0700
committerKartik Agaram <vc@akkartik.com>2020-06-15 17:13:04 -0700
commitd292196ff5ab9f103364e05c42a1edc03dc1b5ab (patch)
tree2e80472fd9d248f3631903aaf2282f7e0831a075
parent5a6d2d0db7ccc1d6b09ce898e3b57f62a5b1b787 (diff)
downloadmu-d292196ff5ab9f103364e05c42a1edc03dc1b5ab.tar.gz
6529 - don't let `addr`s escape functions
I've gone back and forth on this. I initially disallowed this, then allowed
it because I forgot why I disallowed it. The reason to disallow it: if
you return an `addr` to a variable allocated on the stack, the space might
be reused for a different type, which violates type-safety. And once you
can reinterpret bits of one type as another you lose memory-safety as well.

This has some interesting implications for Mu programs; certain kinds of
helper functions become impossible to write. Now I find myself relying a
lot more on scopes (and editor folding support) for abstracting details.
And they won't help manage duplication. We'll see how this goes.

While I'm being draconian about `addr`s on the stack, I'm still abusing
`addr`s on the heap, with the expectation that future checks on reclamation
will protect me. The boon and bane of stack space is that it's constantly
reclaimed.
-rw-r--r--apps/browse.mu40
-rw-r--r--apps/mu.subx3
2 files changed, 24 insertions, 19 deletions
diff --git a/apps/browse.mu b/apps/browse.mu
index 10dd65b1..4a7ab2c1 100644
--- a/apps/browse.mu
+++ b/apps/browse.mu
@@ -6,9 +6,27 @@
 #
 # Press 'q' to quit. All other keys scroll down.
 
-fn main args: (addr array (addr array byte)) -> exit-status/ebx: int {
-  var filename/eax: (addr array byte) <- first-arg args
-  var file/esi: (addr buffered-file) <- load-file filename
+fn main args-on-stack: (addr array (addr array byte)) -> exit-status/ebx: int {
+  # var file/esi: (addr buffered-file) = open args-on-stack[1] for reading {{{
+  var file/esi: (addr buffered-file) <- copy 0
+  {
+    var file-handle: (handle buffered-file)
+    {
+      var address-of-file-handle/esi: (addr handle buffered-file) <- address file-handle
+      # var filename/ecx: (addr array byte) = args-on-stack[1] {{{
+      var filename/ecx: (addr array byte) <- copy 0
+      {
+        var args/eax: (addr array (addr array byte)) <- copy args-on-stack
+        var tmp/eax: (addr addr array byte) <- index args, 1
+        filename <- copy *tmp
+      }
+      # }}}
+      open filename, 0, address-of-file-handle
+    }
+    var tmp/eax: (addr buffered-file) <- lookup file-handle
+    file <- copy tmp
+  }
+  # }}}
   enable-screen-grid-mode
   var nrows/eax: int <- copy 0
   var ncols/ecx: int <- copy 0
@@ -154,22 +172,6 @@ fn clear toprow: int, leftcol: int, botrow: int, rightcol: int {
   }
 }
 
-fn first-arg args-on-stack: (addr array (addr array byte)) -> out/eax: (addr array byte) {
-  var args/eax: (addr array (addr array byte)) <- copy args-on-stack
-  var result/eax: (addr addr array byte) <- index args, 1
-  out <- copy *result
-}
-
-fn load-file filename: (addr array byte) -> out/esi: (addr buffered-file) {
-  var result: (handle buffered-file)
-  {
-    var tmp1/eax: (addr handle buffered-file) <- address result
-    open filename, 0, tmp1
-  }
-  var tmp2/eax: (addr buffered-file) <- lookup result
-  out <- copy tmp2
-}
-
 fn dump in: (addr buffered-file) {
   var c/eax: byte <- read-byte-buffered in
   compare c, 0xffffffff  # EOF marker
diff --git a/apps/mu.subx b/apps/mu.subx
index 70ad482d..cd08466e 100644
--- a/apps/mu.subx
+++ b/apps/mu.subx
@@ -4638,6 +4638,9 @@ $parse-mu:error2:
 # ✓ fn foo x: int {
 # ✓ fn foo x: int {
 # ✓ fn foo x: int -> y/eax: int {
+# TODO:
+#   disallow outputs of type `(... addr ...)`
+#   disallow inputs of type `(... addr ... addr ...)`
 populate-mu-function-header:  # first-line: (addr stream byte), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
     # pseudocode:
     #   var name: slice