https://github.com/akkartik/mu/blob/master/088file.mu
1
2
3
4
5
6
7
8
9
10
11 container resources [
12 lock:bool
13 data:&:@:resource
14 ]
15
16 container resource [
17 name:text
18 contents:text
19 ]
20
21 def start-reading resources:&:resources, filename:text -> contents:&:source:char, error?:bool [
22 local-scope
23 load-inputs
24 error? <- copy false
25 {
26 break-unless resources
27
28 contents, error? <- start-reading-from-fake-resource resources, filename
29 return
30 }
31
32 file:num <- $open-file-for-reading filename
33 return-unless file, null/no-contents, true/error
34 contents:&:source:char, sink:&:sink:char <- new-channel 30
35 start-running receive-from-file file, sink
36 ]
37
38 def slurp resources:&:resources, filename:text -> contents:text, error?:bool [
39 local-scope
40 load-inputs
41 source:&:source:char, error?:bool <- start-reading resources, filename
42 return-if error?, null/no-contents
43 buf:&:buffer:char <- new-buffer 30/capacity
44 {
45 c:char, done?:bool, source <- read source
46 break-if done?
47 buf <- append buf, c
48 loop
49 }
50 contents <- buffer-to-array buf
51 ]
52
53 def start-reading-from-fake-resource resources:&:resources, resource:text -> contents:&:source:char, error?:bool [
54 local-scope
55 load-inputs
56 error? <- copy false
57 i:num <- copy 0
58 data:&:@:resource <- get *resources, data:offset
59 len:num <- length *data
60 {
61 done?:bool <- greater-or-equal i, len
62 break-if done?
63 tmp:resource <- index *data, i
64 i <- add i, 1
65 curr-resource:text <- get tmp, name:offset
66 found?:bool <- equal resource, curr-resource
67 loop-unless found?
68 contents:&:source:char, sink:&:sink:char <- new-channel 30
69 curr-contents:text <- get tmp, contents:offset
70 start-running receive-from-text curr-contents, sink
71 return
72 }
73 return null/no-such-resource, true/error-found
74 ]
75
76 def receive-from-file file:num, sink:&:sink:char -> sink:&:sink:char [
77 local-scope
78 load-inputs
79 {
80 c:char, eof?:bool <- $read-from-file file
81 break-if eof?
82 ">like an array, except that you can index it with arbitrary types
# and not just non-negative whole numbers.
# incomplete; doesn't handle hash conflicts
scenario table-read-write [
local-scope
tab:&:table:num:num <- new-table 30
run [
put-index tab, 12, 34
60:num/raw, 61:bool/raw <- index tab, 12
]
memory-should-contain [
60 <- 34
61 <- 1 # found
]
]
scenario table-read-write-non-integer [
local-scope
tab:&:table:text:num <- new-table 30
run [
put-index tab, [abc def], 34
1:num/raw, 2:bool/raw <- index tab, [abc def]
]
memory-should-contain [
1 <- 34
2 <- 1 # found
]
]
scenario table-read-not-found [
local-scope
tab:&:table:text:num <- new-table 30
run [
1:num/raw, 2:bool/raw <- index tab, [abc def]
]
memory-should-contain [
1 <- 0
2 <- 0 # not found
]
]
container table:_key:_value [
length:num
capacity:num
data:&:@:table-row:_key:_value
]
container table-row:_key:_value [
occupied?:bool
key:_key
value:_value
]
def new-table capacity:num -> result:&:table:_key:_value [
local-scope
load-ingredients
result <- new {(table _key _value): type}
data:&:@:table-row:_key:_value <- new {(table-row _key _value): type}, capacity
*result <- merge 0/length, capacity, data
]
# todo: tag results as /required so that call-sites are forbidden from ignoring them
# then we could handle conflicts simply by resizing the table
def put-index table:&:table:_key:_value, key:_key, value:_value -> table:&:table:_key:_value [
local-scope
load-ingredients
hash:num <- hash key
hash