This commit is contained in:
Kartik K. Agaram 2016-09-17 12:55:10 -07:00
parent 80df524b56
commit 760f683f27
45 changed files with 720 additions and 713 deletions

View File

@ -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

View File

@ -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

View File

@ -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
]

View File

@ -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

View File

@ -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
]

View File

@ -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

View File

@ -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'

View File

@ -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

View File

@ -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);

View File

@ -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 [

View File

@ -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

View File

@ -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
]

View File

@ -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

View File

@ -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")}

View File

@ -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, [ -> ]

View File

@ -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, [: ]

View File

@ -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
]

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -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
]

View File

@ -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

View File

@ -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?

View File

@ -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]

View File

@ -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

View File

@ -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);
}
}

View File

@ -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 [
. .

View File

@ -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
{

View File

@ -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'

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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?

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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?

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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]
]

View File

@ -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