about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-03-05 06:07:50 -0800
committerKartik K. Agaram <vc@akkartik.com>2021-03-05 06:07:50 -0800
commit275a652402e296eeef4f2e139bde44330bf85a6f (patch)
tree9bbd7f21282cf7296f8fc8c1e262d3031e12284c
parent3417a0b32a9d560c8b0f55fa9e524335343b5b1a (diff)
downloadmu-275a652402e296eeef4f2e139bde44330bf85a6f.tar.gz
7853
-rw-r--r--shell/trace.mu89
1 files changed, 88 insertions, 1 deletions
diff --git a/shell/trace.mu b/shell/trace.mu
index 7d6e4091..34303f43 100644
--- a/shell/trace.mu
+++ b/shell/trace.mu
@@ -5,6 +5,7 @@ type trace {
   curr-depth: int  # depth that will be assigned to next line appended
   data: (handle array trace-line)
   first-free: int
+  first-full: int  # used only by check-trace-scan
 
   # steady-state life cycle of a trace:
   #   reload loop:
@@ -137,6 +138,92 @@ fn trace-higher _self: (addr trace) {
 
 ## checking traces
 
+fn check-trace-scans-to self: (addr trace), label: (addr array byte), data: (addr array byte), message: (addr array byte) {
+  var tmp/eax: boolean <- trace-scans-to? self, label, data
+  check tmp, message
+}
+
+fn trace-scans-to? _self: (addr trace), label: (addr array byte), data: (addr array byte) -> _/eax: boolean {
+  var self/esi: (addr trace) <- copy _self
+  var start/eax: (addr int) <- get self, first-full
+  var result/eax: boolean <- trace-contains? self, label, data, *start
+  return result
+}
+
+fn test-trace-scans-to {
+  var t-storage: trace
+  var t/esi: (addr trace) <- address t-storage
+  initialize-trace t, 0x10, 0/visible  # we don't use trace UI
+  #
+  trace-text t, "label", "line 1"
+  trace-text t, "label", "line 2"
+  check-trace-scans-to t, "label", "line 1", "F - test-trace-scans-to/0"
+  check-trace-scans-to t, "label", "line 2", "F - test-trace-scans-to/1"
+  var tmp/eax: boolean <- trace-scans-to? t, "label", "line 1"
+  check-not tmp, "F - test-trace-scans-to: fail on previously encountered lines"
+  var tmp/eax: boolean <- trace-scans-to? t, "label", "line 3"
+  check-not tmp, "F - test-trace-scans-to: fail on missing"
+}
+
+# scan trace from start
+# resets previous scans
+fn check-trace-contains self: (addr trace), label: (addr array byte), data: (addr array byte), message: (addr array byte) {
+  var tmp/eax: boolean <- trace-contains? self, label, data, 0
+  check tmp, message
+}
+
+fn test-trace-contains {
+  var t-storage: trace
+  var t/esi: (addr trace) <- address t-storage
+  initialize-trace t, 0x10, 0/visible  # we don't use trace UI
+  #
+  trace-text t, "label", "line 1"
+  trace-text t, "label", "line 2"
+  check-trace-contains t, "label", "line 1", "F - test-trace-contains/0"
+  check-trace-contains t, "label", "line 2", "F - test-trace-contains/1"
+  check-trace-contains t, "label", "line 1", "F - test-trace-contains: find previously encountered lines"
+  var tmp/eax: boolean <- trace-contains? t, "label", "line 3", 0/start
+  check-not tmp, "F - test-trace-contains: fail on missing"
+}
+
+# this is super-inefficient, string comparing every trace line
+# against every visible line on every render
+fn trace-contains? _self: (addr trace), label: (addr array byte), data: (addr array byte), start: int -> _/eax: boolean {
+  var self/esi: (addr trace) <- copy _self
+  var candidates-ah/eax: (addr handle array trace-line) <- get self, data
+  var candidates/eax: (addr array trace-line) <- lookup *candidates-ah
+  var i/ecx: int <- copy start
+  var max/edx: (addr int) <- get self, first-free
+  {
+    compare i, *max
+    break-if->=
+    {
+      var read-until-index/eax: (addr int) <- get self, first-full
+      copy-to *read-until-index, i
+    }
+    {
+      var curr-offset/ecx: (offset trace-line) <- compute-offset candidates, i
+      var curr/ecx: (addr trace-line) <- index candidates, curr-offset
+      # if curr->label does not match, return false
+      var curr-label-ah/eax: (addr handle array byte) <- get curr, label
+      var curr-label/eax: (addr array byte) <- lookup *curr-label-ah
+      var match?/eax: boolean <- string-equal? curr-label, label
+      compare match?, 0/false
+      break-if-=
+      # if curr->data does not match, return false
+      var curr-data-ah/eax: (addr handle array byte) <- get curr, data
+      var curr-data/eax: (addr array byte) <- lookup *curr-data-ah
+      var match?/eax: boolean <- string-equal? curr-data, data
+      compare match?, 0/false
+      break-if-=
+      return 1/true
+    }
+    i <- increment
+    loop
+  }
+  return 0/false
+}
+
 fn trace-lines-equal? _a: (addr trace-line), _b: (addr trace-line) -> _/eax: boolean {
   var a/esi: (addr trace-line) <- copy _a
   var b/edi: (addr trace-line) <- copy _b
@@ -283,7 +370,7 @@ fn render-trace-line screen: (addr screen), _self: (addr trace-line), xmin: int,
   return y
 }
 
-# this is probably super-inefficient, string comparing every trace line
+# this is super-inefficient, string comparing every trace line
 # against every visible line on every render
 fn should-render? _self: (addr trace), _line: (addr trace-line) -> _/eax: boolean {
   var self/esi: (addr trace) <- copy _self