container duplex-list:_elem [
value:_elem
next:&:duplex-list:_elem
prev:&:duplex-list:_elem
]
def push x:_elem, in:&:duplex-list:_elem -> in:&:duplex-list:_elem [
local-scope
load-ingredients
result:&:duplex-list:_elem <- new {(duplex-list _elem): type}
*result <- merge x, in, 0
{
break-unless in
*in <- put *in, prev:offset, result
}
return result
]
def first in:&:duplex-list:_elem -> result:_elem [
local-scope
load-ingredients
return-unless in, 0
result <- get *in, value:offset
]
def next in:&:duplex-list:_elem -> result:&:duplex-list:_elem/contained-in:in [
local-scope
load-ingredients
return-unless in, 0
result <- get *in, next:offset
]
def prev in:&:duplex-list:_elem -> result:&:duplex-list:_elem/contained-in:in [
local-scope
load-ingredients
return-unless in, 0
result <- get *in, prev:offset
return result
]
scenario duplex-list-handling [
run [
local-scope
10:num/raw <- copy 34
11:num/raw <- copy 35
list:&:duplex-list:char <- push 3, 0
list <- push 4, list
list <- push 5, list
list2:&:duplex-list:char <- copy list
20:char/raw <- first list2
list2 <- next list2
21:char/raw <- first list2
list2 <- next list2
22:char/raw <- first list2
30:&:duplex-list:char/raw <- next list2
31:char/raw <- first 30:&:duplex-list:char/raw
32:&:duplex-list:char/raw <- next 30:&:duplex-list:char/raw
33:&:duplex-list:char/raw <- prev 30:&:duplex-list:char/raw
list2 <- prev list2
40:char/raw <- first list2
list2 <- prev list2
41:char/raw <- first list2
50:bool/raw <- equal list, list2
]
memory-should-contain [
0 <- 0
10 <- 34
11 <- 35
20 <- 5
21 <- 4
22 <- 3
30 <- 0
31 <- 0
32 <- 0
33 <- 0
40 <- 4
41 <- 5
50 <- 1
]
]
def insert x:_elem, in:&:duplex-list:_elem -> in:&:duplex-list:_elem [
local-scope
load-ingredients
new-node:&:duplex-list:_elem <- new {(duplex-list _elem): type}
*new-node <- put *new-node, value:offset, x
next-node:&:duplex-list:_elem <- get *in, next:offset
*in <- put *in, next:offset, new-node
*new-node <- put *new-node, prev:offset, in
*new-node <- put *new-node, next:offset, next-node
return-unless next-node
*next-node <- put *next-node, prev:offset, new-node
]
scenario inserting-into-duplex-list [
local-scope
list:&:duplex-list:char <- push 3, 0
list <- push 4, list
list <- push 5, list
run [
list2:&:duplex-list:char <- next list
list2 <- insert 6, list2
list2 <- copy list
10:char/raw <- first list2
list2 <- next list2
11:char/raw <- first list2
list2 <- next list2
12:char/raw <- first list2
list2 <- next list2
13:char/raw <- first list2
list2 <- prev list2
20:char/raw <- first list2
list2 <- prev list2
21:char/raw <- first list2
list2 <- prev list2
22:char/raw <- first list2
30:bool/raw <- equal list, list2
]
memory-should-contain [
10 <- 5
11 <- 4
12 <- 6
13 <- 3
20(selective-load "mu.arc" section-level)
(set allow-raw-addresses*)
(add-code:readfile "chessboard.mu")
(freeze function*)
(load-system-functions)
(reset2)
(new-trace "read-move-legal")
(run-code main
(default-space:space-address <- new space:literal 30:literal/capacity)
(stdin:channel-address <- init-channel 1:literal)
(r:integer/routine <- fork read-move:fn nil:literal/globals 2000:literal/limit stdin:channel-address)
(c:character <- copy ((#\a literal)))
(x:tagged-value <- save-type c:character)
(stdin:channel-address/deref <- write stdin:channel-address x:tagged-value)
(c:character <- copy ((#\2 literal)))
(x:tagged-value <- save-type c:character)
(stdin:channel-address/deref <- write stdin:channel-address x:tagged-value)
(c:character <- copy ((#\- literal)))
(x:tagged-value <- save-type c:character)
(stdin:channel-address/deref <- write stdin:channel-address x:tagged-value)
(c:character <- copy ((#\a literal)))
(x:tagged-value <- save-type c:character)
(stdin:channel-address/deref <- write stdin:channel-address x:tagged-value)
(c:character <- copy ((#\4 literal)))
(x:tagged-value <- save-type c:character)
(stdin:channel-address/deref <- write stdin:channel-address x:tagged-value)
(c:character <- copy ((#\newline literal)))
(x:tagged-value <- save-type c:character)
(stdin:channel-address/deref <- write stdin:channel-address x:tagged-value)
(sleep until-routine-done:literal r:integer/routine)
)
(each routine completed-routines*
;? (prn " " routine)
(awhen rep.routine!error
(prn "error - " it)))
(when (~ran-to-completion 'read-move)
(prn "F - chessboard accepts legal moves (<rank><file>-<rank><file>)"))
; todo: we can't test that keys pressed are printed to screen
; but that's at a lower level
;? (quit)
(reset2)
(new-trace "read-move-incomplete")
; initialize some variables at specific raw locations
;? (prn "== init")
(run-code test-init
(1:channel-address/raw <- init-channel 1:literal)
(2:terminal-address/raw <- init-fake-terminal 20:literal 10:literal)
(3:string-address/raw <- get 2:terminal-address/raw/deref data:offset))
(wipe completed-routines*)
; the component under test; we'll be running this repeatedly
(let read-move-routine (make-routine 'read-move memory*.1 memory*.2)
;? (prn "== first key")
(run-code send-first-key
(default-space:space-address <- new space:literal 30:literal/capacity)
(c:character <- copy ((#\a literal)))
(x:tagged-value <- save-type c:character)
(1:channel-address/raw/deref <- write 1:channel-address/raw x:tagged-value))
(wipe completed-routines*)
; check that read-move consumes it and then goes to sleep
(enq read-move-routine running-routines*)
(run-more)
(when (ran-to-completion 'read-move)
(prn "F - chessboard waits after first letter of move"))
(wipe completed-routines*)
; send in a few more letters
;? (prn "== more keys")
(restart read-move-routine)
(run-code send-more-keys
(default-space:space-address <- new space:literal 30:literal/capacity)
(c:character <- copy ((#\2 literal)))
(x:tagged-value <- save-type c:character)
(1:channel-address/raw/deref <- write 1:channel-address/raw x:tagged-value)
(c:character <- copy ((#\- literal)))
(x:tagged-value <- save-type c:character)
(1:channel-address/raw/deref <- write 1:channel-address/raw x:tagged-value)
(c:character <- copy ((#\a literal)))
(x:tagged-value <- save-type c:character)
(1:channel-address/raw/deref <- write 1:channel-address/raw x:tagged-value)
(c:character <- copy ((#\4 literal)))
(x:tagged-value <- save-type c:character)
(1:channel-address/raw/deref <- write 1:channel-address/raw x:tagged-value))
; check that read-move consumes them and then goes to sleep
(when (ran-to-completion 'read-move)
(prn "F - chessboard waits after each subsequent letter of move until the last"))
(wipe completed-routines*)
; send final key
;? (prn "== final key")
(restart read-move-routine)
;? (set dump-trace*)
(run-code send-final-key
(default-space:space-address <- new space:literal 30:literal/capacity)
(c:character <- copy ((#\newline literal)))
(x:tagged-value <- save-type c:charac