3389
This commit is contained in:
parent
80df524b56
commit
760f683f27
|
@ -224,9 +224,9 @@ $error: 0
|
|||
|
||||
:(scenario transform_names_transforms_container_elements)
|
||||
def main [
|
||||
p:address:point <- copy 0
|
||||
a:num <- get *p:address:point, y:offset
|
||||
b:num <- get *p:address:point, x:offset
|
||||
p:&:point <- copy 0
|
||||
a:num <- get *p:&:point, y:offset
|
||||
b:num <- get *p:&:point, x:offset
|
||||
]
|
||||
+name: element y of type point is at offset 1
|
||||
+name: element x of type point is at offset 0
|
||||
|
|
62
043space.cc
62
043space.cc
|
@ -9,7 +9,7 @@ def main [
|
|||
# pretend address:array:location; in practice we'll use new
|
||||
10:num <- copy 0 # refcount
|
||||
11:num <- copy 5 # length
|
||||
default-space:address:array:location <- copy 10/unsafe
|
||||
default-space:&:array:location <- copy 10/unsafe
|
||||
1:num <- copy 23
|
||||
]
|
||||
+mem: storing 23 in location 13
|
||||
|
@ -22,9 +22,9 @@ def main [
|
|||
1000:num <- copy 0 # refcount
|
||||
1001:num <- copy 5 # length
|
||||
# actual start of this recipe
|
||||
default-space:address:array:location <- copy 1000/unsafe
|
||||
1:address:num <- copy 2000/unsafe # even local variables always contain raw addresses
|
||||
8:num/raw <- copy *1:address:num
|
||||
default-space:&:array:location <- copy 1000/unsafe
|
||||
1:&:num <- copy 2000/unsafe # even local variables always contain raw addresses
|
||||
8:num/raw <- copy *1:&:num
|
||||
]
|
||||
+mem: storing 34 in location 8
|
||||
|
||||
|
@ -95,8 +95,8 @@ bool is_space(const reagent& r) {
|
|||
|
||||
:(scenario get_default_space)
|
||||
def main [
|
||||
default-space:address:array:location <- copy 10/unsafe
|
||||
1:address:array:location/raw <- copy default-space:address:array:location
|
||||
default-space:&:array:location <- copy 10/unsafe
|
||||
1:&:array:location/raw <- copy default-space:&:array:location
|
||||
]
|
||||
+mem: storing 10 in location 1
|
||||
|
||||
|
@ -118,9 +118,9 @@ def main [
|
|||
1000:num <- copy 0 # refcount
|
||||
1001:num <- copy 5 # length
|
||||
# actual start of this recipe
|
||||
default-space:address:array:location <- copy 1000/unsafe
|
||||
1:address:point <- copy 2000/unsafe
|
||||
9:num/raw <- get *1:address:point, 1:offset
|
||||
default-space:&:array:location <- copy 1000/unsafe
|
||||
1:&:point <- copy 2000/unsafe
|
||||
9:num/raw <- get *1:&:point, 1:offset
|
||||
]
|
||||
+mem: storing 35 in location 9
|
||||
|
||||
|
@ -139,9 +139,9 @@ def main [
|
|||
1000:num <- copy 0 # refcount
|
||||
1001:num <- copy 5 # length
|
||||
# actual start of this recipe
|
||||
default-space:address:array:location <- copy 1000/unsafe
|
||||
1:address:array:num <- copy 2000/unsafe
|
||||
9:num/raw <- index *1:address:array:num, 1
|
||||
default-space:&:array:location <- copy 1000/unsafe
|
||||
1:&:array:num <- copy 2000/unsafe
|
||||
9:num/raw <- index *1:&:array:num, 1
|
||||
]
|
||||
+mem: storing 35 in location 9
|
||||
|
||||
|
@ -168,7 +168,7 @@ if (s == "number-of-locals") return true;
|
|||
|
||||
:(before "End Rewrite Instruction(curr, recipe result)")
|
||||
// rewrite `new-default-space` to
|
||||
// `default-space:address:array:location <- new location:type, number-of-locals:literal`
|
||||
// `default-space:&:array:location <- new location:type, number-of-locals:literal`
|
||||
// where N is Name[recipe][""]
|
||||
if (curr.name == "new-default-space") {
|
||||
rewrite_default_space_instruction(curr);
|
||||
|
@ -192,14 +192,14 @@ if (x.name == "number-of-locals") {
|
|||
|
||||
:(scenario local_scope)
|
||||
def main [
|
||||
1:address <- foo
|
||||
2:address <- foo
|
||||
3:bool <- equal 1:address, 2:address
|
||||
1:& <- foo
|
||||
2:& <- foo
|
||||
3:bool <- equal 1:&, 2:&
|
||||
]
|
||||
def foo [
|
||||
local-scope
|
||||
x:num <- copy 34
|
||||
return default-space:address:array:location
|
||||
return default-space:&:array:location
|
||||
]
|
||||
# both calls to foo should have received the same default-space
|
||||
+mem: storing 1 in location 3
|
||||
|
@ -304,21 +304,21 @@ void rewrite_default_space_instruction(instruction& curr) {
|
|||
curr.ingredients.push_back(reagent("number-of-locals:literal"));
|
||||
if (!curr.products.empty())
|
||||
raise << "new-default-space can't take any results\n" << end();
|
||||
curr.products.push_back(reagent("default-space:address:array:location"));
|
||||
curr.products.push_back(reagent("default-space:&:array:location"));
|
||||
}
|
||||
|
||||
:(scenario local_scope_frees_up_addresses_inside_containers)
|
||||
container foo [
|
||||
x:num
|
||||
y:address:num
|
||||
y:&:num
|
||||
]
|
||||
def main [
|
||||
local-scope
|
||||
x:address:num <- new number:type
|
||||
y:foo <- merge 34, x:address:num
|
||||
x:&:num <- new number:type
|
||||
y:foo <- merge 34, x:&:num
|
||||
# x and y are both cleared when main returns
|
||||
]
|
||||
+mem: clearing x:address:num
|
||||
+mem: clearing x:&:num
|
||||
+mem: decrementing refcount of 1006: 2 -> 1
|
||||
+mem: clearing y:foo
|
||||
+mem: decrementing refcount of 1006: 1 -> 0
|
||||
|
@ -327,23 +327,23 @@ def main [
|
|||
:(scenario local_scope_returns_addresses_inside_containers)
|
||||
container foo [
|
||||
x:num
|
||||
y:address:num
|
||||
y:&:num
|
||||
]
|
||||
def f [
|
||||
local-scope
|
||||
x:address:num <- new number:type
|
||||
*x:address:num <- copy 12
|
||||
y:foo <- merge 34, x:address:num
|
||||
x:&:num <- new number:type
|
||||
*x:&:num <- copy 12
|
||||
y:foo <- merge 34, x:&:num
|
||||
# since y is 'escaping' f, it should not be cleared
|
||||
return y:foo
|
||||
]
|
||||
def main [
|
||||
1:foo <- f
|
||||
3:num <- get 1:foo, x:offset
|
||||
4:address:num <- get 1:foo, y:offset
|
||||
5:num <- copy *4:address:num
|
||||
4:&:num <- get 1:foo, y:offset
|
||||
5:num <- copy *4:&:num
|
||||
1:foo <- put 1:foo, y:offset, 0
|
||||
4:address:num <- copy 0
|
||||
4:&:num <- copy 0
|
||||
]
|
||||
+mem: storing 34 in location 1
|
||||
+mem: storing 1006 in location 2
|
||||
|
@ -363,8 +363,8 @@ def main [
|
|||
:(scenario local_scope_claims_return_values_when_not_saved)
|
||||
def f [
|
||||
local-scope
|
||||
x:address:num <- new number:type
|
||||
reply x:address:num
|
||||
x:&:num <- new number:type
|
||||
reply x:&:num
|
||||
]
|
||||
def main [
|
||||
f # doesn't save result
|
||||
|
|
|
@ -14,8 +14,8 @@ def main [
|
|||
20:num <- copy 0 # refcount
|
||||
21:num <- copy 5 # length
|
||||
# actual start of this recipe
|
||||
default-space:address:array:location <- copy 10/unsafe
|
||||
0:address:array:location/names:dummy <- copy 20/unsafe # later layers will explain the /names: property
|
||||
default-space:&:array:location <- copy 10/unsafe
|
||||
0:&:array:location/names:dummy <- copy 20/unsafe # later layers will explain the /names: property
|
||||
1:num <- copy 32
|
||||
1:num/space:1 <- copy 33
|
||||
]
|
||||
|
|
|
@ -5,20 +5,20 @@
|
|||
|
||||
:(scenario closure)
|
||||
def main [
|
||||
default-space:address:array:location <- new location:type, 30
|
||||
1:address:array:location/names:new-counter <- new-counter
|
||||
2:num/raw <- increment-counter 1:address:array:location/names:new-counter
|
||||
3:num/raw <- increment-counter 1:address:array:location/names:new-counter
|
||||
default-space:&:array:location <- new location:type, 30
|
||||
1:&:array:location/names:new-counter <- new-counter
|
||||
2:num/raw <- increment-counter 1:&:array:location/names:new-counter
|
||||
3:num/raw <- increment-counter 1:&:array:location/names:new-counter
|
||||
]
|
||||
def new-counter [
|
||||
default-space:address:array:location <- new location:type, 30
|
||||
default-space:&:array:location <- new location:type, 30
|
||||
x:num <- copy 23
|
||||
y:num <- copy 3 # variable that will be incremented
|
||||
return default-space:address:array:location
|
||||
return default-space:&:array:location
|
||||
]
|
||||
def increment-counter [
|
||||
default-space:address:array:location <- new location:type, 30
|
||||
0:address:array:location/names:new-counter <- next-ingredient # outer space must be created by 'new-counter' above
|
||||
default-space:&:array:location <- new location:type, 30
|
||||
0:&:array:location/names:new-counter <- next-ingredient # outer space must be created by 'new-counter' above
|
||||
y:num/space:1 <- add y:num/space:1, 1 # increment
|
||||
y:num <- copy 234 # dummy
|
||||
return y:num/space:1
|
||||
|
@ -151,18 +151,18 @@ def f [
|
|||
:(scenario local_scope_ignores_nonlocal_spaces)
|
||||
def new-scope [
|
||||
new-default-space
|
||||
x:address:num <- new number:type
|
||||
*x:address:num <- copy 34
|
||||
return default-space:address:array:location
|
||||
x:&:num <- new number:type
|
||||
*x:&:num <- copy 34
|
||||
return default-space:&:array:location
|
||||
]
|
||||
def use-scope [
|
||||
local-scope
|
||||
outer:address:array:location <- next-ingredient
|
||||
0:address:array:location/names:new-scope <- copy outer:address:array:location
|
||||
return *x:address:num/space:1
|
||||
outer:&:array:location <- next-ingredient
|
||||
0:&:array:location/names:new-scope <- copy outer:&:array:location
|
||||
return *x:&:num/space:1
|
||||
]
|
||||
def main [
|
||||
1:address:array:location/raw <- new-scope
|
||||
2:num/raw <- use-scope 1:address:array:location/raw
|
||||
1:&:array:location/raw <- new-scope
|
||||
2:num/raw <- use-scope 1:&:array:location/raw
|
||||
]
|
||||
+mem: storing 34 in location 2
|
||||
|
|
|
@ -18,8 +18,8 @@ def main [
|
|||
20:num <- copy 0 # refcount
|
||||
21:num <- copy 5 # length
|
||||
# actual start of this recipe
|
||||
global-space:address:array:location <- copy 20/unsafe
|
||||
default-space:address:array:location <- copy 10/unsafe
|
||||
global-space:&:array:location <- copy 20/unsafe
|
||||
default-space:&:array:location <- copy 10/unsafe
|
||||
1:num <- copy 23
|
||||
1:num/space:global <- copy 24
|
||||
]
|
||||
|
@ -63,7 +63,7 @@ if (x.name == "global-space") {
|
|||
|
||||
:(scenario global_space_with_names)
|
||||
def main [
|
||||
global-space:address:array:location <- new location:type, 10
|
||||
global-space:&:array:location <- new location:type, 10
|
||||
x:num <- copy 23
|
||||
1:num/space:global <- copy 24
|
||||
]
|
||||
|
|
|
@ -101,10 +101,10 @@ def main [
|
|||
:(scenario typo_in_address_type_fails)
|
||||
% Hide_errors = true;
|
||||
def main [
|
||||
y:address:charcter <- new character:type
|
||||
y:&:charcter <- new character:type
|
||||
*y <- copy 67
|
||||
]
|
||||
+error: main: unknown type charcter in 'y:address:charcter <- new character:type'
|
||||
+error: main: unknown type charcter in 'y:&:charcter <- new character:type'
|
||||
|
||||
:(scenario array_type_without_size_fails)
|
||||
% Hide_errors = true;
|
||||
|
@ -119,7 +119,7 @@ def foo [ # dummy
|
|||
]
|
||||
def main [
|
||||
local-scope
|
||||
0:address:array:location/names:foo <- copy 0 # specify surrounding space
|
||||
0:&:array:location/names:foo <- copy 0 # specify surrounding space
|
||||
x:bool <- copy 1/true
|
||||
x:num/space:1 <- copy 34
|
||||
x/space:1 <- copy 35
|
||||
|
|
|
@ -272,7 +272,7 @@ void check_calls_against_header(const recipe_ordinal r) {
|
|||
def add2 x:num, y:num -> z:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z:address:num <- copy 0/unsafe
|
||||
z:&:num <- copy 0/unsafe
|
||||
return z
|
||||
]
|
||||
+error: add2: replied with the wrong type at 'return z'
|
||||
|
@ -304,7 +304,7 @@ void check_reply_instructions_against_header(const recipe_ordinal r) {
|
|||
def add2 x:num, y:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z:address:num <- copy 0/unsafe
|
||||
z:&:num <- copy 0/unsafe
|
||||
return z
|
||||
]
|
||||
+error: add2: replied with the wrong number of products at 'return z'
|
||||
|
|
|
@ -452,13 +452,13 @@ $error: 0
|
|||
|
||||
:(scenario static_dispatch_works_with_compound_type_containing_container_defined_after_first_use)
|
||||
def main [
|
||||
x:address:foo <- new foo:type
|
||||
x:&:foo <- new foo:type
|
||||
test x
|
||||
]
|
||||
container foo [
|
||||
x:num
|
||||
]
|
||||
def test a:address:foo -> z:num [
|
||||
def test a:&:foo -> z:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z:num <- get *a, x:offset
|
||||
|
@ -467,10 +467,10 @@ $error: 0
|
|||
|
||||
:(scenario static_dispatch_works_with_compound_type_containing_container_defined_after_second_use)
|
||||
def main [
|
||||
x:address:foo <- new foo:type
|
||||
x:&:foo <- new foo:type
|
||||
test x
|
||||
]
|
||||
def test a:address:foo -> z:num [
|
||||
def test a:&:foo -> z:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z:num <- get *a, x:offset
|
||||
|
@ -484,7 +484,7 @@ $error: 0
|
|||
def main [
|
||||
1:num <- foo 0
|
||||
]
|
||||
def foo x:address:num -> y:num [
|
||||
def foo x:&:num -> y:num [
|
||||
return 34
|
||||
]
|
||||
def foo x:num -> y:num [
|
||||
|
@ -582,12 +582,12 @@ def foo x:num -> y:num [
|
|||
load-ingredients
|
||||
return 34
|
||||
]
|
||||
def foo x:address:num -> y:num [
|
||||
def foo x:&:num -> y:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return 35
|
||||
]
|
||||
def! foo x:address:num -> y:num [
|
||||
def! foo x:&:num -> y:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return 36
|
||||
|
|
|
@ -252,8 +252,8 @@ container foo:_t [
|
|||
y:num
|
||||
]
|
||||
def main [
|
||||
1:foo:address:point <- merge 34/unsafe, 48
|
||||
3:address:point <- get 1:foo:address:point, x:offset
|
||||
1:foo:&:point <- merge 34/unsafe, 48
|
||||
3:&:point <- get 1:foo:&:point, x:offset
|
||||
]
|
||||
+mem: storing 34 in location 3
|
||||
|
||||
|
@ -449,7 +449,7 @@ void test_replace_middle_type_ingredient_with_multiple2() {
|
|||
|
||||
void test_replace_middle_type_ingredient_with_multiple3() {
|
||||
run("container foo_table:_key:_value [\n"
|
||||
" data:address:array:foo_table_row:_key:_value\n"
|
||||
" data:&:array:foo_table_row:_key:_value\n"
|
||||
"]\n"
|
||||
"\n"
|
||||
"container foo_table_row:_key:_value [\n"
|
||||
|
@ -528,7 +528,7 @@ void test_container_sizes_compound_type_ingredient() {
|
|||
" x:num\n"
|
||||
" y:_t\n"
|
||||
"]\n");
|
||||
reagent r("x:foo:address:point");
|
||||
reagent r("x:foo:&:point");
|
||||
compute_container_sizes(r);
|
||||
CHECK_EQ(r.metadata.size, 2);
|
||||
// scan also pre-computes metadata for type ingredient
|
||||
|
@ -540,7 +540,7 @@ void test_container_sizes_compound_type_ingredient() {
|
|||
void test_container_sizes_recursive_shape_shifting_container() {
|
||||
run("container foo:_t [\n"
|
||||
" x:num\n"
|
||||
" y:address:foo:_t\n"
|
||||
" y:&:foo:_t\n"
|
||||
"]\n");
|
||||
reagent r2("x:foo:num");
|
||||
compute_container_sizes(r2);
|
||||
|
@ -565,7 +565,7 @@ void test_container_address_offsets_in_shape_shifting_container() {
|
|||
" x:num\n"
|
||||
" y:_t\n"
|
||||
"]\n");
|
||||
reagent r("x:foo:address:num");
|
||||
reagent r("x:foo:&:num");
|
||||
compute_container_sizes(r);
|
||||
compute_container_address_offsets(r);
|
||||
CHECK_EQ(SIZE(r.metadata.address), 1);
|
||||
|
@ -586,7 +586,7 @@ void test_container_address_offsets_in_nested_shape_shifting_container() {
|
|||
" x:_t\n"
|
||||
" y:foo:_t\n"
|
||||
"]\n");
|
||||
reagent r("x:bar:address:num");
|
||||
reagent r("x:bar:&:num");
|
||||
CLEAR_TRACE;
|
||||
compute_container_sizes(r);
|
||||
compute_container_address_offsets(r);
|
||||
|
|
|
@ -587,14 +587,14 @@ def foo a:_t [
|
|||
|
||||
:(scenario shape_shifting_recipe_handles_shape_shifting_new_ingredient)
|
||||
def main [
|
||||
1:address:foo:point <- bar 3
|
||||
11:foo:point <- copy *1:address:foo:point
|
||||
1:&:foo:point <- bar 3
|
||||
11:foo:point <- copy *1:&:foo:point
|
||||
]
|
||||
container foo:_t [
|
||||
x:_t
|
||||
y:num
|
||||
]
|
||||
def bar x:num -> result:address:foo:_t [
|
||||
def bar x:num -> result:&:foo:_t [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# new refers to _t in its ingredient *value*
|
||||
|
@ -606,10 +606,10 @@ def bar x:num -> result:address:foo:_t [
|
|||
|
||||
:(scenario shape_shifting_recipe_handles_shape_shifting_new_ingredient_2)
|
||||
def main [
|
||||
1:address:foo:point <- bar 3
|
||||
11:foo:point <- copy *1:address:foo:point
|
||||
1:&:foo:point <- bar 3
|
||||
11:foo:point <- copy *1:&:foo:point
|
||||
]
|
||||
def bar x:num -> result:address:foo:_t [
|
||||
def bar x:num -> result:&:foo:_t [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# new refers to _t in its ingredient *value*
|
||||
|
@ -628,7 +628,7 @@ container foo:_t [
|
|||
def main [
|
||||
_ <- bar 34
|
||||
]
|
||||
def bar x:_t -> result:address:_t [
|
||||
def bar x:_t -> result:&:_t [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- copy 0
|
||||
|
@ -642,7 +642,7 @@ void test_shape_shifting_new_ingredient_does_not_pollute_global_namespace() {
|
|||
transform("def barz x:_elem [\n"
|
||||
" local-scope\n"
|
||||
" load-ingredients\n"
|
||||
" y:address:num <- new _elem:type\n"
|
||||
" y:&:num <- new _elem:type\n"
|
||||
"]\n"
|
||||
"def fooz [\n"
|
||||
" local-scope\n"
|
||||
|
@ -664,10 +664,10 @@ void test_shape_shifting_new_ingredient_does_not_pollute_global_namespace() {
|
|||
|
||||
:(scenario shape_shifting_recipe_supports_compound_types)
|
||||
def main [
|
||||
1:address:point <- new point:type
|
||||
*1:address:point <- put *1:address:point, y:offset, 34
|
||||
3:address:point <- bar 1:address:point # specialize _t to address:point
|
||||
4:point <- copy *3:address:point
|
||||
1:&:point <- new point:type
|
||||
*1:&:point <- put *1:&:point, y:offset, 34
|
||||
3:&:point <- bar 1:&:point # specialize _t to address:point
|
||||
4:point <- copy *3:&:point
|
||||
]
|
||||
def bar a:_t -> result:_t [
|
||||
local-scope
|
||||
|
@ -680,13 +680,13 @@ def bar a:_t -> result:_t [
|
|||
% Hide_errors = true;
|
||||
def main [
|
||||
a:num <- copy 3
|
||||
b:address:num <- foo a
|
||||
b:&:num <- foo a
|
||||
]
|
||||
def foo a:_t -> b:_t [
|
||||
load-ingredients
|
||||
b <- copy a
|
||||
]
|
||||
+error: main: no call found for 'b:address:num <- foo a'
|
||||
+error: main: no call found for 'b:&:num <- foo a'
|
||||
|
||||
:(scenario specialize_inside_recipe_without_header)
|
||||
def main [
|
||||
|
@ -734,9 +734,9 @@ def foo x:_elem -> y:_elem [
|
|||
def main [
|
||||
local-scope
|
||||
# permit '0' to map to address to shape-shifting type-ingredient
|
||||
1:address:char/raw <- foo 0
|
||||
1:&:char/raw <- foo 0
|
||||
]
|
||||
def foo x:address:_elem -> y:address:_elem [
|
||||
def foo x:&:_elem -> y:&:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- copy x
|
||||
|
@ -751,7 +751,7 @@ def main [
|
|||
# ambiguous call: what's the type of its ingredient?!
|
||||
foo 0
|
||||
]
|
||||
def foo x:address:_elem -> y:address:_elem [
|
||||
def foo x:&:_elem -> y:&:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- copy x
|
||||
|
@ -803,7 +803,7 @@ container d2:_elem [
|
|||
# static dispatch between shape-shifting variants, _including pointer lookups_
|
||||
def main [
|
||||
e1:d1:num <- merge 3
|
||||
e2:address:d2:num <- new {(d2 number): type}
|
||||
e2:&:d2:num <- new {(d2 number): type}
|
||||
1:num/raw <- foo e1
|
||||
2:num/raw <- foo *e2 # different from previous scenario
|
||||
]
|
||||
|
@ -886,15 +886,15 @@ def foo x:_elem -> y:num [
|
|||
:(scenarios run)
|
||||
:(scenario specialize_most_similar_variant)
|
||||
def main [
|
||||
1:address:num <- new number:type
|
||||
2:num <- foo 1:address:num
|
||||
1:&:num <- new number:type
|
||||
2:num <- foo 1:&:num
|
||||
]
|
||||
def foo x:_elem -> y:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return 34
|
||||
]
|
||||
def foo x:address:_elem -> y:num [
|
||||
def foo x:&:_elem -> y:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return 35
|
||||
|
@ -905,17 +905,17 @@ def foo x:address:_elem -> y:num [
|
|||
# version with headers padded with lots of unrelated concrete types
|
||||
def main [
|
||||
1:num <- copy 23
|
||||
2:address:array:num <- copy 0
|
||||
3:num <- foo 2:address:array:num, 1:num
|
||||
2:&:array:num <- copy 0
|
||||
3:num <- foo 2:&:array:num, 1:num
|
||||
]
|
||||
# variant with concrete type
|
||||
def foo dummy:address:array:num, x:num -> y:num, dummy:address:array:num [
|
||||
def foo dummy:&:array:num, x:num -> y:num, dummy:&:array:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return 34
|
||||
]
|
||||
# shape-shifting variant
|
||||
def foo dummy:address:array:num, x:_elem -> y:num, dummy:address:array:num [
|
||||
def foo dummy:&:array:num, x:_elem -> y:num, dummy:&:array:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return 35
|
||||
|
@ -931,7 +931,7 @@ def main [
|
|||
def foo x:text [
|
||||
2:num <- copy 34
|
||||
]
|
||||
def foo x:address:_elem [
|
||||
def foo x:&:_elem [
|
||||
2:num <- copy 35
|
||||
]
|
||||
# make sure the more precise version was used
|
||||
|
@ -965,7 +965,7 @@ def foo x:num -> y:num [
|
|||
return 34
|
||||
]
|
||||
# shape-shifting variant
|
||||
def foo x:address:_elem -> y:num [
|
||||
def foo x:&:_elem -> y:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return 35
|
||||
|
@ -978,13 +978,13 @@ def main [
|
|||
1:num <- foo 0
|
||||
]
|
||||
# variant with concrete address type
|
||||
def foo x:address:num -> y:num [
|
||||
def foo x:&:num -> y:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return 34
|
||||
]
|
||||
# shape-shifting variant
|
||||
def foo x:address:_elem -> y:num [
|
||||
def foo x:&:_elem -> y:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return 35
|
||||
|
@ -1026,7 +1026,7 @@ def main [
|
|||
x:foo2 <- merge 34
|
||||
y:num <- get x, z:offse # typo in 'offset'
|
||||
# define a variable with the same name 'z'
|
||||
z:address:num <- copy 34
|
||||
z:&:num <- copy 34
|
||||
# trigger specialization of the shape-shifting recipe
|
||||
foo *z
|
||||
]
|
||||
|
@ -1052,7 +1052,7 @@ $error: 0
|
|||
|
||||
:(scenario shape_shifting_recipe_coexists_with_primitive)
|
||||
# recipe overloading a primitive with a generic type
|
||||
def add a:address:foo:_elem [
|
||||
def add a:&:foo:_elem [
|
||||
assert 0, [should not get here]
|
||||
]
|
||||
def main [
|
||||
|
|
126
057immutable.cc
126
057immutable.cc
|
@ -20,11 +20,11 @@ $error: 0
|
|||
:(scenario can_modify_ingredients_that_are_also_products_2)
|
||||
def main [
|
||||
local-scope
|
||||
p:address:point <- new point:type
|
||||
p:&:point <- new point:type
|
||||
p <- foo p
|
||||
]
|
||||
# mutable address to container
|
||||
def foo p:address:point -> p:address:point [
|
||||
def foo p:&:point -> p:&:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
*p <- put *p, x:offset, 34
|
||||
|
@ -34,11 +34,11 @@ $error: 0
|
|||
:(scenario can_modify_ingredients_that_are_also_products_3)
|
||||
def main [
|
||||
local-scope
|
||||
p:address:array:num <- new number:type, 3
|
||||
p:&:array:num <- new number:type, 3
|
||||
p <- foo p
|
||||
]
|
||||
# mutable address
|
||||
def foo p:address:array:num -> p:address:array:num [
|
||||
def foo p:&:array:num -> p:&:array:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
*p <- put-index *p, 0, 34
|
||||
|
@ -48,13 +48,13 @@ $error: 0
|
|||
:(scenario ignore_literal_ingredients_for_immutability_checks)
|
||||
def main [
|
||||
local-scope
|
||||
p:address:d1 <- new d1:type
|
||||
p:&:d1 <- new d1:type
|
||||
q:num <- foo p
|
||||
]
|
||||
def foo p:address:d1 -> q:num [
|
||||
def foo p:&:d1 -> q:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:address:d1 <- new d1:type
|
||||
x:&:d1 <- new d1:type
|
||||
*x <- put *x, p:offset, 34 # ignore this 'p'
|
||||
reply 36
|
||||
]
|
||||
|
@ -68,11 +68,11 @@ $error: 0
|
|||
% Hide_errors = true;
|
||||
def main [
|
||||
local-scope
|
||||
x:address:num <- new number:type
|
||||
x:&:num <- new number:type
|
||||
foo x
|
||||
]
|
||||
# immutable address to primitive
|
||||
def foo x:address:num [
|
||||
def foo x:&:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
*x <- copy 34
|
||||
|
@ -102,10 +102,10 @@ def foo x:point-number [
|
|||
:(scenario can_modify_immutable_pointers)
|
||||
def main [
|
||||
local-scope
|
||||
x:address:num <- new number:type
|
||||
x:&:num <- new number:type
|
||||
foo x
|
||||
]
|
||||
def foo x:address:num [
|
||||
def foo x:&:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# modify the address, not the payload
|
||||
|
@ -117,10 +117,10 @@ $error: 0
|
|||
% Hide_errors = true;
|
||||
def main [
|
||||
local-scope
|
||||
x:address:num <- new number:type
|
||||
x:&:num <- new number:type
|
||||
foo x
|
||||
]
|
||||
def foo x:address:num [
|
||||
def foo x:&:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# modify address; ok
|
||||
|
@ -135,15 +135,15 @@ def foo x:address:num [
|
|||
% Hide_errors = true;
|
||||
def main [
|
||||
local-scope
|
||||
p:address:point <- new point:type
|
||||
p:&:point <- new point:type
|
||||
foo p
|
||||
]
|
||||
def foo p:address:point [
|
||||
def foo p:&:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
bar p
|
||||
]
|
||||
def bar p:address:point -> p:address:point [
|
||||
def bar p:&:point -> p:&:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# p could be modified here, but it doesn't have to be, it's already marked
|
||||
|
@ -155,13 +155,13 @@ def bar p:address:point -> p:address:point [
|
|||
% Hide_errors = true;
|
||||
def main [
|
||||
local-scope
|
||||
p:address:point <- new point:type
|
||||
p:&:point <- new point:type
|
||||
foo p
|
||||
]
|
||||
def foo p:address:point [
|
||||
def foo p:&:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
q:address:point <- copy p
|
||||
q:&:point <- copy p
|
||||
*q <- put *q, x:offset, 34
|
||||
]
|
||||
+error: foo: cannot modify 'q' in instruction '*q <- put *q, x:offset, 34' because that would modify p which is an ingredient of recipe foo but not also a product
|
||||
|
@ -169,13 +169,13 @@ def foo p:address:point [
|
|||
:(scenario can_modify_copies_of_mutable_ingredients)
|
||||
def main [
|
||||
local-scope
|
||||
p:address:point <- new point:type
|
||||
p:&:point <- new point:type
|
||||
foo p
|
||||
]
|
||||
def foo p:address:point -> p:address:point [
|
||||
def foo p:&:point -> p:&:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
q:address:point <- copy p
|
||||
q:&:point <- copy p
|
||||
*q <- put *q, x:offset, 34
|
||||
]
|
||||
$error: 0
|
||||
|
@ -183,32 +183,32 @@ $error: 0
|
|||
:(scenario cannot_modify_address_inside_immutable_ingredients)
|
||||
% Hide_errors = true;
|
||||
container foo [
|
||||
x:address:array:num # contains an address
|
||||
x:&:array:num # contains an address
|
||||
]
|
||||
def main [
|
||||
# don't run anything
|
||||
]
|
||||
def foo a:address:foo [
|
||||
def foo a:&:foo [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:address:array:num <- get *a, x:offset # just a regular get of the container
|
||||
x:&:array:num <- get *a, x:offset # just a regular get of the container
|
||||
*x <- put-index *x, 0, 34 # but then a put-index on the result
|
||||
]
|
||||
+error: foo: cannot modify 'x' in instruction '*x <- put-index *x, 0, 34' because that would modify a which is an ingredient of recipe foo but not also a product
|
||||
|
||||
:(scenario cannot_modify_address_inside_immutable_ingredients_2)
|
||||
container foo [
|
||||
x:address:array:num # contains an address
|
||||
x:&:array:num # contains an address
|
||||
]
|
||||
def main [
|
||||
# don't run anything
|
||||
]
|
||||
def foo a:address:foo [
|
||||
def foo a:&:foo [
|
||||
local-scope
|
||||
load-ingredients
|
||||
b:foo <- merge 0
|
||||
# modify b, completely unrelated to immutable ingredient a
|
||||
x:address:array:num <- get b, x:offset
|
||||
x:&:array:num <- get b, x:offset
|
||||
*x <- put-index *x, 0, 34
|
||||
]
|
||||
$error: 0
|
||||
|
@ -221,46 +221,46 @@ container foo [
|
|||
def main [
|
||||
# don't run anything
|
||||
]
|
||||
def foo a:address:array:address:num [
|
||||
def foo a:&:array:&:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:address:num <- index *a, 0 # just a regular index of the array
|
||||
x:&:num <- index *a, 0 # just a regular index of the array
|
||||
*x <- copy 34 # but then modify the result
|
||||
]
|
||||
+error: foo: cannot modify 'x' in instruction '*x <- copy 34' because that would modify a which is an ingredient of recipe foo but not also a product
|
||||
|
||||
:(scenario cannot_modify_address_inside_immutable_ingredients_4)
|
||||
container foo [
|
||||
x:address:array:num # contains an address
|
||||
x:&:array:num # contains an address
|
||||
]
|
||||
def main [
|
||||
# don't run anything
|
||||
]
|
||||
def foo a:address:array:address:num [
|
||||
def foo a:&:array:&:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
b:address:array:address:num <- new {(address number): type}, 3
|
||||
b:&:array:&:num <- new {(address number): type}, 3
|
||||
# modify b, completely unrelated to immutable ingredient a
|
||||
x:address:num <- index *b, 0
|
||||
x:&:num <- index *b, 0
|
||||
*x <- copy 34
|
||||
]
|
||||
$error: 0
|
||||
|
||||
:(scenario can_traverse_immutable_ingredients)
|
||||
container test-list [
|
||||
next:address:test-list
|
||||
next:&:test-list
|
||||
]
|
||||
def main [
|
||||
local-scope
|
||||
p:address:test-list <- new test-list:type
|
||||
p:&:test-list <- new test-list:type
|
||||
foo p
|
||||
]
|
||||
def foo p:address:test-list [
|
||||
def foo p:&:test-list [
|
||||
local-scope
|
||||
load-ingredients
|
||||
p2:address:test-list <- bar p
|
||||
p2:&:test-list <- bar p
|
||||
]
|
||||
def bar x:address:test-list -> y:address:test-list [
|
||||
def bar x:&:test-list -> y:&:test-list [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- get *x, next:offset
|
||||
|
@ -269,11 +269,11 @@ $error: 0
|
|||
|
||||
:(scenario treat_optional_ingredients_as_mutable)
|
||||
def main [
|
||||
k:address:num <- new number:type
|
||||
k:&:num <- new number:type
|
||||
test k
|
||||
]
|
||||
# recipe taking an immutable address ingredient
|
||||
def test k:address:num [
|
||||
def test k:&:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
foo k
|
||||
|
@ -282,7 +282,7 @@ def test k:address:num [
|
|||
def foo -> [
|
||||
local-scope
|
||||
load-ingredients
|
||||
k:address:num, found?:bool <- next-ingredient
|
||||
k:&:num, found?:bool <- next-ingredient
|
||||
# we don't further check k for immutability, but assume it's mutable
|
||||
]
|
||||
$error: 0
|
||||
|
@ -291,10 +291,10 @@ $error: 0
|
|||
% Hide_errors = true;
|
||||
def main [
|
||||
local-scope
|
||||
p:address:point <- new point:type
|
||||
p:&:point <- new point:type
|
||||
foo p
|
||||
]
|
||||
def foo p:address:point [
|
||||
def foo p:&:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
bar p
|
||||
|
@ -302,28 +302,28 @@ def foo p:address:point [
|
|||
def bar [
|
||||
local-scope
|
||||
load-ingredients
|
||||
p:address:point <- next-ingredient # optional ingredient; assumed to be mutable
|
||||
p:&:point <- next-ingredient # optional ingredient; assumed to be mutable
|
||||
]
|
||||
+error: foo: cannot modify 'p' in instruction 'bar p' because it's an ingredient of recipe foo but not also a product
|
||||
|
||||
//: when checking for immutable ingredients, remember to take space into account
|
||||
:(scenario check_space_of_reagents_in_immutability_checks)
|
||||
def main [
|
||||
a:address:array:location <- new-closure
|
||||
b:address:num <- new number:type
|
||||
run-closure b:address:num, a:address:array:location
|
||||
a:&:array:location <- new-closure
|
||||
b:&:num <- new number:type
|
||||
run-closure b:&:num, a:&:array:location
|
||||
]
|
||||
def new-closure [
|
||||
new-default-space
|
||||
x:address:num <- new number:type
|
||||
x:&:num <- new number:type
|
||||
return default-space
|
||||
]
|
||||
def run-closure x:address:num, s:address:array:location [
|
||||
def run-closure x:&:num, s:&:array:location [
|
||||
local-scope
|
||||
load-ingredients
|
||||
0:address:array:location/names:new-closure <- copy s
|
||||
0:&:array:location/names:new-closure <- copy s
|
||||
# different space; always mutable
|
||||
*x:address:num/space:1 <- copy 34
|
||||
*x:&:num/space:1 <- copy 34
|
||||
]
|
||||
$error: 0
|
||||
|
||||
|
@ -407,20 +407,20 @@ set<int> scan_contained_in_product_indices(const instruction& inst, set<int>& in
|
|||
% Hide_errors = true;
|
||||
container test-list [
|
||||
value:num
|
||||
next:address:test-list
|
||||
next:&:test-list
|
||||
]
|
||||
def main [
|
||||
local-scope
|
||||
p:address:test-list <- new test-list:type
|
||||
p:&:test-list <- new test-list:type
|
||||
foo p
|
||||
]
|
||||
def foo p:address:test-list [ # p is immutable
|
||||
def foo p:&:test-list [ # p is immutable
|
||||
local-scope
|
||||
load-ingredients
|
||||
p2:address:test-list <- test-next p # p2 is immutable
|
||||
p2:&:test-list <- test-next p # p2 is immutable
|
||||
*p2 <- put *p2, value:offset, 34
|
||||
]
|
||||
def test-next x:address:test-list -> y:address:test-list/contained-in:x [
|
||||
def test-next x:&:test-list -> y:&:test-list/contained-in:x [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- get *x, next:offset
|
||||
|
@ -527,25 +527,25 @@ set<int> ingredient_indices(const instruction& inst, const set<reagent>& ingredi
|
|||
:(scenario can_modify_contained_in_addresses)
|
||||
container test-list [
|
||||
value:num
|
||||
next:address:test-list
|
||||
next:&:test-list
|
||||
]
|
||||
def main [
|
||||
local-scope
|
||||
p:address:test-list <- new test-list:type
|
||||
p:&:test-list <- new test-list:type
|
||||
foo p
|
||||
]
|
||||
def foo p:address:test-list -> p:address:test-list [
|
||||
def foo p:&:test-list -> p:&:test-list [
|
||||
local-scope
|
||||
load-ingredients
|
||||
p2:address:test-list <- test-next p
|
||||
p2:&:test-list <- test-next p
|
||||
p <- test-remove p2, p
|
||||
]
|
||||
def test-next x:address:test-list -> y:address:test-list [
|
||||
def test-next x:&:test-list -> y:&:test-list [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- get *x, next:offset
|
||||
]
|
||||
def test-remove x:address:test-list/contained-in:from, from:address:test-list -> from:address:test-list [
|
||||
def test-remove x:&:test-list/contained-in:from, from:&:test-list -> from:&:test-list [
|
||||
local-scope
|
||||
load-ingredients
|
||||
*x <- put *x, value:offset, 34 # can modify x
|
||||
|
|
|
@ -13,7 +13,7 @@ def to-text-line x:_elem -> y:text [
|
|||
]
|
||||
|
||||
# variant for arrays (since we can't pass them around otherwise)
|
||||
def array-to-text-line x:address:array:_elem -> y:text [
|
||||
def array-to-text-line x:&:array:_elem -> y:text [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- to-text *x
|
||||
|
@ -25,7 +25,7 @@ scenario to-text-line-early-warning-for-static-dispatch [
|
|||
]
|
||||
|
||||
scenario array-to-text-line-early-warning-for-static-dispatch [
|
||||
n:address:array:num <- new number:type, 3
|
||||
n:&:array:num <- new number:type, 3
|
||||
x:text <- array-to-text-line n
|
||||
# just ensure there were no errors
|
||||
]
|
||||
|
|
34
061text.mu
34
061text.mu
|
@ -102,7 +102,7 @@ container buffer [
|
|||
data:text
|
||||
]
|
||||
|
||||
def new-buffer capacity:num -> result:address:buffer [
|
||||
def new-buffer capacity:num -> result:&:buffer [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- new buffer:type
|
||||
|
@ -117,7 +117,7 @@ def new-buffer capacity:num -> result:address:buffer [
|
|||
return result
|
||||
]
|
||||
|
||||
def grow-buffer buf:address:buffer -> buf:address:buffer [
|
||||
def grow-buffer buf:&:buffer -> buf:&:buffer [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# double buffer size
|
||||
|
@ -138,7 +138,7 @@ def grow-buffer buf:address:buffer -> buf:address:buffer [
|
|||
}
|
||||
]
|
||||
|
||||
def buffer-full? in:address:buffer -> result:bool [
|
||||
def buffer-full? in:&:buffer -> result:bool [
|
||||
local-scope
|
||||
load-ingredients
|
||||
len:num <- get *in, length:offset
|
||||
|
@ -148,7 +148,7 @@ def buffer-full? in:address:buffer -> result:bool [
|
|||
]
|
||||
|
||||
# most broadly applicable definition of append to a buffer: just call to-text
|
||||
def append buf:address:buffer, x:_elem -> buf:address:buffer [
|
||||
def append buf:&:buffer, x:_elem -> buf:&:buffer [
|
||||
local-scope
|
||||
load-ingredients
|
||||
text:text <- to-text x
|
||||
|
@ -164,7 +164,7 @@ def append buf:address:buffer, x:_elem -> buf:address:buffer [
|
|||
}
|
||||
]
|
||||
|
||||
def append buf:address:buffer, c:char -> buf:address:buffer [
|
||||
def append buf:&:buffer, c:char -> buf:&:buffer [
|
||||
local-scope
|
||||
load-ingredients
|
||||
len:num <- get *buf, length:offset
|
||||
|
@ -190,7 +190,7 @@ def append buf:address:buffer, c:char -> buf:address:buffer [
|
|||
*buf <- put *buf, length:offset, len
|
||||
]
|
||||
|
||||
def append buf:address:buffer, t:text -> buf:address:buffer [
|
||||
def append buf:&:buffer, t:text -> buf:&:buffer [
|
||||
local-scope
|
||||
load-ingredients
|
||||
len:num <- length *t
|
||||
|
@ -208,7 +208,7 @@ def append buf:address:buffer, t:text -> buf:address:buffer [
|
|||
scenario buffer-append-works [
|
||||
run [
|
||||
local-scope
|
||||
x:address:buffer <- new-buffer 3
|
||||
x:&:buffer <- new-buffer 3
|
||||
s1:text <- get *x, data:offset
|
||||
c:char <- copy 97/a
|
||||
x <- append x, c
|
||||
|
@ -250,7 +250,7 @@ scenario buffer-append-works [
|
|||
scenario buffer-append-to-empty [
|
||||
run [
|
||||
local-scope
|
||||
x:address:buffer <- new-buffer
|
||||
x:&:buffer <- new-buffer
|
||||
c:char <- copy 97/a
|
||||
x <- append x, c
|
||||
]
|
||||
|
@ -259,7 +259,7 @@ scenario buffer-append-to-empty [
|
|||
scenario buffer-append-handles-backspace [
|
||||
run [
|
||||
local-scope
|
||||
x:address:buffer <- new-buffer 3
|
||||
x:&:buffer <- new-buffer 3
|
||||
c:char <- copy 97/a
|
||||
x <- append x, c
|
||||
c:char <- copy 98/b
|
||||
|
@ -276,7 +276,7 @@ scenario buffer-append-handles-backspace [
|
|||
]
|
||||
]
|
||||
|
||||
def buffer-to-array in:address:buffer -> result:text [
|
||||
def buffer-to-array in:&:buffer -> result:text [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -310,7 +310,7 @@ def buffer-to-array in:address:buffer -> result:text [
|
|||
def append first:text -> result:text [
|
||||
local-scope
|
||||
load-ingredients
|
||||
buf:address:buffer <- new-buffer 30
|
||||
buf:&:buffer <- new-buffer 30
|
||||
# append first ingredient
|
||||
{
|
||||
break-unless first
|
||||
|
@ -1061,7 +1061,7 @@ scenario match-at-inside-bounds-2 [
|
|||
]
|
||||
]
|
||||
|
||||
def split s:text, delim:char -> result:address:array:text [
|
||||
def split s:text, delim:char -> result:&:array:text [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# empty text? return empty array
|
||||
|
@ -1107,7 +1107,7 @@ scenario text-split-1 [
|
|||
run [
|
||||
local-scope
|
||||
x:text <- new [a/b]
|
||||
y:address:array:text <- split x, 47/slash
|
||||
y:&:array:text <- split x, 47/slash
|
||||
10:num/raw <- length *y
|
||||
a:text <- index *y, 0
|
||||
b:text <- index *y, 1
|
||||
|
@ -1125,7 +1125,7 @@ scenario text-split-2 [
|
|||
run [
|
||||
local-scope
|
||||
x:text <- new [a/b/c]
|
||||
y:address:array:text <- split x, 47/slash
|
||||
y:&:array:text <- split x, 47/slash
|
||||
10:num/raw <- length *y
|
||||
a:text <- index *y, 0
|
||||
b:text <- index *y, 1
|
||||
|
@ -1146,7 +1146,7 @@ scenario text-split-missing [
|
|||
run [
|
||||
local-scope
|
||||
x:text <- new [abc]
|
||||
y:address:array:text <- split x, 47/slash
|
||||
y:&:array:text <- split x, 47/slash
|
||||
10:num/raw <- length *y
|
||||
a:text <- index *y, 0
|
||||
20:array:char/raw <- copy *a
|
||||
|
@ -1161,7 +1161,7 @@ scenario text-split-empty [
|
|||
run [
|
||||
local-scope
|
||||
x:text <- new []
|
||||
y:address:array:text <- split x, 47/slash
|
||||
y:&:array:text <- split x, 47/slash
|
||||
10:num/raw <- length *y
|
||||
]
|
||||
memory-should-contain [
|
||||
|
@ -1173,7 +1173,7 @@ scenario text-split-empty-piece [
|
|||
run [
|
||||
local-scope
|
||||
x:text <- new [a/b//c]
|
||||
y:address:array:text <- split x:text, 47/slash
|
||||
y:&:array:text <- split x:text, 47/slash
|
||||
10:num/raw <- length *y
|
||||
a:text <- index *y, 0
|
||||
b:text <- index *y, 1
|
||||
|
|
|
@ -25,7 +25,7 @@ def main [
|
|||
:(scenario rewrite_stashes_of_arrays)
|
||||
def main [
|
||||
local-scope
|
||||
n:address:array:num <- new number:type, 3
|
||||
n:&:array:num <- new number:type, 3
|
||||
stash *n
|
||||
]
|
||||
+transform: {stash_2_0: ("address" "array" "character")} <- array-to-text-line {n: ("address" "array" "number")}
|
||||
|
|
74
064list.mu
74
064list.mu
|
@ -5,23 +5,23 @@
|
|||
|
||||
container list:_elem [
|
||||
value:_elem
|
||||
next:address:list:_elem
|
||||
next:&:list:_elem
|
||||
]
|
||||
|
||||
def push x:_elem, in:address:list:_elem -> result:address:list:_elem [
|
||||
def push x:_elem, in:&:list:_elem -> result:&:list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- new {(list _elem): type}
|
||||
*result <- merge x, in
|
||||
]
|
||||
|
||||
def first in:address:list:_elem -> result:_elem [
|
||||
def first in:&:list:_elem -> result:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- get *in, value:offset
|
||||
]
|
||||
|
||||
def rest in:address:list:_elem -> result:address:list:_elem/contained-in:in [
|
||||
def rest in:&:list:_elem -> result:&:list:_elem/contained-in:in [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- get *in, next:offset
|
||||
|
@ -30,7 +30,7 @@ def rest in:address:list:_elem -> result:address:list:_elem/contained-in:in [
|
|||
scenario list-handling [
|
||||
run [
|
||||
local-scope
|
||||
x:address:list:num <- push 3, 0
|
||||
x:&:list:num <- push 3, 0
|
||||
x <- push 4, x
|
||||
x <- push 5, x
|
||||
10:num/raw <- first x
|
||||
|
@ -38,7 +38,7 @@ scenario list-handling [
|
|||
11:num/raw <- first x
|
||||
x <- rest x
|
||||
12:num/raw <- first x
|
||||
20:address:list:num/raw <- rest x
|
||||
20:&:list:num/raw <- rest x
|
||||
]
|
||||
memory-should-contain [
|
||||
10 <- 5
|
||||
|
@ -48,22 +48,22 @@ scenario list-handling [
|
|||
]
|
||||
]
|
||||
|
||||
def length l:address:list:_elem -> result:num [
|
||||
def length l:&:list:_elem -> result:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return-unless l, 0
|
||||
rest:address:list:_elem <- rest l
|
||||
rest:&:list:_elem <- rest l
|
||||
length-of-rest:num <- length rest
|
||||
result <- add length-of-rest, 1
|
||||
]
|
||||
|
||||
# insert 'x' after 'in'
|
||||
def insert x:_elem, in:address:list:_elem -> in:address:list:_elem [
|
||||
def insert x:_elem, in:&:list:_elem -> in:&:list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
new-node:address:list:_elem <- new {(list _elem): type}
|
||||
new-node:&:list:_elem <- new {(list _elem): type}
|
||||
*new-node <- put *new-node, value:offset, x
|
||||
next-node:address:list:_elem <- get *in, next:offset
|
||||
next-node:&:list:_elem <- get *in, next:offset
|
||||
*in <- put *in, next:offset, new-node
|
||||
*new-node <- put *new-node, next:offset, next-node
|
||||
]
|
||||
|
@ -71,10 +71,10 @@ def insert x:_elem, in:address:list:_elem -> in:address:list:_elem [
|
|||
scenario inserting-into-list [
|
||||
run [
|
||||
local-scope
|
||||
list:address:list:char <- push 3, 0
|
||||
list:&:list:char <- push 3, 0
|
||||
list <- push 4, list
|
||||
list <- push 5, list
|
||||
list2:address:list:char <- rest list # inside list
|
||||
list2:&:list:char <- rest list # inside list
|
||||
list2 <- insert 6, list2
|
||||
# check structure
|
||||
list2 <- copy list
|
||||
|
@ -97,10 +97,10 @@ scenario inserting-into-list [
|
|||
scenario inserting-at-end-of-list [
|
||||
run [
|
||||
local-scope
|
||||
list:address:list:char <- push 3, 0
|
||||
list:&:list:char <- push 3, 0
|
||||
list <- push 4, list
|
||||
list <- push 5, list
|
||||
list2:address:list:char <- rest list # inside list
|
||||
list2:&:list:char <- rest list # inside list
|
||||
list2 <- rest list2 # now at end of list
|
||||
list2 <- insert 6, list2
|
||||
# check structure like before
|
||||
|
@ -124,12 +124,12 @@ scenario inserting-at-end-of-list [
|
|||
scenario inserting-after-start-of-list [
|
||||
run [
|
||||
local-scope
|
||||
list:address:list:char <- push 3, 0
|
||||
list:&:list:char <- push 3, 0
|
||||
list <- push 4, list
|
||||
list <- push 5, list
|
||||
list <- insert 6, list
|
||||
# check structure like before
|
||||
list2:address:list:char <- copy list
|
||||
list2:&:list:char <- copy list
|
||||
10:char/raw <- first list2
|
||||
list2 <- rest list2
|
||||
11:char/raw <- first list2
|
||||
|
@ -150,20 +150,20 @@ scenario inserting-after-start-of-list [
|
|||
#
|
||||
# Returns null if and only if list is empty. Beware: in that case any other
|
||||
# pointers to the head are now invalid.
|
||||
def remove x:address:list:_elem/contained-in:in, in:address:list:_elem -> in:address:list:_elem [
|
||||
def remove x:&:list:_elem/contained-in:in, in:&:list:_elem -> in:&:list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if 'x' is null, return
|
||||
return-unless x
|
||||
next-node:address:list:_elem <- rest x
|
||||
next-node:&:list:_elem <- rest x
|
||||
# clear next pointer of 'x'
|
||||
*x <- put *x, next:offset, 0
|
||||
# if 'x' is at the head of 'in', return the new head
|
||||
at-head?:bool <- equal x, in
|
||||
return-if at-head?, next-node
|
||||
# compute prev-node
|
||||
prev-node:address:list:_elem <- copy in
|
||||
curr:address:list:_elem <- rest prev-node
|
||||
prev-node:&:list:_elem <- copy in
|
||||
curr:&:list:_elem <- rest prev-node
|
||||
{
|
||||
return-unless curr
|
||||
found?:bool <- equal curr, x
|
||||
|
@ -178,10 +178,10 @@ def remove x:address:list:_elem/contained-in:in, in:address:list:_elem -> in:add
|
|||
scenario removing-from-list [
|
||||
run [
|
||||
local-scope
|
||||
list:address:list:char <- push 3, 0
|
||||
list:&:list:char <- push 3, 0
|
||||
list <- push 4, list
|
||||
list <- push 5, list
|
||||
list2:address:list:char <- rest list # second element
|
||||
list2:&:list:char <- rest list # second element
|
||||
list <- remove list2, list
|
||||
10:bool/raw <- equal list2, 0
|
||||
# check structure like before
|
||||
|
@ -189,7 +189,7 @@ scenario removing-from-list [
|
|||
11:char/raw <- first list2
|
||||
list2 <- rest list2
|
||||
12:char/raw <- first list2
|
||||
20:address:list:char/raw <- rest list2
|
||||
20:&:list:char/raw <- rest list2
|
||||
]
|
||||
memory-should-contain [
|
||||
10 <- 0 # remove returned non-null
|
||||
|
@ -202,16 +202,16 @@ scenario removing-from-list [
|
|||
scenario removing-from-start-of-list [
|
||||
run [
|
||||
local-scope
|
||||
list:address:list:char <- push 3, 0
|
||||
list:&:list:char <- push 3, 0
|
||||
list <- push 4, list
|
||||
list <- push 5, list
|
||||
list <- remove list, list
|
||||
# check structure like before
|
||||
list2:address:list:char <- copy list
|
||||
list2:&:list:char <- copy list
|
||||
10:char/raw <- first list2
|
||||
list2 <- rest list2
|
||||
11:char/raw <- first list2
|
||||
20:address:list:char/raw <- rest list2
|
||||
20:&:list:char/raw <- rest list2
|
||||
]
|
||||
memory-should-contain [
|
||||
10 <- 4 # scanning next, skipping deleted element
|
||||
|
@ -223,11 +223,11 @@ scenario removing-from-start-of-list [
|
|||
scenario removing-from-end-of-list [
|
||||
run [
|
||||
local-scope
|
||||
list:address:list:char <- push 3, 0
|
||||
list:&:list:char <- push 3, 0
|
||||
list <- push 4, list
|
||||
list <- push 5, list
|
||||
# delete last element
|
||||
list2:address:list:char <- rest list
|
||||
list2:&:list:char <- rest list
|
||||
list2 <- rest list2
|
||||
list <- remove list2, list
|
||||
10:bool/raw <- equal list2, 0
|
||||
|
@ -236,7 +236,7 @@ scenario removing-from-end-of-list [
|
|||
11:char/raw <- first list2
|
||||
list2 <- rest list2
|
||||
12:char/raw <- first list2
|
||||
20:address:list:char/raw <- rest list2
|
||||
20:&:list:char/raw <- rest list2
|
||||
]
|
||||
memory-should-contain [
|
||||
10 <- 0 # remove returned non-null
|
||||
|
@ -249,7 +249,7 @@ scenario removing-from-end-of-list [
|
|||
scenario removing-from-singleton-list [
|
||||
run [
|
||||
local-scope
|
||||
list:address:list:char <- push 3, 0
|
||||
list:&:list:char <- push 3, 0
|
||||
list <- remove list, list
|
||||
1:num/raw <- copy list
|
||||
]
|
||||
|
@ -258,24 +258,24 @@ scenario removing-from-singleton-list [
|
|||
]
|
||||
]
|
||||
|
||||
def to-text in:address:list:_elem -> result:text [
|
||||
def to-text in:&:list:_elem -> result:text [
|
||||
local-scope
|
||||
load-ingredients
|
||||
buf:address:buffer <- new-buffer 80
|
||||
buf:&:buffer <- new-buffer 80
|
||||
buf <- to-buffer in, buf
|
||||
result <- buffer-to-array buf
|
||||
]
|
||||
|
||||
# variant of 'to-text' which stops printing after a few elements (and so is robust to cycles)
|
||||
def to-text-line in:address:list:_elem -> result:text [
|
||||
def to-text-line in:&:list:_elem -> result:text [
|
||||
local-scope
|
||||
load-ingredients
|
||||
buf:address:buffer <- new-buffer 80
|
||||
buf:&:buffer <- new-buffer 80
|
||||
buf <- to-buffer in, buf, 6 # max elements to display
|
||||
result <- buffer-to-array buf
|
||||
]
|
||||
|
||||
def to-buffer in:address:list:_elem, buf:address:buffer -> buf:address:buffer [
|
||||
def to-buffer in:&:list:_elem, buf:&:buffer -> buf:&:buffer [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -287,7 +287,7 @@ def to-buffer in:address:list:_elem, buf:address:buffer -> buf:address:buffer [
|
|||
val:_elem <- get *in, value:offset
|
||||
buf <- append buf, val
|
||||
# now prepare next
|
||||
next:address:list:_elem <- rest in
|
||||
next:&:list:_elem <- rest in
|
||||
nextn:num <- copy next
|
||||
return-unless next
|
||||
buf <- append buf, [ -> ]
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
|
||||
container duplex-list:_elem [
|
||||
value:_elem
|
||||
next:address:duplex-list:_elem
|
||||
prev:address:duplex-list:_elem
|
||||
next:&:duplex-list:_elem
|
||||
prev:&:duplex-list:_elem
|
||||
]
|
||||
|
||||
# should I say in/contained-in:result, allow ingredients to refer to products?
|
||||
def push x:_elem, in:address:duplex-list:_elem -> in:address:duplex-list:_elem [
|
||||
def push x:_elem, in:&:duplex-list:_elem -> in:&:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result:address:duplex-list:_elem <- new {(duplex-list _elem): type}
|
||||
result:&:duplex-list:_elem <- new {(duplex-list _elem): type}
|
||||
*result <- merge x, in, 0
|
||||
{
|
||||
break-unless in
|
||||
|
@ -19,21 +19,21 @@ def push x:_elem, in:address:duplex-list:_elem -> in:address:duplex-list:_elem [
|
|||
return result # needed explicitly because we need to replace 'in' with 'result'
|
||||
]
|
||||
|
||||
def first in:address:duplex-list:_elem -> result:_elem [
|
||||
def first in:&:duplex-list:_elem -> result:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return-unless in, 0
|
||||
result <- get *in, value:offset
|
||||
]
|
||||
|
||||
def next in:address:duplex-list:_elem -> result:address:duplex-list:_elem/contained-in:in [
|
||||
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:address:duplex-list:_elem -> result:address:duplex-list:_elem/contained-in:in [
|
||||
def prev in:&:duplex-list:_elem -> result:&:duplex-list:_elem/contained-in:in [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return-unless in, 0
|
||||
|
@ -47,19 +47,19 @@ scenario duplex-list-handling [
|
|||
# reserve locations 0-9 to check for missing null check
|
||||
10:num/raw <- copy 34
|
||||
11:num/raw <- copy 35
|
||||
list:address:duplex-list:char <- push 3, 0
|
||||
list:&:duplex-list:char <- push 3, 0
|
||||
list <- push 4, list
|
||||
list <- push 5, list
|
||||
list2:address:duplex-list:char <- copy 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:address:duplex-list:char/raw <- next list2
|
||||
31:char/raw <- first 30:address:duplex-list:char/raw
|
||||
32:address:duplex-list:char/raw <- next 30:address:duplex-list:char/raw
|
||||
33:address:duplex-list:char/raw <- prev 30:address:duplex-list:char/raw
|
||||
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
|
||||
|
@ -84,13 +84,13 @@ scenario duplex-list-handling [
|
|||
]
|
||||
|
||||
# insert 'x' after 'in'
|
||||
def insert x:_elem, in:address:duplex-list:_elem -> in:address:duplex-list:_elem [
|
||||
def insert x:_elem, in:&:duplex-list:_elem -> in:&:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
new-node:address:duplex-list:_elem <- new {(duplex-list _elem): type}
|
||||
new-node:&:duplex-list:_elem <- new {(duplex-list _elem): type}
|
||||
*new-node <- put *new-node, value:offset, x
|
||||
# save old next before changing it
|
||||
next-node:address:duplex-list:_elem <- get *in, next:offset
|
||||
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
|
||||
|
@ -101,10 +101,10 @@ def insert x:_elem, in:address:duplex-list:_elem -> in:address:duplex-list:_elem
|
|||
scenario inserting-into-duplex-list [
|
||||
run [
|
||||
local-scope
|
||||
list:address:duplex-list:char <- push 3, 0
|
||||
list:&:duplex-list:char <- push 3, 0
|
||||
list <- push 4, list
|
||||
list <- push 5, list
|
||||
list2:address:duplex-list:char <- next list # inside list
|
||||
list2:&:duplex-list:char <- next list # inside list
|
||||
list2 <- insert 6, list2
|
||||
# check structure like before
|
||||
list2 <- copy list
|
||||
|
@ -138,10 +138,10 @@ scenario inserting-into-duplex-list [
|
|||
scenario inserting-at-end-of-duplex-list [
|
||||
run [
|
||||
local-scope
|
||||
list:address:duplex-list:char <- push 3, 0
|
||||
list:&:duplex-list:char <- push 3, 0
|
||||
list <- push 4, list
|
||||
list <- push 5, list
|
||||
list2:address:duplex-list:char <- next list # inside list
|
||||
list2:&:duplex-list:char <- next list # inside list
|
||||
list2 <- next list2 # now at end of list
|
||||
list2 <- insert 6, list2
|
||||
# check structure like before
|
||||
|
@ -176,12 +176,12 @@ scenario inserting-at-end-of-duplex-list [
|
|||
scenario inserting-after-start-of-duplex-list [
|
||||
run [
|
||||
local-scope
|
||||
list:address:duplex-list:char <- push 3, 0
|
||||
list:&:duplex-list:char <- push 3, 0
|
||||
list <- push 4, list
|
||||
list <- push 5, list
|
||||
list <- insert 6, list
|
||||
# check structure like before
|
||||
list2:address:duplex-list:char <- copy list
|
||||
list2:&:duplex-list:char <- copy list
|
||||
10:char/raw <- first list2
|
||||
list2 <- next list2
|
||||
11:char/raw <- first list2
|
||||
|
@ -213,13 +213,13 @@ scenario inserting-after-start-of-duplex-list [
|
|||
#
|
||||
# Returns null if and only if list is empty. Beware: in that case any other
|
||||
# pointers to the head are now invalid.
|
||||
def remove x:address:duplex-list:_elem/contained-in:in, in:address:duplex-list:_elem -> in:address:duplex-list:_elem [
|
||||
def remove x:&:duplex-list:_elem/contained-in:in, in:&:duplex-list:_elem -> in:&:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if 'x' is null, return
|
||||
return-unless x
|
||||
next-node:address:duplex-list:_elem <- get *x, next:offset
|
||||
prev-node:address:duplex-list:_elem <- get *x, prev:offset
|
||||
next-node:&:duplex-list:_elem <- get *x, next:offset
|
||||
prev-node:&:duplex-list:_elem <- get *x, prev:offset
|
||||
# null x's pointers
|
||||
*x <- put *x, next:offset, 0
|
||||
*x <- put *x, prev:offset, 0
|
||||
|
@ -242,10 +242,10 @@ def remove x:address:duplex-list:_elem/contained-in:in, in:address:duplex-list:_
|
|||
scenario removing-from-duplex-list [
|
||||
run [
|
||||
local-scope
|
||||
list:address:duplex-list:char <- push 3, 0
|
||||
list:&:duplex-list:char <- push 3, 0
|
||||
list <- push 4, list
|
||||
list <- push 5, list
|
||||
list2:address:duplex-list:char <- next list # second element
|
||||
list2:&:duplex-list:char <- next list # second element
|
||||
list <- remove list2, list
|
||||
10:bool/raw <- equal list2, 0
|
||||
# check structure like before
|
||||
|
@ -253,7 +253,7 @@ scenario removing-from-duplex-list [
|
|||
11:char/raw <- first list2
|
||||
list2 <- next list2
|
||||
12:char/raw <- first list2
|
||||
20:address:duplex-list:char/raw <- next list2
|
||||
20:&:duplex-list:char/raw <- next list2
|
||||
list2 <- prev list2
|
||||
30:char/raw <- first list2
|
||||
40:bool/raw <- equal list, list2
|
||||
|
@ -271,16 +271,16 @@ scenario removing-from-duplex-list [
|
|||
scenario removing-from-start-of-duplex-list [
|
||||
run [
|
||||
local-scope
|
||||
list:address:duplex-list:char <- push 3, 0
|
||||
list:&:duplex-list:char <- push 3, 0
|
||||
list <- push 4, list
|
||||
list <- push 5, list
|
||||
list <- remove list, list
|
||||
# check structure like before
|
||||
list2:address:duplex-list:char <- copy list
|
||||
list2:&:duplex-list:char <- copy list
|
||||
10:char/raw <- first list2
|
||||
list2 <- next list2
|
||||
11:char/raw <- first list2
|
||||
20:address:duplex-list:char/raw <- next list2
|
||||
20:&:duplex-list:char/raw <- next list2
|
||||
list2 <- prev list2
|
||||
30:char/raw <- first list2
|
||||
40:bool/raw <- equal list, list2
|
||||
|
@ -297,11 +297,11 @@ scenario removing-from-start-of-duplex-list [
|
|||
scenario removing-from-end-of-duplex-list [
|
||||
run [
|
||||
local-scope
|
||||
list:address:duplex-list:char <- push 3, 0
|
||||
list:&:duplex-list:char <- push 3, 0
|
||||
list <- push 4, list
|
||||
list <- push 5, list
|
||||
# delete last element
|
||||
list2:address:duplex-list:char <- next list
|
||||
list2:&:duplex-list:char <- next list
|
||||
list2 <- next list2
|
||||
list <- remove list2, list
|
||||
10:bool/raw <- equal list2, 0
|
||||
|
@ -310,7 +310,7 @@ scenario removing-from-end-of-duplex-list [
|
|||
11:char/raw <- first list2
|
||||
list2 <- next list2
|
||||
12:char/raw <- first list2
|
||||
20:address:duplex-list:char/raw <- next list2
|
||||
20:&:duplex-list:char/raw <- next list2
|
||||
list2 <- prev list2
|
||||
30:char/raw <- first list2
|
||||
40:bool/raw <- equal list, list2
|
||||
|
@ -328,7 +328,7 @@ scenario removing-from-end-of-duplex-list [
|
|||
scenario removing-from-singleton-duplex-list [
|
||||
run [
|
||||
local-scope
|
||||
list:address:duplex-list:char <- push 3, 0
|
||||
list:&:duplex-list:char <- push 3, 0
|
||||
list <- remove list, list
|
||||
1:num/raw <- copy list
|
||||
]
|
||||
|
@ -342,10 +342,10 @@ scenario removing-from-singleton-duplex-list [
|
|||
# set end to 0 to delete everything past start.
|
||||
# can't set start to 0 to delete everything before end, because there's no
|
||||
# clean way to return the new head pointer.
|
||||
def remove-between start:address:duplex-list:_elem, end:address:duplex-list:_elem/contained-in:start -> start:address:duplex-list:_elem [
|
||||
def remove-between start:&:duplex-list:_elem, end:&:duplex-list:_elem/contained-in:start -> start:&:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
next:address:duplex-list:_elem <- get *start, next:offset
|
||||
next:&:duplex-list:_elem <- get *start, next:offset
|
||||
nothing-to-delete?:bool <- equal next, end
|
||||
return-if nothing-to-delete?
|
||||
assert next, [malformed duplex list]
|
||||
|
@ -356,7 +356,7 @@ def remove-between start:address:duplex-list:_elem, end:address:duplex-list:_ele
|
|||
return-unless end
|
||||
# end->prev->next = 0
|
||||
# end->prev = start
|
||||
prev:address:duplex-list:_elem <- get *end, prev:offset
|
||||
prev:&:duplex-list:_elem <- get *end, prev:offset
|
||||
assert prev, [malformed duplex list - 2]
|
||||
*prev <- put *prev, next:offset, 0
|
||||
*end <- put *end, prev:offset, start
|
||||
|
@ -365,19 +365,19 @@ def remove-between start:address:duplex-list:_elem, end:address:duplex-list:_ele
|
|||
scenario remove-range [
|
||||
# construct a duplex list with six elements [13, 14, 15, 16, 17, 18]
|
||||
local-scope
|
||||
list:address:duplex-list:char <- push 18, 0
|
||||
list:&:duplex-list:char <- push 18, 0
|
||||
list <- push 17, list
|
||||
list <- push 16, list
|
||||
list <- push 15, list
|
||||
list <- push 14, list
|
||||
list <- push 13, list
|
||||
1:address:duplex-list:char/raw <- copy list # save list
|
||||
1:&:duplex-list:char/raw <- copy list # save list
|
||||
run [
|
||||
local-scope
|
||||
list:address:duplex-list:char <- copy 1:address:duplex-list:char/raw # restore list
|
||||
list:&:duplex-list:char <- copy 1:&:duplex-list:char/raw # restore list
|
||||
# delete 16 onwards
|
||||
# first pointer: to the third element
|
||||
list2:address:duplex-list:char <- next list
|
||||
list2:&:duplex-list:char <- next list
|
||||
list2 <- next list2
|
||||
list2 <- remove-between list2, 0
|
||||
# now check the list
|
||||
|
@ -386,7 +386,7 @@ scenario remove-range [
|
|||
11:char/raw <- get *list, value:offset
|
||||
list <- next list
|
||||
12:char/raw <- get *list, value:offset
|
||||
20:address:duplex-list:char/raw <- next list
|
||||
20:&:duplex-list:char/raw <- next list
|
||||
]
|
||||
memory-should-contain [
|
||||
10 <- 13
|
||||
|
@ -399,21 +399,21 @@ scenario remove-range [
|
|||
scenario remove-range-to-final [
|
||||
local-scope
|
||||
# construct a duplex list with six elements [13, 14, 15, 16, 17, 18]
|
||||
list:address:duplex-list:char <- push 18, 0
|
||||
list:&:duplex-list:char <- push 18, 0
|
||||
list <- push 17, list
|
||||
list <- push 16, list
|
||||
list <- push 15, list
|
||||
list <- push 14, list
|
||||
list <- push 13, list
|
||||
1:address:duplex-list:char/raw <- copy list # save list
|
||||
1:&:duplex-list:char/raw <- copy list # save list
|
||||
run [
|
||||
local-scope
|
||||
list:address:duplex-list:char <- copy 1:address:duplex-list:char/raw # restore list
|
||||
list:&:duplex-list:char <- copy 1:&:duplex-list:char/raw # restore list
|
||||
# delete 15, 16 and 17
|
||||
# start pointer: to the second element
|
||||
list2:address:duplex-list:char <- next list
|
||||
list2:&:duplex-list:char <- next list
|
||||
# end pointer: to the last (sixth) element
|
||||
end:address:duplex-list:char <- next list2
|
||||
end:&:duplex-list:char <- next list2
|
||||
end <- next end
|
||||
end <- next end
|
||||
end <- next end
|
||||
|
@ -424,7 +424,7 @@ scenario remove-range-to-final [
|
|||
11:char/raw <- get *list, value:offset
|
||||
list <- next list
|
||||
12:char/raw <- get *list, value:offset
|
||||
20:address:duplex-list:char/raw <- next list
|
||||
20:&:duplex-list:char/raw <- next list
|
||||
]
|
||||
memory-should-contain [
|
||||
10 <- 13
|
||||
|
@ -437,15 +437,15 @@ scenario remove-range-to-final [
|
|||
scenario remove-range-empty [
|
||||
local-scope
|
||||
# construct a duplex list with three elements [13, 14, 15]
|
||||
list:address:duplex-list:char <- push 15, 0
|
||||
list:&:duplex-list:char <- push 15, 0
|
||||
list <- push 14, list
|
||||
list <- push 13, list
|
||||
1:address:duplex-list:char/raw <- copy list # save list
|
||||
1:&:duplex-list:char/raw <- copy list # save list
|
||||
run [
|
||||
local-scope
|
||||
list:address:duplex-list:char <- copy 1:address:duplex-list:char/raw # restore list
|
||||
list:&:duplex-list:char <- copy 1:&:duplex-list:char/raw # restore list
|
||||
# delete between first and second element (i.e. nothing)
|
||||
list2:address:duplex-list:char <- next list
|
||||
list2:&:duplex-list:char <- next list
|
||||
remove-between list, list2
|
||||
# now check the list
|
||||
10:char/raw <- get *list, value:offset
|
||||
|
@ -453,7 +453,7 @@ scenario remove-range-empty [
|
|||
11:char/raw <- get *list, value:offset
|
||||
list <- next list
|
||||
12:char/raw <- get *list, value:offset
|
||||
20:address:duplex-list:char/raw <- next list
|
||||
20:&:duplex-list:char/raw <- next list
|
||||
]
|
||||
# no change
|
||||
memory-should-contain [
|
||||
|
@ -467,24 +467,24 @@ scenario remove-range-empty [
|
|||
scenario remove-range-to-end [
|
||||
local-scope
|
||||
# construct a duplex list with six elements [13, 14, 15, 16, 17, 18]
|
||||
list:address:duplex-list:char <- push 18, 0
|
||||
list:&:duplex-list:char <- push 18, 0
|
||||
list <- push 17, list
|
||||
list <- push 16, list
|
||||
list <- push 15, list
|
||||
list <- push 14, list
|
||||
list <- push 13, list
|
||||
1:address:duplex-list:char/raw <- copy list # save list
|
||||
1:&:duplex-list:char/raw <- copy list # save list
|
||||
run [
|
||||
local-scope
|
||||
list:address:duplex-list:char <- copy 1:address:duplex-list:char/raw # restore list
|
||||
list:&:duplex-list:char <- copy 1:&:duplex-list:char/raw # restore list
|
||||
# remove the third element and beyond
|
||||
list2:address:duplex-list:char <- next list
|
||||
list2:&:duplex-list:char <- next list
|
||||
remove-between list2, 0
|
||||
# now check the list
|
||||
10:char/raw <- get *list, value:offset
|
||||
list <- next list
|
||||
11:char/raw <- get *list, value:offset
|
||||
20:address:duplex-list:char/raw <- next list
|
||||
20:&:duplex-list:char/raw <- next list
|
||||
]
|
||||
memory-should-contain [
|
||||
10 <- 13
|
||||
|
@ -494,19 +494,19 @@ scenario remove-range-to-end [
|
|||
]
|
||||
|
||||
# insert list beginning at 'new' after 'in'
|
||||
def insert-range in:address:duplex-list:_elem, start:address:duplex-list:_elem/contained-in:in -> in:address:duplex-list:_elem [
|
||||
def insert-range in:&:duplex-list:_elem, start:&:duplex-list:_elem/contained-in:in -> in:&:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return-unless in
|
||||
return-unless start
|
||||
end:address:duplex-list:_elem <- copy start
|
||||
end:&:duplex-list:_elem <- copy start
|
||||
{
|
||||
next:address:duplex-list:_elem <- next end/insert-range
|
||||
next:&:duplex-list:_elem <- next end/insert-range
|
||||
break-unless next
|
||||
end <- copy next
|
||||
loop
|
||||
}
|
||||
next:address:duplex-list:_elem <- next in
|
||||
next:&:duplex-list:_elem <- next in
|
||||
*end <- put *end, next:offset, next
|
||||
{
|
||||
break-unless next
|
||||
|
@ -516,21 +516,21 @@ def insert-range in:address:duplex-list:_elem, start:address:duplex-list:_elem/c
|
|||
*start <- put *start, prev:offset, in
|
||||
]
|
||||
|
||||
def append in:address:duplex-list:_elem, new:address:duplex-list:_elem/contained-in:in -> in:address:duplex-list:_elem [
|
||||
def append in:&:duplex-list:_elem, new:&:duplex-list:_elem/contained-in:in -> in:&:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
last:address:duplex-list:_elem <- last in
|
||||
last:&:duplex-list:_elem <- last in
|
||||
*last <- put *last, next:offset, new
|
||||
return-unless new
|
||||
*new <- put *new, prev:offset, last
|
||||
]
|
||||
|
||||
def last in:address:duplex-list:_elem -> result:address:duplex-list:_elem [
|
||||
def last in:&:duplex-list:_elem -> result:&:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- copy in
|
||||
{
|
||||
next:address:duplex-list:_elem <- next result
|
||||
next:&:duplex-list:_elem <- next result
|
||||
break-unless next
|
||||
result <- copy next
|
||||
loop
|
||||
|
@ -538,7 +538,7 @@ def last in:address:duplex-list:_elem -> result:address:duplex-list:_elem [
|
|||
]
|
||||
|
||||
# helper for debugging
|
||||
def dump-from x:address:duplex-list:_elem [
|
||||
def dump-from x:&:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
$print x, [: ]
|
||||
|
|
24
066stream.mu
24
066stream.mu
|
@ -1,10 +1,10 @@
|
|||
# new type to help incrementally scan arrays
|
||||
container stream:_elem [
|
||||
index:num
|
||||
data:address:array:_elem
|
||||
data:&:array:_elem
|
||||
]
|
||||
|
||||
def new-stream s:address:array:_elem -> result:address:stream:_elem [
|
||||
def new-stream s:&:array:_elem -> result:&:stream:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- new {(stream _elem): type}
|
||||
|
@ -12,23 +12,23 @@ def new-stream s:address:array:_elem -> result:address:stream:_elem [
|
|||
*result <- put *result, data:offset, s
|
||||
]
|
||||
|
||||
def rewind in:address:stream:_elem -> in:address:stream:_elem [
|
||||
def rewind in:&:stream:_elem -> in:&:stream:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
*in <- put *in, index:offset, 0
|
||||
]
|
||||
|
||||
def read in:address:stream:_elem -> result:_elem, empty?:bool, in:address:stream:_elem [
|
||||
def read in:&:stream:_elem -> result:_elem, empty?:bool, in:&:stream:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
empty? <- copy 0/false
|
||||
idx:num <- get *in, index:offset
|
||||
s:address:array:_elem <- get *in, data:offset
|
||||
s:&:array:_elem <- get *in, data:offset
|
||||
len:num <- length *s
|
||||
at-end?:bool <- greater-or-equal idx len
|
||||
{
|
||||
break-unless at-end?
|
||||
empty-result:address:_elem <- new _elem:type
|
||||
empty-result:&:_elem <- new _elem:type
|
||||
return *empty-result, 1/true
|
||||
}
|
||||
result <- index *s, idx
|
||||
|
@ -36,23 +36,23 @@ def read in:address:stream:_elem -> result:_elem, empty?:bool, in:address:stream
|
|||
*in <- put *in, index:offset, idx
|
||||
]
|
||||
|
||||
def peek in:address:stream:_elem -> result:_elem, empty?:bool [
|
||||
def peek in:&:stream:_elem -> result:_elem, empty?:bool [
|
||||
local-scope
|
||||
load-ingredients
|
||||
empty?:bool <- copy 0/false
|
||||
idx:num <- get *in, index:offset
|
||||
s:address:array:_elem <- get *in, data:offset
|
||||
s:&:array:_elem <- get *in, data:offset
|
||||
len:num <- length *s
|
||||
at-end?:bool <- greater-or-equal idx len
|
||||
{
|
||||
break-unless at-end?
|
||||
empty-result:address:_elem <- new _elem:type
|
||||
empty-result:&:_elem <- new _elem:type
|
||||
return *empty-result, 1/true
|
||||
}
|
||||
result <- index *s, idx
|
||||
]
|
||||
|
||||
def read-line in:address:stream:char -> result:text, in:address:stream:char [
|
||||
def read-line in:&:stream:char -> result:text, in:&:stream:char [
|
||||
local-scope
|
||||
load-ingredients
|
||||
idx:num <- get *in, index:offset
|
||||
|
@ -64,11 +64,11 @@ def read-line in:address:stream:char -> result:text, in:address:stream:char [
|
|||
*in <- put *in, index:offset, idx
|
||||
]
|
||||
|
||||
def end-of-stream? in:address:stream:_elem -> result:bool [
|
||||
def end-of-stream? in:&:stream:_elem -> result:bool [
|
||||
local-scope
|
||||
load-ingredients
|
||||
idx:num <- get *in, index:offset
|
||||
s:address:array:_elem <- get *in, data:offset
|
||||
s:&:array:_elem <- get *in, data:offset
|
||||
len:num <- length *s
|
||||
result <- greater-or-equal idx, len
|
||||
]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
def random generator:address:stream:num -> result:num, fail?:bool, generator:address:stream:num [
|
||||
def random generator:&:stream:num -> result:num, fail?:bool, generator:&:stream:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -11,7 +11,7 @@ def random generator:address:stream:num -> result:num, fail?:bool, generator:add
|
|||
]
|
||||
|
||||
# helper for tests
|
||||
def assume-random-numbers -> result:address:stream:num [
|
||||
def assume-random-numbers -> result:&:stream:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# compute result-len, space to allocate in result
|
||||
|
@ -23,7 +23,7 @@ def assume-random-numbers -> result:address:stream:num [
|
|||
loop
|
||||
}
|
||||
rewind-ingredients
|
||||
result-data:address:array:num <- new number:type, result-len
|
||||
result-data:&:array:num <- new number:type, result-len
|
||||
idx:num <- copy 0
|
||||
{
|
||||
curr:num, arg-received?:bool <- next-ingredient
|
||||
|
@ -37,7 +37,7 @@ def assume-random-numbers -> result:address:stream:num [
|
|||
|
||||
scenario random-numbers-in-scenario [
|
||||
local-scope
|
||||
source:address:stream:num <- assume-random-numbers 34, 35, 37
|
||||
source:&:stream:num <- assume-random-numbers 34, 35, 37
|
||||
1:num/raw, 2:bool/raw <- random source
|
||||
3:num/raw, 4:bool/raw <- random source
|
||||
5:num/raw, 6:bool/raw <- random source
|
||||
|
|
40
069hash.cc
40
069hash.cc
|
@ -187,8 +187,8 @@ def main [
|
|||
|
||||
:(scenario hash_of_zero_address)
|
||||
def main [
|
||||
1:address:num <- copy 0
|
||||
2:num <- hash 1:address:num
|
||||
1:&:num <- copy 0
|
||||
2:num <- hash 1:&:num
|
||||
]
|
||||
+mem: storing 0 in location 2
|
||||
|
||||
|
@ -219,12 +219,12 @@ def main [
|
|||
|
||||
:(scenario hash_ignores_address_value)
|
||||
def main [
|
||||
1:address:num <- new number:type
|
||||
*1:address:num <- copy 34
|
||||
2:num <- hash 1:address:num
|
||||
3:address:num <- new number:type
|
||||
*3:address:num <- copy 34
|
||||
4:num <- hash 3:address:num
|
||||
1:&:num <- new number:type
|
||||
*1:&:num <- copy 34
|
||||
2:num <- hash 1:&:num
|
||||
3:&:num <- new number:type
|
||||
*3:&:num <- copy 34
|
||||
4:num <- hash 3:&:num
|
||||
5:bool <- equal 2:num, 4:num
|
||||
]
|
||||
# different addresses hash to the same result as long as the values the point to do so
|
||||
|
@ -232,13 +232,13 @@ def main [
|
|||
|
||||
:(scenario hash_ignores_address_refcount)
|
||||
def main [
|
||||
1:address:num <- new number:type
|
||||
*1:address:num <- copy 34
|
||||
2:num <- hash 1:address:num
|
||||
1:&:num <- new number:type
|
||||
*1:&:num <- copy 34
|
||||
2:num <- hash 1:&:num
|
||||
return-unless 2:num
|
||||
# increment refcount
|
||||
3:address:num <- copy 1:address:num
|
||||
4:num <- hash 3:address:num
|
||||
3:&:num <- copy 1:&:num
|
||||
4:num <- hash 3:&:num
|
||||
return-unless 4:num
|
||||
5:bool <- equal 2:num, 4:num
|
||||
]
|
||||
|
@ -270,17 +270,17 @@ def main [
|
|||
container foo [
|
||||
x:num
|
||||
y:char
|
||||
z:address:num
|
||||
z:&:num
|
||||
]
|
||||
def main [
|
||||
1:address:num <- new number:type
|
||||
*1:address:num <- copy 34
|
||||
2:foo <- merge 34, 97/a, 1:address:num
|
||||
1:&:num <- new number:type
|
||||
*1:&:num <- copy 34
|
||||
2:foo <- merge 34, 97/a, 1:&:num
|
||||
5:num <- hash 2:foo
|
||||
return-unless 5:num
|
||||
6:address:num <- new number:type
|
||||
*6:address:num <- copy 34
|
||||
7:foo <- merge 34, 97/a, 6:address:num
|
||||
6:&:num <- new number:type
|
||||
*6:&:num <- copy 34
|
||||
7:foo <- merge 34, 97/a, 6:&:num
|
||||
10:num <- hash 7:foo
|
||||
return-unless 10:num
|
||||
11:bool <- equal 5:num, 10:num
|
||||
|
|
16
070table.mu
16
070table.mu
|
@ -4,7 +4,7 @@
|
|||
scenario table-read-write [
|
||||
run [
|
||||
local-scope
|
||||
tab:address:table:num:num <- new-table 30
|
||||
tab:&:table:num:num <- new-table 30
|
||||
put-index tab, 12, 34
|
||||
1:num/raw <- index tab, 12
|
||||
]
|
||||
|
@ -29,7 +29,7 @@ scenario table-read-write-non-integer [
|
|||
container table:_key:_value [
|
||||
length:num
|
||||
capacity:num
|
||||
data:address:array:table_row:_key:_value
|
||||
data:&:array:table_row:_key:_value
|
||||
]
|
||||
|
||||
container table_row:_key:_value [
|
||||
|
@ -38,15 +38,15 @@ container table_row:_key:_value [
|
|||
value:_value
|
||||
]
|
||||
|
||||
def new-table capacity:num -> result:address:table:_key:_value [
|
||||
def new-table capacity:num -> result:&:table:_key:_value [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- new {(table _key _value): type}
|
||||
data:address:array:table_row:_key:_value <- new {(table_row _key _value): type}, capacity
|
||||
data:&:array:table_row:_key:_value <- new {(table_row _key _value): type}, capacity
|
||||
*result <- merge 0/length, capacity, data
|
||||
]
|
||||
|
||||
def put-index table:address:table:_key:_value, key:_key, value:_value -> table:address:table:_key:_value [
|
||||
def put-index table:&:table:_key:_value, key:_key, value:_value -> table:&:table:_key:_value [
|
||||
local-scope
|
||||
load-ingredients
|
||||
hash:num <- hash key
|
||||
|
@ -54,7 +54,7 @@ def put-index table:address:table:_key:_value, key:_key, value:_value -> table:a
|
|||
capacity:num <- get *table, capacity:offset
|
||||
_, hash <- divide-with-remainder hash, capacity
|
||||
hash <- abs hash # in case hash overflows into a negative integer
|
||||
table-data:address:array:table_row:_key:_value <- get *table, data:offset
|
||||
table-data:&:array:table_row:_key:_value <- get *table, data:offset
|
||||
x:table_row:_key:_value <- index *table-data, hash
|
||||
occupied?:bool <- get x, occupied?:offset
|
||||
not-occupied?:bool <- not occupied?:bool
|
||||
|
@ -71,7 +71,7 @@ def abs n:num -> result:num [
|
|||
result <- multiply n, -1
|
||||
]
|
||||
|
||||
def index table:address:table:_key:_value, key:_key -> result:_value [
|
||||
def index table:&:table:_key:_value, key:_key -> result:_value [
|
||||
local-scope
|
||||
load-ingredients
|
||||
hash:num <- hash key
|
||||
|
@ -79,7 +79,7 @@ def index table:address:table:_key:_value, key:_key -> result:_value [
|
|||
capacity:num <- get *table, capacity:offset
|
||||
_, hash <- divide-with-remainder hash, capacity
|
||||
hash <- abs hash # in case hash overflows into a negative integer
|
||||
table-data:address:array:table_row:_key:_value <- get *table, data:offset
|
||||
table-data:&:array:table_row:_key:_value <- get *table, data:offset
|
||||
x:table_row:_key:_value <- index *table-data, hash
|
||||
occupied?:bool <- get x, occupied?:offset
|
||||
assert occupied?, [can't handle missing elements yet]
|
||||
|
|
|
@ -300,10 +300,10 @@ if (is_mu_recipe(to)) {
|
|||
:(scenario call_variable_compound_ingredient)
|
||||
def main [
|
||||
{1: (recipe (address number) -> number)} <- copy f
|
||||
2:address:num <- copy 0
|
||||
3:num <- call {1: (recipe (address number) -> number)}, 2:address:num
|
||||
2:&:num <- copy 0
|
||||
3:num <- call {1: (recipe (address number) -> number)}, 2:&:num
|
||||
]
|
||||
def f x:address:num -> y:num [
|
||||
def f x:&:num -> y:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- copy x
|
||||
|
|
|
@ -253,12 +253,12 @@ def main [
|
|||
]
|
||||
def create-new-routine [
|
||||
local-scope
|
||||
n:address:num <- new number:type
|
||||
n:&:num <- new number:type
|
||||
*n <- copy 34
|
||||
start-running new-routine, n
|
||||
# refcount of n decremented
|
||||
]
|
||||
def new-routine n:address:num [
|
||||
def new-routine n:&:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
1:num/raw <- copy *n
|
||||
|
@ -281,24 +281,24 @@ if (inst.operation == NEXT_INGREDIENT || inst.operation == NEXT_INGREDIENT_WITHO
|
|||
}
|
||||
|
||||
:(scenario next_ingredient_never_leaks_refcounts)
|
||||
def create-scope n:address:num -> default-space:address:array:location [
|
||||
def create-scope n:&:num -> default-space:&:array:location [
|
||||
default-space <- new location:type, 2
|
||||
load-ingredients
|
||||
]
|
||||
def use-scope [
|
||||
local-scope
|
||||
0:address:array:location/names:create-scope <- next-ingredient
|
||||
n:address:num/space:1 <- next-ingredient # should decrement refcount
|
||||
0:&:array:location/names:create-scope <- next-ingredient
|
||||
n:&:num/space:1 <- next-ingredient # should decrement refcount
|
||||
*n/space:1 <- copy 34
|
||||
n2:num <- add *n/space:1, 1
|
||||
reply n2
|
||||
]
|
||||
def main [
|
||||
local-scope
|
||||
n:address:num <- copy 12000/unsafe # pretend allocation with a known address
|
||||
n:&:num <- copy 12000/unsafe # pretend allocation with a known address
|
||||
*n <- copy 23
|
||||
scope:address:array:location <- create-scope n
|
||||
n2:address:num <- copy 13000/unsafe
|
||||
scope:&:array:location <- create-scope n
|
||||
n2:&:num <- copy 13000/unsafe
|
||||
n3:num <- use-scope scope, n2
|
||||
]
|
||||
+run: {n: ("address" "number"), "space": "1"} <- next-ingredient
|
||||
|
@ -664,16 +664,16 @@ def f2 [
|
|||
:(scenario new_concurrent)
|
||||
def f1 [
|
||||
start-running f2
|
||||
1:address:num/raw <- new number:type
|
||||
1:&:num/raw <- new number:type
|
||||
# wait for f2 to complete
|
||||
{
|
||||
loop-unless 4:num/raw
|
||||
}
|
||||
]
|
||||
def f2 [
|
||||
2:address:num/raw <- new number:type
|
||||
2:&:num/raw <- new number:type
|
||||
# hack: assumes scheduler implementation
|
||||
3:bool/raw <- equal 1:address:num/raw, 2:address:num/raw
|
||||
3:bool/raw <- equal 1:&:num/raw, 2:&:num/raw
|
||||
# signal f2 complete
|
||||
4:num/raw <- copy 1
|
||||
]
|
||||
|
|
|
@ -260,7 +260,7 @@ def main [
|
|||
# 10 reserved for refcount
|
||||
11:num <- copy 34
|
||||
12:num <- copy 35
|
||||
4:location <- get-location 1:address:point/lookup, 0:offset
|
||||
4:location <- get-location 1:&:point/lookup, 0:offset
|
||||
]
|
||||
+mem: storing 11 in location 4
|
||||
|
||||
|
@ -270,8 +270,8 @@ def main [
|
|||
# 10 reserved for refcount
|
||||
11:num <- copy 34
|
||||
12:num <- copy 35
|
||||
4:address:num <- copy 20/unsafe
|
||||
4:address:location/lookup <- get-location 1:address:point/lookup, 0:offset
|
||||
4:&:num <- copy 20/unsafe
|
||||
4:&:location/lookup <- get-location 1:&:point/lookup, 0:offset
|
||||
]
|
||||
+mem: storing 11 in location 21
|
||||
|
||||
|
|
128
074deep_copy.cc
128
074deep_copy.cc
|
@ -39,12 +39,12 @@ def main [
|
|||
def main [
|
||||
# avoid all memory allocations except the implicit ones inside deep-copy, so
|
||||
# that the result is deterministic
|
||||
1:address:num <- copy 100/unsafe # pretend allocation
|
||||
*1:address:num <- copy 34
|
||||
2:address:num <- deep-copy 1:address:num
|
||||
10:bool <- equal 1:address:num, 2:address:num
|
||||
11:bool <- equal *1:address:num, *2:address:num
|
||||
2:address:num <- copy 0
|
||||
1:&:num <- copy 100/unsafe # pretend allocation
|
||||
*1:&:num <- copy 34
|
||||
2:&:num <- deep-copy 1:&:num
|
||||
10:bool <- equal 1:&:num, 2:&:num
|
||||
11:bool <- equal *1:&:num, *2:&:num
|
||||
2:&:num <- copy 0
|
||||
]
|
||||
# the result of deep-copy is a new address
|
||||
+mem: storing 0 in location 10
|
||||
|
@ -61,11 +61,11 @@ def main [
|
|||
def main [
|
||||
# avoid all memory allocations except the implicit ones inside deep-copy, so
|
||||
# that the result is deterministic
|
||||
1:address:point <- copy 100/unsafe # pretend allocation
|
||||
*1:address:point <- merge 34, 35
|
||||
2:address:point <- deep-copy 1:address:point
|
||||
10:bool <- equal 1:address:point, 2:address:point
|
||||
11:bool <- equal *1:address:point, *2:address:point
|
||||
1:&:point <- copy 100/unsafe # pretend allocation
|
||||
*1:&:point <- merge 34, 35
|
||||
2:&:point <- deep-copy 1:&:point
|
||||
10:bool <- equal 1:&:point, 2:&:point
|
||||
11:bool <- equal *1:&:point, *2:&:point
|
||||
]
|
||||
# the result of deep-copy is a new address
|
||||
+mem: storing 0 in location 10
|
||||
|
@ -77,13 +77,13 @@ def main [
|
|||
def main [
|
||||
# avoid all memory allocations except the implicit ones inside deep-copy, so
|
||||
# that the result is deterministic
|
||||
1:address:address:num <- copy 100/unsafe # pretend allocation
|
||||
*1:address:address:num <- copy 150/unsafe
|
||||
**1:address:address:num <- copy 34
|
||||
2:address:address:num <- deep-copy 1:address:address:num
|
||||
10:bool <- equal 1:address:address:num, 2:address:address:num
|
||||
11:bool <- equal *1:address:address:num, *2:address:address:num
|
||||
12:bool <- equal **1:address:address:num, **2:address:address:num
|
||||
1:&:&:num <- copy 100/unsafe # pretend allocation
|
||||
*1:&:&:num <- copy 150/unsafe
|
||||
**1:&:&:num <- copy 34
|
||||
2:&:&:num <- deep-copy 1:&:&:num
|
||||
10:bool <- equal 1:&:&:num, 2:&:&:num
|
||||
11:bool <- equal *1:&:&:num, *2:&:&:num
|
||||
12:bool <- equal **1:&:&:num, **2:&:&:num
|
||||
]
|
||||
# the result of deep-copy is a new address
|
||||
+mem: storing 0 in location 10
|
||||
|
@ -99,16 +99,16 @@ def main [
|
|||
# that the result is deterministic
|
||||
100:num <- copy 1 # pretend refcount
|
||||
101:num <- copy 3 # pretend array length
|
||||
1:address:array:num <- copy 100/unsafe # pretend allocation
|
||||
put-index *1:address:array:num, 0, 34
|
||||
put-index *1:address:array:num, 1, 35
|
||||
put-index *1:address:array:num, 2, 36
|
||||
stash [old:], *1:address:array:num
|
||||
2:address:array:num <- deep-copy 1:address:array:num
|
||||
stash 2:address:array:num
|
||||
stash [new:], *2:address:array:num
|
||||
10:bool <- equal 1:address:array:num, 2:address:array:num
|
||||
11:bool <- equal *1:address:array:num, *2:address:array:num
|
||||
1:&:array:num <- copy 100/unsafe # pretend allocation
|
||||
put-index *1:&:array:num, 0, 34
|
||||
put-index *1:&:array:num, 1, 35
|
||||
put-index *1:&:array:num, 2, 36
|
||||
stash [old:], *1:&:array:num
|
||||
2:&:array:num <- deep-copy 1:&:array:num
|
||||
stash 2:&:array:num
|
||||
stash [new:], *2:&:array:num
|
||||
10:bool <- equal 1:&:array:num, 2:&:array:num
|
||||
11:bool <- equal *1:&:array:num, *2:&:array:num
|
||||
]
|
||||
+app: old: 3 34 35 36
|
||||
+app: new: 3 34 35 36
|
||||
|
@ -120,16 +120,16 @@ def main [
|
|||
:(scenario deep_copy_container_with_address)
|
||||
container foo [
|
||||
x:num
|
||||
y:address:num
|
||||
y:&:num
|
||||
]
|
||||
def main [
|
||||
local-scope
|
||||
y0:address:num <- new number:type
|
||||
y0:&:num <- new number:type
|
||||
*y0 <- copy 35
|
||||
a:foo <- merge 34, y0
|
||||
b:foo <- deep-copy a
|
||||
10:bool/raw <- equal a, b
|
||||
y1:address:num <- get b, y:offset
|
||||
y1:&:num <- get b, y:offset
|
||||
11:bool/raw <- equal y0, y1
|
||||
12:num/raw <- copy *y1
|
||||
]
|
||||
|
@ -142,16 +142,16 @@ def main [
|
|||
:(scenario deep_copy_exclusive_container_with_address)
|
||||
exclusive-container foo [
|
||||
x:num
|
||||
y:address:num
|
||||
y:&:num
|
||||
]
|
||||
def main [
|
||||
local-scope
|
||||
y0:address:num <- new number:type
|
||||
y0:&:num <- new number:type
|
||||
*y0 <- copy 34
|
||||
a:foo <- merge 1/y, y0
|
||||
b:foo <- deep-copy a
|
||||
10:bool/raw <- equal a, b
|
||||
y1:address:num, z:bool <- maybe-convert b, y:variant
|
||||
y1:&:num, z:bool <- maybe-convert b, y:variant
|
||||
11:bool/raw <- equal y0, y1
|
||||
12:num/raw <- copy *y1
|
||||
]
|
||||
|
@ -167,18 +167,18 @@ exclusive-container foo [
|
|||
y:bar # inline
|
||||
]
|
||||
container bar [
|
||||
x:address:num
|
||||
x:&:num
|
||||
]
|
||||
def main [
|
||||
local-scope
|
||||
y0:address:num <- new number:type
|
||||
y0:&:num <- new number:type
|
||||
*y0 <- copy 34
|
||||
a:bar <- merge y0
|
||||
b:foo <- merge 1/y, a
|
||||
c:foo <- deep-copy b
|
||||
10:bool/raw <- equal b, c
|
||||
d:bar, z:bool <- maybe-convert c, y:variant
|
||||
y1:address:num <- get d, x:offset
|
||||
y1:&:num <- get d, x:offset
|
||||
11:bool/raw <- equal y0, y1
|
||||
12:num/raw <- copy *y1
|
||||
]
|
||||
|
@ -302,63 +302,63 @@ int payload_address(reagent/*copy*/ x) {
|
|||
|
||||
:(scenario deep_copy_stress_test_1)
|
||||
container foo1 [
|
||||
p:address:num
|
||||
p:&:num
|
||||
]
|
||||
container foo2 [
|
||||
p:address:foo1
|
||||
p:&:foo1
|
||||
]
|
||||
exclusive-container foo3 [
|
||||
p:address:foo1
|
||||
q:address:foo2
|
||||
p:&:foo1
|
||||
q:&:foo2
|
||||
]
|
||||
def main [
|
||||
local-scope
|
||||
x:address:num <- new number:type
|
||||
x:&:num <- new number:type
|
||||
*x <- copy 34
|
||||
a:address:foo1 <- new foo1:type
|
||||
a:&:foo1 <- new foo1:type
|
||||
*a <- merge x
|
||||
b:address:foo2 <- new foo2:type
|
||||
b:&:foo2 <- new foo2:type
|
||||
*b <- merge a
|
||||
c:foo3 <- merge 1/q, b
|
||||
d:foo3 <- deep-copy c
|
||||
e:address:foo2, z:bool <- maybe-convert d, q:variant
|
||||
f:address:foo1 <- get *e, p:offset
|
||||
g:address:num <- get *f, p:offset
|
||||
e:&:foo2, z:bool <- maybe-convert d, q:variant
|
||||
f:&:foo1 <- get *e, p:offset
|
||||
g:&:num <- get *f, p:offset
|
||||
1:num/raw <- copy *g
|
||||
]
|
||||
+mem: storing 34 in location 1
|
||||
|
||||
:(scenario deep_copy_stress_test_2)
|
||||
container foo1 [
|
||||
p:address:num
|
||||
p:&:num
|
||||
]
|
||||
container foo2 [
|
||||
p:address:foo1
|
||||
p:&:foo1
|
||||
]
|
||||
exclusive-container foo3 [
|
||||
p:address:foo1
|
||||
q:address:foo2
|
||||
p:&:foo1
|
||||
q:&:foo2
|
||||
]
|
||||
container foo4 [
|
||||
p:num
|
||||
q:address:foo3
|
||||
q:&:foo3
|
||||
]
|
||||
def main [
|
||||
local-scope
|
||||
x:address:num <- new number:type
|
||||
x:&:num <- new number:type
|
||||
*x <- copy 34
|
||||
a:address:foo1 <- new foo1:type
|
||||
a:&:foo1 <- new foo1:type
|
||||
*a <- merge x
|
||||
b:address:foo2 <- new foo2:type
|
||||
b:&:foo2 <- new foo2:type
|
||||
*b <- merge a
|
||||
c:address:foo3 <- new foo3:type
|
||||
c:&:foo3 <- new foo3:type
|
||||
*c <- merge 1/q, b
|
||||
d:foo4 <- merge 35, c
|
||||
e:foo4 <- deep-copy d
|
||||
f:address:foo3 <- get e, q:offset
|
||||
g:address:foo2, z:bool <- maybe-convert *f, q:variant
|
||||
h:address:foo1 <- get *g, p:offset
|
||||
y:address:num <- get *h, p:offset
|
||||
f:&:foo3 <- get e, q:offset
|
||||
g:&:foo2, z:bool <- maybe-convert *f, q:variant
|
||||
h:&:foo1 <- get *g, p:offset
|
||||
y:&:num <- get *h, p:offset
|
||||
1:num/raw <- copy *y
|
||||
]
|
||||
+mem: storing 34 in location 1
|
||||
|
@ -366,16 +366,16 @@ def main [
|
|||
:(scenario deep_copy_cycles)
|
||||
container foo [
|
||||
p:num
|
||||
q:address:foo
|
||||
q:&:foo
|
||||
]
|
||||
def main [
|
||||
local-scope
|
||||
x:address:foo <- new foo:type
|
||||
x:&:foo <- new foo:type
|
||||
*x <- put *x, p:offset, 34
|
||||
*x <- put *x, q:offset, x # create a cycle
|
||||
y:address:foo <- deep-copy x
|
||||
y:&:foo <- deep-copy x
|
||||
1:num/raw <- get *y, p:offset
|
||||
y2:address:foo <- get *y, q:offset
|
||||
y2:&:foo <- get *y, q:offset
|
||||
stash y [vs] y2
|
||||
2:bool/raw <- equal y, y2 # is it still a cycle?
|
||||
3:bool/raw <- equal x, y # is it the same cycle?
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
scenario channel [
|
||||
run [
|
||||
local-scope
|
||||
source:address:source:num, sink:address:sink:num <- new-channel 3/capacity
|
||||
source:&:source:num, sink:&:sink:num <- new-channel 3/capacity
|
||||
sink <- write sink, 34
|
||||
10:num/raw, 11:bool/raw, source <- read source
|
||||
]
|
||||
|
@ -30,28 +30,28 @@ container channel:_elem [
|
|||
# A circular buffer contains values from index first-full up to (but not
|
||||
# including) index first-empty. The reader always modifies it at first-full,
|
||||
# while the writer always modifies it at first-empty.
|
||||
data:address:array:_elem
|
||||
data:&:array:_elem
|
||||
]
|
||||
|
||||
# Since channels have two ends, and since it's an error to use either end from
|
||||
# multiple routines, let's distinguish the ends.
|
||||
|
||||
container source:_elem [
|
||||
chan:address:channel:_elem
|
||||
chan:&:channel:_elem
|
||||
]
|
||||
|
||||
container sink:_elem [
|
||||
chan:address:channel:_elem
|
||||
chan:&:channel:_elem
|
||||
]
|
||||
|
||||
def new-channel capacity:num -> in:address:source:_elem, out:address:sink:_elem [
|
||||
def new-channel capacity:num -> in:&:source:_elem, out:&:sink:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result:address:channel:_elem <- new {(channel _elem): type}
|
||||
result:&:channel:_elem <- new {(channel _elem): type}
|
||||
*result <- put *result, first-full:offset, 0
|
||||
*result <- put *result, first-free:offset, 0
|
||||
capacity <- add capacity, 1 # unused slot for 'full?' below
|
||||
data:address:array:_elem <- new _elem:type, capacity
|
||||
data:&:array:_elem <- new _elem:type, capacity
|
||||
*result <- put *result, data:offset, data
|
||||
in <- new {(source _elem): type}
|
||||
*in <- put *in, chan:offset, result
|
||||
|
@ -59,11 +59,11 @@ def new-channel capacity:num -> in:address:source:_elem, out:address:sink:_elem
|
|||
*out <- put *out, chan:offset, result
|
||||
]
|
||||
|
||||
def write out:address:sink:_elem, val:_elem -> out:address:sink:_elem [
|
||||
def write out:&:sink:_elem, val:_elem -> out:&:sink:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
assert out, [write to null channel]
|
||||
chan:address:channel:_elem <- get *out, chan:offset
|
||||
chan:&:channel:_elem <- get *out, chan:offset
|
||||
<channel-write-initial>
|
||||
# block until lock is acquired AND queue has room
|
||||
lock:location <- get-location *chan, lock:offset
|
||||
|
@ -85,7 +85,7 @@ def write out:address:sink:_elem, val:_elem -> out:address:sink:_elem [
|
|||
current-routine-is-unblocked
|
||||
#? $print [performing write], 10/newline
|
||||
# store a deep copy of val
|
||||
circular-buffer:address:array:_elem <- get *chan, data:offset
|
||||
circular-buffer:&:array:_elem <- get *chan, data:offset
|
||||
free:num <- get *chan, first-free:offset
|
||||
val-copy:_elem <- deep-copy val # on this instruction rests all Mu's concurrency-safety
|
||||
*circular-buffer <- put-index *circular-buffer, free, val-copy
|
||||
|
@ -104,12 +104,12 @@ def write out:address:sink:_elem, val:_elem -> out:address:sink:_elem [
|
|||
reset lock
|
||||
]
|
||||
|
||||
def read in:address:source:_elem -> result:_elem, eof?:bool, in:address:source:_elem [
|
||||
def read in:&:source:_elem -> result:_elem, eof?:bool, in:&:source:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
assert in, [read on null channel]
|
||||
eof? <- copy 0/false # default result
|
||||
chan:address:channel:_elem <- get *in, chan:offset
|
||||
chan:&:channel:_elem <- get *in, chan:offset
|
||||
# block until lock is acquired AND queue has data
|
||||
lock:location <- get-location *chan, lock:offset
|
||||
#? $print [read], 10/newline
|
||||
|
@ -131,10 +131,10 @@ def read in:address:source:_elem -> result:_elem, eof?:bool, in:address:source:_
|
|||
current-routine-is-unblocked
|
||||
# pull result off
|
||||
full:num <- get *chan, first-full:offset
|
||||
circular-buffer:address:array:_elem <- get *chan, data:offset
|
||||
circular-buffer:&:array:_elem <- get *chan, data:offset
|
||||
result <- index *circular-buffer, full
|
||||
# clear the slot
|
||||
empty:address:_elem <- new _elem:type
|
||||
empty:&:_elem <- new _elem:type
|
||||
*circular-buffer <- put-index *circular-buffer, full, *empty
|
||||
# mark its slot as empty
|
||||
full <- add full, 1
|
||||
|
@ -151,10 +151,10 @@ def read in:address:source:_elem -> result:_elem, eof?:bool, in:address:source:_
|
|||
reset lock
|
||||
]
|
||||
|
||||
def clear in:address:source:_elem -> in:address:source:_elem [
|
||||
def clear in:&:source:_elem -> in:&:source:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
chan:address:channel:_elem <- get *in, chan:offset
|
||||
chan:&:channel:_elem <- get *in, chan:offset
|
||||
{
|
||||
empty?:bool <- channel-empty? chan
|
||||
break-if empty?
|
||||
|
@ -165,8 +165,8 @@ def clear in:address:source:_elem -> in:address:source:_elem [
|
|||
scenario channel-initialization [
|
||||
run [
|
||||
local-scope
|
||||
source:address:source:num <- new-channel 3/capacity
|
||||
chan:address:channel:num <- get *source, chan:offset
|
||||
source:&:source:num <- new-channel 3/capacity
|
||||
chan:&:channel:num <- get *source, chan:offset
|
||||
10:num/raw <- get *chan, first-full:offset
|
||||
11:num/raw <- get *chan, first-free:offset
|
||||
]
|
||||
|
@ -179,9 +179,9 @@ scenario channel-initialization [
|
|||
scenario channel-write-increments-free [
|
||||
run [
|
||||
local-scope
|
||||
_, sink:address:sink:num <- new-channel 3/capacity
|
||||
_, sink:&:sink:num <- new-channel 3/capacity
|
||||
sink <- write sink, 34
|
||||
chan:address:channel:num <- get *sink, chan:offset
|
||||
chan:&:channel:num <- get *sink, chan:offset
|
||||
10:num/raw <- get *chan, first-full:offset
|
||||
11:num/raw <- get *chan, first-free:offset
|
||||
]
|
||||
|
@ -194,10 +194,10 @@ scenario channel-write-increments-free [
|
|||
scenario channel-read-increments-full [
|
||||
run [
|
||||
local-scope
|
||||
source:address:source:num, sink:address:sink:num <- new-channel 3/capacity
|
||||
source:&:source:num, sink:&:sink:num <- new-channel 3/capacity
|
||||
sink <- write sink, 34
|
||||
_, _, source <- read source
|
||||
chan:address:channel:num <- get *source, chan:offset
|
||||
chan:&:channel:num <- get *source, chan:offset
|
||||
10:num/raw <- get *chan, first-full:offset
|
||||
11:num/raw <- get *chan, first-free:offset
|
||||
]
|
||||
|
@ -211,8 +211,8 @@ scenario channel-wrap [
|
|||
run [
|
||||
local-scope
|
||||
# channel with just 1 slot
|
||||
source:address:source:num, sink:address:sink:num <- new-channel 1/capacity
|
||||
chan:address:channel:num <- get *source, chan:offset
|
||||
source:&:source:num, sink:&:sink:num <- new-channel 1/capacity
|
||||
chan:&:channel:num <- get *source, chan:offset
|
||||
# write and read a value
|
||||
sink <- write sink, 34
|
||||
_, _, source <- read source
|
||||
|
@ -237,8 +237,8 @@ scenario channel-wrap [
|
|||
scenario channel-new-empty-not-full [
|
||||
run [
|
||||
local-scope
|
||||
source:address:source:num <- new-channel 3/capacity
|
||||
chan:address:channel:num <- get *source, chan:offset
|
||||
source:&:source:num <- new-channel 3/capacity
|
||||
chan:&:channel:num <- get *source, chan:offset
|
||||
10:bool/raw <- channel-empty? chan
|
||||
11:bool/raw <- channel-full? chan
|
||||
]
|
||||
|
@ -250,8 +250,8 @@ scenario channel-new-empty-not-full [
|
|||
|
||||
scenario channel-write-not-empty [
|
||||
run [
|
||||
source:address:source:num, sink:address:sink:num <- new-channel 3/capacity
|
||||
chan:address:channel:num <- get *source, chan:offset
|
||||
source:&:source:num, sink:&:sink:num <- new-channel 3/capacity
|
||||
chan:&:channel:num <- get *source, chan:offset
|
||||
sink <- write sink, 34
|
||||
10:bool/raw <- channel-empty? chan
|
||||
11:bool/raw <- channel-full? chan
|
||||
|
@ -265,8 +265,8 @@ scenario channel-write-not-empty [
|
|||
scenario channel-write-full [
|
||||
run [
|
||||
local-scope
|
||||
source:address:source:num, sink:address:sink:num <- new-channel 1/capacity
|
||||
chan:address:channel:num <- get *source, chan:offset
|
||||
source:&:source:num, sink:&:sink:num <- new-channel 1/capacity
|
||||
chan:&:channel:num <- get *source, chan:offset
|
||||
sink <- write sink, 34
|
||||
10:bool/raw <- channel-empty? chan
|
||||
11:bool/raw <- channel-full? chan
|
||||
|
@ -280,8 +280,8 @@ scenario channel-write-full [
|
|||
scenario channel-read-not-full [
|
||||
run [
|
||||
local-scope
|
||||
source:address:source:num, sink:address:sink:num <- new-channel 1/capacity
|
||||
chan:address:channel:num <- get *source, chan:offset
|
||||
source:&:source:num, sink:&:sink:num <- new-channel 1/capacity
|
||||
chan:&:channel:num <- get *source, chan:offset
|
||||
sink <- write sink, 34
|
||||
_, _, source <- read source
|
||||
10:bool/raw <- channel-empty? chan
|
||||
|
@ -303,16 +303,16 @@ container channel:_elem [
|
|||
|
||||
# a channel can be closed from either the source or the sink
|
||||
# both routines can modify the 'closed?' bit, but they can only ever set it, so this is a benign race
|
||||
def close x:address:source:_elem -> x:address:source:_elem [
|
||||
def close x:&:source:_elem -> x:&:source:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
chan:address:channel:_elem <- get *x, chan:offset
|
||||
chan:&:channel:_elem <- get *x, chan:offset
|
||||
*chan <- put *chan, closed?:offset, 1/true
|
||||
]
|
||||
def close x:address:sink:_elem -> x:address:sink:_elem [
|
||||
def close x:&:sink:_elem -> x:&:sink:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
chan:address:channel:_elem <- get *x, chan:offset
|
||||
chan:&:channel:_elem <- get *x, chan:offset
|
||||
*chan <- put *chan, closed?:offset, 1/true
|
||||
]
|
||||
|
||||
|
@ -330,7 +330,7 @@ after <channel-read-empty> [
|
|||
closed?:boolean <- get *chan, closed?:offset
|
||||
{
|
||||
break-unless closed?
|
||||
empty-result:address:_elem <- new _elem:type
|
||||
empty-result:&:_elem <- new _elem:type
|
||||
current-routine-is-unblocked
|
||||
return *empty-result, 1/true
|
||||
}
|
||||
|
@ -339,7 +339,7 @@ after <channel-read-empty> [
|
|||
## helpers
|
||||
|
||||
# An empty channel has first-empty and first-full both at the same value.
|
||||
def channel-empty? chan:address:channel:_elem -> result:bool [
|
||||
def channel-empty? chan:&:channel:_elem -> result:bool [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# return chan.first-full == chan.first-free
|
||||
|
@ -350,7 +350,7 @@ def channel-empty? chan:address:channel:_elem -> result:bool [
|
|||
|
||||
# A full channel has first-empty just before first-full, wasting one slot.
|
||||
# (Other alternatives: https://en.wikipedia.org/wiki/Circular_buffer#Full_.2F_Empty_Buffer_Distinction)
|
||||
def channel-full? chan:address:channel:_elem -> result:bool [
|
||||
def channel-full? chan:&:channel:_elem -> result:bool [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# tmp = chan.first-free + 1
|
||||
|
@ -368,21 +368,21 @@ def channel-full? chan:address:channel:_elem -> result:bool [
|
|||
result <- equal full, tmp
|
||||
]
|
||||
|
||||
def capacity chan:address:channel:_elem -> result:num [
|
||||
def capacity chan:&:channel:_elem -> result:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
q:address:array:_elem <- get *chan, data:offset
|
||||
q:&:array:_elem <- get *chan, data:offset
|
||||
result <- length *q
|
||||
]
|
||||
|
||||
# helper for channels of characters in particular
|
||||
def buffer-lines in:address:source:char, buffered-out:address:sink:char -> buffered-out:address:sink:char, in:address:source:char [
|
||||
def buffer-lines in:&:source:char, buffered-out:&:sink:char -> buffered-out:&:sink:char, in:&:source:char [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# repeat forever
|
||||
eof?:bool <- copy 0/false
|
||||
{
|
||||
line:address:buffer <- new-buffer 30
|
||||
line:&:buffer <- new-buffer 30
|
||||
# read characters from 'in' until newline, copy into line
|
||||
{
|
||||
+next-character
|
||||
|
@ -434,9 +434,9 @@ def buffer-lines in:address:source:char, buffered-out:address:sink:char -> buffe
|
|||
scenario buffer-lines-blocks-until-newline [
|
||||
run [
|
||||
local-scope
|
||||
source:address:source:char, sink:address:sink:char <- new-channel 10/capacity
|
||||
_, buffered-stdin:address:sink:char/buffered-stdin <- new-channel 10/capacity
|
||||
buffered-chan:address:channel:char <- get *buffered-stdin, chan:offset
|
||||
source:&:source:char, sink:&:sink:char <- new-channel 10/capacity
|
||||
_, buffered-stdin:&:sink:char/buffered-stdin <- new-channel 10/capacity
|
||||
buffered-chan:&:channel:char <- get *buffered-stdin, chan:offset
|
||||
empty?:bool <- channel-empty? buffered-chan
|
||||
assert empty?, [
|
||||
F buffer-lines-blocks-until-newline: channel should be empty after init]
|
||||
|
|
100
081print.mu
100
081print.mu
|
@ -6,7 +6,7 @@ container screen [
|
|||
num-columns:num
|
||||
cursor-row:num
|
||||
cursor-column:num
|
||||
data:address:array:screen-cell
|
||||
data:&:array:screen-cell
|
||||
]
|
||||
|
||||
container screen-cell [
|
||||
|
@ -14,24 +14,24 @@ container screen-cell [
|
|||
color:num
|
||||
]
|
||||
|
||||
def new-fake-screen w:num, h:num -> result:address:screen [
|
||||
def new-fake-screen w:num, h:num -> result:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- new screen:type
|
||||
bufsize:num <- multiply w, h
|
||||
data:address:array:screen-cell <- new screen-cell:type, bufsize
|
||||
data:&:array:screen-cell <- new screen-cell:type, bufsize
|
||||
*result <- merge h/num-rows, w/num-columns, 0/cursor-row, 0/cursor-column, data
|
||||
result <- clear-screen result
|
||||
]
|
||||
|
||||
def clear-screen screen:address:screen -> screen:address:screen [
|
||||
def clear-screen screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists
|
||||
{
|
||||
break-unless screen
|
||||
# clear fake screen
|
||||
buf:address:array:screen-cell <- get *screen, data:offset
|
||||
buf:&:array:screen-cell <- get *screen, data:offset
|
||||
max:num <- length *buf
|
||||
i:num <- copy 0
|
||||
{
|
||||
|
@ -51,7 +51,7 @@ def clear-screen screen:address:screen -> screen:address:screen [
|
|||
clear-display
|
||||
]
|
||||
|
||||
def sync-screen screen:address:screen -> screen:address:screen [
|
||||
def sync-screen screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -61,11 +61,11 @@ def sync-screen screen:address:screen -> screen:address:screen [
|
|||
# do nothing for fake screens
|
||||
]
|
||||
|
||||
def fake-screen-is-empty? screen:address:screen -> result:bool [
|
||||
def fake-screen-is-empty? screen:&:screen -> result:bool [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return-unless screen, 1/true
|
||||
buf:address:array:screen-cell <- get *screen, data:offset
|
||||
buf:&:array:screen-cell <- get *screen, data:offset
|
||||
i:num <- copy 0
|
||||
len:num <- length *buf
|
||||
{
|
||||
|
@ -81,7 +81,7 @@ def fake-screen-is-empty? screen:address:screen -> result:bool [
|
|||
return 1/true
|
||||
]
|
||||
|
||||
def print screen:address:screen, c:char -> screen:address:screen [
|
||||
def print screen:&:screen, c:char -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
color:num, color-found?:bool <- next-ingredient
|
||||
|
@ -136,7 +136,7 @@ def print screen:address:screen, c:char -> screen:address:screen [
|
|||
# save character in fake screen
|
||||
index:num <- multiply row, width
|
||||
index <- add index, column
|
||||
buf:address:array:screen-cell <- get *screen, data:offset
|
||||
buf:&:array:screen-cell <- get *screen, data:offset
|
||||
len:num <- length *buf
|
||||
# special-case: backspace
|
||||
{
|
||||
|
@ -174,10 +174,10 @@ def print screen:address:screen, c:char -> screen:address:screen [
|
|||
scenario print-character-at-top-left [
|
||||
run [
|
||||
local-scope
|
||||
fake-screen:address:screen <- new-fake-screen 3/width, 2/height
|
||||
fake-screen:&:screen <- new-fake-screen 3/width, 2/height
|
||||
a:char <- copy 97/a
|
||||
fake-screen <- print fake-screen, a:char
|
||||
cell:address:array:screen-cell <- get *fake-screen, data:offset
|
||||
cell:&:array:screen-cell <- get *fake-screen, data:offset
|
||||
1:array:screen-cell/raw <- copy *cell
|
||||
]
|
||||
memory-should-contain [
|
||||
|
@ -192,10 +192,10 @@ scenario print-character-at-top-left [
|
|||
scenario print-character-in-color [
|
||||
run [
|
||||
local-scope
|
||||
fake-screen:address:screen <- new-fake-screen 3/width, 2/height
|
||||
fake-screen:&:screen <- new-fake-screen 3/width, 2/height
|
||||
a:char <- copy 97/a
|
||||
fake-screen <- print fake-screen, a:char, 1/red
|
||||
cell:address:array:screen-cell <- get *fake-screen, data:offset
|
||||
cell:&:array:screen-cell <- get *fake-screen, data:offset
|
||||
1:array:screen-cell/raw <- copy *cell
|
||||
]
|
||||
memory-should-contain [
|
||||
|
@ -210,13 +210,13 @@ scenario print-character-in-color [
|
|||
scenario print-backspace-character [
|
||||
run [
|
||||
local-scope
|
||||
fake-screen:address:screen <- new-fake-screen 3/width, 2/height
|
||||
fake-screen:&:screen <- new-fake-screen 3/width, 2/height
|
||||
a:char <- copy 97/a
|
||||
fake-screen <- print fake-screen, a
|
||||
backspace:char <- copy 8/backspace
|
||||
fake-screen <- print fake-screen, backspace
|
||||
10:num/raw <- get *fake-screen, cursor-column:offset
|
||||
cell:address:array:screen-cell <- get *fake-screen, data:offset
|
||||
cell:&:array:screen-cell <- get *fake-screen, data:offset
|
||||
11:array:screen-cell/raw <- copy *cell
|
||||
]
|
||||
memory-should-contain [
|
||||
|
@ -232,14 +232,14 @@ scenario print-backspace-character [
|
|||
scenario print-extra-backspace-character [
|
||||
run [
|
||||
local-scope
|
||||
fake-screen:address:screen <- new-fake-screen 3/width, 2/height
|
||||
fake-screen:&:screen <- new-fake-screen 3/width, 2/height
|
||||
a:char <- copy 97/a
|
||||
fake-screen <- print fake-screen, a
|
||||
backspace:char <- copy 8/backspace
|
||||
fake-screen <- print fake-screen, backspace
|
||||
fake-screen <- print fake-screen, backspace
|
||||
1:num/raw <- get *fake-screen, cursor-column:offset
|
||||
cell:address:array:screen-cell <- get *fake-screen, data:offset
|
||||
cell:&:array:screen-cell <- get *fake-screen, data:offset
|
||||
3:array:screen-cell/raw <- copy *cell
|
||||
]
|
||||
memory-should-contain [
|
||||
|
@ -255,7 +255,7 @@ scenario print-extra-backspace-character [
|
|||
scenario print-character-at-right-margin [
|
||||
run [
|
||||
local-scope
|
||||
fake-screen:address:screen <- new-fake-screen 2/width, 2/height
|
||||
fake-screen:&:screen <- new-fake-screen 2/width, 2/height
|
||||
a:char <- copy 97/a
|
||||
fake-screen <- print fake-screen, a
|
||||
b:char <- copy 98/b
|
||||
|
@ -263,7 +263,7 @@ scenario print-character-at-right-margin [
|
|||
c:char <- copy 99/c
|
||||
fake-screen <- print fake-screen, c
|
||||
10:num/raw <- get *fake-screen, cursor-column:offset
|
||||
cell:address:array:screen-cell <- get *fake-screen, data:offset
|
||||
cell:&:array:screen-cell <- get *fake-screen, data:offset
|
||||
11:array:screen-cell/raw <- copy *cell
|
||||
]
|
||||
memory-should-contain [
|
||||
|
@ -281,14 +281,14 @@ scenario print-character-at-right-margin [
|
|||
scenario print-newline-character [
|
||||
run [
|
||||
local-scope
|
||||
fake-screen:address:screen <- new-fake-screen 3/width, 2/height
|
||||
fake-screen:&:screen <- new-fake-screen 3/width, 2/height
|
||||
newline:char <- copy 10/newline
|
||||
a:char <- copy 97/a
|
||||
fake-screen <- print fake-screen, a
|
||||
fake-screen <- print fake-screen, newline
|
||||
10:num/raw <- get *fake-screen, cursor-row:offset
|
||||
11:num/raw <- get *fake-screen, cursor-column:offset
|
||||
cell:address:array:screen-cell <- get *fake-screen, data:offset
|
||||
cell:&:array:screen-cell <- get *fake-screen, data:offset
|
||||
12:array:screen-cell/raw <- copy *cell
|
||||
]
|
||||
memory-should-contain [
|
||||
|
@ -305,7 +305,7 @@ scenario print-newline-character [
|
|||
scenario print-newline-at-bottom-line [
|
||||
run [
|
||||
local-scope
|
||||
fake-screen:address:screen <- new-fake-screen 3/width, 2/height
|
||||
fake-screen:&:screen <- new-fake-screen 3/width, 2/height
|
||||
newline:char <- copy 10/newline
|
||||
fake-screen <- print fake-screen, newline
|
||||
fake-screen <- print fake-screen, newline
|
||||
|
@ -322,7 +322,7 @@ scenario print-newline-at-bottom-line [
|
|||
scenario print-character-at-bottom-right [
|
||||
run [
|
||||
local-scope
|
||||
fake-screen:address:screen <- new-fake-screen 2/width, 2/height
|
||||
fake-screen:&:screen <- new-fake-screen 2/width, 2/height
|
||||
newline:char <- copy 10/newline
|
||||
fake-screen <- print fake-screen, newline
|
||||
a:char <- copy 97/a
|
||||
|
@ -336,7 +336,7 @@ scenario print-character-at-bottom-right [
|
|||
fake-screen <- print fake-screen, d
|
||||
10:num/raw <- get *fake-screen, cursor-row:offset
|
||||
11:num/raw <- get *fake-screen, cursor-column:offset
|
||||
cell:address:array:screen-cell <- get *fake-screen, data:offset
|
||||
cell:&:array:screen-cell <- get *fake-screen, data:offset
|
||||
20:array:screen-cell/raw <- copy *cell
|
||||
]
|
||||
memory-should-contain [
|
||||
|
@ -356,7 +356,7 @@ scenario print-character-at-bottom-right [
|
|||
]
|
||||
]
|
||||
|
||||
def clear-line screen:address:screen -> screen:address:screen [
|
||||
def clear-line screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
space:char <- copy 0/nul
|
||||
|
@ -383,7 +383,7 @@ def clear-line screen:address:screen -> screen:address:screen [
|
|||
clear-line-on-display
|
||||
]
|
||||
|
||||
def clear-line-until screen:address:screen, right:num/inclusive -> screen:address:screen [
|
||||
def clear-line-until screen:&:screen, right:num/inclusive -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
_, column:num <- cursor-position screen
|
||||
|
@ -403,7 +403,7 @@ def clear-line-until screen:address:screen, right:num/inclusive -> screen:addres
|
|||
}
|
||||
]
|
||||
|
||||
def cursor-position screen:address:screen -> row:num, column:num [
|
||||
def cursor-position screen:&:screen -> row:num, column:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, lookup cursor in fake screen
|
||||
|
@ -416,7 +416,7 @@ def cursor-position screen:address:screen -> row:num, column:num [
|
|||
row, column <- cursor-position-on-display
|
||||
]
|
||||
|
||||
def move-cursor screen:address:screen, new-row:num, new-column:num -> screen:address:screen [
|
||||
def move-cursor screen:&:screen, new-row:num, new-column:num -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -433,7 +433,7 @@ def move-cursor screen:address:screen, new-row:num, new-column:num -> screen:add
|
|||
scenario clear-line-erases-printed-characters [
|
||||
run [
|
||||
local-scope
|
||||
fake-screen:address:screen <- new-fake-screen 3/width, 2/height
|
||||
fake-screen:&:screen <- new-fake-screen 3/width, 2/height
|
||||
# print a character
|
||||
a:char <- copy 97/a
|
||||
fake-screen <- print fake-screen, a
|
||||
|
@ -441,7 +441,7 @@ scenario clear-line-erases-printed-characters [
|
|||
fake-screen <- move-cursor fake-screen, 0/row, 0/column
|
||||
# clear line
|
||||
fake-screen <- clear-line fake-screen
|
||||
cell:address:array:screen-cell <- get *fake-screen, data:offset
|
||||
cell:&:array:screen-cell <- get *fake-screen, data:offset
|
||||
10:array:screen-cell/raw <- copy *cell
|
||||
]
|
||||
# screen should be blank
|
||||
|
@ -462,7 +462,7 @@ scenario clear-line-erases-printed-characters [
|
|||
]
|
||||
]
|
||||
|
||||
def cursor-down screen:address:screen -> screen:address:screen [
|
||||
def cursor-down screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -484,7 +484,7 @@ def cursor-down screen:address:screen -> screen:address:screen [
|
|||
move-cursor-down-on-display
|
||||
]
|
||||
|
||||
def cursor-up screen:address:screen -> screen:address:screen [
|
||||
def cursor-up screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -504,7 +504,7 @@ def cursor-up screen:address:screen -> screen:address:screen [
|
|||
move-cursor-up-on-display
|
||||
]
|
||||
|
||||
def cursor-right screen:address:screen -> screen:address:screen [
|
||||
def cursor-right screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -526,7 +526,7 @@ def cursor-right screen:address:screen -> screen:address:screen [
|
|||
move-cursor-right-on-display
|
||||
]
|
||||
|
||||
def cursor-left screen:address:screen -> screen:address:screen [
|
||||
def cursor-left screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -546,7 +546,7 @@ def cursor-left screen:address:screen -> screen:address:screen [
|
|||
move-cursor-left-on-display
|
||||
]
|
||||
|
||||
def cursor-to-start-of-line screen:address:screen -> screen:address:screen [
|
||||
def cursor-to-start-of-line screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
row:num <- cursor-position screen
|
||||
|
@ -554,21 +554,21 @@ def cursor-to-start-of-line screen:address:screen -> screen:address:screen [
|
|||
screen <- move-cursor screen, row, column
|
||||
]
|
||||
|
||||
def cursor-to-next-line screen:address:screen -> screen:address:screen [
|
||||
def cursor-to-next-line screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
screen <- cursor-down screen
|
||||
screen <- cursor-to-start-of-line screen
|
||||
]
|
||||
|
||||
def move-cursor-to-column screen:address:screen, column:num -> screen:address:screen [
|
||||
def move-cursor-to-column screen:&:screen, column:num -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
row:num, _ <- cursor-position screen
|
||||
move-cursor screen, row, column
|
||||
]
|
||||
|
||||
def screen-width screen:address:screen -> width:num [
|
||||
def screen-width screen:&:screen -> width:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -581,7 +581,7 @@ def screen-width screen:address:screen -> width:num [
|
|||
width <- display-width
|
||||
]
|
||||
|
||||
def screen-height screen:address:screen -> height:num [
|
||||
def screen-height screen:&:screen -> height:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -594,7 +594,7 @@ def screen-height screen:address:screen -> height:num [
|
|||
height <- display-height
|
||||
]
|
||||
|
||||
def hide-cursor screen:address:screen -> screen:address:screen [
|
||||
def hide-cursor screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists (not real display), do nothing
|
||||
|
@ -606,7 +606,7 @@ def hide-cursor screen:address:screen -> screen:address:screen [
|
|||
hide-cursor-on-display
|
||||
]
|
||||
|
||||
def show-cursor screen:address:screen -> screen:address:screen [
|
||||
def show-cursor screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists (not real display), do nothing
|
||||
|
@ -618,7 +618,7 @@ def show-cursor screen:address:screen -> screen:address:screen [
|
|||
show-cursor-on-display
|
||||
]
|
||||
|
||||
def hide-screen screen:address:screen -> screen:address:screen [
|
||||
def hide-screen screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists (not real display), do nothing
|
||||
|
@ -631,7 +631,7 @@ def hide-screen screen:address:screen -> screen:address:screen [
|
|||
hide-display
|
||||
]
|
||||
|
||||
def show-screen screen:address:screen -> screen:address:screen [
|
||||
def show-screen screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists (not real display), do nothing
|
||||
|
@ -644,7 +644,7 @@ def show-screen screen:address:screen -> screen:address:screen [
|
|||
show-display
|
||||
]
|
||||
|
||||
def print screen:address:screen, s:text -> screen:address:screen [
|
||||
def print screen:&:screen, s:text -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
color:num, color-found?:bool <- next-ingredient
|
||||
|
@ -674,10 +674,10 @@ def print screen:address:screen, s:text -> screen:address:screen [
|
|||
scenario print-text-stops-at-right-margin [
|
||||
run [
|
||||
local-scope
|
||||
fake-screen:address:screen <- new-fake-screen 3/width, 2/height
|
||||
fake-screen:&:screen <- new-fake-screen 3/width, 2/height
|
||||
s:text <- new [abcd]
|
||||
fake-screen <- print fake-screen, s:text
|
||||
cell:address:array:screen-cell <- get *fake-screen, data:offset
|
||||
cell:&:array:screen-cell <- get *fake-screen, data:offset
|
||||
10:array:screen-cell/raw <- copy *cell
|
||||
]
|
||||
memory-should-contain [
|
||||
|
@ -693,7 +693,7 @@ scenario print-text-stops-at-right-margin [
|
|||
]
|
||||
]
|
||||
|
||||
def print-integer screen:address:screen, n:num -> screen:address:screen [
|
||||
def print-integer screen:&:screen, n:num -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
color:num, color-found?:bool <- next-ingredient
|
||||
|
@ -714,7 +714,7 @@ def print-integer screen:address:screen, n:num -> screen:address:screen [
|
|||
]
|
||||
|
||||
# for now, we can only print integers
|
||||
def print screen:address:screen, n:num -> screen:address:screen [
|
||||
def print screen:&:screen, n:num -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
color:num, color-found?:bool <- next-ingredient
|
||||
|
@ -733,7 +733,7 @@ def print screen:address:screen, n:num -> screen:address:screen [
|
|||
]
|
||||
|
||||
# addresses
|
||||
def print screen:address:screen, n:address:_elem -> screen:address:screen [
|
||||
def print screen:&:screen, n:&:_elem -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
color:num, color-found?:bool <- next-ingredient
|
||||
|
|
|
@ -15,7 +15,7 @@ scenario screen-in-scenario [
|
|||
assume-screen 5/width, 3/height
|
||||
run [
|
||||
1:char <- copy 97/a
|
||||
screen:address:screen <- print screen:address:screen, 1:char/a
|
||||
screen:&:screen <- print screen:&:screen, 1:char/a
|
||||
]
|
||||
screen-should-contain [
|
||||
# 01234
|
||||
|
@ -31,9 +31,9 @@ scenario screen-in-scenario-unicode-color [
|
|||
assume-screen 5/width, 3/height
|
||||
run [
|
||||
1:char <- copy 955/greek-small-lambda
|
||||
screen:address:screen <- print screen:address:screen, 1:char/lambda, 1/red
|
||||
screen:&:screen <- print screen:&:screen, 1:char/lambda, 1/red
|
||||
2:char <- copy 97/a
|
||||
screen:address:screen <- print screen:address:screen, 2:char/a
|
||||
screen:&:screen <- print screen:&:screen, 2:char/a
|
||||
]
|
||||
screen-should-contain [
|
||||
# 01234
|
||||
|
@ -50,9 +50,9 @@ scenario screen-in-scenario-color [
|
|||
assume-screen 5/width, 3/height
|
||||
run [
|
||||
1:char <- copy 955/greek-small-lambda
|
||||
screen:address:screen <- print screen:address:screen, 1:char/lambda, 1/red
|
||||
screen:&:screen <- print screen:&:screen, 1:char/lambda, 1/red
|
||||
2:char <- copy 97/a
|
||||
screen:address:screen <- print screen:address:screen, 2:char/a, 7/white
|
||||
screen:&:screen <- print screen:&:screen, 2:char/a, 7/white
|
||||
]
|
||||
# screen-should-contain shows everything
|
||||
screen-should-contain [
|
||||
|
@ -86,7 +86,7 @@ scenario screen-in-scenario-error [
|
|||
assume-screen 5/width, 3/height
|
||||
run [
|
||||
1:char <- copy 97/a
|
||||
screen:address:screen <- print screen:address:screen, 1:char/a
|
||||
screen:&:screen <- print screen:&:screen, 1:char/a
|
||||
]
|
||||
screen-should-contain [
|
||||
# 01234
|
||||
|
@ -105,7 +105,7 @@ scenario screen-in-scenario-color [
|
|||
assume-screen 5/width, 3/height
|
||||
run [
|
||||
1:char <- copy 97/a
|
||||
screen:address:screen <- print screen:address:screen, 1:char/a, 1/red
|
||||
screen:&:screen <- print screen:&:screen, 1:char/a, 1/red
|
||||
]
|
||||
screen-should-contain-in-color 2/green, [
|
||||
# 01234
|
||||
|
@ -157,7 +157,7 @@ if (s == "screen") return true;
|
|||
|
||||
:(before "End Rewrite Instruction(curr, recipe result)")
|
||||
// rewrite `assume-screen width, height` to
|
||||
// `screen:address:screen <- new-fake-screen width, height`
|
||||
// `screen:&:screen <- new-fake-screen width, height`
|
||||
if (curr.name == "assume-screen") {
|
||||
curr.name = "new-fake-screen";
|
||||
if (!curr.products.empty()) {
|
||||
|
@ -168,7 +168,7 @@ if (curr.name == "assume-screen") {
|
|||
}
|
||||
else {
|
||||
assert(curr.products.empty());
|
||||
curr.products.push_back(reagent("screen:address:screen/raw"));
|
||||
curr.products.push_back(reagent("screen:&:screen/raw"));
|
||||
curr.products.at(0).set_value(SCREEN);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ scenario print-character-at-top-left-2 [
|
|||
run [
|
||||
local-scope
|
||||
a:char <- copy 97/a
|
||||
screen:address:screen <- print screen:address:screen, a
|
||||
screen:&:screen <- print screen:&:screen, a
|
||||
]
|
||||
screen-should-contain [
|
||||
.a .
|
||||
|
@ -19,11 +19,11 @@ scenario clear-line-erases-printed-characters-2 [
|
|||
local-scope
|
||||
# print a character
|
||||
a:char <- copy 97/a
|
||||
screen:address:screen <- print screen:address:screen, a
|
||||
screen:&:screen <- print screen:&:screen, a
|
||||
# move cursor to start of line
|
||||
screen:address:screen <- move-cursor screen:address:screen, 0/row, 0/column
|
||||
screen:&:screen <- move-cursor screen:&:screen, 0/row, 0/column
|
||||
# clear line
|
||||
screen:address:screen <- clear-line screen:address:screen
|
||||
screen:&:screen <- clear-line screen:&:screen
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
|
|
@ -22,28 +22,28 @@ container resize-event [
|
|||
|
||||
container console [
|
||||
current-event-index:num
|
||||
events:address:array:event
|
||||
events:&:array:event
|
||||
]
|
||||
|
||||
def new-fake-console events:address:array:event -> result:address:console [
|
||||
def new-fake-console events:&:array:event -> result:&:console [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result:address:console <- new console:type
|
||||
result:&:console <- new console:type
|
||||
*result <- put *result, events:offset, events
|
||||
]
|
||||
|
||||
def read-event console:address:console -> result:event, console:address:console, found?:bool, quit?:bool [
|
||||
def read-event console:&:console -> result:event, console:&:console, found?:bool, quit?:bool [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
break-unless console
|
||||
current-event-index:num <- get *console, current-event-index:offset
|
||||
buf:address:array:event <- get *console, events:offset
|
||||
buf:&:array:event <- get *console, events:offset
|
||||
{
|
||||
max:num <- length *buf
|
||||
done?:bool <- greater-or-equal current-event-index, max
|
||||
break-unless done?
|
||||
dummy:address:event <- new event:type
|
||||
dummy:&:event <- new event:type
|
||||
return *dummy, console/same-as-ingredient:0, 1/found, 1/quit
|
||||
}
|
||||
result <- index *buf, current-event-index
|
||||
|
@ -59,7 +59,7 @@ def read-event console:address:console -> result:event, console:address:console,
|
|||
# variant of read-event for just keyboard events. Discards everything that
|
||||
# isn't unicode, so no arrow keys, page-up/page-down, etc. But you still get
|
||||
# newlines, tabs, ctrl-d..
|
||||
def read-key console:address:console -> result:char, console:address:console, found?:bool, quit?:bool [
|
||||
def read-key console:&:console -> result:char, console:&:console, found?:bool, quit?:bool [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:event, console, found?:bool, quit?:bool <- read-event console
|
||||
|
@ -70,7 +70,7 @@ def read-key console:address:console -> result:char, console:address:console, fo
|
|||
return c, console/same-as-ingredient:0, 1/found, 0/quit
|
||||
]
|
||||
|
||||
def send-keys-to-channel console:address:console, chan:address:sink:char, screen:address:screen -> console:address:console, chan:address:sink:char, screen:address:screen [
|
||||
def send-keys-to-channel console:&:console, chan:&:sink:char, screen:&:screen -> console:&:console, chan:&:sink:char, screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -85,7 +85,7 @@ def send-keys-to-channel console:address:console, chan:address:sink:char, screen
|
|||
chan <- close chan
|
||||
]
|
||||
|
||||
def wait-for-event console:address:console -> console:address:console [
|
||||
def wait-for-event console:&:console -> console:&:console [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -95,7 +95,7 @@ def wait-for-event console:address:console -> console:address:console [
|
|||
]
|
||||
|
||||
# use this helper to skip rendering if there's lots of other events queued up
|
||||
def has-more-events? console:address:console -> result:bool [
|
||||
def has-more-events? console:&:console -> result:bool [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
|
|
@ -15,10 +15,10 @@ scenario keyboard-in-scenario [
|
|||
type [abc]
|
||||
]
|
||||
run [
|
||||
1:char, console:address:console, 2:bool <- read-key console:address:console
|
||||
3:char, console:address:console, 4:bool <- read-key console:address:console
|
||||
5:char, console:address:console, 6:bool <- read-key console:address:console
|
||||
7:char, console:address:console, 8:bool, 9:bool <- read-key console:address:console
|
||||
1:char, console:&:console, 2:bool <- read-key console:&:console
|
||||
3:char, console:&:console, 4:bool <- read-key console:&:console
|
||||
5:char, console:&:console, 6:bool <- read-key console:&:console
|
||||
7:char, console:&:console, 8:bool, 9:bool <- read-key console:&:console
|
||||
]
|
||||
memory-should-contain [
|
||||
1 <- 97 # 'a'
|
||||
|
@ -197,15 +197,15 @@ scenario events-in-scenario [
|
|||
]
|
||||
run [
|
||||
# 3 keyboard events; each event occupies 4 locations
|
||||
1:event <- read-event console:address:console
|
||||
5:event <- read-event console:address:console
|
||||
9:event <- read-event console:address:console
|
||||
1:event <- read-event console:&:console
|
||||
5:event <- read-event console:&:console
|
||||
9:event <- read-event console:&:console
|
||||
# mouse click
|
||||
13:event <- read-event console:address:console
|
||||
13:event <- read-event console:&:console
|
||||
# non-character keycode
|
||||
17:event <- read-event console:address:console
|
||||
17:event <- read-event console:&:console
|
||||
# final keyboard event
|
||||
21:event <- read-event console:address:console
|
||||
21:event <- read-event console:&:console
|
||||
]
|
||||
memory-should-contain [
|
||||
1 <- 0 # 'text'
|
||||
|
|
|
@ -7,10 +7,10 @@ scenario read-key-in-mu [
|
|||
type [abc]
|
||||
]
|
||||
run [
|
||||
1:char, console:address:console, 2:bool <- read-key console:address:console
|
||||
3:char, console:address:console, 4:bool <- read-key console:address:console
|
||||
5:char, console:address:console, 6:bool <- read-key console:address:console
|
||||
7:char, console:address:console, 8:bool <- read-key console:address:console
|
||||
1:char, console:&:console, 2:bool <- read-key console:&:console
|
||||
3:char, console:&:console, 4:bool <- read-key console:&:console
|
||||
5:char, console:&:console, 6:bool <- read-key console:&:console
|
||||
7:char, console:&:console, 8:bool <- read-key console:&:console
|
||||
]
|
||||
memory-should-contain [
|
||||
1 <- 97 # 'a'
|
||||
|
|
28
088file.mu
28
088file.mu
|
@ -2,7 +2,7 @@
|
|||
# are thus easier to test.
|
||||
|
||||
container filesystem [
|
||||
data:address:array:file-mapping
|
||||
data:&:array:file-mapping
|
||||
]
|
||||
|
||||
container file-mapping [
|
||||
|
@ -10,7 +10,7 @@ container file-mapping [
|
|||
contents:text
|
||||
]
|
||||
|
||||
def start-reading fs:address:filesystem, filename:text -> contents:address:source:char [
|
||||
def start-reading fs:&:filesystem, filename:text -> contents:&:source:char [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -18,13 +18,13 @@ def start-reading fs:address:filesystem, filename:text -> contents:address:sourc
|
|||
# real file system
|
||||
file:num <- $open-file-for-reading filename
|
||||
assert file, [file not found]
|
||||
contents:address:source:char, sink:address:sink:char <- new-channel 30
|
||||
contents:&:source:char, sink:&:sink:char <- new-channel 30
|
||||
start-running transmit-from-file file, sink
|
||||
return
|
||||
}
|
||||
# fake file system
|
||||
i:num <- copy 0
|
||||
data:address:array:file-mapping <- get *fs, data:offset
|
||||
data:&:array:file-mapping <- get *fs, data:offset
|
||||
len:num <- length *data
|
||||
{
|
||||
done?:bool <- greater-or-equal i, len
|
||||
|
@ -34,7 +34,7 @@ def start-reading fs:address:filesystem, filename:text -> contents:address:sourc
|
|||
curr-filename:text <- get tmp, name:offset
|
||||
found?:bool <- equal filename, curr-filename
|
||||
loop-unless found?
|
||||
contents:address:source:char, sink:address:sink:char <- new-channel 30
|
||||
contents:&:source:char, sink:&:sink:char <- new-channel 30
|
||||
curr-contents:text <- get tmp, contents:offset
|
||||
start-running transmit-from-text curr-contents, sink
|
||||
return
|
||||
|
@ -42,7 +42,7 @@ def start-reading fs:address:filesystem, filename:text -> contents:address:sourc
|
|||
return 0/not-found
|
||||
]
|
||||
|
||||
def transmit-from-file file:num, sink:address:sink:char -> sink:address:sink:char [
|
||||
def transmit-from-file file:num, sink:&:sink:char -> sink:&:sink:char [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -55,7 +55,7 @@ def transmit-from-file file:num, sink:address:sink:char -> sink:address:sink:cha
|
|||
file <- $close-file file
|
||||
]
|
||||
|
||||
def transmit-from-text contents:text, sink:address:sink:char -> sink:address:sink:char [
|
||||
def transmit-from-text contents:text, sink:&:sink:char -> sink:&:sink:char [
|
||||
local-scope
|
||||
load-ingredients
|
||||
i:num <- copy 0
|
||||
|
@ -71,10 +71,10 @@ def transmit-from-text contents:text, sink:address:sink:char -> sink:address:sin
|
|||
sink <- close sink
|
||||
]
|
||||
|
||||
def start-writing fs:address:filesystem, filename:text -> sink:address:sink:char, routine-id:num [
|
||||
def start-writing fs:&:filesystem, filename:text -> sink:&:sink:char, routine-id:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
source:address:source:char, sink:address:sink:char <- new-channel 30
|
||||
source:&:source:char, sink:&:sink:char <- new-channel 30
|
||||
{
|
||||
break-if fs
|
||||
# real file system
|
||||
|
@ -88,7 +88,7 @@ def start-writing fs:address:filesystem, filename:text -> sink:address:sink:char
|
|||
routine-id <- start-running transmit-to-fake-file fs, filename, source
|
||||
]
|
||||
|
||||
def transmit-to-file file:num, source:address:source:char -> source:address:source:char [
|
||||
def transmit-to-file file:num, source:&:source:char -> source:&:source:char [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -100,11 +100,11 @@ def transmit-to-file file:num, source:address:source:char -> source:address:sour
|
|||
file <- $close-file file
|
||||
]
|
||||
|
||||
def transmit-to-fake-file fs:address:filesystem, filename:text, source:address:source:char -> fs:address:filesystem, source:address:source:char [
|
||||
def transmit-to-fake-file fs:&:filesystem, filename:text, source:&:source:char -> fs:&:filesystem, source:&:source:char [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# compute new file contents
|
||||
buf:address:buffer <- new-buffer 30
|
||||
buf:&:buffer <- new-buffer 30
|
||||
{
|
||||
c:char, done?:bool, source <- read source
|
||||
break-if done?
|
||||
|
@ -115,7 +115,7 @@ def transmit-to-fake-file fs:address:filesystem, filename:text, source:address:s
|
|||
new-file-mapping:file-mapping <- merge filename, contents
|
||||
# write to filesystem
|
||||
curr-filename:text <- copy 0
|
||||
data:address:array:file-mapping <- get *fs, data:offset
|
||||
data:&:array:file-mapping <- get *fs, data:offset
|
||||
# replace file contents if it already exists
|
||||
i:num <- copy 0
|
||||
len:num <- length *data
|
||||
|
@ -131,7 +131,7 @@ def transmit-to-fake-file fs:address:filesystem, filename:text, source:address:s
|
|||
}
|
||||
# if file didn't already exist, make room for it
|
||||
new-len:num <- add len, 1
|
||||
new-data:address:array:file-mapping <- new file-mapping:type, new-len
|
||||
new-data:&:array:file-mapping <- new file-mapping:type, new-len
|
||||
put *fs, data:offset, new-data
|
||||
# copy over old files
|
||||
i:num <- copy 0
|
||||
|
|
|
@ -20,7 +20,7 @@ scenario assume-filesystem [
|
|||
|xyz|
|
||||
]
|
||||
]
|
||||
data:address:array:file-mapping <- get *filesystem:address:filesystem, data:offset
|
||||
data:&:array:file-mapping <- get *filesystem:&:filesystem, data:offset
|
||||
file1:file-mapping <- index *data, 0
|
||||
file1-name:text <- get file1, name:offset
|
||||
10:array:char/raw <- copy *file1-name
|
||||
|
@ -59,7 +59,7 @@ scenario assume-filesystem [
|
|||
|x\\\\|yz|
|
||||
]
|
||||
]
|
||||
data:address:array:file-mapping <- get *filesystem:address:filesystem, data:offset
|
||||
data:&:array:file-mapping <- get *filesystem:&:filesystem, data:offset
|
||||
file1:file-mapping <- index *data, 0
|
||||
file1-name:text <- get file1, name:offset
|
||||
10:array:char/raw <- copy *file1-name
|
||||
|
|
|
@ -7,7 +7,7 @@ scenario read-from-fake-file [
|
|||
|xyz|
|
||||
]
|
||||
]
|
||||
contents:address:source:char <- start-reading filesystem:address:filesystem, [a]
|
||||
contents:&:source:char <- start-reading filesystem:&:filesystem, [a]
|
||||
1:char/raw <- read contents
|
||||
2:char/raw <- read contents
|
||||
3:char/raw <- read contents
|
||||
|
@ -26,7 +26,7 @@ scenario write-to-fake-file [
|
|||
local-scope
|
||||
assume-filesystem [
|
||||
]
|
||||
sink:address:sink:char, writer:num/routine <- start-writing filesystem:address:filesystem, [a]
|
||||
sink:&:sink:char, writer:num/routine <- start-writing filesystem:&:filesystem, [a]
|
||||
sink <- write sink, 120/x
|
||||
sink <- write sink, 121/y
|
||||
close sink
|
||||
|
@ -43,7 +43,7 @@ scenario write-to-fake-file-that-exists [
|
|||
assume-filesystem [
|
||||
[a] <- []
|
||||
]
|
||||
sink:address:sink:char, writer:num/routine <- start-writing filesystem:address:filesystem, [a]
|
||||
sink:&:sink:char, writer:num/routine <- start-writing filesystem:&:filesystem, [a]
|
||||
sink <- write sink, 120/x
|
||||
sink <- write sink, 121/y
|
||||
close sink
|
||||
|
@ -63,7 +63,7 @@ scenario write-to-existing-file-preserves-other-files [
|
|||
|bcd|
|
||||
]
|
||||
]
|
||||
sink:address:sink:char, writer:num/routine <- start-writing filesystem:address:filesystem, [a]
|
||||
sink:&:sink:char, writer:num/routine <- start-writing filesystem:&:filesystem, [a]
|
||||
sink <- write sink, 120/x
|
||||
sink <- write sink, 121/y
|
||||
close sink
|
||||
|
@ -79,11 +79,11 @@ scenario write-to-existing-file-preserves-other-files [
|
|||
]
|
||||
]
|
||||
|
||||
def slurp fs:address:filesystem, filename:text -> contents:text [
|
||||
def slurp fs:&:filesystem, filename:text -> contents:text [
|
||||
local-scope
|
||||
load-ingredients
|
||||
source:address:source:char <- start-reading fs, filename
|
||||
buf:address:buffer <- new-buffer 30/capacity
|
||||
source:&:source:char <- start-reading fs, filename
|
||||
buf:&:buffer <- new-buffer 30/capacity
|
||||
{
|
||||
c:char, done?:bool, source <- read source
|
||||
break-if done?
|
||||
|
|
|
@ -105,7 +105,7 @@ bool run_interactive(int address) {
|
|||
// call run(string) but without the scheduling
|
||||
load(string("recipe! interactive [\n") +
|
||||
"new-default-space\n" + // disable automatic abandon so tests can see changes
|
||||
"screen:address:screen <- next-ingredient\n" +
|
||||
"screen:&:screen <- next-ingredient\n" +
|
||||
"$start-tracking-products\n" +
|
||||
command + "\n" +
|
||||
"$stop-tracking-products\n" +
|
||||
|
@ -194,7 +194,7 @@ load(string(
|
|||
"]\n" +
|
||||
"recipe sandbox [\n" +
|
||||
"local-scope\n" +
|
||||
"screen:address:screen <- new-fake-screen 30, 5\n" +
|
||||
"screen:&:screen <- new-fake-screen 30, 5\n" +
|
||||
"routine-id:num <- start-running interactive, screen\n" +
|
||||
"limit-time routine-id, 100000/instructions\n" +
|
||||
"wait-for-routine routine-id\n" +
|
||||
|
@ -352,7 +352,7 @@ get x:num, foo:offset]
|
|||
:(scenario run_interactive_with_comment)
|
||||
def main [
|
||||
# 2 instructions, with a comment after the first
|
||||
1:address:array:num <- new [a:num <- copy 0 # abc
|
||||
1:&:array:num <- new [a:num <- copy 0 # abc
|
||||
b:num <- copy 0
|
||||
]
|
||||
2:text, 3:text <- run-sandboxed 1:text
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# example program: communicating between routines using channels
|
||||
|
||||
def producer sink:address:sink:char -> sink:address:sink:char [
|
||||
def producer sink:&:sink:char -> sink:&:sink:char [
|
||||
# produce characters 1 to 5 on a channel
|
||||
local-scope
|
||||
load-ingredients
|
||||
|
@ -19,7 +19,7 @@ def producer sink:address:sink:char -> sink:address:sink:char [
|
|||
close sink
|
||||
]
|
||||
|
||||
def consumer source:address:source:char -> source:address:source:char [
|
||||
def consumer source:&:source:char -> source:&:source:char [
|
||||
# consume and print integers from a channel
|
||||
local-scope
|
||||
load-ingredients
|
||||
|
@ -36,7 +36,7 @@ def consumer source:address:source:char -> source:address:source:char [
|
|||
|
||||
def main [
|
||||
local-scope
|
||||
source:address:source:char, sink:address:sink:char <- new-channel 3/capacity
|
||||
source:&:source:char, sink:&:sink:char <- new-channel 3/capacity
|
||||
# create two background 'routines' that communicate by a channel
|
||||
routine1:num <- start-running producer, sink
|
||||
routine2:num <- start-running consumer, source
|
||||
|
|
|
@ -29,7 +29,7 @@ scenario print-board-and-read-move [
|
|||
]
|
||||
run [
|
||||
local-scope
|
||||
screen:address:screen, console:address:console <- chessboard screen:address:screen, console:address:console
|
||||
screen:&:screen, console:&:console <- chessboard screen:&:screen, console:&:console
|
||||
# icon for the cursor
|
||||
cursor-icon:char <- copy 9251/␣
|
||||
screen <- print screen, cursor-icon
|
||||
|
@ -62,17 +62,17 @@ scenario print-board-and-read-move [
|
|||
|
||||
## Here's how 'chessboard' is implemented.
|
||||
|
||||
type board = address:array:address:array:char
|
||||
type board = address:array:&:array:char
|
||||
|
||||
def chessboard screen:address:screen, console:address:console -> screen:address:screen, console:address:console [
|
||||
def chessboard screen:&:screen, console:&:console -> screen:&:screen, console:&:console [
|
||||
local-scope
|
||||
load-ingredients
|
||||
board:board <- initial-position
|
||||
# hook up stdin
|
||||
stdin-in:address:source:char, stdin-out:address:sink:char <- new-channel 10/capacity
|
||||
stdin-in:&:source:char, stdin-out:&:sink:char <- new-channel 10/capacity
|
||||
start-running send-keys-to-channel, console, stdin-out, screen
|
||||
# buffer lines in stdin
|
||||
buffered-stdin-in:address:source:char, buffered-stdin-out:address:sink:char <- new-channel 10/capacity
|
||||
buffered-stdin-in:&:source:char, buffered-stdin-out:&:sink:char <- new-channel 10/capacity
|
||||
start-running buffer-lines, stdin-in, buffered-stdin-out
|
||||
{
|
||||
print screen, [Stupid text-mode chessboard. White pieces in uppercase; black pieces in lowercase. No checking for legal moves.
|
||||
|
@ -88,7 +88,7 @@ def chessboard screen:address:screen, console:address:console -> screen:address:
|
|||
{
|
||||
cursor-to-next-line screen
|
||||
screen <- print screen, [move: ]
|
||||
m:address:move, quit:boolean, error:boolean <- read-move buffered-stdin-in, screen
|
||||
m:&:move, quit:boolean, error:boolean <- read-move buffered-stdin-in, screen
|
||||
break-if quit, +quit:label
|
||||
buffered-stdin-in <- clear buffered-stdin-in # cleanup after error. todo: test this?
|
||||
loop-if error
|
||||
|
@ -102,7 +102,7 @@ def chessboard screen:address:screen, console:address:console -> screen:address:
|
|||
|
||||
## a board is an array of files, a file is an array of characters (squares)
|
||||
|
||||
def new-board initial-position:address:array:char -> board:board [
|
||||
def new-board initial-position:&:array:char -> board:board [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# assert(length(initial-position) == 64)
|
||||
|
@ -115,14 +115,14 @@ def new-board initial-position:address:array:char -> board:board [
|
|||
{
|
||||
done?:boolean <- equal col, 8
|
||||
break-if done?
|
||||
file:address:array:char <- new-file initial-position, col
|
||||
file:&:array:char <- new-file initial-position, col
|
||||
*board <- put-index *board, col, file
|
||||
col <- add col, 1
|
||||
loop
|
||||
}
|
||||
]
|
||||
|
||||
def new-file position:address:array:char, index:num -> result:address:array:char [
|
||||
def new-file position:&:array:char, index:num -> result:&:array:char [
|
||||
local-scope
|
||||
load-ingredients
|
||||
index <- multiply index, 8
|
||||
|
@ -139,7 +139,7 @@ def new-file position:address:array:char, index:num -> result:address:array:char
|
|||
}
|
||||
]
|
||||
|
||||
def print-board screen:address:screen, board:board -> screen:address:screen [
|
||||
def print-board screen:&:screen, board:board -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
row:num <- copy 7 # start printing from the top of the board
|
||||
|
@ -157,7 +157,7 @@ def print-board screen:address:screen, board:board -> screen:address:screen [
|
|||
{
|
||||
done?:boolean <- equal col:num, 8
|
||||
break-if done?:boolean
|
||||
f:address:array:char <- index *board, col
|
||||
f:&:array:char <- index *board, col
|
||||
c:char <- index *f, row
|
||||
print screen, c
|
||||
print screen, space
|
||||
|
@ -186,7 +186,7 @@ def initial-position -> board:board [
|
|||
# B P _ _ _ _ p B
|
||||
# N P _ _ _ _ p n
|
||||
# R P _ _ _ _ p r
|
||||
initial-position:address:array:char <- new-array 82/R, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 114/r, 78/N, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 110/n, 66/B, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 98/b, 81/Q, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 113/q, 75/K, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 107/k, 66/B, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 98/b, 78/N, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 110/n, 82/R, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 114/r
|
||||
initial-position:&:array:char <- new-array 82/R, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 114/r, 78/N, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 110/n, 66/B, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 98/b, 81/Q, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 113/q, 75/K, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 107/k, 66/B, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 98/b, 78/N, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 110/n, 82/R, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 114/r
|
||||
#? 82/R, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 114/r,
|
||||
#? 78/N, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 110/n,
|
||||
#? 66/B, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 98/b,
|
||||
|
@ -203,7 +203,7 @@ scenario printing-the-board [
|
|||
run [
|
||||
local-scope
|
||||
board:board <- initial-position
|
||||
screen:address:screen <- print-board screen:address:screen, board
|
||||
screen:&:screen <- print-board screen:&:screen, board
|
||||
]
|
||||
screen-should-contain [
|
||||
# 012345678901234567890123456789
|
||||
|
@ -233,14 +233,14 @@ container move [
|
|||
]
|
||||
|
||||
# prints only error messages to screen
|
||||
def read-move stdin:address:source:char, screen:address:screen -> result:address:move, quit?:boolean, error?:boolean, stdin:address:source:char, screen:address:screen [
|
||||
def read-move stdin:&:source:char, screen:&:screen -> result:&:move, quit?:boolean, error?:boolean, stdin:&:source:char, screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
from-file:num, quit?:boolean, error?:boolean <- read-file stdin, screen
|
||||
return-if quit?, 0/dummy
|
||||
return-if error?, 0/dummy
|
||||
# construct the move object
|
||||
result:address:move <- new move:type
|
||||
result:&:move <- new move:type
|
||||
*result <- put *result, from-file:offset, from-file
|
||||
from-rank:num, quit?, error? <- read-rank stdin, screen
|
||||
return-if quit?, 0/dummy
|
||||
|
@ -261,7 +261,7 @@ def read-move stdin:address:source:char, screen:address:screen -> result:address
|
|||
]
|
||||
|
||||
# valid values for file: 0-7
|
||||
def read-file stdin:address:source:char, screen:address:screen -> file:num, quit:boolean, error:boolean, stdin:address:source:char, screen:address:screen [
|
||||
def read-file stdin:&:source:char, screen:&:screen -> file:num, quit:boolean, error:boolean, stdin:&:source:char, screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
c:char, eof?:boolean, stdin <- read stdin
|
||||
|
@ -308,7 +308,7 @@ def read-file stdin:address:source:char, screen:address:screen -> file:num, quit
|
|||
]
|
||||
|
||||
# valid values for rank: 0-7
|
||||
def read-rank stdin:address:source:char, screen:address:screen -> rank:num, quit?:boolean, error?:boolean, stdin:address:source:char, screen:address:screen [
|
||||
def read-rank stdin:&:source:char, screen:&:screen -> rank:num, quit?:boolean, error?:boolean, stdin:&:source:char, screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
c:char, eof?:boolean, stdin <- read stdin
|
||||
|
@ -350,7 +350,7 @@ def read-rank stdin:address:source:char, screen:address:screen -> rank:num, quit
|
|||
|
||||
# read a character from the given channel and check that it's what we expect
|
||||
# return true on error
|
||||
def expect-from-channel stdin:address:source:char, expected:char, screen:address:screen -> result:boolean, stdin:address:source:char, screen:address:screen [
|
||||
def expect-from-channel stdin:&:source:char, expected:char, screen:&:screen -> result:boolean, stdin:&:source:char, screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
c:char, eof?:boolean, stdin <- read stdin
|
||||
|
@ -367,8 +367,8 @@ scenario read-move-blocking [
|
|||
assume-screen 20/width, 2/height
|
||||
run [
|
||||
local-scope
|
||||
source:address:source:char, sink:address:sink:char <- new-channel 2/capacity
|
||||
read-move-routine:num/routine <- start-running read-move, source, screen:address:screen
|
||||
source:&:source:char, sink:&:sink:char <- new-channel 2/capacity
|
||||
read-move-routine:num/routine <- start-running read-move, source, screen:&:screen
|
||||
# 'read-move' is waiting for input
|
||||
wait-for-routine-to-block read-move-routine
|
||||
read-move-state:num <- routine-state read-move-routine
|
||||
|
@ -440,8 +440,8 @@ scenario read-move-quit [
|
|||
assume-screen 20/width, 2/height
|
||||
run [
|
||||
local-scope
|
||||
source:address:source:char, sink:address:sink:char <- new-channel 2/capacity
|
||||
read-move-routine:num <- start-running read-move, source, screen:address:screen
|
||||
source:&:source:char, sink:&:sink:char <- new-channel 2/capacity
|
||||
read-move-routine:num <- start-running read-move, source, screen:&:screen
|
||||
# 'read-move' is waiting for input
|
||||
wait-for-routine-to-block read-move-routine
|
||||
read-move-state:num <- routine-state read-move-routine
|
||||
|
@ -468,8 +468,8 @@ scenario read-move-illegal-file [
|
|||
assume-screen 20/width, 2/height
|
||||
run [
|
||||
local-scope
|
||||
source:address:source:char, sink:address:sink:char <- new-channel 2/capacity
|
||||
read-move-routine:num <- start-running read-move, source, screen:address:screen
|
||||
source:&:source:char, sink:&:sink:char <- new-channel 2/capacity
|
||||
read-move-routine:num <- start-running read-move, source, screen:&:screen
|
||||
# 'read-move' is waiting for input
|
||||
wait-for-routine-to-block read-move-routine
|
||||
read-move-state:num <- routine-state read-move-routine
|
||||
|
@ -490,8 +490,8 @@ scenario read-move-illegal-rank [
|
|||
assume-screen 20/width, 2/height
|
||||
run [
|
||||
local-scope
|
||||
source:address:source:char, sink:address:sink:char <- new-channel 2/capacity
|
||||
read-move-routine:num <- start-running read-move, source, screen:address:screen
|
||||
source:&:source:char, sink:&:sink:char <- new-channel 2/capacity
|
||||
read-move-routine:num <- start-running read-move, source, screen:&:screen
|
||||
# 'read-move' is waiting for input
|
||||
wait-for-routine-to-block read-move-routine
|
||||
read-move-state:num <- routine-state read-move-routine
|
||||
|
@ -513,8 +513,8 @@ scenario read-move-empty [
|
|||
assume-screen 20/width, 2/height
|
||||
run [
|
||||
local-scope
|
||||
source:address:source:char, sink:address:sink:char <- new-channel 2/capacity
|
||||
read-move-routine:num <- start-running read-move, source, screen:address:screen
|
||||
source:&:source:char, sink:&:sink:char <- new-channel 2/capacity
|
||||
read-move-routine:num <- start-running read-move, source, screen:&:screen
|
||||
# 'read-move' is waiting for input
|
||||
wait-for-routine-to-block read-move-routine
|
||||
read-move-state:num <- routine-state read-move-routine
|
||||
|
@ -532,15 +532,15 @@ F read-move-empty: routine failed to pause after coming up (before any keys were
|
|||
]
|
||||
]
|
||||
|
||||
def make-move board:board, m:address:move -> board:board [
|
||||
def make-move board:board, m:&:move -> board:board [
|
||||
local-scope
|
||||
load-ingredients
|
||||
from-file:num <- get *m, from-file:offset
|
||||
from-rank:num <- get *m, from-rank:offset
|
||||
to-file:num <- get *m, to-file:offset
|
||||
to-rank:num <- get *m, to-rank:offset
|
||||
from-f:address:array:char <- index *board, from-file
|
||||
to-f:address:array:char <- index *board, to-file
|
||||
from-f:&:array:char <- index *board, from-file
|
||||
to-f:&:array:char <- index *board, to-file
|
||||
src:char/square <- index *from-f, from-rank
|
||||
*to-f <- put-index *to-f, to-rank, src
|
||||
*from-f <- put-index *from-f, from-rank, 32/space
|
||||
|
@ -551,10 +551,10 @@ scenario making-a-move [
|
|||
run [
|
||||
local-scope
|
||||
board:board <- initial-position
|
||||
move:address:move <- new move:type
|
||||
move:&:move <- new move:type
|
||||
*move <- merge 6/g, 1/'2', 6/g, 3/'4'
|
||||
board <- make-move board, move
|
||||
screen:address:screen <- print-board screen:address:screen, board
|
||||
screen:&:screen <- print-board screen:&:screen, board
|
||||
]
|
||||
screen-should-contain [
|
||||
# 012345678901234567890123456789
|
||||
|
|
10
counters.mu
10
counters.mu
|
@ -1,24 +1,24 @@
|
|||
# example program: maintain multiple counters with isolated lexical scopes
|
||||
# (spaces)
|
||||
|
||||
def new-counter n:num -> default-space:address:array:location [
|
||||
def new-counter n:num -> default-space:&:array:location [
|
||||
default-space <- new location:type, 30
|
||||
load-ingredients
|
||||
]
|
||||
|
||||
def increment-counter outer:address:array:location/names:new-counter, x:num -> n:num/space:1 [
|
||||
def increment-counter outer:&:array:location/names:new-counter, x:num -> n:num/space:1 [
|
||||
local-scope
|
||||
load-ingredients
|
||||
0:address:array:location/names:new-counter <- copy outer # setup outer space; it *must* come from 'new-counter'
|
||||
0:&:array:location/names:new-counter <- copy outer # setup outer space; it *must* come from 'new-counter'
|
||||
n/space:1 <- add n/space:1, x
|
||||
]
|
||||
|
||||
def main [
|
||||
local-scope
|
||||
# counter A
|
||||
a:address:array:location <- new-counter 34
|
||||
a:&:array:location <- new-counter 34
|
||||
# counter B
|
||||
b:address:array:location <- new-counter 23
|
||||
b:&:array:location <- new-counter 23
|
||||
# increment both by 2 but in different ways
|
||||
increment-counter a, 1
|
||||
b-value:num <- increment-counter b, 2
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
def main [
|
||||
local-scope
|
||||
source-file:address:source:char <- start-reading 0/real-filesystem, [/tmp/mu-x]
|
||||
sink-file:address:sink:char, write-routine:num <- start-writing 0/real-filesystem, [/tmp/mu-y]
|
||||
source-file:&:source:char <- start-reading 0/real-filesystem, [/tmp/mu-x]
|
||||
sink-file:&:sink:char, write-routine:num <- start-writing 0/real-filesystem, [/tmp/mu-y]
|
||||
{
|
||||
c:char, done?:boolean, source-file <- read source-file
|
||||
break-if done?
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
def main [
|
||||
# allocate 5 locations for globals
|
||||
global-space:address:array:location <- new location:type, 5
|
||||
global-space:&:array:location <- new location:type, 5
|
||||
# read to globals by using /space:global
|
||||
1:num/space:global <- copy 3
|
||||
foo
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
def main [
|
||||
local-scope
|
||||
x:address:num <- new number:type
|
||||
x:&:num <- new number:type
|
||||
foo x
|
||||
]
|
||||
|
||||
def foo x:address:num [
|
||||
def foo x:&:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
*x <- copy 34 # will cause an error because x is immutable in this function
|
||||
|
|
164
lambda_to_mu.mu
164
lambda_to_mu.mu
|
@ -17,7 +17,7 @@ def lambda-to-mu in:text -> out:text [
|
|||
local-scope
|
||||
load-ingredients
|
||||
out <- copy 0
|
||||
cells:address:cell <- parse in
|
||||
cells:&:cell <- parse in
|
||||
out <- to-mu cells
|
||||
]
|
||||
|
||||
|
@ -29,32 +29,32 @@ exclusive-container cell [
|
|||
|
||||
# printed below as < first | rest >
|
||||
container pair [
|
||||
first:address:cell
|
||||
rest:address:cell
|
||||
first:&:cell
|
||||
rest:&:cell
|
||||
]
|
||||
|
||||
def new-atom name:text -> result:address:cell [
|
||||
def new-atom name:text -> result:&:cell [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- new cell:type
|
||||
*result <- merge 0/tag:atom, name
|
||||
]
|
||||
|
||||
def new-pair a:address:cell, b:address:cell -> result:address:cell [
|
||||
def new-pair a:&:cell, b:&:cell -> result:&:cell [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- new cell:type
|
||||
*result <- merge 1/tag:pair, a/first, b/rest
|
||||
]
|
||||
|
||||
def is-atom? x:address:cell -> result:boolean [
|
||||
def is-atom? x:&:cell -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless x, 0/false
|
||||
_, result <- maybe-convert *x, atom:variant
|
||||
]
|
||||
|
||||
def is-pair? x:address:cell -> result:boolean [
|
||||
def is-pair? x:&:cell -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless x, 0/false
|
||||
|
@ -64,7 +64,7 @@ def is-pair? x:address:cell -> result:boolean [
|
|||
scenario atom-is-not-pair [
|
||||
local-scope
|
||||
s:text <- new [a]
|
||||
x:address:cell <- new-atom s
|
||||
x:&:cell <- new-atom s
|
||||
10:boolean/raw <- is-atom? x
|
||||
11:boolean/raw <- is-pair? x
|
||||
memory-should-contain [
|
||||
|
@ -77,8 +77,8 @@ scenario pair-is-not-atom [
|
|||
local-scope
|
||||
# construct (a . nil)
|
||||
s:text <- new [a]
|
||||
x:address:cell <- new-atom s
|
||||
y:address:cell <- new-pair x, 0/nil
|
||||
x:&:cell <- new-atom s
|
||||
y:&:cell <- new-pair x, 0/nil
|
||||
10:boolean/raw <- is-atom? y
|
||||
11:boolean/raw <- is-pair? y
|
||||
memory-should-contain [
|
||||
|
@ -87,7 +87,7 @@ scenario pair-is-not-atom [
|
|||
]
|
||||
]
|
||||
|
||||
def atom-match? x:address:cell, pat:text -> result:boolean [
|
||||
def atom-match? x:&:cell, pat:text -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
s:text, is-atom?:boolean <- maybe-convert *x, atom:variant
|
||||
|
@ -97,14 +97,14 @@ def atom-match? x:address:cell, pat:text -> result:boolean [
|
|||
|
||||
scenario atom-match [
|
||||
local-scope
|
||||
x:address:cell <- new-atom [abc]
|
||||
x:&:cell <- new-atom [abc]
|
||||
10:boolean/raw <- atom-match? x, [abc]
|
||||
memory-should-contain [
|
||||
10 <- 1
|
||||
]
|
||||
]
|
||||
|
||||
def first x:address:cell -> result:address:cell [
|
||||
def first x:&:cell -> result:&:cell [
|
||||
local-scope
|
||||
load-ingredients
|
||||
pair:pair, pair?:boolean <- maybe-convert *x, pair:variant
|
||||
|
@ -112,7 +112,7 @@ def first x:address:cell -> result:address:cell [
|
|||
result <- get pair, first:offset
|
||||
]
|
||||
|
||||
def rest x:address:cell -> result:address:cell [
|
||||
def rest x:&:cell -> result:&:cell [
|
||||
local-scope
|
||||
load-ingredients
|
||||
pair:pair, pair?:boolean <- maybe-convert *x, pair:variant
|
||||
|
@ -120,7 +120,7 @@ def rest x:address:cell -> result:address:cell [
|
|||
result <- get pair, rest:offset
|
||||
]
|
||||
|
||||
def set-first base:address:cell, new-first:address:cell -> base:address:cell [
|
||||
def set-first base:&:cell, new-first:&:cell -> base:&:cell [
|
||||
local-scope
|
||||
load-ingredients
|
||||
pair:pair, is-pair?:boolean <- maybe-convert *base, pair:variant
|
||||
|
@ -129,7 +129,7 @@ def set-first base:address:cell, new-first:address:cell -> base:address:cell [
|
|||
*base <- merge 1/pair, pair
|
||||
]
|
||||
|
||||
def set-rest base:address:cell, new-rest:address:cell -> base:address:cell [
|
||||
def set-rest base:&:cell, new-rest:&:cell -> base:&:cell [
|
||||
local-scope
|
||||
load-ingredients
|
||||
pair:pair, is-pair?:boolean <- maybe-convert *base, pair:variant
|
||||
|
@ -141,9 +141,9 @@ def set-rest base:address:cell, new-rest:address:cell -> base:address:cell [
|
|||
scenario cell-operations-on-atom [
|
||||
local-scope
|
||||
s:text <- new [a]
|
||||
x:address:cell <- new-atom s
|
||||
10:address:cell/raw <- first x
|
||||
11:address:cell/raw <- rest x
|
||||
x:&:cell <- new-atom s
|
||||
10:&:cell/raw <- first x
|
||||
11:&:cell/raw <- rest x
|
||||
memory-should-contain [
|
||||
10 <- 0 # first is nil
|
||||
11 <- 0 # rest is nil
|
||||
|
@ -154,11 +154,11 @@ scenario cell-operations-on-pair [
|
|||
local-scope
|
||||
# construct (a . nil)
|
||||
s:text <- new [a]
|
||||
x:address:cell <- new-atom s
|
||||
y:address:cell <- new-pair x, 0/nil
|
||||
x2:address:cell <- first y
|
||||
x:&:cell <- new-atom s
|
||||
y:&:cell <- new-pair x, 0/nil
|
||||
x2:&:cell <- first y
|
||||
10:boolean/raw <- equal x, x2
|
||||
11:address:cell/raw <- rest y
|
||||
11:&:cell/raw <- rest y
|
||||
memory-should-contain [
|
||||
10 <- 1 # first is correct
|
||||
11 <- 0 # rest is nil
|
||||
|
@ -167,15 +167,15 @@ scenario cell-operations-on-pair [
|
|||
|
||||
## convert lambda text to a tree of cells
|
||||
|
||||
def parse in:text -> out:address:cell [
|
||||
def parse in:text -> out:&:cell [
|
||||
local-scope
|
||||
load-ingredients
|
||||
s:address:stream:char <- new-stream in
|
||||
s:&:stream:char <- new-stream in
|
||||
out, s <- parse s
|
||||
trace 2, [app/parse], out
|
||||
]
|
||||
|
||||
def parse in:address:stream:char -> out:address:cell, in:address:stream:char [
|
||||
def parse in:&:stream:char -> out:&:cell, in:&:stream:char [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# skip whitespace
|
||||
|
@ -186,7 +186,7 @@ def parse in:address:stream:char -> out:address:cell, in:address:stream:char [
|
|||
{
|
||||
break-if pair?
|
||||
# atom
|
||||
b:address:buffer <- new-buffer 30
|
||||
b:&:buffer <- new-buffer 30
|
||||
{
|
||||
done?:boolean <- end-of-stream? in
|
||||
break-if done?
|
||||
|
@ -216,11 +216,11 @@ def parse in:address:stream:char -> out:address:cell, in:address:stream:char [
|
|||
c <- peek in
|
||||
close-paren?:boolean <- equal c, 41/close-paren
|
||||
break-if close-paren?
|
||||
first:address:cell, in <- parse in
|
||||
first:&:cell, in <- parse in
|
||||
*out <- merge 1/pair, first, 0/nil
|
||||
}
|
||||
# read in any remaining elements
|
||||
curr:address:cell <- copy out
|
||||
curr:&:cell <- copy out
|
||||
{
|
||||
in <- skip-whitespace in
|
||||
end?:boolean <- end-of-stream? in
|
||||
|
@ -235,11 +235,11 @@ def parse in:address:stream:char -> out:address:cell, in:address:stream:char [
|
|||
break +end-pair:label
|
||||
}
|
||||
# still here? read next element of pair
|
||||
next:address:cell, in <- parse in
|
||||
next:&:cell, in <- parse in
|
||||
is-dot?:boolean <- atom-match? next, [.]
|
||||
{
|
||||
break-if is-dot?
|
||||
next-curr:address:cell <- new-pair next, 0/nil
|
||||
next-curr:&:cell <- new-pair next, 0/nil
|
||||
curr <- set-rest curr, next-curr
|
||||
curr <- rest curr
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ def parse in:address:stream:char -> out:address:cell, in:address:stream:char [
|
|||
c <- peek in
|
||||
not-close-paren?:boolean <- not-equal c, 41/close-paren
|
||||
assert not-close-paren?, [')' cannot immediately follow '.']
|
||||
final:address:cell <- parse in
|
||||
final:&:cell <- parse in
|
||||
curr <- set-rest curr, final
|
||||
# we're not gonna update curr, so better make sure the next iteration
|
||||
# is going to end the pair
|
||||
|
@ -265,7 +265,7 @@ def parse in:address:stream:char -> out:address:cell, in:address:stream:char [
|
|||
}
|
||||
]
|
||||
|
||||
def skip-whitespace in:address:stream:char -> in:address:stream:char [
|
||||
def skip-whitespace in:&:stream:char -> in:&:stream:char [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -279,15 +279,15 @@ def skip-whitespace in:address:stream:char -> in:address:stream:char [
|
|||
}
|
||||
]
|
||||
|
||||
def to-text x:address:cell -> out:text [
|
||||
def to-text x:&:cell -> out:text [
|
||||
local-scope
|
||||
load-ingredients
|
||||
buf:address:buffer <- new-buffer 30
|
||||
buf:&:buffer <- new-buffer 30
|
||||
buf <- to-buffer x, buf
|
||||
out <- buffer-to-array buf
|
||||
]
|
||||
|
||||
def to-buffer x:address:cell, buf:address:buffer -> buf:address:buffer [
|
||||
def to-buffer x:&:cell, buf:&:buffer -> buf:&:buffer [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# base case: empty cell
|
||||
|
@ -305,10 +305,10 @@ def to-buffer x:address:cell, buf:address:buffer -> buf:address:buffer [
|
|||
}
|
||||
# recursive case: pair
|
||||
buf <- append buf, [< ]
|
||||
first:address:cell <- first x
|
||||
first:&:cell <- first x
|
||||
buf <- to-buffer first, buf
|
||||
buf <- append buf, [ | ]
|
||||
rest:address:cell <- rest x
|
||||
rest:&:cell <- rest x
|
||||
buf <- to-buffer rest, buf
|
||||
buf <- append buf, [ >]
|
||||
]
|
||||
|
@ -316,7 +316,7 @@ def to-buffer x:address:cell, buf:address:buffer -> buf:address:buffer [
|
|||
scenario parse-single-letter-atom [
|
||||
local-scope
|
||||
s:text <- new [a]
|
||||
x:address:cell <- parse s
|
||||
x:&:cell <- parse s
|
||||
s2:text, 10:boolean/raw <- maybe-convert *x, atom:variant
|
||||
11:array:char/raw <- copy *s2
|
||||
memory-should-contain [
|
||||
|
@ -328,7 +328,7 @@ scenario parse-single-letter-atom [
|
|||
scenario parse-atom [
|
||||
local-scope
|
||||
s:text <- new [abc]
|
||||
x:address:cell <- parse s
|
||||
x:&:cell <- parse s
|
||||
s2:text, 10:boolean/raw <- maybe-convert *x, atom:variant
|
||||
11:array:char/raw <- copy *s2
|
||||
memory-should-contain [
|
||||
|
@ -340,18 +340,18 @@ scenario parse-atom [
|
|||
scenario parse-list-of-two-atoms [
|
||||
local-scope
|
||||
s:text <- new [(abc def)]
|
||||
x:address:cell <- parse s
|
||||
x:&:cell <- parse s
|
||||
trace-should-contain [
|
||||
app/parse: < abc | < def | <> > >
|
||||
]
|
||||
10:boolean/raw <- is-pair? x
|
||||
x1:address:cell <- first x
|
||||
x2:address:cell <- rest x
|
||||
x1:&:cell <- first x
|
||||
x2:&:cell <- rest x
|
||||
s1:text, 11:boolean/raw <- maybe-convert *x1, atom:variant
|
||||
12:boolean/raw <- is-pair? x2
|
||||
x3:address:cell <- first x2
|
||||
x3:&:cell <- first x2
|
||||
s2:text, 13:boolean/raw <- maybe-convert *x3, atom:variant
|
||||
14:address:cell/raw <- rest x2
|
||||
14:&:cell/raw <- rest x2
|
||||
20:array:char/raw <- copy *s1
|
||||
30:array:char/raw <- copy *s2
|
||||
memory-should-contain [
|
||||
|
@ -368,18 +368,18 @@ scenario parse-list-of-two-atoms [
|
|||
scenario parse-list-with-extra-spaces [
|
||||
local-scope
|
||||
s:text <- new [ ( abc def ) ] # extra spaces
|
||||
x:address:cell <- parse s
|
||||
x:&:cell <- parse s
|
||||
trace-should-contain [
|
||||
app/parse: < abc | < def | <> > >
|
||||
]
|
||||
10:boolean/raw <- is-pair? x
|
||||
x1:address:cell <- first x
|
||||
x2:address:cell <- rest x
|
||||
x1:&:cell <- first x
|
||||
x2:&:cell <- rest x
|
||||
s1:text, 11:boolean/raw <- maybe-convert *x1, atom:variant
|
||||
12:boolean/raw <- is-pair? x2
|
||||
x3:address:cell <- first x2
|
||||
x3:&:cell <- first x2
|
||||
s2:text, 13:boolean/raw <- maybe-convert *x3, atom:variant
|
||||
14:address:cell/raw <- rest x2
|
||||
14:&:cell/raw <- rest x2
|
||||
20:array:char/raw <- copy *s1
|
||||
30:array:char/raw <- copy *s2
|
||||
memory-should-contain [
|
||||
|
@ -396,22 +396,22 @@ scenario parse-list-with-extra-spaces [
|
|||
scenario parse-list-of-more-than-two-atoms [
|
||||
local-scope
|
||||
s:text <- new [(abc def ghi)]
|
||||
x:address:cell <- parse s
|
||||
x:&:cell <- parse s
|
||||
trace-should-contain [
|
||||
app/parse: < abc | < def | < ghi | <> > > >
|
||||
]
|
||||
10:boolean/raw <- is-pair? x
|
||||
x1:address:cell <- first x
|
||||
x2:address:cell <- rest x
|
||||
x1:&:cell <- first x
|
||||
x2:&:cell <- rest x
|
||||
s1:text, 11:boolean/raw <- maybe-convert *x1, atom:variant
|
||||
12:boolean/raw <- is-pair? x2
|
||||
x3:address:cell <- first x2
|
||||
x3:&:cell <- first x2
|
||||
s2:text, 13:boolean/raw <- maybe-convert *x3, atom:variant
|
||||
x4:address:cell <- rest x2
|
||||
x4:&:cell <- rest x2
|
||||
14:boolean/raw <- is-pair? x4
|
||||
x5:address:cell <- first x4
|
||||
x5:&:cell <- first x4
|
||||
s3:text, 15:boolean/raw <- maybe-convert *x5, atom:variant
|
||||
16:address:cell/raw <- rest x4
|
||||
16:&:cell/raw <- rest x4
|
||||
20:array:char/raw <- copy *s1
|
||||
30:array:char/raw <- copy *s2
|
||||
40:array:char/raw <- copy *s3
|
||||
|
@ -432,17 +432,17 @@ scenario parse-list-of-more-than-two-atoms [
|
|||
scenario parse-nested-list [
|
||||
local-scope
|
||||
s:text <- new [((abc))]
|
||||
x:address:cell <- parse s
|
||||
x:&:cell <- parse s
|
||||
trace-should-contain [
|
||||
app/parse: < < abc | <> > | <> >
|
||||
]
|
||||
10:boolean/raw <- is-pair? x
|
||||
x1:address:cell <- first x
|
||||
x1:&:cell <- first x
|
||||
11:boolean/raw <- is-pair? x
|
||||
x2:address:cell <- first x1
|
||||
x2:&:cell <- first x1
|
||||
s1:text, 12:boolean/raw <- maybe-convert *x2, atom:variant
|
||||
13:address:cell/raw <- rest x1
|
||||
14:address:cell/raw <- rest x
|
||||
13:&:cell/raw <- rest x1
|
||||
14:&:cell/raw <- rest x
|
||||
20:array:char/raw <- copy *s1
|
||||
memory-should-contain [
|
||||
10 <- 1 # parse result is a pair
|
||||
|
@ -457,20 +457,20 @@ scenario parse-nested-list [
|
|||
scenario parse-nested-list-2 [
|
||||
local-scope
|
||||
s:text <- new [((abc) def)]
|
||||
x:address:cell <- parse s
|
||||
x:&:cell <- parse s
|
||||
trace-should-contain [
|
||||
app/parse: < < abc | <> > | < def | <> > >
|
||||
]
|
||||
10:boolean/raw <- is-pair? x
|
||||
x1:address:cell <- first x
|
||||
x1:&:cell <- first x
|
||||
11:boolean/raw <- is-pair? x
|
||||
x2:address:cell <- first x1
|
||||
x2:&:cell <- first x1
|
||||
s1:text, 12:boolean/raw <- maybe-convert *x2, atom:variant
|
||||
13:address:cell/raw <- rest x1
|
||||
x3:address:cell <- rest x
|
||||
x4:address:cell <- first x3
|
||||
13:&:cell/raw <- rest x1
|
||||
x3:&:cell <- rest x
|
||||
x4:&:cell <- first x3
|
||||
s2:text, 14:boolean/raw <- maybe-convert *x4, atom:variant
|
||||
15:address:cell/raw <- rest x3
|
||||
15:&:cell/raw <- rest x3
|
||||
20:array:char/raw <- copy *s1
|
||||
30:array:char/raw <- copy *s2
|
||||
memory-should-contain [
|
||||
|
@ -491,7 +491,7 @@ scenario parse-nested-list-2 [
|
|||
#? local-scope
|
||||
#? s:text <- new [(]
|
||||
#? #? hide-errors
|
||||
#? x:address:cell <- parse s
|
||||
#? x:&:cell <- parse s
|
||||
#? #? show-errors
|
||||
#? trace-should-contain [
|
||||
#? error: unbalanced '(' in expression
|
||||
|
@ -502,7 +502,7 @@ scenario parse-nested-list-2 [
|
|||
#? local-scope
|
||||
#? s:text <- new [(abc]
|
||||
#? #? hide-errors
|
||||
#? x:address:cell <- parse s
|
||||
#? x:&:cell <- parse s
|
||||
#? #? show-errors
|
||||
#? trace-should-contain [
|
||||
#? error: unbalanced '(' in expression
|
||||
|
@ -512,13 +512,13 @@ scenario parse-nested-list-2 [
|
|||
scenario parse-dotted-list-of-two-atoms [
|
||||
local-scope
|
||||
s:text <- new [(abc . def)]
|
||||
x:address:cell <- parse s
|
||||
x:&:cell <- parse s
|
||||
trace-should-contain [
|
||||
app/parse: < abc | def >
|
||||
]
|
||||
10:boolean/raw <- is-pair? x
|
||||
x1:address:cell <- first x
|
||||
x2:address:cell <- rest x
|
||||
x1:&:cell <- first x
|
||||
x2:&:cell <- rest x
|
||||
s1:text, 11:boolean/raw <- maybe-convert *x1, atom:variant
|
||||
s2:text, 12:boolean/raw <- maybe-convert *x2, atom:variant
|
||||
20:array:char/raw <- copy *s1
|
||||
|
@ -536,18 +536,18 @@ scenario parse-dotted-list-of-two-atoms [
|
|||
scenario parse-dotted-list-of-more-than-two-atoms [
|
||||
local-scope
|
||||
s:text <- new [(abc def . ghi)]
|
||||
x:address:cell <- parse s
|
||||
x:&:cell <- parse s
|
||||
trace-should-contain [
|
||||
app/parse: < abc | < def | ghi > >
|
||||
]
|
||||
10:boolean/raw <- is-pair? x
|
||||
x1:address:cell <- first x
|
||||
x2:address:cell <- rest x
|
||||
x1:&:cell <- first x
|
||||
x2:&:cell <- rest x
|
||||
s1:text, 11:boolean/raw <- maybe-convert *x1, atom:variant
|
||||
12:boolean/raw <- is-pair? x2
|
||||
x3:address:cell <- first x2
|
||||
x3:&:cell <- first x2
|
||||
s2:text, 13:boolean/raw <- maybe-convert *x3, atom:variant
|
||||
x4:address:cell <- rest x2
|
||||
x4:&:cell <- rest x2
|
||||
s3:text, 14:boolean/raw <- maybe-convert *x4, atom:variant
|
||||
20:array:char/raw <- copy *s1
|
||||
30:array:char/raw <- copy *s2
|
||||
|
@ -566,15 +566,15 @@ scenario parse-dotted-list-of-more-than-two-atoms [
|
|||
|
||||
## convert tree of cells to mu text
|
||||
|
||||
def to-mu in:address:cell -> out:text [
|
||||
def to-mu in:&:cell -> out:text [
|
||||
local-scope
|
||||
load-ingredients
|
||||
buf:address:buffer <- new-buffer 30
|
||||
buf:&:buffer <- new-buffer 30
|
||||
buf <- to-mu in, buf
|
||||
out <- buffer-to-array buf
|
||||
]
|
||||
|
||||
def to-mu in:address:cell, buf:address:buffer -> buf:address:buffer, result-name:text [
|
||||
def to-mu in:&:cell, buf:&:buffer -> buf:&:buffer, result-name:text [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# null cell? no change.
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
def main [
|
||||
local-scope
|
||||
x:address:num <- new number:type
|
||||
x:&:num <- new number:type
|
||||
foo x
|
||||
]
|
||||
|
||||
def foo x:address:num -> x:address:num [
|
||||
def foo x:&:num -> x:&:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
*x <- copy 34
|
||||
|
|
17
nqueens.mu
17
nqueens.mu
|
@ -1,12 +1,14 @@
|
|||
# http://rosettacode.org/wiki/N-queens_problem
|
||||
# port of the Arc solution at http://arclanguage.org/item?id=19743
|
||||
# run with tracing turned on:
|
||||
# ./mu --trace nqueens.mu
|
||||
|
||||
container square [
|
||||
rank:num
|
||||
file:num
|
||||
]
|
||||
|
||||
def nqueens n:num, queens:address:list:square -> result:num [
|
||||
def nqueens n:num, queens:&:list:square -> result:num [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if 'queens' is already long enough, print it and return
|
||||
|
@ -34,7 +36,7 @@ def nqueens n:num, queens:address:list:square -> result:num [
|
|||
{
|
||||
curr-conflicts?:boolean <- conflict? curr, queens
|
||||
break-if curr-conflicts?
|
||||
new-queens:address:list:square <- push curr, queens
|
||||
new-queens:&:list:square <- push curr, queens
|
||||
sub-result:num <- nqueens n, new-queens
|
||||
result <- add result, sub-result
|
||||
}
|
||||
|
@ -43,7 +45,7 @@ def nqueens n:num, queens:address:list:square -> result:num [
|
|||
}
|
||||
]
|
||||
|
||||
def conflict? curr:square, queens:address:list:square -> result:boolean [
|
||||
def conflict? curr:square, queens:&:list:square -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result1:boolean <- conflicting-file? curr, queens
|
||||
|
@ -52,7 +54,7 @@ def conflict? curr:square, queens:address:list:square -> result:boolean [
|
|||
reply result2
|
||||
]
|
||||
|
||||
def conflicting-file? curr:square, queens:address:list:square -> result:boolean [
|
||||
def conflicting-file? curr:square, queens:&:list:square -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
curr-file:num <- get curr, file:offset
|
||||
|
@ -68,7 +70,7 @@ def conflicting-file? curr:square, queens:address:list:square -> result:boolean
|
|||
reply 0/no-conflict-found
|
||||
]
|
||||
|
||||
def conflicting-diagonal? curr:square, queens:address:list:square -> result:boolean [
|
||||
def conflicting-diagonal? curr:square, queens:&:list:square -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
curr-rank:num <- get curr, rank:offset
|
||||
|
@ -89,3 +91,8 @@ def conflicting-diagonal? curr:square, queens:address:list:square -> result:bool
|
|||
}
|
||||
reply 0/no-conflict-found
|
||||
]
|
||||
|
||||
def main [
|
||||
nqueens 4
|
||||
$dump-trace [app]
|
||||
]
|
||||
|
|
|
@ -4,7 +4,7 @@ def main [
|
|||
$print [Mu socket creation returned ], socket, 10/newline
|
||||
session:num <- $accept socket
|
||||
{
|
||||
client-message:address:buffer <- new-buffer 1024
|
||||
client-message:&:buffer <- new-buffer 1024
|
||||
c:char <- $read-from-socket session
|
||||
break-unless c
|
||||
$print c
|
||||
|
|
Loading…
Reference in New Issue