(and-record trace [ label:string-address contents:string-address ]) (address trace-address (trace)) (array trace-address-array (trace-address)) (address trace-address-array-address (trace-address-array)) (address trace-address-array-address-address (trace-address-array-address)) (and-record instruction-trace [ call-stack:string-address-array-address pc:string-address ; should be integer? instruction:string-address children:trace-address-array-address ]) (address instruction-trace-address (instruction-trace)) (array instruction-trace-address-array (instruction-trace-address)) (address instruction-trace-address-array-address (instruction-trace-address-array)) (function parse-traces [ ; stream-address -> instruction-trace-address-array-address (default-space:space-address <- new space:literal 30:literal) ;? ($print (("parse-traces\n" literal))) ;? 2 (in:stream-address <- next-input) ; check input size ($print (("counting lines\n" literal))) (n:integer <- copy 0:literal) { begin (done?:boolean <- end-of-stream? in:stream-address) (break-if done?:boolean) ;? ($start-tracing) ;? 1 (c:character <- read-character in:stream-address) { begin (newline?:boolean <- equal c:character ((#\newline literal))) (break-unless newline?:boolean) (n:integer <- add n:integer 1:literal) { begin ;? (print?:boolean <- divides? n:integer 100:literal) ;? (break-unless print?:boolean) ($print ((" " literal))) ($print n:integer) ($print (("\n" literal))) } } ;? ($quit) ;? 1 (loop) } ($print n:integer) ($print ((" lines\n" literal))) (in:stream-address <- rewind-stream in:stream-address) ; prepare result (result:buffer-address <- init-buffer 30:literal) (curr-tail:instruction-trace-address <- copy nil:literal) (ch:buffer-address <- init-buffer 5:literal) ; accumulator for traces between instructions (run:string-address/const <- new "run") ($print (("parsing\n" literal))) (n:integer <- copy 0:literal) ; reading each line from 'in' { begin next-line (done?:boolean <- end-of-stream? in:stream-address) ;? ($print done?:boolean) ;? 1 ;? ($print (("\n" literal))) ;? 1 (break-if done?:boolean) ; parse next line as a generic trace (line:string-address <- read-line in:stream-address) { begin (n:integer <- add n:integer 1:literal) (print?:boolean <- divides? n:integer 100:literal) (break-unless print?:boolean) ($print ((" " literal))) ($print n:integer) ($print (("\n" literal))) } ;? (print-string nil:literal/terminal line:string-address) ;? 1 (f:trace-address <- parse-trace line:string-address) (l:string-address <- get f:trace-address/deref label:offset) { begin ; if it's an instruction trace with label 'run' (inst?:boolean <- string-equal l:string-address run:string-address/const) (break-unless inst?:boolean) ; add accumulated traces to curr-tail { begin (break-unless curr-tail:instruction-trace-address) (c:trace-address-array-address-address <- get-address curr-tail:instruction-trace-address/deref children:offset) (c:trace-address-array-address-address/deref <- to-array ch:buffer-address) ; clear 'ch' (ch:buffer-address <- init-buffer 5:literal) } ; append a new curr-tail to result (curr-tail:instruction-trace-address <- parse-instruction-trace f:trace-address) (result:buffer-address <- append result:buffer-address curr-tail:instruction-trace-address) (jump next-line:offset) ; loop } ; otherwise accumulate trace (loop-unless curr-tail:instruction-trace-address) (ch:buffer-address <- append ch:buffer-address f:trace-address) (loop) } ; add accumulated traces to final curr-tail ; todo: test { begin (break-unless curr-tail:instruction-trace-address) (c:trace-address-array-address-address <- get-address curr-tail:instruction-trace-address/deref children:offset) (c:trace-address-array-address-address/deref <- to-array ch:buffer-address) } (s:instruction-trace-address-array-address <- to-array result:buffer-address) (reply s:instruction-trace-address-array-address) ]) (function parse-instruction-trace [ ; trace-address -> instruction-trace-address (default-space:space-address <- new space:literal 30:literal) ;? ($print (("parse-instruction-trace\n" literal))) ;? 1
(function producer [
; produce numbers 1 to 5 on a channel
(default-space:space-address <- new space:literal 30:literal)
(chan:channel-address <- next-input)
; n = 0
(n:integer <- copy 0:literal)
{ begin
(done?:boolean <- less-than n:integer 5:literal)
(break-unless done?:boolean)
; other threads might get between these prints
($print (("produce: " literal)))
(print-integer nil:literal/terminal n:integer)
($print (("\n" literal)))
; 'box' n into a dynamically typed 'tagged value' because that's what
; channels take
(n2:integer <- copy n:integer)
(n3:tagged-value-address <- init-tagged-value integer:literal n2:integer)
(chan:channel-address/deref <- write chan:channel-address n3:tagged-value-address/deref)
(n:integer <- add n:integer 1:literal)
(loop)
}
])
(function consumer [
; consume and print integers from a channel
(default-space:space-address <- new space:literal 30:literal)
(chan:channel-address <- next-input)
{ begin
; read a tagged value from the channel
(x:tagged-value chan:channel-address/deref <- read chan:channel-address)
; unbox the tagged value into an integer
(n2:integer <- maybe-coerce x:tagged-value integer:literal)
; other threads might get between these prints
($print (("consume: " literal)))
(print-integer nil:literal/terminal n2:integer)
($print (("\n" literal)))
(loop)
}
])
(function main [
(default-space:space-address <- new space:literal 30:literal)
(chan:channel-address <- init-channel 3:literal)
; create two background 'routines' that communicate by a channel
(routine1:integer <- fork consumer:fn nil:literal/globals nil:literal/limit chan:channel-address)
(routine2:integer <- fork producer:fn nil:literal/globals nil:literal/limit chan:channel-address)
(sleep until-routine-done:literal routine1:integer)
(sleep until-routine-done:literal routine2:integer)
])