From 3350c34a74844e21ea69077e01efff3bae64bdcd Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Tue, 23 Mar 2021 17:31:08 -0700 Subject: . --- html/linux/tile/data.mu.html | 704 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 704 insertions(+) create mode 100644 html/linux/tile/data.mu.html (limited to 'html/linux/tile/data.mu.html') diff --git a/html/linux/tile/data.mu.html b/html/linux/tile/data.mu.html new file mode 100644 index 00000000..ed78f92a --- /dev/null +++ b/html/linux/tile/data.mu.html @@ -0,0 +1,704 @@ + + + + +Mu - linux/tile/data.mu + + + + + + + + + + +https://github.com/akkartik/mu/blob/main/linux/tile/data.mu +
+  1 # widgets in the environment share the following pattern of updates:
+  2 #   process-* functions read keys and update which object the cursor is at
+  3 #   render-* functions print to screen and update which row/col each object's cursor is at
+  4 
+  5 type sandbox {
+  6   setup: (handle line)
+  7   data: (handle line)
+  8   # bookkeeping for process-*
+  9   cursor-call-path: (handle call-path-element)
+ 10   expanded-words: (handle call-path)
+ 11   partial-name-for-cursor-word: (handle word)  # only when renaming word
+ 12   partial-name-for-function: (handle word)  # only when defining function
+ 13   # bookkeeping for render-*
+ 14   cursor-row: int
+ 15   cursor-col: int
+ 16   #
+ 17   next: (handle sandbox)
+ 18   prev: (handle sandbox)
+ 19 }
+ 20 
+ 21 type function {
+ 22   name: (handle array byte)
+ 23   args: (handle word)  # in reverse order
+ 24   body: (handle line)
+ 25   # bookkeeping for process-*
+ 26   cursor-word: (handle word)
+ 27   # bookkeeping for render-*
+ 28   cursor-row: int
+ 29   cursor-col: int
+ 30   # todo: some sort of indication of spatial location
+ 31   next: (handle function)
+ 32 }
+ 33 
+ 34 type line {
+ 35   name: (handle array byte)
+ 36   data: (handle word)
+ 37   result: (handle result)  # might be cached
+ 38   next: (handle line)
+ 39   prev: (handle line)
+ 40 }
+ 41 
+ 42 type word {
+ 43   scalar-data: (handle gap-buffer)
+ 44   next: (handle word)
+ 45   prev: (handle word)
+ 46 }
+ 47 
+ 48 # todo: turn this into a sum type
+ 49 type value {
+ 50   type: int
+ 51   number-data: float  # if type = 0
+ 52   text-data: (handle array byte)  # if type = 1
+ 53   array-data: (handle array value)  # if type = 2
+ 54   file-data: (handle buffered-file)  # if type = 3
+ 55   filename: (handle array byte)  # if type = 3
+ 56   screen-data: (handle screen)  # if type = 4
+ 57 }
+ 58 
+ 59 type table {
+ 60   data: (handle array bind)
+ 61   next: (handle table)
+ 62 }
+ 63 
+ 64 type bind {
+ 65   key: (handle array byte)
+ 66   value: (handle value)  # I'd inline this but we sometimes want to return a specific value from a table
+ 67 }
+ 68 
+ 69 # A call-path is a data structure that can unambiguously refer to any specific
+ 70 # call arbitrarily deep inside the call hierarchy of a program.
+ 71 type call-path {
+ 72   data: (handle call-path-element)
+ 73   next: (handle call-path)
+ 74 }
+ 75 
+ 76 # A call-path element is a list of elements, each of which corresponds to some call.
+ 77 type call-path-element {
+ 78   word: (handle word)
+ 79   next: (handle call-path-element)
+ 80 }
+ 81 
+ 82 type result {
+ 83   data: value-stack
+ 84   error: (handle array byte)  # single error message for now
+ 85 }
+ 86 
+ 87 fn initialize-sandbox _sandbox: (addr sandbox) {
+ 88   var sandbox/esi: (addr sandbox) <- copy _sandbox
+ 89   var line-ah/eax: (addr handle line) <- get sandbox, data
+ 90   allocate line-ah
+ 91   var line/eax: (addr line) <- lookup *line-ah
+ 92   initialize-line line
+ 93   var word-ah/ecx: (addr handle word) <- get line, data
+ 94   var cursor-call-path-ah/eax: (addr handle call-path-element) <- get sandbox, cursor-call-path
+ 95   allocate cursor-call-path-ah
+ 96   var cursor-call-path/eax: (addr call-path-element) <- lookup *cursor-call-path-ah
+ 97   var dest/eax: (addr handle word) <- get cursor-call-path, word
+ 98   copy-object word-ah, dest
+ 99 }
+100 
+101 # initialize line with a single empty word
+102 fn initialize-line _line: (addr line) {
+103   var line/esi: (addr line) <- copy _line
+104   var word-ah/eax: (addr handle word) <- get line, data
+105   allocate word-ah
+106   var word/eax: (addr word) <- lookup *word-ah
+107   initialize-word word
+108 }
+109 
+110 fn create-primitive-functions _self: (addr handle function) {
+111   # x 2* = x 2 *
+112   var self/esi: (addr handle function) <- copy _self
+113   allocate self
+114   var _f/eax: (addr function) <- lookup *self
+115   var f/esi: (addr function) <- copy _f
+116   var name-ah/eax: (addr handle array byte) <- get f, name
+117   populate-text-with name-ah, "2*"
+118   var args-ah/eax: (addr handle word) <- get f, args
+119   allocate args-ah
+120   var args/eax: (addr word) <- lookup *args-ah
+121   initialize-word-with args, "x"
+122   var body-ah/eax: (addr handle line) <- get f, body
+123   allocate body-ah
+124   var body/eax: (addr line) <- lookup *body-ah
+125   initialize-line body
+126   var curr-word-ah/ecx: (addr handle word) <- get body, data
+127   parse-words "x 2 *", curr-word-ah
+128   var cursor-word-ah/edx: (addr handle word) <- get f, cursor-word
+129   copy-object curr-word-ah, cursor-word-ah
+130   # x 1+ = x 1 +
+131   var next/esi: (addr handle function) <- get f, next
+132   allocate next
+133   var _f/eax: (addr function) <- lookup *next
+134   var f/esi: (addr function) <- copy _f
+135   var name-ah/eax: (addr handle array byte) <- get f, name
+136   populate-text-with name-ah, "1+"
+137   var args-ah/eax: (addr handle word) <- get f, args
+138   allocate args-ah
+139   var args/eax: (addr word) <- lookup *args-ah
+140   initialize-word-with args, "x"
+141   var body-ah/eax: (addr handle line) <- get f, body
+142   allocate body-ah
+143   var body/eax: (addr line) <- lookup *body-ah
+144   initialize-line body
+145   curr-word-ah <- get body, data
+146   parse-words "x 1 +", curr-word-ah
+147   var cursor-word-ah/edx: (addr handle word) <- get f, cursor-word
+148   copy-object curr-word-ah, cursor-word-ah
+149   # x 2+ = x 1+ 1+
+150   var next/esi: (addr handle function) <- get f, next
+151   allocate next
+152   var _f/eax: (addr function) <- lookup *next
+153   var f/esi: (addr function) <- copy _f
+154   var name-ah/eax: (addr handle array byte) <- get f, name
+155   populate-text-with name-ah, "2+"
+156   var args-ah/eax: (addr handle word) <- get f, args
+157   allocate args-ah
+158   var args/eax: (addr word) <- lookup *args-ah
+159   initialize-word-with args, "x"
+160   var body-ah/eax: (addr handle line) <- get f, body
+161   allocate body-ah
+162   var body/eax: (addr line) <- lookup *body-ah
+163   initialize-line body
+164   curr-word-ah <- get body, data
+165   parse-words "x 1+ 1+", curr-word-ah
+166   var cursor-word-ah/edx: (addr handle word) <- get f, cursor-word
+167   copy-object curr-word-ah, cursor-word-ah
+168   # x square = x x *
+169   var next/esi: (addr handle function) <- get f, next
+170   allocate next
+171   var _f/eax: (addr function) <- lookup *next
+172   var f/esi: (addr function) <- copy _f
+173   var name-ah/eax: (addr handle array byte) <- get f, name
+174   populate-text-with name-ah, "square"
+175   var args-ah/eax: (addr handle word) <- get f, args
+176   allocate args-ah
+177   var args/eax: (addr word) <- lookup *args-ah
+178   initialize-word-with args, "x"
+179   var body-ah/eax: (addr handle line) <- get f, body
+180   allocate body-ah
+181   var body/eax: (addr line) <- lookup *body-ah
+182   initialize-line body
+183   curr-word-ah <- get body, data
+184   parse-words "x x *", curr-word-ah
+185   var cursor-word-ah/edx: (addr handle word) <- get f, cursor-word
+186   copy-object curr-word-ah, cursor-word-ah
+187   # x 1- = x 1 -
+188   var next/esi: (addr handle function) <- get f, next
+189   allocate next
+190   var _f/eax: (addr function) <- lookup *next
+191   var f/esi: (addr function) <- copy _f
+192   var name-ah/eax: (addr handle array byte) <- get f, name
+193   populate-text-with name-ah, "1-"
+194   var args-ah/eax: (addr handle word) <- get f, args
+195   allocate args-ah
+196   var args/eax: (addr word) <- lookup *args-ah
+197   initialize-word-with args, "x"
+198   var body-ah/eax: (addr handle line) <- get f, body
+199   allocate body-ah
+200   var body/eax: (addr line) <- lookup *body-ah
+201   initialize-line body
+202   curr-word-ah <- get body, data
+203   parse-words "x 1 -", curr-word-ah
+204   var cursor-word-ah/edx: (addr handle word) <- get f, cursor-word
+205   copy-object curr-word-ah, cursor-word-ah
+206   # x y sub = x y -
+207   var next/esi: (addr handle function) <- get f, next
+208   allocate next
+209   var _f/eax: (addr function) <- lookup *next
+210   var f/esi: (addr function) <- copy _f
+211   var name-ah/eax: (addr handle array byte) <- get f, name
+212   populate-text-with name-ah, "sub"
+213   # critical lesson: args are stored in reverse order
+214   var args-ah/eax: (addr handle word) <- get f, args
+215   allocate args-ah
+216   var args/eax: (addr word) <- lookup *args-ah
+217   initialize-word-with args, "y"
+218   var next-arg-ah/eax: (addr handle word) <- get args, next
+219   allocate next-arg-ah
+220   var next-arg/eax: (addr word) <- lookup *next-arg-ah
+221   initialize-word-with next-arg, "x"
+222   var body-ah/eax: (addr handle line) <- get f, body
+223   allocate body-ah
+224   var body/eax: (addr line) <- lookup *body-ah
+225   initialize-line body
+226   curr-word-ah <- get body, data
+227   parse-words "x y -", curr-word-ah
+228   var cursor-word-ah/edx: (addr handle word) <- get f, cursor-word
+229   copy-object curr-word-ah, cursor-word-ah
+230 }
+231 
+232 fn function-body functions: (addr handle function), _word: (addr handle word), out: (addr handle line) {
+233   var function-name-storage: (handle array byte)
+234   var function-name-ah/ecx: (addr handle array byte) <- address function-name-storage
+235   var word-ah/esi: (addr handle word) <- copy _word
+236   var word/eax: (addr word) <- lookup *word-ah
+237   var gap-ah/eax: (addr handle gap-buffer) <- get word, scalar-data
+238   var gap/eax: (addr gap-buffer) <- lookup *gap-ah
+239   gap-buffer-to-string gap, function-name-ah
+240   var _function-name/eax: (addr array byte) <- lookup *function-name-ah
+241   var function-name/esi: (addr array byte) <- copy _function-name
+242   var curr-ah/ecx: (addr handle function) <- copy functions
+243   $function-body:loop: {
+244     var _curr/eax: (addr function) <- lookup *curr-ah
+245     var curr/edx: (addr function) <- copy _curr
+246     compare curr, 0
+247     break-if-=
+248     var curr-name-ah/eax: (addr handle array byte) <- get curr, name
+249     var curr-name/eax: (addr array byte) <- lookup *curr-name-ah
+250     var found?/eax: boolean <- string-equal? curr-name, function-name
+251     compare found?, 0/false
+252     {
+253       break-if-=
+254       var src/eax: (addr handle line) <- get curr, body
+255       copy-object src, out
+256       break $function-body:loop
+257     }
+258     curr-ah <- get curr, next
+259     loop
+260   }
+261 }
+262 
+263 fn body-length functions: (addr handle function), function-name: (addr handle word) -> _/eax: int {
+264   var body-storage: (handle line)
+265   var body-ah/edi: (addr handle line) <- address body-storage
+266   function-body functions, function-name, body-ah
+267   var body/eax: (addr line) <- lookup *body-ah
+268   var result/eax: int <- num-words-in-line body
+269   return result
+270 }
+271 
+272 fn num-words-in-line _in: (addr line) -> _/eax: int {
+273   var in/esi: (addr line) <- copy _in
+274   var curr-ah/ecx: (addr handle word) <- get in, data
+275   var result/edi: int <- copy 0
+276   {
+277     var curr/eax: (addr word) <- lookup *curr-ah
+278     compare curr, 0
+279     break-if-=
+280     curr-ah <- get curr, next
+281     result <- increment
+282     loop
+283   }
+284   return result
+285 }
+286 
+287 fn populate-text-with _out: (addr handle array byte), _in: (addr array byte) {
+288   var in/esi: (addr array byte) <- copy _in
+289   var n/ecx: int <- length in
+290   var out/edx: (addr handle array byte) <- copy _out
+291   populate out, n
+292   var _out-addr/eax: (addr array byte) <- lookup *out
+293   var out-addr/edx: (addr array byte) <- copy _out-addr
+294   var i/eax: int <- copy 0
+295   {
+296     compare i, n
+297     break-if->=
+298     var src/esi: (addr byte) <- index in, i
+299     var val/ecx: byte <- copy-byte *src
+300     var dest/edi: (addr byte) <- index out-addr, i
+301     copy-byte-to *dest, val
+302     i <- increment
+303     loop
+304   }
+305 }
+306 
+307 fn initialize-path-from-sandbox _in: (addr sandbox), _out: (addr handle call-path-element) {
+308   var sandbox/esi: (addr sandbox) <- copy _in
+309   var line-ah/eax: (addr handle line) <- get sandbox, data
+310   var line/eax: (addr line) <- lookup *line-ah
+311   var src/esi: (addr handle word) <- get line, data
+312   var out-ah/edi: (addr handle call-path-element) <- copy _out
+313   var out/eax: (addr call-path-element) <- lookup *out-ah
+314   var dest/edi: (addr handle word) <- get out, word
+315   copy-object src, dest
+316 }
+317 
+318 fn initialize-path-from-line _line: (addr line), _out: (addr handle call-path-element) {
+319   var line/eax: (addr line) <- copy _line
+320   var src/esi: (addr handle word) <- get line, data
+321   var out-ah/edi: (addr handle call-path-element) <- copy _out
+322   var out/eax: (addr call-path-element) <- lookup *out-ah
+323   var dest/edi: (addr handle word) <- get out, word
+324   copy-object src, dest
+325 }
+326 
+327 fn find-in-call-paths call-paths: (addr handle call-path), needle: (addr handle call-path-element) -> _/eax: boolean {
+328   var curr-ah/esi: (addr handle call-path) <- copy call-paths
+329   $find-in-call-path:loop: {
+330     var curr/eax: (addr call-path) <- lookup *curr-ah
+331     compare curr, 0
+332     break-if-=
+333     {
+334       var curr-data/eax: (addr handle call-path-element) <- get curr, data
+335       var match?/eax: boolean <- call-path-element-match? curr-data, needle
+336       compare match?, 0/false
+337       {
+338         break-if-=
+339         return 1/true
+340       }
+341     }
+342     curr-ah <- get curr, next
+343     loop
+344   }
+345   return 0/false
+346 }
+347 
+348 fn call-path-element-match? _x: (addr handle call-path-element), _y: (addr handle call-path-element) -> _/eax: boolean {
+349   var x-ah/eax: (addr handle call-path-element) <- copy _x
+350   var x-a/eax: (addr call-path-element) <- lookup *x-ah
+351   var x/esi: (addr call-path-element) <- copy x-a
+352   var y-ah/eax: (addr handle call-path-element) <- copy _y
+353   var y-a/eax: (addr call-path-element) <- lookup *y-ah
+354   var y/edi: (addr call-path-element) <- copy y-a
+355   compare x, y
+356   {
+357     break-if-!=
+358     return 1/true
+359   }
+360   compare x, 0
+361   {
+362     break-if-!=
+363     return 0/false
+364   }
+365   compare y, 0
+366   {
+367     break-if-!=
+368     return 0/false
+369   }
+370   # compare word addresses, not contents
+371   var x-data-ah/ecx: (addr handle word) <- get x, word
+372   var x-data-a/eax: (addr word) <- lookup *x-data-ah
+373   var x-data/ecx: int <- copy x-data-a
+374   var y-data-ah/eax: (addr handle word) <- get y, word
+375   var y-data-a/eax: (addr word) <- lookup *y-data-ah
+376   var y-data/eax: int <- copy y-data-a
+377 #?   print-string 0, "match? "
+378 #?   print-int32-hex 0, x-data
+379 #?   print-string 0, " vs "
+380 #?   print-int32-hex 0, y-data
+381 #?   print-string 0, "\n"
+382   compare x-data, y-data
+383   {
+384     break-if-=
+385     return 0/false
+386   }
+387   var x-next/ecx: (addr handle call-path-element) <- get x, next
+388   var y-next/eax: (addr handle call-path-element) <- get y, next
+389   var result/eax: boolean <- call-path-element-match? x-next, y-next
+390   return result
+391 }
+392 
+393 # order is irrelevant
+394 fn insert-in-call-path list: (addr handle call-path), new: (addr handle call-path-element) {
+395   var new-path-storage: (handle call-path)
+396   var new-path-ah/edi: (addr handle call-path) <- address new-path-storage
+397   allocate new-path-ah
+398   var new-path/eax: (addr call-path) <- lookup *new-path-ah
+399   var next/ecx: (addr handle call-path) <- get new-path, next
+400   copy-object list, next
+401   var dest/ecx: (addr handle call-path-element) <- get new-path, data
+402   deep-copy-call-path-element new, dest
+403   copy-object new-path-ah, list
+404 }
+405 
+406 # assumes dest is initially clear
+407 fn deep-copy-call-path-element _src: (addr handle call-path-element), _dest: (addr handle call-path-element) {
+408   var src/esi: (addr handle call-path-element) <- copy _src
+409   # if src is null, return
+410   var _src-addr/eax: (addr call-path-element) <- lookup *src
+411   compare _src-addr, 0
+412   break-if-=
+413   # allocate
+414   var src-addr/esi: (addr call-path-element) <- copy _src-addr
+415   var dest/eax: (addr handle call-path-element) <- copy _dest
+416   allocate dest
+417   # copy data
+418   var dest-addr/eax: (addr call-path-element) <- lookup *dest
+419   {
+420     var dest-data-addr/ecx: (addr handle word) <- get dest-addr, word
+421     var src-data-addr/eax: (addr handle word) <- get src-addr, word
+422     copy-object src-data-addr, dest-data-addr
+423   }
+424   # recurse
+425   var src-next/esi: (addr handle call-path-element) <- get src-addr, next
+426   var dest-next/eax: (addr handle call-path-element) <- get dest-addr, next
+427   deep-copy-call-path-element src-next, dest-next
+428 }
+429 
+430 fn delete-in-call-path list: (addr handle call-path), needle: (addr handle call-path-element) {
+431   var curr-ah/esi: (addr handle call-path) <- copy list
+432   $delete-in-call-path:loop: {
+433     var _curr/eax: (addr call-path) <- lookup *curr-ah
+434     var curr/ecx: (addr call-path) <- copy _curr
+435     compare curr, 0
+436     break-if-=
+437     {
+438       var curr-data/eax: (addr handle call-path-element) <- get curr, data
+439       var match?/eax: boolean <- call-path-element-match? curr-data, needle
+440       compare match?, 0/false
+441       {
+442         break-if-=
+443         var next-ah/ecx: (addr handle call-path) <- get curr, next
+444         copy-object next-ah, curr-ah
+445         loop $delete-in-call-path:loop
+446       }
+447     }
+448     curr-ah <- get curr, next
+449     loop
+450   }
+451 }
+452 
+453 fn increment-final-element list: (addr handle call-path-element) {
+454   var final-ah/eax: (addr handle call-path-element) <- copy list
+455   var final/eax: (addr call-path-element) <- lookup *final-ah
+456   var val-ah/ecx: (addr handle word) <- get final, word
+457   var val/eax: (addr word) <- lookup *val-ah
+458   var new-ah/edx: (addr handle word) <- get val, next
+459   var target/eax: (addr word) <- lookup *new-ah
+460   compare target, 0
+461   break-if-=
+462   copy-object new-ah, val-ah
+463 }
+464 
+465 fn decrement-final-element list: (addr handle call-path-element) {
+466   var final-ah/eax: (addr handle call-path-element) <- copy list
+467   var final/eax: (addr call-path-element) <- lookup *final-ah
+468   var val-ah/ecx: (addr handle word) <- get final, word
+469   var val/eax: (addr word) <- lookup *val-ah
+470 #?   print-string 0, "replacing "
+471 #?   {
+472 #?     var foo/eax: int <- copy val
+473 #?     print-int32-hex 0, foo
+474 #?   }
+475   var new-ah/edx: (addr handle word) <- get val, prev
+476   var target/eax: (addr word) <- lookup *new-ah
+477   compare target, 0
+478   break-if-=
+479   # val = val->prev
+480 #?   print-string 0, " with "
+481 #?   {
+482 #?     var foo/eax: int <- copy target
+483 #?     print-int32-hex 0, foo
+484 #?   }
+485 #?   print-string 0, "\n"
+486   copy-object new-ah, val-ah
+487 }
+488 
+489 fn move-final-element-to-start-of-line list: (addr handle call-path-element) {
+490   var final-ah/eax: (addr handle call-path-element) <- copy list
+491   var final/eax: (addr call-path-element) <- lookup *final-ah
+492   var val-ah/ecx: (addr handle word) <- get final, word
+493   var val/eax: (addr word) <- lookup *val-ah
+494   var new-ah/edx: (addr handle word) <- get val, prev
+495   var target/eax: (addr word) <- lookup *new-ah
+496   compare target, 0
+497   break-if-=
+498   copy-object new-ah, val-ah
+499   move-final-element-to-start-of-line list
+500 }
+501 
+502 fn move-final-element-to-end-of-line list: (addr handle call-path-element) {
+503   var final-ah/eax: (addr handle call-path-element) <- copy list
+504   var final/eax: (addr call-path-element) <- lookup *final-ah
+505   var val-ah/ecx: (addr handle word) <- get final, word
+506   var val/eax: (addr word) <- lookup *val-ah
+507   var new-ah/edx: (addr handle word) <- get val, next
+508   var target/eax: (addr word) <- lookup *new-ah
+509   compare target, 0
+510   break-if-=
+511   copy-object new-ah, val-ah
+512   move-final-element-to-end-of-line list
+513 }
+514 
+515 fn push-to-call-path-element list: (addr handle call-path-element), new: (addr handle word) {
+516   var new-element-storage: (handle call-path-element)
+517   var new-element-ah/edi: (addr handle call-path-element) <- address new-element-storage
+518   allocate new-element-ah
+519   var new-element/eax: (addr call-path-element) <- lookup *new-element-ah
+520   # save word
+521   var dest/ecx: (addr handle word) <- get new-element, word
+522   copy-object new, dest
+523   # save next
+524   var dest2/ecx: (addr handle call-path-element) <- get new-element, next
+525   copy-object list, dest2
+526   # return
+527   copy-object new-element-ah, list
+528 }
+529 
+530 fn drop-from-call-path-element _list: (addr handle call-path-element) {
+531   var list-ah/esi: (addr handle call-path-element) <- copy _list
+532   var list/eax: (addr call-path-element) <- lookup *list-ah
+533   var next/eax: (addr handle call-path-element) <- get list, next
+534   copy-object next, _list
+535 }
+536 
+537 fn drop-nested-calls _list: (addr handle call-path-element) {
+538   var list-ah/esi: (addr handle call-path-element) <- copy _list
+539   var list/eax: (addr call-path-element) <- lookup *list-ah
+540   var next-ah/edi: (addr handle call-path-element) <- get list, next
+541   var next/eax: (addr call-path-element) <- lookup *next-ah
+542   compare next, 0
+543   break-if-=
+544   copy-object next-ah, _list
+545   drop-nested-calls _list
+546 }
+547 
+548 fn dump-call-path-element screen: (addr screen), _x-ah: (addr handle call-path-element) {
+549   var x-ah/ecx: (addr handle call-path-element) <- copy _x-ah
+550   var _x/eax: (addr call-path-element) <- lookup *x-ah
+551   var x/esi: (addr call-path-element) <- copy _x
+552   var word-ah/eax: (addr handle word) <- get x, word
+553   var word/eax: (addr word) <- lookup *word-ah
+554   print-word screen, word
+555   var next-ah/ecx: (addr handle call-path-element) <- get x, next
+556   var next/eax: (addr call-path-element) <- lookup *next-ah
+557   compare next, 0
+558   {
+559     break-if-=
+560     print-string screen, " "
+561     dump-call-path-element screen, next-ah
+562     return
+563   }
+564   print-string screen, "\n"
+565 }
+566 
+567 fn dump-call-paths screen: (addr screen), _x-ah: (addr handle call-path) {
+568   var x-ah/ecx: (addr handle call-path) <- copy _x-ah
+569   var x/eax: (addr call-path) <- lookup *x-ah
+570   compare x, 0
+571   break-if-=
+572   var src/ecx: (addr handle call-path-element) <- get x, data
+573   dump-call-path-element screen, src
+574   var next-ah/ecx: (addr handle call-path) <- get x, next
+575   var next/eax: (addr call-path) <- lookup *next-ah
+576   compare next, 0
+577   {
+578     break-if-=
+579     dump-call-paths screen, next-ah
+580   }
+581 }
+582 
+583 fn function-width _self: (addr function) -> _/eax: int {
+584   var self/esi: (addr function) <- copy _self
+585   var args/ecx: (addr handle word) <- get self, args
+586   var arg-width/eax: int <- word-list-length args
+587   var result/edi: int <- copy arg-width
+588   result <- add 4  # function-header-indent + body-indent
+589   var body-ah/eax: (addr handle line) <- get self, body
+590   var body-width/eax: int <- body-width body-ah
+591   body-width <- add 1  # right margin
+592   body-width <- add 2  # body-indent for "≡ "
+593   compare result, body-width
+594   {
+595     break-if->=
+596     result <- copy body-width
+597   }
+598   return result
+599 }
+600 
+601 fn body-width lines: (addr handle line) -> _/eax: int {
+602   var curr-ah/esi: (addr handle line) <- copy lines
+603   var result/edi: int <- copy 0
+604   {
+605     var curr/eax: (addr line) <- lookup *curr-ah
+606     compare curr, 0
+607     break-if-=
+608     {
+609       var words/ecx: (addr handle word) <- get curr, data
+610       var curr-len/eax: int <- word-list-length words
+611       compare curr-len, result
+612       break-if-<=
+613       result <- copy curr-len
+614     }
+615     curr-ah <- get curr, next
+616     loop
+617   }
+618   return result
+619 }
+620 
+621 fn function-height _self: (addr function) -> _/eax: int {
+622   var self/esi: (addr function) <- copy _self
+623   var body-ah/eax: (addr handle line) <- get self, body
+624   var result/eax: int <- line-list-length body-ah
+625   result <- increment  # for function header
+626   return result
+627 }
+628 
+629 fn line-list-length lines: (addr handle line) -> _/eax: int {
+630   var curr-ah/esi: (addr handle line) <- copy lines
+631   var result/edi: int <- copy 0
+632   {
+633     var curr/eax: (addr line) <- lookup *curr-ah
+634     compare curr, 0
+635     break-if-=
+636     curr-ah <- get curr, next
+637     result <- increment
+638     loop
+639   }
+640   return result
+641 }
+
+ + + -- cgit 1.4.1-2-gfad0