about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--mu.arc24
-rw-r--r--mu.arc.t18
2 files changed, 31 insertions, 11 deletions
diff --git a/mu.arc b/mu.arc
index 366895bd..47d50cea 100644
--- a/mu.arc
+++ b/mu.arc
@@ -203,21 +203,19 @@
         (err "can't take len of non-array @operand")))
 
 (def array-ref-addr (operand idx)
-;?   (prn "aref addr: @operand @idx")
   (assert typeinfo.operand!array)
-  (assert (< -1 idx (array-len operand)))
+  (unless (< -1 idx (array-len operand))
+    (die "aref-addr: out of bounds index @idx for @operand of size @array-len.operand"))
   (withs (elem  typeinfo.operand!elem
           offset  (+ 1 (* idx sz.elem)))
     (+ v.operand offset)))
 
 (def array-ref (operand idx)
-;?   (prn "aref: @operand @idx")
   (assert typeinfo.operand!array)
-  (assert (< -1 idx (array-len operand)))
-;?   (prn "aref2: @operand @idx")
+  (unless (< -1 idx (array-len operand))
+    (die "aref: out of bounds index @idx for @operand of size @array-len.operand"))
   (withs (elem  typeinfo.operand!elem
           offset  (+ 1 (* idx sz.elem)))
-;?     (prn "aref3: @elem @v.operand @offset")
     (m `(,(+ v.operand offset) ,elem))))
 
 ; data structure: routine
@@ -269,9 +267,10 @@
   (let (oargs _ _)  (parse-instr ((body routine 1) (pc routine 1)))
     oargs))
 
-(= running-routines* (queue))
-(= completed-routines* (queue))
-(= routine* nil)
+(on-init
+  (= running-routines* (queue))
+  (= completed-routines* (queue))
+  (= routine* nil))
 
 (def run fn-names
   (ret result 0
@@ -287,6 +286,11 @@
         (enq routine* running-routines*)
         (enq-limit routine* completed-routines*)))))
 
+(def die (msg)
+  (= rep.routine*!error msg)
+  (= rep.routine*!stack-trace rep.routine*!call-stack)
+  (wipe rep.routine*!call-stack))
+
 ($:require "charterm/main.rkt")
 
 (def run-for-time-slice (time-slice)
@@ -493,6 +497,8 @@
                         (err "no such op @op"))
                       (continue))
                 )
+              (when rep.routine*!error
+                (return time-slice))
               ; opcode generated some value, stored in 'tmp'
               ; copy to output args
 ;?               (prn "store: " tmp " " oarg)
diff --git a/mu.arc.t b/mu.arc.t
index 52327ef2..8fbbf7ad 100644
--- a/mu.arc.t
+++ b/mu.arc.t
@@ -519,8 +519,6 @@
 (if (~iso memory* (obj 1 2  2 23 3 nil  4 24 5 t  6 1  7 4))
   (prn "F - 'index-address' returns addresses of indices of arrays"))
 
-; todo: test that out-of-bounds access throws an error
-
 ; Array values know their length. Record lengths are saved in the types table.
 
 (reset)
@@ -1340,6 +1338,22 @@
 ; Eventually we want the right stack-management primitives to build delimited
 ; continuations in mu.
 
+; Routines can throw errors.
+(reset)
+(new-trace "array-bounds-check")
+(add-fns
+  '((main
+      ((1 integer) <- copy (2 literal))
+      ((2 integer) <- copy (23 literal))
+      ((3 integer) <- copy (24 literal))
+      ((4 integer) <- index (1 integer-array) (2 literal)))))
+;? (set dump-trace*)
+(run 'main)
+;? (prn memory*)
+(let last-routine (deq completed-routines*)
+  (if (no rep.last-routine!error)
+    (prn "F - 'index' throws an error if out of bounds")))
+
 ; ---
 
 (reset)