1 def random generator:&:stream:num -> result:num, fail?:bool, generator:&:stream:num [
 2   local-scope
 3   load-ingredients
 4   {
 5   ¦ break-if generator
 6   ¦ # generator is 0? use real random-number generator
 7   ¦ result <- real-random
 8   ¦ return result, 0/false
 9   }
10   result, fail?, generator <- read generator
11 ]
12 
13 # helper for tests
14 def assume-random-numbers -> result:&:stream:num [
15   local-scope
16   load-ingredients
17   # compute result-len, space to allocate in result
18   result-len:num <- copy 0
19   {
20   ¦ _, arg-received?:bool <- next-ingredient
21   ¦ break-unless arg-received?
22   ¦ result-len <- add result-len, 1
23   ¦ loop
24   }
25   rewind-ingredients
26   result-data:&:@:num <- new number:type, result-len
27   idx:num <- copy 0
28   {
29   ¦ curr:num, arg-received?:bool <- next-ingredient
30   ¦ break-unless arg-received?
31   ¦ *result-data <- put-index *result-data, idx, curr
32   ¦ idx <- add idx, 1
33   ¦ loop
34   }
35   result <- new-stream result-data
36 ]
37 
38 scenario random-numbers-in-scenario [
39   local-scope
40   source:&:stream:num <- assume-random-numbers 34, 35, 37
41   1:num/raw, 2:bool/raw <- random source
42   3:num/raw, 4:bool/raw <- random source
43   5:num/raw, 6:bool/raw <- random source
44   7:num/raw, 8:bool/raw <- random source
45   memory-should-contain [
46   ¦ 1 <- 34
47   ¦ 2 <- 0  # everything went well
48   ¦ 3 <- 35
49   ¦ 4 <- 0  # everything went well
50   ¦ 5 <- 37
51   ¦ 6 <- 0  # everything went well
52   ¦ 7 <- 0  # empty result
53   ¦ 8 <- 1  # end of stream
54   ]
55 ]
56 
57 # generate a random integer in the semi-open interval [start, end)
58 def random-in-range generator:&:stream:num, start:num, end:num -> result:num, fail?:bool, generator:&:stream:num [
59   local-scope
60   load-ingredients
61   result, fail?, generator <- random generator
62   return-if fail?
63   delta:num <- subtract end, start
64   _, result <- divide-with-remainder result, delta
65   result <- add result, start
66 ]
67 
68 scenario random-in-range [
69   local-scope
70   source:&:stream:num <- assume-random-numbers 91
71   1:num/raw <- random-in-range source, 40, 50
72   memory-should-contain [
73   ¦ 1 <- 41
74   ]
75 ]