2576 - distinguish allocated addresses from others
This is the one major refinement on the C programming model I'm planning to introduce in mu. Instead of Rust's menagerie of pointer types and static checking, I want to introduce just one new type, and use it to perform ref-counting at runtime. So far all we're doing is updating new's interface. The actual ref-counting implementation is next. One implication: I might sometimes need duplicate implementations for a recipe with allocated vs vanilla addresses of the same type. So far it seems I can get away with just always passing in allocated addresses; the situations when you want to pass an unallocated address to a recipe should be few and far between.
This commit is contained in:
parent
7163e18a77
commit
455fbac64f
|
@ -50,14 +50,17 @@ void canonize(reagent& x) {
|
|||
void lookup_memory(reagent& x) {
|
||||
if (!x.type || x.type->value != get(Type_ordinal, "address")) {
|
||||
raise_error << maybe(current_recipe_name()) << "tried to /lookup " << x.original_string << " but it isn't an address\n" << end();
|
||||
return;
|
||||
}
|
||||
// compute value
|
||||
if (x.value == 0) {
|
||||
raise_error << maybe(current_recipe_name()) << "tried to /lookup 0\n" << end();
|
||||
return;
|
||||
}
|
||||
trace(9999, "mem") << "location " << x.value << " is " << no_scientific(get_or_insert(Memory, x.value)) << end();
|
||||
x.set_value(get_or_insert(Memory, x.value));
|
||||
drop_from_type(x, "address");
|
||||
// End Drop Address In lookup_memory(x)
|
||||
drop_one_lookup(x);
|
||||
}
|
||||
|
||||
|
@ -89,6 +92,7 @@ bool canonize_type(reagent& r) {
|
|||
return false;
|
||||
}
|
||||
drop_from_type(r, "address");
|
||||
// End Drop Address In canonize_type(r)
|
||||
drop_one_lookup(r);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -430,8 +430,10 @@ bool is_mu_string(const reagent& x) {
|
|||
return x.type
|
||||
&& x.type->value == get(Type_ordinal, "address")
|
||||
&& x.type->right
|
||||
&& x.type->right->value == get(Type_ordinal, "array")
|
||||
&& x.type->right->value == get(Type_ordinal, "shared")
|
||||
&& x.type->right->right
|
||||
&& x.type->right->right->value == get(Type_ordinal, "character")
|
||||
&& x.type->right->right->right == NULL;
|
||||
&& x.type->right->right->value == get(Type_ordinal, "array")
|
||||
&& x.type->right->right->right
|
||||
&& x.type->right->right->right->value == get(Type_ordinal, "character")
|
||||
&& x.type->right->right->right->right == NULL;
|
||||
}
|
||||
|
|
131
038new.cc
131
038new.cc
|
@ -1,12 +1,55 @@
|
|||
//: A simple memory allocator to create space for new variables at runtime.
|
||||
//: Creating space for new variables at runtime.
|
||||
|
||||
//: Mu has two primitives for managing allocations:
|
||||
//: - 'allocate' reserves a specified amount of space
|
||||
//: - 'abandon' returns allocated space to be reused by future calls to 'allocate'
|
||||
//:
|
||||
//: In practice it's useful to let programs copy addresses anywhere they want,
|
||||
//: but a prime source of (particularly security) bugs is accessing memory
|
||||
//: after it's been abandoned. To avoid this, mu programs use a safer
|
||||
//: primitive called 'new', which performs two operations:
|
||||
//:
|
||||
//: - it takes a type rather than a size, to save you the trouble of
|
||||
//: calculating sizes of different variables.
|
||||
//: - it allocates an extra location where it tracks so-called 'reference
|
||||
//: counts' or refcounts: the number of address variables in your program that
|
||||
//: point to this allocation. The initial refcount of an allocation starts out
|
||||
//: at 1 (the product of the 'new' instruction). When other variables are
|
||||
//: copied from it the refcount is incremented. When a variable stops pointing
|
||||
//: at it the refcount is decremented. When the refcount goes to 0 the
|
||||
//: allocation is automatically abandoned.
|
||||
//:
|
||||
//: Mu programs guarantee you'll have no memory corruption bugs as long as you
|
||||
//: use 'new' and never use 'allocate' or 'abandon'. However, they don't help
|
||||
//: you at all to remember to abandon memory after you're done with it. To
|
||||
//: minimize memory use, be sure to reset allocated addresses to 0 when you're
|
||||
//: done with them.
|
||||
|
||||
//: To help you distinguish addresses that point at allocations, 'new' returns
|
||||
//: type address:shared:___. Think of 'shared' as a generic container that
|
||||
//: contains one extra field: the refcount. However, lookup operations will
|
||||
//: transparently drop the 'shared' and access to the refcount. Copying
|
||||
//: between shared and non-shared addresses is forbidden.
|
||||
:(before "End Mu Types Initialization")
|
||||
type_ordinal shared = put(Type_ordinal, "shared", Next_type_ordinal++);
|
||||
get_or_insert(Type, shared).name = "shared";
|
||||
:(before "End Drop Address In lookup_memory(x)")
|
||||
if (x.properties.at(0).second->value == "shared") {
|
||||
//x.set_value(x.value+1); // doesn't work yet
|
||||
drop_from_type(x, "shared");
|
||||
}
|
||||
:(before "End Drop Address In canonize_type(r)")
|
||||
if (r.properties.at(0).second->value == "shared") {
|
||||
drop_from_type(r, "shared");
|
||||
}
|
||||
|
||||
:(scenarios run)
|
||||
:(scenario new)
|
||||
# call new two times with identical arguments; you should get back different results
|
||||
recipe main [
|
||||
1:address:number/raw <- new number:type
|
||||
2:address:number/raw <- new number:type
|
||||
3:boolean/raw <- equal 1:address:number/raw, 2:address:number/raw
|
||||
1:address:shared:number/raw <- new number:type
|
||||
2:address:shared:number/raw <- new number:type
|
||||
3:boolean/raw <- equal 1:address:shared:number/raw, 2:address:shared:number/raw
|
||||
]
|
||||
+mem: storing 0 in location 3
|
||||
|
||||
|
@ -53,6 +96,7 @@ case NEW: {
|
|||
reagent product(inst.products.at(0));
|
||||
canonize_type(product);
|
||||
drop_from_type(product, "address");
|
||||
drop_from_type(product, "shared");
|
||||
if (SIZE(inst.ingredients) > 1) {
|
||||
// array allocation
|
||||
drop_from_type(product, "array");
|
||||
|
@ -174,29 +218,29 @@ void ensure_space(long long int size) {
|
|||
% Memory_allocated_until = 10;
|
||||
% put(Memory, Memory_allocated_until, 1);
|
||||
recipe main [
|
||||
1:address:number <- new number:type
|
||||
2:number <- copy *1:address:number
|
||||
1:address:shared:number <- new number:type
|
||||
2:number <- copy *1:address:shared:number
|
||||
]
|
||||
+mem: storing 0 in location 2
|
||||
|
||||
:(scenario new_array)
|
||||
recipe main [
|
||||
1:address:array:number/raw <- new number:type, 5
|
||||
2:address:number/raw <- new number:type
|
||||
3:number/raw <- subtract 2:address:number/raw, 1:address:array:number/raw
|
||||
1:address:shared:array:number/raw <- new number:type, 5
|
||||
2:address:shared:number/raw <- new number:type
|
||||
3:number/raw <- subtract 2:address:shared:number/raw, 1:address:shared:array:number/raw
|
||||
]
|
||||
+run: 1:address:array:number/raw <- new number:type, 5
|
||||
+run: 1:address:shared:array:number/raw <- new number:type, 5
|
||||
+mem: array size is 5
|
||||
# don't forget the extra location for array size
|
||||
+mem: storing 6 in location 3
|
||||
|
||||
:(scenario new_empty_array)
|
||||
recipe main [
|
||||
1:address:array:number/raw <- new number:type, 0
|
||||
2:address:number/raw <- new number:type
|
||||
3:number/raw <- subtract 2:address:number/raw, 1:address:array:number/raw
|
||||
1:address:shared:array:number/raw <- new number:type, 0
|
||||
2:address:shared:number/raw <- new number:type
|
||||
3:number/raw <- subtract 2:address:shared:number/raw, 1:address:shared:array:number/raw
|
||||
]
|
||||
+run: 1:address:array:number/raw <- new number:type, 0
|
||||
+run: 1:address:shared:array:number/raw <- new number:type, 0
|
||||
+mem: array size is 0
|
||||
+mem: storing 1 in location 3
|
||||
|
||||
|
@ -204,8 +248,8 @@ recipe main [
|
|||
:(scenario new_overflow)
|
||||
% Initial_memory_per_routine = 2;
|
||||
recipe main [
|
||||
1:address:number/raw <- new number:type
|
||||
2:address:point/raw <- new point:type # not enough room in initial page
|
||||
1:address:shared:number/raw <- new number:type
|
||||
2:address:shared:point/raw <- new point:type # not enough room in initial page
|
||||
]
|
||||
+new: routine allocated memory from 1000 to 1002
|
||||
+new: routine allocated memory from 1002 to 1004
|
||||
|
@ -215,10 +259,10 @@ recipe main [
|
|||
|
||||
:(scenario new_reclaim)
|
||||
recipe main [
|
||||
1:address:number <- new number:type
|
||||
abandon 1:address:number
|
||||
2:address:number <- new number:type # must be same size as abandoned memory to reuse
|
||||
3:boolean <- equal 1:address:number, 2:address:number
|
||||
1:address:shared:number <- new number:type
|
||||
abandon 1:address:shared:number
|
||||
2:address:shared:number <- new number:type # must be same size as abandoned memory to reuse
|
||||
3:boolean <- equal 1:address:shared:number, 2:address:shared:number
|
||||
]
|
||||
# both allocations should have returned the same address
|
||||
+mem: storing 1 in location 3
|
||||
|
@ -240,8 +284,8 @@ case ABANDON: {
|
|||
}
|
||||
reagent types = inst.ingredients.at(0);
|
||||
canonize_type(types);
|
||||
if (!types.type || types.type->value != get(Type_ordinal, "address")) {
|
||||
raise_error << maybe(get(Recipe, r).name) << "first ingredient of 'abandon' should be an address, but got " << inst.ingredients.at(0).original_string << '\n' << end();
|
||||
if (!types.type || types.type->value != get(Type_ordinal, "address") || types.type->right->value != get(Type_ordinal, "shared")) {
|
||||
raise_error << maybe(get(Recipe, r).name) << "first ingredient of 'abandon' should be an address:shared:___, but got " << inst.ingredients.at(0).original_string << '\n' << end();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -254,6 +298,7 @@ case ABANDON: {
|
|||
// lookup_memory without drop_one_lookup {
|
||||
types.set_value(get_or_insert(Memory, types.value));
|
||||
drop_from_type(types, "address");
|
||||
drop_from_type(types, "shared");
|
||||
// }
|
||||
abandon(address, size_of(types));
|
||||
break;
|
||||
|
@ -293,20 +338,20 @@ if (Free_list[size]) {
|
|||
|
||||
:(scenario new_differing_size_no_reclaim)
|
||||
recipe main [
|
||||
1:address:number <- new number:type
|
||||
abandon 1:address:number
|
||||
2:address:array:number <- new number:type, 2 # different size
|
||||
3:boolean <- equal 1:address:number, 2:address:array:number
|
||||
1:address:shared:number <- new number:type
|
||||
abandon 1:address:shared:number
|
||||
2:address:shared:array:number <- new number:type, 2 # different size
|
||||
3:boolean <- equal 1:address:shared:number, 2:address:shared:array:number
|
||||
]
|
||||
# no reuse
|
||||
+mem: storing 0 in location 3
|
||||
|
||||
:(scenario new_reclaim_array)
|
||||
recipe main [
|
||||
1:address:array:number <- new number:type, 2
|
||||
abandon 1:address:array:number
|
||||
2:address:array:number <- new number:type, 2
|
||||
3:boolean <- equal 1:address:array:number, 2:address:array:number
|
||||
1:address:shared:array:number <- new number:type, 2
|
||||
abandon 1:address:shared:array:number
|
||||
2:address:shared:array:number <- new number:type, 2
|
||||
3:boolean <- equal 1:address:shared:array:number, 2:address:shared:array:number
|
||||
]
|
||||
# reuse
|
||||
+mem: storing 1 in location 3
|
||||
|
@ -315,17 +360,17 @@ recipe main [
|
|||
|
||||
:(scenario new_string)
|
||||
recipe main [
|
||||
1:address:array:character <- new [abc def]
|
||||
2:character <- index *1:address:array:character, 5
|
||||
1:address:shared:array:character <- new [abc def]
|
||||
2:character <- index *1:address:shared:array:character, 5
|
||||
]
|
||||
# number code for 'e'
|
||||
+mem: storing 101 in location 2
|
||||
|
||||
:(scenario new_string_handles_unicode)
|
||||
recipe main [
|
||||
1:address:array:character <- new [a«c]
|
||||
2:number <- length *1:address:array:character
|
||||
3:character <- index *1:address:array:character, 1
|
||||
1:address:shared:array:character <- new [a«c]
|
||||
2:number <- length *1:address:shared:array:character
|
||||
3:character <- index *1:address:shared:array:character, 1
|
||||
]
|
||||
+mem: storing 3 in location 2
|
||||
# unicode for '«'
|
||||
|
@ -370,8 +415,8 @@ long long int new_mu_string(const string& contents) {
|
|||
|
||||
:(scenario stash_string)
|
||||
recipe main [
|
||||
1:address:array:character <- new [abc]
|
||||
stash [foo:], 1:address:array:character
|
||||
1:address:shared:array:character <- new [abc]
|
||||
stash [foo:], 1:address:shared:array:character
|
||||
]
|
||||
+app: foo: abc
|
||||
|
||||
|
@ -383,15 +428,15 @@ if (is_mu_string(r)) {
|
|||
|
||||
:(scenario unicode_string)
|
||||
recipe main [
|
||||
1:address:array:character <- new [♠]
|
||||
stash [foo:], 1:address:array:character
|
||||
1:address:shared:array:character <- new [♠]
|
||||
stash [foo:], 1:address:shared:array:character
|
||||
]
|
||||
+app: foo: ♠
|
||||
|
||||
:(scenario stash_space_after_string)
|
||||
recipe main [
|
||||
1:address:array:character <- new [abc]
|
||||
stash 1:address:array:character [foo]
|
||||
1:address:shared:array:character <- new [abc]
|
||||
stash 1:address:shared:array:character, [foo]
|
||||
]
|
||||
+app: abc foo
|
||||
|
||||
|
@ -399,8 +444,8 @@ recipe main [
|
|||
:(scenario new_string_overflow)
|
||||
% Initial_memory_per_routine = 2;
|
||||
recipe main [
|
||||
1:address:number/raw <- new number:type
|
||||
2:address:array:character/raw <- new [a] # not enough room in initial page, if you take the array size into account
|
||||
1:address:shared:number/raw <- new number:type
|
||||
2:address:shared:array:character/raw <- new [a] # not enough room in initial page, if you take the array size into account
|
||||
]
|
||||
+new: routine allocated memory from 1000 to 1002
|
||||
+new: routine allocated memory from 1002 to 1004
|
||||
|
|
|
@ -92,8 +92,10 @@ long long int lookup_name(const reagent& r, const recipe_ordinal default_recipe)
|
|||
}
|
||||
|
||||
type_ordinal skip_addresses(type_tree* type, const string& recipe_name) {
|
||||
type_ordinal address = get(Type_ordinal, "address");
|
||||
type_ordinal shared = get(Type_ordinal, "shared");
|
||||
for (; type; type = type->right) {
|
||||
if (type->value != get(Type_ordinal, "address"))
|
||||
if (type->value != address && type->value != shared)
|
||||
return type->value;
|
||||
}
|
||||
raise_error << maybe(recipe_name) << "expected a container" << '\n' << end();
|
||||
|
|
28
043space.cc
28
043space.cc
|
@ -7,7 +7,7 @@
|
|||
# then location 0 is really location 11, location 1 is really location 12, and so on.
|
||||
recipe main [
|
||||
10:number <- copy 5 # pretend array; in practice we'll use new
|
||||
default-space:address:array:location <- copy 10/unsafe
|
||||
default-space:address:shared:array:location <- copy 10/unsafe
|
||||
1:number <- copy 23
|
||||
]
|
||||
+mem: storing 23 in location 12
|
||||
|
@ -19,7 +19,7 @@ recipe main [
|
|||
# pretend array
|
||||
1000:number <- copy 5
|
||||
# actual start of this recipe
|
||||
default-space:address:array:location <- copy 1000/unsafe
|
||||
default-space:address:shared:array:location <- copy 1000/unsafe
|
||||
1:address:number <- copy 3/unsafe
|
||||
8:number/raw <- copy *1:address:number
|
||||
]
|
||||
|
@ -70,7 +70,7 @@ recipe main [
|
|||
# pretend array
|
||||
1000:number <- copy 5
|
||||
# actual start of this recipe
|
||||
default-space:address:array:location <- copy 1000/unsafe
|
||||
default-space:address:shared:array:location <- copy 1000/unsafe
|
||||
1:address:point <- copy 12/unsafe
|
||||
9:number/raw <- get *1:address:point, 1:offset
|
||||
]
|
||||
|
@ -90,7 +90,7 @@ recipe main [
|
|||
# pretend array
|
||||
1000:number <- copy 5
|
||||
# actual start of this recipe
|
||||
default-space:address:array:location <- copy 1000/unsafe
|
||||
default-space:address:shared:array:location <- copy 1000/unsafe
|
||||
1:address:array:number <- copy 12/unsafe
|
||||
9:number/raw <- index *1:address:array:number, 1
|
||||
]
|
||||
|
@ -119,7 +119,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:address:shared: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);
|
||||
|
@ -150,7 +150,7 @@ recipe main [
|
|||
recipe foo [
|
||||
local-scope
|
||||
x:number <- copy 34
|
||||
reply default-space:address:array:location
|
||||
reply default-space:address:shared:array:location
|
||||
]
|
||||
# both calls to foo should have received the same default-space
|
||||
+mem: storing 1 in location 3
|
||||
|
@ -186,7 +186,7 @@ void rewrite_default_space_instruction(instruction& curr) {
|
|||
curr.ingredients.push_back(reagent("number-of-locals:literal"));
|
||||
if (!curr.products.empty())
|
||||
raise_error << "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:address:shared:array:location"));
|
||||
}
|
||||
|
||||
//:: helpers
|
||||
|
@ -212,11 +212,13 @@ long long int address(long long int offset, long long int base) {
|
|||
|| !x.type
|
||||
|| x.type->value != get(Type_ordinal, "address")
|
||||
|| !x.type->right
|
||||
|| x.type->right->value != get(Type_ordinal, "array")
|
||||
|| x.type->right->value != get(Type_ordinal, "shared")
|
||||
|| !x.type->right->right
|
||||
|| x.type->right->right->value != get(Type_ordinal, "location")
|
||||
|| x.type->right->right->right) {
|
||||
raise_error << maybe(current_recipe_name()) << "'default-space' should be of type address:array:location, but tried to write " << to_string(data) << '\n' << end();
|
||||
|| x.type->right->right->value != get(Type_ordinal, "array")
|
||||
|| !x.type->right->right->right
|
||||
|| x.type->right->right->right->value != get(Type_ordinal, "location")
|
||||
|| x.type->right->right->right->right) {
|
||||
raise_error << maybe(current_recipe_name()) << "'default-space' should be of type address:shared:array:location, but tried to write " << to_string(data) << '\n' << end();
|
||||
}
|
||||
current_call().default_space = data.at(0);
|
||||
return;
|
||||
|
@ -224,8 +226,8 @@ long long int address(long long int offset, long long int base) {
|
|||
|
||||
:(scenario get_default_space)
|
||||
recipe main [
|
||||
default-space:address:array:location <- copy 10/unsafe
|
||||
1:address:array:location/raw <- copy default-space:address:array:location
|
||||
default-space:address:shared:array:location <- copy 10/unsafe
|
||||
1:address:shared:array:location/raw <- copy default-space:address:shared:array:location
|
||||
]
|
||||
+mem: storing 10 in location 1
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
recipe main [
|
||||
10:number <- copy 5 # pretend array
|
||||
20:number <- copy 5 # pretend array
|
||||
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:address:shared:array:location <- copy 10/unsafe
|
||||
0:address:shared:array:location/names:dummy <- copy 20/unsafe # later layers will explain the /names: property
|
||||
1:number <- copy 32
|
||||
1:number/space:1 <- copy 33
|
||||
]
|
||||
|
|
|
@ -5,22 +5,22 @@
|
|||
|
||||
:(scenario closure)
|
||||
recipe main [
|
||||
default-space:address:array:location <- new location:type, 30
|
||||
1:address:array:location/names:new-counter <- new-counter
|
||||
2:number/raw <- increment-counter 1:address:array:location/names:new-counter
|
||||
3:number/raw <- increment-counter 1:address:array:location/names:new-counter
|
||||
default-space:address:shared:array:location <- new location:type, 30
|
||||
1:address:shared:array:location/names:new-counter <- new-counter
|
||||
2:number/raw <- increment-counter 1:address:shared:array:location/names:new-counter
|
||||
3:number/raw <- increment-counter 1:address:shared:array:location/names:new-counter
|
||||
]
|
||||
|
||||
recipe new-counter [
|
||||
default-space:address:array:location <- new location:type, 30
|
||||
default-space:address:shared:array:location <- new location:type, 30
|
||||
x:number <- copy 23
|
||||
y:number <- copy 3 # variable that will be incremented
|
||||
reply default-space:address:array:location
|
||||
reply default-space:address:shared:array:location
|
||||
]
|
||||
|
||||
recipe 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:address:shared:array:location <- new location:type, 30
|
||||
0:address:shared:array:location/names:new-counter <- next-ingredient # outer space must be created by 'new-counter' above
|
||||
y:number/space:1 <- add y:number/space:1, 1 # increment
|
||||
y:number <- copy 234 # dummy
|
||||
reply y:number/space:1
|
||||
|
@ -52,11 +52,13 @@ void collect_surrounding_spaces(const recipe_ordinal r) {
|
|||
if (!type
|
||||
|| type->value != get(Type_ordinal, "address")
|
||||
|| !type->right
|
||||
|| type->right->value != get(Type_ordinal, "array")
|
||||
|| type->right->value != get(Type_ordinal, "shared")
|
||||
|| !type->right->right
|
||||
|| type->right->right->value != get(Type_ordinal, "location")
|
||||
|| type->right->right->right) {
|
||||
raise_error << "slot 0 should always have type address:array:location, but is " << inst.products.at(j).to_string() << '\n' << end();
|
||||
|| type->right->right->value != get(Type_ordinal, "array")
|
||||
|| !type->right->right->right
|
||||
|| type->right->right->right->value != get(Type_ordinal, "location")
|
||||
|| type->right->right->right->right) {
|
||||
raise_error << "slot 0 should always have type address:shared:array:location, but is " << inst.products.at(j).to_string() << '\n' << end();
|
||||
continue;
|
||||
}
|
||||
string_tree* s = property(inst.products.at(j), "names");
|
||||
|
|
16
046global.cc
16
046global.cc
|
@ -9,8 +9,8 @@ recipe main [
|
|||
10:number <- copy 5
|
||||
20:number <- copy 5
|
||||
# actual start of this recipe
|
||||
global-space:address:array:location <- copy 20/unsafe
|
||||
default-space:address:array:location <- copy 10/unsafe
|
||||
global-space:address:shared:array:location <- copy 20/unsafe
|
||||
default-space:address:shared:array:location <- copy 10/unsafe
|
||||
1:number <- copy 23
|
||||
1:number/space:global <- copy 24
|
||||
]
|
||||
|
@ -35,11 +35,13 @@ global_space = 0;
|
|||
|| !x.type
|
||||
|| x.type->value != get(Type_ordinal, "address")
|
||||
|| !x.type->right
|
||||
|| x.type->right->value != get(Type_ordinal, "array")
|
||||
|| x.type->right->value != get(Type_ordinal, "shared")
|
||||
|| !x.type->right->right
|
||||
|| x.type->right->right->value != get(Type_ordinal, "location")
|
||||
|| x.type->right->right->right) {
|
||||
raise_error << maybe(current_recipe_name()) << "'global-space' should be of type address:array:location, but tried to write " << to_string(data) << '\n' << end();
|
||||
|| x.type->right->right->value != get(Type_ordinal, "array")
|
||||
|| !x.type->right->right->right
|
||||
|| x.type->right->right->right->value != get(Type_ordinal, "location")
|
||||
|| x.type->right->right->right->right) {
|
||||
raise_error << maybe(current_recipe_name()) << "'global-space' should be of type address:shared:array:location, but tried to write " << to_string(data) << '\n' << end();
|
||||
}
|
||||
if (Current_routine->global_space)
|
||||
raise_error << "routine already has a global-space; you can't over-write your globals" << end();
|
||||
|
@ -61,7 +63,7 @@ global_space = 0;
|
|||
:(scenario global_space_with_names)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
global-space:address:array:location <- new location:type, 10
|
||||
global-space:address:shared:array:location <- new location:type, 10
|
||||
x:number <- copy 23
|
||||
1:number/space:global <- copy 24
|
||||
]
|
||||
|
|
|
@ -89,7 +89,7 @@ recipe main [
|
|||
:(scenario typo_in_address_type_fails)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
y:address:charcter <- new character:type
|
||||
y:address:shared: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:address:shared:charcter <- new character:type'
|
||||
|
|
|
@ -99,9 +99,9 @@ scenario foo [
|
|||
|
||||
:(scenario read_scenario_with_bracket_in_comment_in_nested_string)
|
||||
scenario foo [
|
||||
1:address:array:character <- new [# not a comment]
|
||||
1:address:shared:array:character <- new [# not a comment]
|
||||
]
|
||||
+run: 1:address:array:character <- new [# not a comment]
|
||||
+run: 1:address:shared:array:character <- new [# not a comment]
|
||||
|
||||
//:: Run scenarios when we run 'mu test'.
|
||||
//: Treat the text of the scenario as a regular series of instructions.
|
||||
|
|
|
@ -38,7 +38,7 @@ void rewrite_stashes_to_text_named(recipe& caller) {
|
|||
def.name = "to-text-line";
|
||||
def.ingredients.push_back(inst.ingredients.at(j));
|
||||
ostringstream ingredient_name;
|
||||
ingredient_name << "stash_" << stash_instruction_idx << '_' << j << ":address:array:character";
|
||||
ingredient_name << "stash_" << stash_instruction_idx << '_' << j << ":address:shared:array:character";
|
||||
def.products.push_back(reagent(ingredient_name.str()));
|
||||
new_instructions.push_back(def);
|
||||
inst.ingredients.at(j).clear(); // reclaim old memory
|
||||
|
|
|
@ -71,7 +71,7 @@ container bar [
|
|||
|
||||
:(scenario dilated_reagent_with_new)
|
||||
recipe main [
|
||||
x:address:address:number <- new {(address number): type}
|
||||
x:address:shared:address:number <- new {(address number): type}
|
||||
]
|
||||
+new: size of <"address" : <"number" : <>>> is 1
|
||||
|
||||
|
|
|
@ -297,13 +297,13 @@ $error: 0
|
|||
:(scenario static_dispatch_works_with_compound_type_containing_container_defined_after_first_use)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
x:address:foo <- new foo:type
|
||||
x:address:shared:foo <- new foo:type
|
||||
test x
|
||||
]
|
||||
container foo [
|
||||
x:number
|
||||
]
|
||||
recipe test a:address:foo -> z:number [
|
||||
recipe test a:address:shared:foo -> z:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z:number <- get *a, x:offset
|
||||
|
@ -313,10 +313,10 @@ $error: 0
|
|||
:(scenario static_dispatch_works_with_compound_type_containing_container_defined_after_second_use)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
x:address:foo <- new foo:type
|
||||
x:address:shared:foo <- new foo:type
|
||||
test x
|
||||
]
|
||||
recipe test a:address:foo -> z:number [
|
||||
recipe test a:address:shared:foo -> z:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z:number <- get *a, x:offset
|
||||
|
|
|
@ -535,14 +535,14 @@ container foo:_t [
|
|||
|
||||
:(scenario shape_shifting_recipe_handles_shape_shifting_new_ingredient)
|
||||
recipe main [
|
||||
1:address:foo:point <- bar 3
|
||||
11:foo:point <- copy *1:address:foo:point
|
||||
1:address:shared:foo:point <- bar 3
|
||||
11:foo:point <- copy *1:address:shared:foo:point
|
||||
]
|
||||
container foo:_t [
|
||||
x:_t
|
||||
y:number
|
||||
]
|
||||
recipe bar x:number -> result:address:foo:_t [
|
||||
recipe bar x:number -> result:address:shared:foo:_t [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# new refers to _t in its ingredient *value*
|
||||
|
@ -554,10 +554,10 @@ recipe bar x:number -> result:address:foo:_t [
|
|||
|
||||
:(scenario shape_shifting_recipe_handles_shape_shifting_new_ingredient_2)
|
||||
recipe main [
|
||||
1:address:foo:point <- bar 3
|
||||
11:foo:point <- copy *1:address:foo:point
|
||||
1:address:shared:foo:point <- bar 3
|
||||
11:foo:point <- copy *1:address:shared:foo:point
|
||||
]
|
||||
recipe bar x:number -> result:address:foo:_t [
|
||||
recipe bar x:number -> result:address:shared:foo:_t [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# new refers to _t in its ingredient *value*
|
||||
|
@ -574,11 +574,11 @@ container foo:_t [
|
|||
|
||||
:(scenario shape_shifting_recipe_supports_compound_types)
|
||||
recipe main [
|
||||
1:address:point <- new point:type
|
||||
2:address:number <- get-address *1:address:point, y:offset
|
||||
1:address:shared:point <- new point:type
|
||||
2:address:number <- get-address *1:address:shared:point, y:offset
|
||||
*2:address:number <- copy 34
|
||||
3:address:point <- bar 1:address:point # specialize _t to address:point
|
||||
4:point <- copy *3:address:point
|
||||
3:address:shared:point <- bar 1:address:shared:point # specialize _t to address:shared:point
|
||||
4:point <- copy *3:address:shared:point
|
||||
]
|
||||
recipe bar a:_t -> result:_t [
|
||||
local-scope
|
||||
|
@ -716,7 +716,7 @@ container d2:_elem [
|
|||
# static dispatch between shape-shifting variants, _including pointer lookups_
|
||||
recipe main [
|
||||
e1:d1:number <- merge 3
|
||||
e2:address:d2:number <- new {(d2 number): type}
|
||||
e2:address:shared:d2:number <- new {(d2 number): type}
|
||||
1:number/raw <- foo e1
|
||||
2:number/raw <- foo *e2 # different from previous scenario
|
||||
]
|
||||
|
@ -799,15 +799,15 @@ recipe foo x:_elem -> y:number [
|
|||
:(scenarios run)
|
||||
:(scenario specialize_most_similar_variant)
|
||||
recipe main [
|
||||
1:address:number <- new number:type
|
||||
2:number <- foo 1:address:number
|
||||
1:address:shared:number <- new number:type
|
||||
2:number <- foo 1:address:shared:number
|
||||
]
|
||||
recipe foo x:_elem -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 34
|
||||
]
|
||||
recipe foo x:address:_elem -> y:number [
|
||||
recipe foo x:address:shared:_elem -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 35
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
% Hide_warnings = true;
|
||||
recipe main [
|
||||
local-scope
|
||||
p:address:point <- new point:type
|
||||
p:address:shared:point <- new point:type
|
||||
foo *p
|
||||
]
|
||||
recipe foo p:point [
|
||||
|
@ -20,10 +20,10 @@ $warn: 0
|
|||
% Hide_warnings = true;
|
||||
recipe main [
|
||||
local-scope
|
||||
p:address:point <- new point:type
|
||||
p:address:shared:point <- new point:type
|
||||
p <- foo p
|
||||
]
|
||||
recipe foo p:address:point -> p:address:point [
|
||||
recipe foo p:address:shared:point -> p:address:shared:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:address:number <- get-address *p, x:offset
|
||||
|
@ -35,13 +35,13 @@ $warn: 0
|
|||
% Hide_warnings = true;
|
||||
recipe main [
|
||||
local-scope
|
||||
p:address:d1 <- new d1:type
|
||||
p:address:shared:d1 <- new d1:type
|
||||
q:number <- foo p
|
||||
]
|
||||
recipe foo p:address:d1 -> q:number [
|
||||
recipe foo p:address:shared:d1 -> q:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:address:d1 <- new d1:type
|
||||
x:address:shared:d1 <- new d1:type
|
||||
y:address:number <- get-address *x, p:offset # ignore this 'p'
|
||||
q <- copy 34
|
||||
]
|
||||
|
@ -55,10 +55,10 @@ $warn: 0
|
|||
% Hide_warnings = true;
|
||||
recipe main [
|
||||
local-scope
|
||||
p:address:point <- new point:type
|
||||
p:address:shared:point <- new point:type
|
||||
foo p
|
||||
]
|
||||
recipe foo p:address:point [
|
||||
recipe foo p:address:shared:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:address:number <- get-address *p, x:offset
|
||||
|
@ -70,15 +70,15 @@ recipe foo p:address:point [
|
|||
% Hide_warnings = true;
|
||||
recipe main [
|
||||
local-scope
|
||||
p:address:point <- new point:type
|
||||
p:address:shared:point <- new point:type
|
||||
foo p
|
||||
]
|
||||
recipe foo p:address:point [
|
||||
recipe foo p:address:shared:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
bar p
|
||||
]
|
||||
recipe bar p:address:point -> p:address:point [
|
||||
recipe bar p:address:shared:point -> p:address:shared:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:address:number <- get-address *p, x:offset
|
||||
|
@ -90,13 +90,13 @@ recipe bar p:address:point -> p:address:point [
|
|||
% Hide_warnings = true;
|
||||
recipe main [
|
||||
local-scope
|
||||
p:address:point <- new point:type
|
||||
p:address:shared:point <- new point:type
|
||||
foo p
|
||||
]
|
||||
recipe foo p:address:point [
|
||||
recipe foo p:address:shared:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
q:address:point <- copy p
|
||||
q:address:shared:point <- copy p
|
||||
x:address:number <- get-address *q, x:offset
|
||||
]
|
||||
+warn: foo: cannot modify q after instruction 'x:address:number <- get-address *q, x:offset' because that would modify ingredient p which is not also a product of foo
|
||||
|
@ -104,19 +104,19 @@ recipe foo p:address:point [
|
|||
:(scenario can_traverse_immutable_ingredients)
|
||||
% Hide_warnings = true;
|
||||
container test-list [
|
||||
next:address:test-list
|
||||
next:address:shared:test-list
|
||||
]
|
||||
recipe main [
|
||||
local-scope
|
||||
p:address:test-list <- new test-list:type
|
||||
p:address:shared:test-list <- new test-list:type
|
||||
foo p
|
||||
]
|
||||
recipe foo p:address:test-list [
|
||||
recipe foo p:address:shared:test-list [
|
||||
local-scope
|
||||
load-ingredients
|
||||
p2:address:test-list <- bar p
|
||||
p2:address:shared:test-list <- bar p
|
||||
]
|
||||
recipe bar x:address:test-list -> y:address:test-list [
|
||||
recipe bar x:address:shared:test-list -> y:address:shared:test-list [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- get *x, next:offset
|
||||
|
@ -126,11 +126,11 @@ $warn: 0
|
|||
:(scenario handle_optional_ingredients_in_immutability_checks)
|
||||
% Hide_warnings = true;
|
||||
recipe main [
|
||||
k:address:number <- new number:type
|
||||
k:address:shared:number <- new number:type
|
||||
test k
|
||||
]
|
||||
# recipe taking an immutable address ingredient
|
||||
recipe test k:address:number [
|
||||
recipe test k:address:shared:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
foo k
|
||||
|
@ -139,7 +139,7 @@ recipe test k:address:number [
|
|||
recipe foo -> [
|
||||
local-scope
|
||||
load-ingredients
|
||||
k:address:number, found?:boolean <- next-ingredient
|
||||
k:address:shared:number, found?:boolean <- next-ingredient
|
||||
]
|
||||
$warn: 0
|
||||
|
||||
|
@ -212,25 +212,25 @@ set<long long int> scan_contained_in_product_indices(const instruction& inst, se
|
|||
:(scenario immutability_infects_contained_in_variables)
|
||||
% Hide_warnings = true;
|
||||
container test-list [
|
||||
next:address:test-list
|
||||
next:address:shared:test-list
|
||||
]
|
||||
recipe main [
|
||||
local-scope
|
||||
p:address:test-list <- new test-list:type
|
||||
p:address:shared:test-list <- new test-list:type
|
||||
foo p
|
||||
]
|
||||
recipe foo p:address:test-list [ # p is immutable
|
||||
recipe foo p:address:shared:test-list [ # p is immutable
|
||||
local-scope
|
||||
load-ingredients
|
||||
p2:address:test-list <- test-next p # p2 is immutable
|
||||
p3:address:address:test-list <- get-address *p2, next:offset # signal modification of p2
|
||||
p2:address:shared:test-list <- test-next p # p2 is immutable
|
||||
p3:address:address:shared:test-list <- get-address *p2, next:offset # signal modification of p2
|
||||
]
|
||||
recipe test-next x:address:test-list -> y:address:test-list/contained-in:x [
|
||||
recipe test-next x:address:shared:test-list -> y:address:shared:test-list/contained-in:x [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- get *x, next:offset
|
||||
]
|
||||
+warn: foo: cannot modify p2 after instruction 'p3:address:address:test-list <- get-address *p2, next:offset' because that would modify ingredient p which is not also a product of foo
|
||||
+warn: foo: cannot modify p2 after instruction 'p3:address:address:shared:test-list <- get-address *p2, next:offset' because that would modify ingredient p which is not also a product of foo
|
||||
|
||||
:(code)
|
||||
void check_immutable_ingredient_in_instruction(const instruction& inst, const set<string>& current_ingredient_and_aliases, const string& original_ingredient_name, const recipe& caller) {
|
||||
|
@ -315,28 +315,28 @@ set<long long int> ingredient_indices(const instruction& inst, const set<string>
|
|||
:(scenario can_modify_contained_in_addresses)
|
||||
% Hide_warnings = true;
|
||||
container test-list [
|
||||
next:address:test-list
|
||||
next:address:shared:test-list
|
||||
]
|
||||
recipe main [
|
||||
local-scope
|
||||
p:address:test-list <- new test-list:type
|
||||
p:address:shared:test-list <- new test-list:type
|
||||
foo p
|
||||
]
|
||||
recipe foo p:address:test-list -> p:address:test-list [
|
||||
recipe foo p:address:shared:test-list -> p:address:shared:test-list [
|
||||
local-scope
|
||||
load-ingredients
|
||||
p2:address:test-list <- test-next p
|
||||
p2:address:shared:test-list <- test-next p
|
||||
p <- test-remove p2, p
|
||||
]
|
||||
recipe test-next x:address:test-list -> y:address:test-list [
|
||||
recipe test-next x:address:shared:test-list -> y:address:shared:test-list [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- get *x, next:offset
|
||||
]
|
||||
recipe test-remove x:address:test-list/contained-in:from, from:address:test-list -> from:address:test-list [
|
||||
recipe test-remove x:address:shared:test-list/contained-in:from, from:address:shared:test-list -> from:address:shared:test-list [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x2:address:address:test-list <- get-address *x, next:offset # pretend modification
|
||||
x2:address:address:shared:test-list <- get-address *x, next:offset # pretend modification
|
||||
]
|
||||
$warn: 0
|
||||
|
||||
|
|
|
@ -517,16 +517,16 @@ case LIMIT_TIME: {
|
|||
:(scenario new_concurrent)
|
||||
recipe f1 [
|
||||
start-running f2
|
||||
1:address:number/raw <- new number:type
|
||||
1:address:shared:number/raw <- new number:type
|
||||
# wait for f2 to complete
|
||||
{
|
||||
loop-unless 4:number/raw
|
||||
}
|
||||
]
|
||||
recipe f2 [
|
||||
2:address:number/raw <- new number:type
|
||||
2:address:shared:number/raw <- new number:type
|
||||
# hack: assumes scheduler implementation
|
||||
3:boolean/raw <- equal 1:address:number/raw, 2:address:number/raw
|
||||
3:boolean/raw <- equal 1:address:shared:number/raw, 2:address:shared:number/raw
|
||||
# signal f2 complete
|
||||
4:number/raw <- copy 1
|
||||
]
|
||||
|
|
456
070text.mu
456
070text.mu
File diff suppressed because it is too large
Load Diff
134
071channel.mu
134
071channel.mu
|
@ -10,9 +10,9 @@
|
|||
|
||||
scenario channel [
|
||||
run [
|
||||
1:address:channel <- new-channel 3/capacity
|
||||
1:address:channel <- write 1:address:channel, 34
|
||||
2:character, 1:address:channel <- read 1:address:channel
|
||||
1:address:shared:channel <- new-channel 3/capacity
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 34
|
||||
2:character, 1:address:shared:channel <- read 1:address:shared:channel
|
||||
]
|
||||
memory-should-contain [
|
||||
2 <- 34
|
||||
|
@ -28,11 +28,10 @@ container channel [
|
|||
# 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:character
|
||||
data:address:shared:array:character
|
||||
]
|
||||
|
||||
# result:address:channel <- new-channel capacity:number
|
||||
recipe new-channel capacity:number -> result:address:channel [
|
||||
recipe new-channel capacity:number -> result:address:shared:channel [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- new channel:type
|
||||
|
@ -44,11 +43,11 @@ recipe new-channel capacity:number -> result:address:channel [
|
|||
*free <- copy 0
|
||||
# result.data = new location[ingredient+1]
|
||||
capacity <- add capacity, 1 # unused slot for 'full?' below
|
||||
dest:address:address:array:character <- get-address *result, data:offset
|
||||
dest:address:address:shared:array:character <- get-address *result, data:offset
|
||||
*dest <- new character:type, capacity
|
||||
]
|
||||
|
||||
recipe write chan:address:channel, val:character -> chan:address:channel [
|
||||
recipe write chan:address:shared:channel, val:character -> chan:address:shared:channel [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -59,7 +58,7 @@ recipe write chan:address:channel, val:character -> chan:address:channel [
|
|||
wait-for-location *full-address
|
||||
}
|
||||
# store val
|
||||
circular-buffer:address:array:character <- get *chan, data:offset
|
||||
circular-buffer:address:shared:array:character <- get *chan, data:offset
|
||||
free:address:number <- get-address *chan, first-free:offset
|
||||
dest:address:character <- index-address *circular-buffer, *free
|
||||
*dest <- copy val
|
||||
|
@ -74,7 +73,7 @@ recipe write chan:address:channel, val:character -> chan:address:channel [
|
|||
}
|
||||
]
|
||||
|
||||
recipe read chan:address:channel -> result:character, chan:address:channel [
|
||||
recipe read chan:address:shared:channel -> result:character, chan:address:shared:channel [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -86,7 +85,7 @@ recipe read chan:address:channel -> result:character, chan:address:channel [
|
|||
}
|
||||
# read result
|
||||
full:address:number <- get-address *chan, first-full:offset
|
||||
circular-buffer:address:array:character <- get *chan, data:offset
|
||||
circular-buffer:address:shared:array:character <- get *chan, data:offset
|
||||
result <- index *circular-buffer, *full
|
||||
# mark its slot as empty
|
||||
*full <- add *full, 1
|
||||
|
@ -99,7 +98,7 @@ recipe read chan:address:channel -> result:character, chan:address:channel [
|
|||
}
|
||||
]
|
||||
|
||||
recipe clear-channel chan:address:channel -> chan:address:channel [
|
||||
recipe clear-channel chan:address:shared:channel -> chan:address:shared:channel [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -111,9 +110,9 @@ recipe clear-channel chan:address:channel -> chan:address:channel [
|
|||
|
||||
scenario channel-initialization [
|
||||
run [
|
||||
1:address:channel <- new-channel 3/capacity
|
||||
2:number <- get *1:address:channel, first-full:offset
|
||||
3:number <- get *1:address:channel, first-free:offset
|
||||
1:address:shared:channel <- new-channel 3/capacity
|
||||
2:number <- get *1:address:shared:channel, first-full:offset
|
||||
3:number <- get *1:address:shared:channel, first-free:offset
|
||||
]
|
||||
memory-should-contain [
|
||||
2 <- 0 # first-full
|
||||
|
@ -123,10 +122,10 @@ scenario channel-initialization [
|
|||
|
||||
scenario channel-write-increments-free [
|
||||
run [
|
||||
1:address:channel <- new-channel 3/capacity
|
||||
1:address:channel <- write 1:address:channel, 34
|
||||
2:number <- get *1:address:channel, first-full:offset
|
||||
3:number <- get *1:address:channel, first-free:offset
|
||||
1:address:shared:channel <- new-channel 3/capacity
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 34
|
||||
2:number <- get *1:address:shared:channel, first-full:offset
|
||||
3:number <- get *1:address:shared:channel, first-free:offset
|
||||
]
|
||||
memory-should-contain [
|
||||
2 <- 0 # first-full
|
||||
|
@ -136,11 +135,11 @@ scenario channel-write-increments-free [
|
|||
|
||||
scenario channel-read-increments-full [
|
||||
run [
|
||||
1:address:channel <- new-channel 3/capacity
|
||||
1:address:channel <- write 1:address:channel, 34
|
||||
_, 1:address:channel <- read 1:address:channel
|
||||
2:number <- get *1:address:channel, first-full:offset
|
||||
3:number <- get *1:address:channel, first-free:offset
|
||||
1:address:shared:channel <- new-channel 3/capacity
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 34
|
||||
_, 1:address:shared:channel <- read 1:address:shared:channel
|
||||
2:number <- get *1:address:shared:channel, first-full:offset
|
||||
3:number <- get *1:address:shared:channel, first-free:offset
|
||||
]
|
||||
memory-should-contain [
|
||||
2 <- 1 # first-full
|
||||
|
@ -151,19 +150,19 @@ scenario channel-read-increments-full [
|
|||
scenario channel-wrap [
|
||||
run [
|
||||
# channel with just 1 slot
|
||||
1:address:channel <- new-channel 1/capacity
|
||||
1:address:shared:channel <- new-channel 1/capacity
|
||||
# write and read a value
|
||||
1:address:channel <- write 1:address:channel, 34
|
||||
_, 1:address:channel <- read 1:address:channel
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 34
|
||||
_, 1:address:shared:channel <- read 1:address:shared:channel
|
||||
# first-free will now be 1
|
||||
2:number <- get *1:address:channel, first-free:offset
|
||||
3:number <- get *1:address:channel, first-free:offset
|
||||
2:number <- get *1:address:shared:channel, first-free:offset
|
||||
3:number <- get *1:address:shared:channel, first-free:offset
|
||||
# write second value, verify that first-free wraps
|
||||
1:address:channel <- write 1:address:channel, 34
|
||||
4:number <- get *1:address:channel, first-free:offset
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 34
|
||||
4:number <- get *1:address:shared:channel, first-free:offset
|
||||
# read second value, verify that first-full wraps
|
||||
_, 1:address:channel <- read 1:address:channel
|
||||
5:number <- get *1:address:channel, first-full:offset
|
||||
_, 1:address:shared:channel <- read 1:address:shared:channel
|
||||
5:number <- get *1:address:shared:channel, first-full:offset
|
||||
]
|
||||
memory-should-contain [
|
||||
2 <- 1 # first-free after first write
|
||||
|
@ -176,7 +175,7 @@ scenario channel-wrap [
|
|||
## helpers
|
||||
|
||||
# An empty channel has first-empty and first-full both at the same value.
|
||||
recipe channel-empty? chan:address:channel -> result:boolean [
|
||||
recipe channel-empty? chan:address:shared:channel -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# return chan.first-full == chan.first-free
|
||||
|
@ -187,7 +186,7 @@ recipe channel-empty? chan:address:channel -> result:boolean [
|
|||
|
||||
# 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)
|
||||
recipe channel-full? chan:address:channel -> result:boolean [
|
||||
recipe channel-full? chan:address:shared:channel -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# tmp = chan.first-free + 1
|
||||
|
@ -205,19 +204,18 @@ recipe channel-full? chan:address:channel -> result:boolean [
|
|||
result <- equal full, tmp
|
||||
]
|
||||
|
||||
# result:number <- channel-capacity chan:address:channel
|
||||
recipe channel-capacity chan:address:channel -> result:number [
|
||||
recipe channel-capacity chan:address:shared:channel -> result:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
q:address:array:character <- get *chan, data:offset
|
||||
q:address:shared:array:character <- get *chan, data:offset
|
||||
result <- length *q
|
||||
]
|
||||
|
||||
scenario channel-new-empty-not-full [
|
||||
run [
|
||||
1:address:channel <- new-channel 3/capacity
|
||||
2:boolean <- channel-empty? 1:address:channel
|
||||
3:boolean <- channel-full? 1:address:channel
|
||||
1:address:shared:channel <- new-channel 3/capacity
|
||||
2:boolean <- channel-empty? 1:address:shared:channel
|
||||
3:boolean <- channel-full? 1:address:shared:channel
|
||||
]
|
||||
memory-should-contain [
|
||||
2 <- 1 # empty?
|
||||
|
@ -227,10 +225,10 @@ scenario channel-new-empty-not-full [
|
|||
|
||||
scenario channel-write-not-empty [
|
||||
run [
|
||||
1:address:channel <- new-channel 3/capacity
|
||||
1:address:channel <- write 1:address:channel, 34
|
||||
2:boolean <- channel-empty? 1:address:channel
|
||||
3:boolean <- channel-full? 1:address:channel
|
||||
1:address:shared:channel <- new-channel 3/capacity
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 34
|
||||
2:boolean <- channel-empty? 1:address:shared:channel
|
||||
3:boolean <- channel-full? 1:address:shared:channel
|
||||
]
|
||||
memory-should-contain [
|
||||
2 <- 0 # empty?
|
||||
|
@ -240,10 +238,10 @@ scenario channel-write-not-empty [
|
|||
|
||||
scenario channel-write-full [
|
||||
run [
|
||||
1:address:channel <- new-channel 1/capacity
|
||||
1:address:channel <- write 1:address:channel, 34
|
||||
2:boolean <- channel-empty? 1:address:channel
|
||||
3:boolean <- channel-full? 1:address:channel
|
||||
1:address:shared:channel <- new-channel 1/capacity
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 34
|
||||
2:boolean <- channel-empty? 1:address:shared:channel
|
||||
3:boolean <- channel-full? 1:address:shared:channel
|
||||
]
|
||||
memory-should-contain [
|
||||
2 <- 0 # empty?
|
||||
|
@ -253,11 +251,11 @@ scenario channel-write-full [
|
|||
|
||||
scenario channel-read-not-full [
|
||||
run [
|
||||
1:address:channel <- new-channel 1/capacity
|
||||
1:address:channel <- write 1:address:channel, 34
|
||||
_, 1:address:channel <- read 1:address:channel
|
||||
2:boolean <- channel-empty? 1:address:channel
|
||||
3:boolean <- channel-full? 1:address:channel
|
||||
1:address:shared:channel <- new-channel 1/capacity
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 34
|
||||
_, 1:address:shared:channel <- read 1:address:shared:channel
|
||||
2:boolean <- channel-empty? 1:address:shared:channel
|
||||
3:boolean <- channel-full? 1:address:shared:channel
|
||||
]
|
||||
memory-should-contain [
|
||||
2 <- 1 # empty?
|
||||
|
@ -266,12 +264,12 @@ scenario channel-read-not-full [
|
|||
]
|
||||
|
||||
# helper for channels of characters in particular
|
||||
recipe buffer-lines in:address:channel, out:address:channel -> out:address:channel, in:address:channel [
|
||||
recipe buffer-lines in:address:shared:channel, out:address:shared:channel -> out:address:shared:channel, in:address:shared:channel [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# repeat forever
|
||||
{
|
||||
line:address:buffer <- new-buffer, 30
|
||||
line:address:shared:buffer <- new-buffer 30
|
||||
# read characters from 'in' until newline, copy into line
|
||||
{
|
||||
+next-character
|
||||
|
@ -302,7 +300,7 @@ recipe buffer-lines in:address:channel, out:address:channel -> out:address:chann
|
|||
}
|
||||
# copy line into 'out'
|
||||
i:number <- copy 0
|
||||
line-contents:address:array:character <- get *line, data:offset
|
||||
line-contents:address:shared:array:character <- get *line, data:offset
|
||||
max:number <- get *line, length:offset
|
||||
{
|
||||
done?:boolean <- greater-or-equal i, max
|
||||
|
@ -318,36 +316,36 @@ recipe buffer-lines in:address:channel, out:address:channel -> out:address:chann
|
|||
|
||||
scenario buffer-lines-blocks-until-newline [
|
||||
run [
|
||||
1:address:channel/stdin <- new-channel 10/capacity
|
||||
2:address:channel/buffered-stdin <- new-channel 10/capacity
|
||||
3:boolean <- channel-empty? 2:address:channel/buffered-stdin
|
||||
1:address:shared:channel/stdin <- new-channel 10/capacity
|
||||
2:address:shared:channel/buffered-stdin <- new-channel 10/capacity
|
||||
3:boolean <- channel-empty? 2:address:shared:channel/buffered-stdin
|
||||
assert 3:boolean, [
|
||||
F buffer-lines-blocks-until-newline: channel should be empty after init]
|
||||
# buffer stdin into buffered-stdin, try to read from buffered-stdin
|
||||
4:number/buffer-routine <- start-running buffer-lines, 1:address:channel/stdin, 2:address:channel/buffered-stdin
|
||||
4:number/buffer-routine <- start-running buffer-lines, 1:address:shared:channel/stdin, 2:address:shared:channel/buffered-stdin
|
||||
wait-for-routine 4:number/buffer-routine
|
||||
5:boolean <- channel-empty? 2:address:channel/buffered-stdin
|
||||
5:boolean <- channel-empty? 2:address:shared:channel/buffered-stdin
|
||||
assert 5:boolean, [
|
||||
F buffer-lines-blocks-until-newline: channel should be empty after buffer-lines bring-up]
|
||||
# write 'a'
|
||||
1:address:channel <- write 1:address:channel, 97/a
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 97/a
|
||||
restart 4:number/buffer-routine
|
||||
wait-for-routine 4:number/buffer-routine
|
||||
6:boolean <- channel-empty? 2:address:channel/buffered-stdin
|
||||
6:boolean <- channel-empty? 2:address:shared:channel/buffered-stdin
|
||||
assert 6:boolean, [
|
||||
F buffer-lines-blocks-until-newline: channel should be empty after writing 'a']
|
||||
# write 'b'
|
||||
1:address:channel <- write 1:address:channel, 98/b
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 98/b
|
||||
restart 4:number/buffer-routine
|
||||
wait-for-routine 4:number/buffer-routine
|
||||
7:boolean <- channel-empty? 2:address:channel/buffered-stdin
|
||||
7:boolean <- channel-empty? 2:address:shared:channel/buffered-stdin
|
||||
assert 7:boolean, [
|
||||
F buffer-lines-blocks-until-newline: channel should be empty after writing 'b']
|
||||
# write newline
|
||||
1:address:channel <- write 1:address:channel, 10/newline
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 10/newline
|
||||
restart 4:number/buffer-routine
|
||||
wait-for-routine 4:number/buffer-routine
|
||||
8:boolean <- channel-empty? 2:address:channel/buffered-stdin
|
||||
8:boolean <- channel-empty? 2:address:shared:channel/buffered-stdin
|
||||
9:boolean/completed? <- not 8:boolean
|
||||
assert 9:boolean/completed?, [
|
||||
F buffer-lines-blocks-until-newline: channel should contain data after writing newline]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
scenario array-from-args [
|
||||
run [
|
||||
1:address:array:character <- new-array 0, 1, 2
|
||||
2:array:character <- copy *1:address:array:character
|
||||
1:address:shared:array:character <- new-array 0, 1, 2
|
||||
2:array:character <- copy *1:address:shared:array:character
|
||||
]
|
||||
memory-should-contain [
|
||||
2 <- 3 # array length
|
||||
|
@ -12,7 +12,7 @@ scenario array-from-args [
|
|||
]
|
||||
|
||||
# create an array out of a list of scalar args
|
||||
recipe new-array [
|
||||
recipe new-array -> result:address:shared:array:character [
|
||||
local-scope
|
||||
capacity:number <- copy 0
|
||||
{
|
||||
|
@ -22,7 +22,7 @@ recipe new-array [
|
|||
capacity <- add capacity, 1
|
||||
loop
|
||||
}
|
||||
result:address:array:character <- new character:type, capacity
|
||||
result <- new character:type, capacity
|
||||
rewind-ingredients
|
||||
i:number <- copy 0
|
||||
{
|
||||
|
|
52
073list.mu
52
073list.mu
|
@ -5,27 +5,27 @@
|
|||
|
||||
container list:_elem [
|
||||
value:_elem
|
||||
next:address:list:_elem
|
||||
next:address:shared:list:_elem
|
||||
]
|
||||
|
||||
recipe push x:_elem, in:address:list:_elem -> in:address:list:_elem [
|
||||
recipe push x:_elem, in:address:shared:list:_elem -> in:address:shared:list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result:address:list:_elem <- new {(list _elem): type}
|
||||
result:address:shared:list:_elem <- new {(list _elem): type}
|
||||
val:address:_elem <- get-address *result, value:offset
|
||||
*val <- copy x
|
||||
next:address:address:list:_elem <- get-address *result, next:offset
|
||||
next:address:address:shared:list:_elem <- get-address *result, next:offset
|
||||
*next <- copy in
|
||||
reply result # needed explicitly because we need to replace 'in' with 'result'
|
||||
]
|
||||
|
||||
recipe first in:address:list:_elem -> result:_elem [
|
||||
recipe first in:address:shared:list:_elem -> result:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- get *in, value:offset
|
||||
]
|
||||
|
||||
recipe rest in:address:list:_elem -> result:address:list:_elem/contained-in:in [
|
||||
recipe rest in:address:shared:list:_elem -> result:address:shared:list:_elem/contained-in:in [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- get *in, next:offset
|
||||
|
@ -33,15 +33,15 @@ recipe rest in:address:list:_elem -> result:address:list:_elem/contained-in:in [
|
|||
|
||||
scenario list-handling [
|
||||
run [
|
||||
1:address:list:number <- push 3, 0
|
||||
1:address:list:number <- push 4, 1:address:list:number
|
||||
1:address:list:number <- push 5, 1:address:list:number
|
||||
2:number <- first 1:address:list:number
|
||||
1:address:list:number <- rest 1:address:list:number
|
||||
3:number <- first 1:address:list:number
|
||||
1:address:list:number <- rest 1:address:list:number
|
||||
4:number <- first 1:address:list:number
|
||||
1:address:list:number <- rest 1:address:list:number
|
||||
1:address:shared:list:number <- push 3, 0
|
||||
1:address:shared:list:number <- push 4, 1:address:shared:list:number
|
||||
1:address:shared:list:number <- push 5, 1:address:shared:list:number
|
||||
2:number <- first 1:address:shared:list:number
|
||||
1:address:shared:list:number <- rest 1:address:shared:list:number
|
||||
3:number <- first 1:address:shared:list:number
|
||||
1:address:shared:list:number <- rest 1:address:shared:list:number
|
||||
4:number <- first 1:address:shared:list:number
|
||||
1:address:shared:list:number <- rest 1:address:shared:list:number
|
||||
]
|
||||
memory-should-contain [
|
||||
1 <- 0 # empty to empty, dust to dust..
|
||||
|
@ -51,26 +51,26 @@ scenario list-handling [
|
|||
]
|
||||
]
|
||||
|
||||
recipe to-text in:address:list:_elem -> result:address:array:character [
|
||||
recipe to-text in:address:shared:list:_elem -> result:address:shared:array:character [
|
||||
local-scope
|
||||
#? $print [to text: list], 10/newline
|
||||
load-ingredients
|
||||
buf:address:buffer <- new-buffer 80
|
||||
buf:address:shared: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)
|
||||
recipe to-text-line in:address:list:_elem -> result:address:array:character [
|
||||
recipe to-text-line in:address:shared:list:_elem -> result:address:shared:array:character [
|
||||
local-scope
|
||||
#? $print [to text line: list], 10/newline
|
||||
load-ingredients
|
||||
buf:address:buffer <- new-buffer 80
|
||||
buf:address:shared:buffer <- new-buffer 80
|
||||
buf <- to-buffer in, buf, 6 # max elements to display
|
||||
result <- buffer-to-array buf
|
||||
]
|
||||
|
||||
recipe to-buffer in:address:list:_elem, buf:address:buffer -> buf:address:buffer [
|
||||
recipe to-buffer in:address:shared:list:_elem, buf:address:shared:buffer -> buf:address:shared:buffer [
|
||||
local-scope
|
||||
#? $print [to buffer: list], 10/newline
|
||||
load-ingredients
|
||||
|
@ -83,13 +83,13 @@ recipe 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:address:shared:list:_elem <- rest in
|
||||
nextn:number <- copy next
|
||||
#? buf <- append buf, nextn
|
||||
reply-unless next
|
||||
space:character <- copy 32/space
|
||||
buf <- append buf, space:character
|
||||
s:address:array:character <- new [-> ]
|
||||
s:address:shared:array:character <- new [-> ]
|
||||
n:number <- length *s
|
||||
buf <- append buf, s
|
||||
# and recurse
|
||||
|
@ -108,13 +108,13 @@ recipe to-buffer in:address:list:_elem, buf:address:buffer -> buf:address:buffer
|
|||
reply
|
||||
}
|
||||
# past recursion depth; insert ellipses and stop
|
||||
s:address:array:character <- new [...]
|
||||
s:address:shared:array:character <- new [...]
|
||||
append buf, s
|
||||
]
|
||||
|
||||
scenario stash-on-list-converts-to-text [
|
||||
run [
|
||||
x:address:list:number <- push 4, 0
|
||||
x:address:shared:list:number <- push 4, 0
|
||||
x <- push 5, x
|
||||
x <- push 6, x
|
||||
stash [foo foo], x
|
||||
|
@ -126,8 +126,8 @@ scenario stash-on-list-converts-to-text [
|
|||
|
||||
scenario stash-handles-list-with-cycle [
|
||||
run [
|
||||
x:address:list:number <- push 4, 0
|
||||
y:address:address:list:number <- get-address *x, next:offset
|
||||
x:address:shared:list:number <- push 4, 0
|
||||
y:address:address:shared:list:number <- get-address *x, next:offset
|
||||
*y <- copy x
|
||||
stash [foo foo], x
|
||||
]
|
||||
|
|
|
@ -2,42 +2,42 @@
|
|||
|
||||
container duplex-list:_elem [
|
||||
value:_elem
|
||||
next:address:duplex-list:_elem
|
||||
prev:address:duplex-list:_elem
|
||||
next:address:shared:duplex-list:_elem
|
||||
prev:address:shared:duplex-list:_elem
|
||||
]
|
||||
|
||||
# should I say in/contained-in:result, allow ingredients to refer to products?
|
||||
recipe push x:_elem, in:address:duplex-list:_elem -> in:address:duplex-list:_elem [
|
||||
recipe push x:_elem, in:address:shared:duplex-list:_elem -> in:address:shared:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result:address:duplex-list:_elem <- new {(duplex-list _elem): type}
|
||||
result:address:shared:duplex-list:_elem <- new {(duplex-list _elem): type}
|
||||
val:address:_elem <- get-address *result, value:offset
|
||||
*val <- copy x
|
||||
next:address:address:duplex-list:_elem <- get-address *result, next:offset
|
||||
next:address:address:shared:duplex-list:_elem <- get-address *result, next:offset
|
||||
*next <- copy in
|
||||
{
|
||||
break-unless in
|
||||
prev:address:address:duplex-list:_elem <- get-address *in, prev:offset
|
||||
prev:address:address:shared:duplex-list:_elem <- get-address *in, prev:offset
|
||||
*prev <- copy result
|
||||
}
|
||||
reply result # needed explicitly because we need to replace 'in' with 'result'
|
||||
]
|
||||
|
||||
recipe first in:address:duplex-list:_elem -> result:_elem [
|
||||
recipe first in:address:shared:duplex-list:_elem -> result:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless in, 0
|
||||
result <- get *in, value:offset
|
||||
]
|
||||
|
||||
recipe next in:address:duplex-list:_elem -> result:address:duplex-list:_elem/contained-in:in [
|
||||
recipe next in:address:shared:duplex-list:_elem -> result:address:shared:duplex-list:_elem/contained-in:in [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless in, 0
|
||||
result <- get *in, next:offset
|
||||
]
|
||||
|
||||
recipe prev in:address:duplex-list:_elem -> result:address:duplex-list:_elem/contained-in:in [
|
||||
recipe prev in:address:shared:duplex-list:_elem -> result:address:shared:duplex-list:_elem/contained-in:in [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless in, 0
|
||||
|
@ -50,24 +50,24 @@ scenario duplex-list-handling [
|
|||
# reserve locations 0, 1 and 2 to check for missing null check
|
||||
1:number <- copy 34
|
||||
2:number <- copy 35
|
||||
3:address:duplex-list:character <- push 3, 0
|
||||
3:address:duplex-list:character <- push 4, 3:address:duplex-list:character
|
||||
3:address:duplex-list:character <- push 5, 3:address:duplex-list:character
|
||||
4:address:duplex-list:character <- copy 3:address:duplex-list:character
|
||||
5:character <- first 4:address:duplex-list:character
|
||||
4:address:duplex-list:character <- next 4:address:duplex-list:character
|
||||
6:character <- first 4:address:duplex-list:character
|
||||
4:address:duplex-list:character <- next 4:address:duplex-list:character
|
||||
7:character <- first 4:address:duplex-list:character
|
||||
8:address:duplex-list:character <- next 4:address:duplex-list:character
|
||||
9:character <- first 8:address:duplex-list:character
|
||||
10:address:duplex-list:character <- next 8:address:duplex-list:character
|
||||
11:address:duplex-list:character <- prev 8:address:duplex-list:character
|
||||
4:address:duplex-list:character <- prev 4:address:duplex-list:character
|
||||
12:character <- first 4:address:duplex-list:character
|
||||
4:address:duplex-list:character <- prev 4:address:duplex-list:character
|
||||
13:character <- first 4:address:duplex-list:character
|
||||
14:boolean <- equal 3:address:duplex-list:character, 4:address:duplex-list:character
|
||||
3:address:shared:duplex-list:character <- push 3, 0
|
||||
3:address:shared:duplex-list:character <- push 4, 3:address:shared:duplex-list:character
|
||||
3:address:shared:duplex-list:character <- push 5, 3:address:shared:duplex-list:character
|
||||
4:address:shared:duplex-list:character <- copy 3:address:shared:duplex-list:character
|
||||
5:character <- first 4:address:shared:duplex-list:character
|
||||
4:address:shared:duplex-list:character <- next 4:address:shared:duplex-list:character
|
||||
6:character <- first 4:address:shared:duplex-list:character
|
||||
4:address:shared:duplex-list:character <- next 4:address:shared:duplex-list:character
|
||||
7:character <- first 4:address:shared:duplex-list:character
|
||||
8:address:shared:duplex-list:character <- next 4:address:shared:duplex-list:character
|
||||
9:character <- first 8:address:shared:duplex-list:character
|
||||
10:address:shared:duplex-list:character <- next 8:address:shared:duplex-list:character
|
||||
11:address:shared:duplex-list:character <- prev 8:address:shared:duplex-list:character
|
||||
4:address:shared:duplex-list:character <- prev 4:address:shared:duplex-list:character
|
||||
12:character <- first 4:address:shared:duplex-list:character
|
||||
4:address:shared:duplex-list:character <- prev 4:address:shared:duplex-list:character
|
||||
13:character <- first 4:address:shared:duplex-list:character
|
||||
14:boolean <- equal 3:address:shared:duplex-list:character, 4:address:shared:duplex-list:character
|
||||
]
|
||||
memory-should-contain [
|
||||
0 <- 0 # no modifications to null pointers
|
||||
|
@ -87,15 +87,15 @@ scenario duplex-list-handling [
|
|||
]
|
||||
|
||||
# insert 'x' after 'in'
|
||||
recipe insert x:_elem, in:address:duplex-list:_elem -> in:address:duplex-list:_elem [
|
||||
recipe insert x:_elem, in:address:shared:duplex-list:_elem -> in:address:shared:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
new-node:address:duplex-list:_elem <- new {(duplex-list _elem): type}
|
||||
new-node:address:shared:duplex-list:_elem <- new {(duplex-list _elem): type}
|
||||
val:address:_elem <- get-address *new-node, value:offset
|
||||
*val <- copy x
|
||||
next-node:address:duplex-list:_elem <- get *in, next:offset
|
||||
next-node:address:shared:duplex-list:_elem <- get *in, next:offset
|
||||
# in.next = new-node
|
||||
y:address:address:duplex-list:_elem <- get-address *in, next:offset
|
||||
y:address:address:shared:duplex-list:_elem <- get-address *in, next:offset
|
||||
*y <- copy new-node
|
||||
# new-node.prev = in
|
||||
y <- get-address *new-node, prev:offset
|
||||
|
@ -112,27 +112,27 @@ recipe insert x:_elem, in:address:duplex-list:_elem -> in:address:duplex-list:_e
|
|||
|
||||
scenario inserting-into-duplex-list [
|
||||
run [
|
||||
1:address:duplex-list:character <- push 3, 0
|
||||
1:address:duplex-list:character <- push 4, 1:address:duplex-list:character
|
||||
1:address:duplex-list:character <- push 5, 1:address:duplex-list:character
|
||||
2:address:duplex-list:character <- next 1:address:duplex-list:character # 2 points inside list
|
||||
2:address:duplex-list:character <- insert 6, 2:address:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 3, 0
|
||||
1:address:shared:duplex-list:character <- push 4, 1:address:shared:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 5, 1:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 1:address:shared:duplex-list:character # 2 points inside list
|
||||
2:address:shared:duplex-list:character <- insert 6, 2:address:shared:duplex-list:character
|
||||
# check structure like before
|
||||
2:address:duplex-list:character <- copy 1:address:duplex-list:character
|
||||
3:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
4:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
5:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
6:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- prev 2:address:duplex-list:character
|
||||
7:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- prev 2:address:duplex-list:character
|
||||
8:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- prev 2:address:duplex-list:character
|
||||
9:character <- first 2:address:duplex-list:character
|
||||
10:boolean <- equal 1:address:duplex-list:character, 2:address:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- copy 1:address:shared:duplex-list:character
|
||||
3:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
4:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
5:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
6:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- prev 2:address:shared:duplex-list:character
|
||||
7:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- prev 2:address:shared:duplex-list:character
|
||||
8:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- prev 2:address:shared:duplex-list:character
|
||||
9:character <- first 2:address:shared:duplex-list:character
|
||||
10:boolean <- equal 1:address:shared:duplex-list:character, 2:address:shared:duplex-list:character
|
||||
]
|
||||
memory-should-contain [
|
||||
3 <- 5 # scanning next
|
||||
|
@ -148,28 +148,28 @@ scenario inserting-into-duplex-list [
|
|||
|
||||
scenario inserting-at-end-of-duplex-list [
|
||||
run [
|
||||
1:address:duplex-list:character <- push 3, 0
|
||||
1:address:duplex-list:character <- push 4, 1:address:duplex-list:character
|
||||
1:address:duplex-list:character <- push 5, 1:address:duplex-list:character
|
||||
2:address:duplex-list:character <- next 1:address:duplex-list:character # 2 points inside list
|
||||
2:address:duplex-list:character <- next 2:address:duplex-list:character # now at end of list
|
||||
2:address:duplex-list:character <- insert 6, 2:address:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 3, 0
|
||||
1:address:shared:duplex-list:character <- push 4, 1:address:shared:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 5, 1:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 1:address:shared:duplex-list:character # 2 points inside list
|
||||
2:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character # now at end of list
|
||||
2:address:shared:duplex-list:character <- insert 6, 2:address:shared:duplex-list:character
|
||||
# check structure like before
|
||||
2:address:duplex-list:character <- copy 1:address:duplex-list:character
|
||||
3:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
4:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
5:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
6:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- prev 2:address:duplex-list:character
|
||||
7:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- prev 2:address:duplex-list:character
|
||||
8:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- prev 2:address:duplex-list:character
|
||||
9:character <- first 2:address:duplex-list:character
|
||||
10:boolean <- equal 1:address:duplex-list:character, 2:address:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- copy 1:address:shared:duplex-list:character
|
||||
3:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
4:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
5:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
6:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- prev 2:address:shared:duplex-list:character
|
||||
7:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- prev 2:address:shared:duplex-list:character
|
||||
8:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- prev 2:address:shared:duplex-list:character
|
||||
9:character <- first 2:address:shared:duplex-list:character
|
||||
10:boolean <- equal 1:address:shared:duplex-list:character, 2:address:shared:duplex-list:character
|
||||
]
|
||||
memory-should-contain [
|
||||
3 <- 5 # scanning next
|
||||
|
@ -185,26 +185,26 @@ scenario inserting-at-end-of-duplex-list [
|
|||
|
||||
scenario inserting-after-start-of-duplex-list [
|
||||
run [
|
||||
1:address:duplex-list:character <- push 3, 0
|
||||
1:address:duplex-list:character <- push 4, 1:address:duplex-list:character
|
||||
1:address:duplex-list:character <- push 5, 1:address:duplex-list:character
|
||||
1:address:duplex-list:character <- insert 6, 1:address:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 3, 0
|
||||
1:address:shared:duplex-list:character <- push 4, 1:address:shared:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 5, 1:address:shared:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- insert 6, 1:address:shared:duplex-list:character
|
||||
# check structure like before
|
||||
2:address:duplex-list:character <- copy 1:address:duplex-list:character
|
||||
3:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
4:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
5:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
6:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- prev 2:address:duplex-list:character
|
||||
7:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- prev 2:address:duplex-list:character
|
||||
8:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- prev 2:address:duplex-list:character
|
||||
9:character <- first 2:address:duplex-list:character
|
||||
10:boolean <- equal 1:address:duplex-list:character, 2:address:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- copy 1:address:shared:duplex-list:character
|
||||
3:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
4:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
5:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
6:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- prev 2:address:shared:duplex-list:character
|
||||
7:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- prev 2:address:shared:duplex-list:character
|
||||
8:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- prev 2:address:shared:duplex-list:character
|
||||
9:character <- first 2:address:shared:duplex-list:character
|
||||
10:boolean <- equal 1:address:shared:duplex-list:character, 2:address:shared:duplex-list:character
|
||||
]
|
||||
memory-should-contain [
|
||||
3 <- 5 # scanning next
|
||||
|
@ -222,15 +222,15 @@ 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.
|
||||
recipe remove x:address:duplex-list:_elem/contained-in:in, in:address:duplex-list:_elem -> in:address:duplex-list:_elem [
|
||||
recipe remove x:address:shared:duplex-list:_elem/contained-in:in, in:address:shared:duplex-list:_elem -> in:address:shared:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if 'x' is null, return
|
||||
reply-unless x
|
||||
next-node:address:duplex-list:_elem <- get *x, next:offset
|
||||
prev-node:address:duplex-list:_elem <- get *x, prev:offset
|
||||
next-node:address:shared:duplex-list:_elem <- get *x, next:offset
|
||||
prev-node:address:shared:duplex-list:_elem <- get *x, prev:offset
|
||||
# null x's pointers
|
||||
tmp:address:address:duplex-list:_elem <- get-address *x, next:offset
|
||||
tmp:address:address:shared:duplex-list:_elem <- get-address *x, next:offset
|
||||
*tmp <- copy 0
|
||||
tmp <- get-address *x, prev:offset
|
||||
*tmp <- copy 0
|
||||
|
@ -254,21 +254,21 @@ recipe remove x:address:duplex-list:_elem/contained-in:in, in:address:duplex-lis
|
|||
|
||||
scenario removing-from-duplex-list [
|
||||
run [
|
||||
1:address:duplex-list:character <- push 3, 0
|
||||
1:address:duplex-list:character <- push 4, 1:address:duplex-list:character
|
||||
1:address:duplex-list:character <- push 5, 1:address:duplex-list:character
|
||||
2:address:duplex-list:character <- next 1:address:duplex-list:character # 2 points at second element
|
||||
1:address:duplex-list:character <- remove 2:address:duplex-list:character, 1:address:duplex-list:character
|
||||
3:boolean <- equal 2:address:duplex-list:character, 0
|
||||
1:address:shared:duplex-list:character <- push 3, 0
|
||||
1:address:shared:duplex-list:character <- push 4, 1:address:shared:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 5, 1:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 1:address:shared:duplex-list:character # 2 points at second element
|
||||
1:address:shared:duplex-list:character <- remove 2:address:shared:duplex-list:character, 1:address:shared:duplex-list:character
|
||||
3:boolean <- equal 2:address:shared:duplex-list:character, 0
|
||||
# check structure like before
|
||||
2:address:duplex-list:character <- copy 1:address:duplex-list:character
|
||||
4:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
5:character <- first 2:address:duplex-list:character
|
||||
6:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- prev 2:address:duplex-list:character
|
||||
7:character <- first 2:address:duplex-list:character
|
||||
8:boolean <- equal 1:address:duplex-list:character, 2:address:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- copy 1:address:shared:duplex-list:character
|
||||
4:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
5:character <- first 2:address:shared:duplex-list:character
|
||||
6:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- prev 2:address:shared:duplex-list:character
|
||||
7:character <- first 2:address:shared:duplex-list:character
|
||||
8:boolean <- equal 1:address:shared:duplex-list:character, 2:address:shared:duplex-list:character
|
||||
]
|
||||
memory-should-contain [
|
||||
3 <- 0 # remove returned non-null
|
||||
|
@ -282,19 +282,19 @@ scenario removing-from-duplex-list [
|
|||
|
||||
scenario removing-from-start-of-duplex-list [
|
||||
run [
|
||||
1:address:duplex-list:character <- push 3, 0
|
||||
1:address:duplex-list:character <- push 4, 1:address:duplex-list:character
|
||||
1:address:duplex-list:character <- push 5, 1:address:duplex-list:character
|
||||
1:address:duplex-list:character <- remove 1:address:duplex-list:character, 1:address:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 3, 0
|
||||
1:address:shared:duplex-list:character <- push 4, 1:address:shared:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 5, 1:address:shared:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- remove 1:address:shared:duplex-list:character, 1:address:shared:duplex-list:character
|
||||
# check structure like before
|
||||
2:address:duplex-list:character <- copy 1:address:duplex-list:character
|
||||
3:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
4:character <- first 2:address:duplex-list:character
|
||||
5:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- prev 2:address:duplex-list:character
|
||||
6:character <- first 2:address:duplex-list:character
|
||||
7:boolean <- equal 1:address:duplex-list:character, 2:address:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- copy 1:address:shared:duplex-list:character
|
||||
3:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
4:character <- first 2:address:shared:duplex-list:character
|
||||
5:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- prev 2:address:shared:duplex-list:character
|
||||
6:character <- first 2:address:shared:duplex-list:character
|
||||
7:boolean <- equal 1:address:shared:duplex-list:character, 2:address:shared:duplex-list:character
|
||||
]
|
||||
memory-should-contain [
|
||||
3 <- 4 # scanning next, skipping deleted element
|
||||
|
@ -307,23 +307,23 @@ scenario removing-from-start-of-duplex-list [
|
|||
|
||||
scenario removing-from-end-of-duplex-list [
|
||||
run [
|
||||
1:address:duplex-list:character <- push 3, 0
|
||||
1:address:duplex-list:character <- push 4, 1:address:duplex-list:character
|
||||
1:address:duplex-list:character <- push 5, 1:address:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 3, 0
|
||||
1:address:shared:duplex-list:character <- push 4, 1:address:shared:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 5, 1:address:shared:duplex-list:character
|
||||
# delete last element
|
||||
2:address:duplex-list:character <- next 1:address:duplex-list:character
|
||||
2:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
1:address:duplex-list:character <- remove 2:address:duplex-list:character, 1:address:duplex-list:character
|
||||
3:boolean <- equal 2:address:duplex-list:character, 0
|
||||
2:address:shared:duplex-list:character <- next 1:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- remove 2:address:shared:duplex-list:character, 1:address:shared:duplex-list:character
|
||||
3:boolean <- equal 2:address:shared:duplex-list:character, 0
|
||||
# check structure like before
|
||||
2:address:duplex-list:character <- copy 1:address:duplex-list:character
|
||||
4:character <- first 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
5:character <- first 2:address:duplex-list:character
|
||||
6:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- prev 2:address:duplex-list:character
|
||||
7:character <- first 2:address:duplex-list:character
|
||||
8:boolean <- equal 1:address:duplex-list:character, 2:address:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- copy 1:address:shared:duplex-list:character
|
||||
4:character <- first 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
5:character <- first 2:address:shared:duplex-list:character
|
||||
6:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- prev 2:address:shared:duplex-list:character
|
||||
7:character <- first 2:address:shared:duplex-list:character
|
||||
8:boolean <- equal 1:address:shared:duplex-list:character, 2:address:shared:duplex-list:character
|
||||
]
|
||||
memory-should-contain [
|
||||
3 <- 0 # remove returned non-null
|
||||
|
@ -337,8 +337,8 @@ scenario removing-from-end-of-duplex-list [
|
|||
|
||||
scenario removing-from-singleton-list [
|
||||
run [
|
||||
1:address:duplex-list:character <- push 3, 0
|
||||
1:address:duplex-list:character <- remove 1:address:duplex-list:character, 1:address:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 3, 0
|
||||
1:address:shared:duplex-list:character <- remove 1:address:shared:duplex-list:character, 1:address:shared:duplex-list:character
|
||||
]
|
||||
memory-should-contain [
|
||||
1 <- 0 # back to an empty list
|
||||
|
@ -347,16 +347,16 @@ scenario removing-from-singleton-list [
|
|||
|
||||
# remove values between 'start' and 'end' (both exclusive)
|
||||
# also clear pointers back out from start/end for hygiene
|
||||
recipe remove-between start:address:duplex-list:_elem, end:address:duplex-list:_elem/contained-in:start -> start:address:duplex-list:_elem [
|
||||
recipe remove-between start:address:shared:duplex-list:_elem, end:address:shared:duplex-list:_elem/contained-in:start -> start:address:shared:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless start
|
||||
# start->next->prev = 0
|
||||
# start->next = end
|
||||
next:address:address:duplex-list:_elem <- get-address *start, next:offset
|
||||
next:address:address:shared:duplex-list:_elem <- get-address *start, next:offset
|
||||
nothing-to-delete?:boolean <- equal *next, end
|
||||
reply-if nothing-to-delete?
|
||||
prev:address:address:duplex-list:_elem <- get-address **next, prev:offset
|
||||
prev:address:address:shared:duplex-list:_elem <- get-address **next, prev:offset
|
||||
*prev <- copy 0
|
||||
*next <- copy end
|
||||
reply-unless end
|
||||
|
@ -370,25 +370,25 @@ recipe remove-between start:address:duplex-list:_elem, end:address:duplex-list:_
|
|||
|
||||
scenario remove-range [
|
||||
# construct a duplex list with six elements [13, 14, 15, 16, 17, 18]
|
||||
1:address:duplex-list:character <- push 18, 0
|
||||
1:address:duplex-list:character <- push 17, 1:address:duplex-list:character
|
||||
1:address:duplex-list:character <- push 16, 1:address:duplex-list:character
|
||||
1:address:duplex-list:character <- push 15, 1:address:duplex-list:character
|
||||
1:address:duplex-list:character <- push 14, 1:address:duplex-list:character
|
||||
1:address:duplex-list:character <- push 13, 1:address:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 18, 0
|
||||
1:address:shared:duplex-list:character <- push 17, 1:address:shared:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 16, 1:address:shared:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 15, 1:address:shared:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 14, 1:address:shared:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 13, 1:address:shared:duplex-list:character
|
||||
run [
|
||||
# delete 16 onwards
|
||||
# first pointer: to the third element
|
||||
2:address:duplex-list:character <- next 1:address:duplex-list:character
|
||||
2:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
2:address:duplex-list:character <- remove-between 2:address:duplex-list:character, 0
|
||||
2:address:shared:duplex-list:character <- next 1:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- remove-between 2:address:shared:duplex-list:character, 0
|
||||
# now check the list
|
||||
4:character <- get *1:address:duplex-list:character, value:offset
|
||||
5:address:duplex-list:character <- next 1:address:duplex-list:character
|
||||
6:character <- get *5:address:duplex-list:character, value:offset
|
||||
7:address:duplex-list:character <- next 5:address:duplex-list:character
|
||||
8:character <- get *7:address:duplex-list:character, value:offset
|
||||
9:address:duplex-list:character <- next 7:address:duplex-list:character
|
||||
4:character <- get *1:address:shared:duplex-list:character, value:offset
|
||||
5:address:shared:duplex-list:character <- next 1:address:shared:duplex-list:character
|
||||
6:character <- get *5:address:shared:duplex-list:character, value:offset
|
||||
7:address:shared:duplex-list:character <- next 5:address:shared:duplex-list:character
|
||||
8:character <- get *7:address:shared:duplex-list:character, value:offset
|
||||
9:address:shared:duplex-list:character <- next 7:address:shared:duplex-list:character
|
||||
]
|
||||
memory-should-contain [
|
||||
4 <- 13
|
||||
|
@ -400,29 +400,29 @@ scenario remove-range [
|
|||
|
||||
scenario remove-range-to-end [
|
||||
# construct a duplex list with six elements [13, 14, 15, 16, 17, 18]
|
||||
1:address:duplex-list:character <- push 18, 0
|
||||
1:address:duplex-list:character <- push 17, 1:address:duplex-list:character
|
||||
1:address:duplex-list:character <- push 16, 1:address:duplex-list:character
|
||||
1:address:duplex-list:character <- push 15, 1:address:duplex-list:character
|
||||
1:address:duplex-list:character <- push 14, 1:address:duplex-list:character
|
||||
1:address:duplex-list:character <- push 13, 1:address:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 18, 0
|
||||
1:address:shared:duplex-list:character <- push 17, 1:address:shared:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 16, 1:address:shared:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 15, 1:address:shared:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 14, 1:address:shared:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 13, 1:address:shared:duplex-list:character
|
||||
run [
|
||||
# delete 15, 16 and 17
|
||||
# first pointer: to the third element
|
||||
2:address:duplex-list:character <- next 1:address:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 1:address:shared:duplex-list:character
|
||||
# second pointer: to the fifth element
|
||||
3:address:duplex-list:character <- next 2:address:duplex-list:character
|
||||
3:address:duplex-list:character <- next 3:address:duplex-list:character
|
||||
3:address:duplex-list:character <- next 3:address:duplex-list:character
|
||||
3:address:duplex-list:character <- next 3:address:duplex-list:character
|
||||
remove-between 2:address:duplex-list:character, 3:address:duplex-list:character
|
||||
3:address:shared:duplex-list:character <- next 2:address:shared:duplex-list:character
|
||||
3:address:shared:duplex-list:character <- next 3:address:shared:duplex-list:character
|
||||
3:address:shared:duplex-list:character <- next 3:address:shared:duplex-list:character
|
||||
3:address:shared:duplex-list:character <- next 3:address:shared:duplex-list:character
|
||||
remove-between 2:address:shared:duplex-list:character, 3:address:shared:duplex-list:character
|
||||
# now check the list
|
||||
4:character <- get *1:address:duplex-list:character, value:offset
|
||||
5:address:duplex-list:character <- next 1:address:duplex-list:character
|
||||
6:character <- get *5:address:duplex-list:character, value:offset
|
||||
7:address:duplex-list:character <- next 5:address:duplex-list:character
|
||||
8:character <- get *7:address:duplex-list:character, value:offset
|
||||
9:address:duplex-list:character <- next 7:address:duplex-list:character
|
||||
4:character <- get *1:address:shared:duplex-list:character, value:offset
|
||||
5:address:shared:duplex-list:character <- next 1:address:shared:duplex-list:character
|
||||
6:character <- get *5:address:shared:duplex-list:character, value:offset
|
||||
7:address:shared:duplex-list:character <- next 5:address:shared:duplex-list:character
|
||||
8:character <- get *7:address:shared:duplex-list:character, value:offset
|
||||
9:address:shared:duplex-list:character <- next 7:address:shared:duplex-list:character
|
||||
]
|
||||
memory-should-contain [
|
||||
4 <- 13
|
||||
|
@ -434,18 +434,18 @@ scenario remove-range-to-end [
|
|||
|
||||
scenario remove-range-empty [
|
||||
# construct a duplex list with six elements [13, 14, 15, 16, 17, 18]
|
||||
1:address:duplex-list:character <- push 14, 0
|
||||
1:address:duplex-list:character <- push 13, 1:address:duplex-list:character
|
||||
1:address:shared:duplex-list:character <- push 14, 0
|
||||
1:address:shared:duplex-list:character <- push 13, 1:address:shared:duplex-list:character
|
||||
run [
|
||||
# delete 16 onwards
|
||||
# first pointer: to the third element
|
||||
2:address:duplex-list:character <- next 1:address:duplex-list:character
|
||||
remove-between 1:address:duplex-list:character, 2:address:duplex-list:character
|
||||
2:address:shared:duplex-list:character <- next 1:address:shared:duplex-list:character
|
||||
remove-between 1:address:shared:duplex-list:character, 2:address:shared:duplex-list:character
|
||||
# now check the list
|
||||
4:character <- get *1:address:duplex-list:character, value:offset
|
||||
5:address:duplex-list:character <- next 1:address:duplex-list:character
|
||||
6:character <- get *5:address:duplex-list:character, value:offset
|
||||
7:address:duplex-list:character <- next 5:address:duplex-list:character
|
||||
4:character <- get *1:address:shared:duplex-list:character, value:offset
|
||||
5:address:shared:duplex-list:character <- next 1:address:shared:duplex-list:character
|
||||
6:character <- get *5:address:shared:duplex-list:character, value:offset
|
||||
7:address:shared:duplex-list:character <- next 5:address:shared:duplex-list:character
|
||||
]
|
||||
memory-should-contain [
|
||||
4 <- 13
|
||||
|
@ -455,20 +455,20 @@ scenario remove-range-empty [
|
|||
]
|
||||
|
||||
# insert list beginning at 'new' after 'in'
|
||||
recipe insert-range in:address:duplex-list:_elem, start:address:duplex-list:_elem/contained-in:in -> in:address:duplex-list:_elem [
|
||||
recipe insert-range in:address:shared:duplex-list:_elem, start:address:shared:duplex-list:_elem/contained-in:in -> in:address:shared:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless in
|
||||
reply-unless start
|
||||
end:address:duplex-list:_elem <- copy start
|
||||
end:address:shared:duplex-list:_elem <- copy start
|
||||
{
|
||||
next:address:duplex-list:_elem <- next end/insert-range
|
||||
next:address:shared:duplex-list:_elem <- next end/insert-range
|
||||
break-unless next
|
||||
end <- copy next
|
||||
loop
|
||||
}
|
||||
next:address:duplex-list:_elem <- next in
|
||||
dest:address:address:duplex-list:_elem <- get-address *end, next:offset
|
||||
next:address:shared:duplex-list:_elem <- next in
|
||||
dest:address:address:shared:duplex-list:_elem <- get-address *end, next:offset
|
||||
*dest <- copy next
|
||||
{
|
||||
break-unless next
|
||||
|
@ -481,23 +481,23 @@ recipe insert-range in:address:duplex-list:_elem, start:address:duplex-list:_ele
|
|||
*dest <- copy in
|
||||
]
|
||||
|
||||
recipe append in:address:duplex-list:_elem, new:address:duplex-list:_elem/contained-in:in -> in:address:duplex-list:_elem [
|
||||
recipe append in:address:shared:duplex-list:_elem, new:address:shared:duplex-list:_elem/contained-in:in -> in:address:shared:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
last:address:duplex-list:_elem <- last in
|
||||
dest:address:address:duplex-list:_elem <- get-address *last, next:offset
|
||||
last:address:shared:duplex-list:_elem <- last in
|
||||
dest:address:address:shared:duplex-list:_elem <- get-address *last, next:offset
|
||||
*dest <- copy new
|
||||
reply-unless new
|
||||
dest <- get-address *new, prev:offset
|
||||
*dest <- copy last
|
||||
]
|
||||
|
||||
recipe last in:address:duplex-list:_elem -> result:address:duplex-list:_elem [
|
||||
recipe last in:address:shared:duplex-list:_elem -> result:address:shared:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- copy in
|
||||
{
|
||||
next:address:duplex-list:_elem <- next result
|
||||
next:address:shared:duplex-list:_elem <- next result
|
||||
break-unless next
|
||||
result <- copy next
|
||||
loop
|
||||
|
@ -505,7 +505,7 @@ recipe last in:address:duplex-list:_elem -> result:address:duplex-list:_elem [
|
|||
]
|
||||
|
||||
# helper for debugging
|
||||
recipe dump-from x:address:duplex-list:_elem [
|
||||
recipe dump-from x:address:shared:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
$print x, [: ]
|
||||
|
|
16
076stream.mu
16
076stream.mu
|
@ -1,41 +1,41 @@
|
|||
# new type to help incrementally read texts (arrays of characters)
|
||||
container stream [
|
||||
index:number
|
||||
data:address:array:character
|
||||
data:address:shared:array:character
|
||||
]
|
||||
|
||||
recipe new-stream s:address:array:character -> result:address:stream [
|
||||
recipe new-stream s:address:shared:array:character -> result:address:shared:stream [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- new stream:type
|
||||
i:address:number <- get-address *result, index:offset
|
||||
*i <- copy 0
|
||||
d:address:address:array:character <- get-address *result, data:offset
|
||||
d:address:address:shared:array:character <- get-address *result, data:offset
|
||||
*d <- copy s
|
||||
]
|
||||
|
||||
recipe rewind-stream in:address:stream -> in:address:stream [
|
||||
recipe rewind-stream in:address:shared:stream -> in:address:shared:stream [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:address:number <- get-address *in, index:offset
|
||||
*x <- copy 0
|
||||
]
|
||||
|
||||
recipe read-line in:address:stream -> result:address:array:character, in:address:stream [
|
||||
recipe read-line in:address:shared:stream -> result:address:shared:array:character, in:address:shared:stream [
|
||||
local-scope
|
||||
load-ingredients
|
||||
idx:address:number <- get-address *in, index:offset
|
||||
s:address:array:character <- get *in, data:offset
|
||||
s:address:shared:array:character <- get *in, data:offset
|
||||
next-idx:number <- find-next s, 10/newline, *idx
|
||||
result <- copy-range s, *idx, next-idx
|
||||
*idx <- add next-idx, 1 # skip newline
|
||||
]
|
||||
|
||||
recipe end-of-stream? in:address:stream -> result:boolean [
|
||||
recipe end-of-stream? in:address:shared:stream -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
idx:number <- get *in, index:offset
|
||||
s:address:array:character <- get *in, data:offset
|
||||
s:address:shared:array:character <- get *in, data:offset
|
||||
len:number <- length *s
|
||||
result <- greater-or-equal idx, len
|
||||
]
|
||||
|
|
184
081print.mu
184
081print.mu
|
@ -6,7 +6,7 @@ container screen [
|
|||
num-columns:number
|
||||
cursor-row:number
|
||||
cursor-column:number
|
||||
data:address:array:screen-cell
|
||||
data:address:shared:array:screen-cell
|
||||
]
|
||||
|
||||
container screen-cell [
|
||||
|
@ -14,7 +14,7 @@ container screen-cell [
|
|||
color:number
|
||||
]
|
||||
|
||||
recipe new-fake-screen w:number, h:number -> result:address:screen [
|
||||
recipe new-fake-screen w:number, h:number -> result:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- new screen:type
|
||||
|
@ -27,19 +27,19 @@ recipe new-fake-screen w:number, h:number -> result:address:screen [
|
|||
column:address:number <- get-address *result, cursor-column:offset
|
||||
*column <- copy 0
|
||||
bufsize:number <- multiply *width, *height
|
||||
buf:address:address:array:screen-cell <- get-address *result, data:offset
|
||||
buf:address:address:shared:array:screen-cell <- get-address *result, data:offset
|
||||
*buf <- new screen-cell:type, bufsize
|
||||
result <- clear-screen result
|
||||
]
|
||||
|
||||
recipe clear-screen screen:address:screen -> screen:address:screen [
|
||||
recipe clear-screen screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists
|
||||
{
|
||||
break-unless screen
|
||||
# clear fake screen
|
||||
buf:address:array:screen-cell <- get *screen, data:offset
|
||||
buf:address:shared:array:screen-cell <- get *screen, data:offset
|
||||
max:number <- length *buf
|
||||
i:number <- copy 0
|
||||
{
|
||||
|
@ -64,7 +64,7 @@ recipe clear-screen screen:address:screen -> screen:address:screen [
|
|||
clear-display
|
||||
]
|
||||
|
||||
recipe sync-screen screen:address:screen -> screen:address:screen [
|
||||
recipe sync-screen screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -74,11 +74,11 @@ recipe sync-screen screen:address:screen -> screen:address:screen [
|
|||
# do nothing for fake screens
|
||||
]
|
||||
|
||||
recipe fake-screen-is-empty? screen:address:screen -> result:boolean [
|
||||
recipe fake-screen-is-empty? screen:address:shared:screen -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless screen, 1/true
|
||||
buf:address:array:screen-cell <- get *screen, data:offset
|
||||
buf:address:shared:array:screen-cell <- get *screen, data:offset
|
||||
i:number <- copy 0
|
||||
len:number <- length *buf
|
||||
{
|
||||
|
@ -94,7 +94,7 @@ recipe fake-screen-is-empty? screen:address:screen -> result:boolean [
|
|||
reply 1/true
|
||||
]
|
||||
|
||||
recipe print screen:address:screen, c:character -> screen:address:screen [
|
||||
recipe print screen:address:shared:screen, c:character -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
color:number, color-found?:boolean <- next-ingredient
|
||||
|
@ -145,7 +145,7 @@ recipe print screen:address:screen, c:character -> screen:address:screen [
|
|||
# save character in fake screen
|
||||
index:number <- multiply *row, width
|
||||
index <- add index, *column
|
||||
buf:address:array:screen-cell <- get *screen, data:offset
|
||||
buf:address:shared:array:screen-cell <- get *screen, data:offset
|
||||
len:number <- length *buf
|
||||
# special-case: backspace
|
||||
{
|
||||
|
@ -186,11 +186,11 @@ recipe print screen:address:screen, c:character -> screen:address:screen [
|
|||
|
||||
scenario print-character-at-top-left [
|
||||
run [
|
||||
1:address:screen <- new-fake-screen 3/width, 2/height
|
||||
1:address:shared:screen <- new-fake-screen 3/width, 2/height
|
||||
11:character <- copy 97/a
|
||||
1:address:screen <- print 1:address:screen, 11:character/a
|
||||
2:address:array:screen-cell <- get *1:address:screen, data:offset
|
||||
3:array:screen-cell <- copy *2:address:array:screen-cell
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 11:character/a
|
||||
2:address:shared:array:screen-cell <- get *1:address:shared:screen, data:offset
|
||||
3:array:screen-cell <- copy *2:address:shared:array:screen-cell
|
||||
]
|
||||
memory-should-contain [
|
||||
3 <- 6 # width*height
|
||||
|
@ -202,11 +202,11 @@ scenario print-character-at-top-left [
|
|||
|
||||
scenario print-character-in-color [
|
||||
run [
|
||||
1:address:screen <- new-fake-screen 3/width, 2/height
|
||||
1:address:shared:screen <- new-fake-screen 3/width, 2/height
|
||||
11:character <- copy 97/a
|
||||
1:address:screen <- print 1:address:screen, 11:character/a, 1/red
|
||||
2:address:array:screen-cell <- get *1:address:screen, data:offset
|
||||
3:array:screen-cell <- copy *2:address:array:screen-cell
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 11:character/a, 1/red
|
||||
2:address:shared:array:screen-cell <- get *1:address:shared:screen, data:offset
|
||||
3:array:screen-cell <- copy *2:address:shared:array:screen-cell
|
||||
]
|
||||
memory-should-contain [
|
||||
3 <- 6 # width*height
|
||||
|
@ -218,14 +218,14 @@ scenario print-character-in-color [
|
|||
|
||||
scenario print-backspace-character [
|
||||
run [
|
||||
1:address:screen <- new-fake-screen 3/width, 2/height
|
||||
1:address:shared:screen <- new-fake-screen 3/width, 2/height
|
||||
11:character <- copy 97/a
|
||||
1:address:screen <- print 1:address:screen, 11:character/a
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 11:character/a
|
||||
12:character <- copy 8/backspace
|
||||
1:address:screen <- print 1:address:screen, 12:character/backspace
|
||||
2:number <- get *1:address:screen, cursor-column:offset
|
||||
3:address:array:screen-cell <- get *1:address:screen, data:offset
|
||||
4:array:screen-cell <- copy *3:address:array:screen-cell
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 12:character/backspace
|
||||
2:number <- get *1:address:shared:screen, cursor-column:offset
|
||||
3:address:shared:array:screen-cell <- get *1:address:shared:screen, data:offset
|
||||
4:array:screen-cell <- copy *3:address:shared:array:screen-cell
|
||||
]
|
||||
memory-should-contain [
|
||||
2 <- 0 # cursor column
|
||||
|
@ -238,16 +238,16 @@ scenario print-backspace-character [
|
|||
|
||||
scenario print-extra-backspace-character [
|
||||
run [
|
||||
1:address:screen <- new-fake-screen 3/width, 2/height
|
||||
1:address:shared:screen <- new-fake-screen 3/width, 2/height
|
||||
11:character <- copy 97/a
|
||||
1:address:screen <- print 1:address:screen, 11:character/a
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 11:character/a
|
||||
12:character <- copy 8/backspace
|
||||
1:address:screen <- print 1:address:screen, 12:character/backspace
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 12:character/backspace
|
||||
12:character <- copy 8/backspace
|
||||
1:address:screen <- print 1:address:screen, 12:character/backspace
|
||||
2:number <- get *1:address:screen, cursor-column:offset
|
||||
3:address:array:screen-cell <- get *1:address:screen, data:offset
|
||||
4:array:screen-cell <- copy *3:address:array:screen-cell
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 12:character/backspace
|
||||
2:number <- get *1:address:shared:screen, cursor-column:offset
|
||||
3:address:shared:array:screen-cell <- get *1:address:shared:screen, data:offset
|
||||
4:array:screen-cell <- copy *3:address:shared:array:screen-cell
|
||||
]
|
||||
memory-should-contain [
|
||||
2 <- 0 # cursor column
|
||||
|
@ -260,16 +260,16 @@ scenario print-extra-backspace-character [
|
|||
|
||||
scenario print-character-at-right-margin [
|
||||
run [
|
||||
1:address:screen <- new-fake-screen 2/width, 2/height
|
||||
1:address:shared:screen <- new-fake-screen 2/width, 2/height
|
||||
11:character <- copy 97/a
|
||||
1:address:screen <- print 1:address:screen, 11:character/a
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 11:character/a
|
||||
12:character <- copy 98/b
|
||||
1:address:screen <- print 1:address:screen, 12:character/b
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 12:character/b
|
||||
13:character <- copy 99/b
|
||||
1:address:screen <- print 1:address:screen, 13:character/c
|
||||
2:number <- get *1:address:screen, cursor-column:offset
|
||||
3:address:array:screen-cell <- get *1:address:screen, data:offset
|
||||
4:array:screen-cell <- copy *3:address:array:screen-cell
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 13:character/c
|
||||
2:number <- get *1:address:shared:screen, cursor-column:offset
|
||||
3:address:shared:array:screen-cell <- get *1:address:shared:screen, data:offset
|
||||
4:array:screen-cell <- copy *3:address:shared:array:screen-cell
|
||||
]
|
||||
memory-should-contain [
|
||||
2 <- 1 # cursor column
|
||||
|
@ -284,15 +284,15 @@ scenario print-character-at-right-margin [
|
|||
|
||||
scenario print-newline-character [
|
||||
run [
|
||||
1:address:screen <- new-fake-screen 3/width, 2/height
|
||||
1:address:shared:screen <- new-fake-screen 3/width, 2/height
|
||||
10:character <- copy 10/newline
|
||||
11:character <- copy 97/a
|
||||
1:address:screen <- print 1:address:screen, 11:character/a
|
||||
1:address:screen <- print 1:address:screen, 10:character/newline
|
||||
2:number <- get *1:address:screen, cursor-row:offset
|
||||
3:number <- get *1:address:screen, cursor-column:offset
|
||||
4:address:array:screen-cell <- get *1:address:screen, data:offset
|
||||
5:array:screen-cell <- copy *4:address:array:screen-cell
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 11:character/a
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 10:character/newline
|
||||
2:number <- get *1:address:shared:screen, cursor-row:offset
|
||||
3:number <- get *1:address:shared:screen, cursor-column:offset
|
||||
4:address:shared:array:screen-cell <- get *1:address:shared:screen, data:offset
|
||||
5:array:screen-cell <- copy *4:address:shared:array:screen-cell
|
||||
]
|
||||
memory-should-contain [
|
||||
2 <- 1 # cursor row
|
||||
|
@ -306,13 +306,13 @@ scenario print-newline-character [
|
|||
|
||||
scenario print-newline-at-bottom-line [
|
||||
run [
|
||||
1:address:screen <- new-fake-screen 3/width, 2/height
|
||||
1:address:shared:screen <- new-fake-screen 3/width, 2/height
|
||||
10:character <- copy 10/newline
|
||||
1:address:screen <- print 1:address:screen, 10:character/newline
|
||||
1:address:screen <- print 1:address:screen, 10:character/newline
|
||||
1:address:screen <- print 1:address:screen, 10:character/newline
|
||||
2:number <- get *1:address:screen, cursor-row:offset
|
||||
3:number <- get *1:address:screen, cursor-column:offset
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 10:character/newline
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 10:character/newline
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 10:character/newline
|
||||
2:number <- get *1:address:shared:screen, cursor-row:offset
|
||||
3:number <- get *1:address:shared:screen, cursor-column:offset
|
||||
]
|
||||
memory-should-contain [
|
||||
2 <- 1 # cursor row
|
||||
|
@ -322,22 +322,22 @@ scenario print-newline-at-bottom-line [
|
|||
|
||||
scenario print-character-at-bottom-right [
|
||||
run [
|
||||
1:address:screen <- new-fake-screen 2/width, 2/height
|
||||
1:address:shared:screen <- new-fake-screen 2/width, 2/height
|
||||
10:character <- copy 10/newline
|
||||
1:address:screen <- print 1:address:screen, 10:character/newline
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 10:character/newline
|
||||
11:character <- copy 97/a
|
||||
1:address:screen <- print 1:address:screen, 11:character/a
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 11:character/a
|
||||
12:character <- copy 98/b
|
||||
1:address:screen <- print 1:address:screen, 12:character/b
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 12:character/b
|
||||
13:character <- copy 99/c
|
||||
1:address:screen <- print 1:address:screen, 13:character/c
|
||||
1:address:screen <- print 1:address:screen, 10:character/newline
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 13:character/c
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 10:character/newline
|
||||
14:character <- copy 100/d
|
||||
1:address:screen <- print 1:address:screen, 14:character/d
|
||||
2:number <- get *1:address:screen, cursor-row:offset
|
||||
3:number <- get *1:address:screen, cursor-column:offset
|
||||
4:address:array:screen-cell <- get *1:address:screen, data:offset
|
||||
20:array:screen-cell <- copy *4:address:array:screen-cell
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 14:character/d
|
||||
2:number <- get *1:address:shared:screen, cursor-row:offset
|
||||
3:number <- get *1:address:shared:screen, cursor-column:offset
|
||||
4:address:shared:array:screen-cell <- get *1:address:shared:screen, data:offset
|
||||
20:array:screen-cell <- copy *4:address:shared:array:screen-cell
|
||||
]
|
||||
memory-should-contain [
|
||||
2 <- 1 # cursor row
|
||||
|
@ -355,7 +355,7 @@ scenario print-character-at-bottom-right [
|
|||
]
|
||||
]
|
||||
|
||||
recipe clear-line screen:address:screen -> screen:address:screen [
|
||||
recipe clear-line screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
space:character <- copy 0/nul
|
||||
|
@ -381,7 +381,7 @@ recipe clear-line screen:address:screen -> screen:address:screen [
|
|||
clear-line-on-display
|
||||
]
|
||||
|
||||
recipe cursor-position screen:address:screen -> row:number, column:number [
|
||||
recipe cursor-position screen:address:shared:screen -> row:number, column:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, lookup cursor in fake screen
|
||||
|
@ -394,7 +394,7 @@ recipe cursor-position screen:address:screen -> row:number, column:number [
|
|||
row, column <- cursor-position-on-display
|
||||
]
|
||||
|
||||
recipe move-cursor screen:address:screen, new-row:number, new-column:number -> screen:address:screen [
|
||||
recipe move-cursor screen:address:shared:screen, new-row:number, new-column:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -412,16 +412,16 @@ recipe move-cursor screen:address:screen, new-row:number, new-column:number -> s
|
|||
|
||||
scenario clear-line-erases-printed-characters [
|
||||
run [
|
||||
1:address:screen <- new-fake-screen 3/width, 2/height
|
||||
1:address:shared:screen <- new-fake-screen 3/width, 2/height
|
||||
# print a character
|
||||
10:character <- copy 97/a
|
||||
1:address:screen <- print 1:address:screen, 10:character/a
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 10:character/a
|
||||
# move cursor to start of line
|
||||
1:address:screen <- move-cursor 1:address:screen, 0/row, 0/column
|
||||
1:address:shared:screen <- move-cursor 1:address:shared:screen, 0/row, 0/column
|
||||
# clear line
|
||||
1:address:screen <- clear-line 1:address:screen
|
||||
2:address:array:screen-cell <- get *1:address:screen, data:offset
|
||||
20:array:screen-cell <- copy *2:address:array:screen-cell
|
||||
1:address:shared:screen <- clear-line 1:address:shared:screen
|
||||
2:address:shared:array:screen-cell <- get *1:address:shared:screen, data:offset
|
||||
20:array:screen-cell <- copy *2:address:shared:array:screen-cell
|
||||
]
|
||||
# screen should be blank
|
||||
memory-should-contain [
|
||||
|
@ -441,7 +441,7 @@ scenario clear-line-erases-printed-characters [
|
|||
]
|
||||
]
|
||||
|
||||
recipe cursor-down screen:address:screen -> screen:address:screen [
|
||||
recipe cursor-down screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -462,7 +462,7 @@ recipe cursor-down screen:address:screen -> screen:address:screen [
|
|||
move-cursor-down-on-display
|
||||
]
|
||||
|
||||
recipe cursor-up screen:address:screen -> screen:address:screen [
|
||||
recipe cursor-up screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -481,7 +481,7 @@ recipe cursor-up screen:address:screen -> screen:address:screen [
|
|||
move-cursor-up-on-display
|
||||
]
|
||||
|
||||
recipe cursor-right screen:address:screen -> screen:address:screen [
|
||||
recipe cursor-right screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -502,7 +502,7 @@ recipe cursor-right screen:address:screen -> screen:address:screen [
|
|||
move-cursor-right-on-display
|
||||
]
|
||||
|
||||
recipe cursor-left screen:address:screen -> screen:address:screen [
|
||||
recipe cursor-left screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -521,7 +521,7 @@ recipe cursor-left screen:address:screen -> screen:address:screen [
|
|||
move-cursor-left-on-display
|
||||
]
|
||||
|
||||
recipe cursor-to-start-of-line screen:address:screen -> screen:address:screen [
|
||||
recipe cursor-to-start-of-line screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
row:number <- cursor-position screen
|
||||
|
@ -529,14 +529,14 @@ recipe cursor-to-start-of-line screen:address:screen -> screen:address:screen [
|
|||
screen <- move-cursor screen, row, column
|
||||
]
|
||||
|
||||
recipe cursor-to-next-line screen:address:screen -> screen:address:screen [
|
||||
recipe cursor-to-next-line screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
screen <- cursor-down screen
|
||||
screen <- cursor-to-start-of-line screen
|
||||
]
|
||||
|
||||
recipe screen-width screen:address:screen -> width:number [
|
||||
recipe screen-width screen:address:shared:screen -> width:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -549,7 +549,7 @@ recipe screen-width screen:address:screen -> width:number [
|
|||
width <- display-width
|
||||
]
|
||||
|
||||
recipe screen-height screen:address:screen -> height:number [
|
||||
recipe screen-height screen:address:shared:screen -> height:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -562,7 +562,7 @@ recipe screen-height screen:address:screen -> height:number [
|
|||
height <- display-height
|
||||
]
|
||||
|
||||
recipe hide-cursor screen:address:screen -> screen:address:screen [
|
||||
recipe hide-cursor screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists (not real display), do nothing
|
||||
|
@ -574,7 +574,7 @@ recipe hide-cursor screen:address:screen -> screen:address:screen [
|
|||
hide-cursor-on-display
|
||||
]
|
||||
|
||||
recipe show-cursor screen:address:screen -> screen:address:screen [
|
||||
recipe show-cursor screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists (not real display), do nothing
|
||||
|
@ -586,7 +586,7 @@ recipe show-cursor screen:address:screen -> screen:address:screen [
|
|||
show-cursor-on-display
|
||||
]
|
||||
|
||||
recipe hide-screen screen:address:screen -> screen:address:screen [
|
||||
recipe hide-screen screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists (not real display), do nothing
|
||||
|
@ -599,7 +599,7 @@ recipe hide-screen screen:address:screen -> screen:address:screen [
|
|||
hide-display
|
||||
]
|
||||
|
||||
recipe show-screen screen:address:screen -> screen:address:screen [
|
||||
recipe show-screen screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists (not real display), do nothing
|
||||
|
@ -612,7 +612,7 @@ recipe show-screen screen:address:screen -> screen:address:screen [
|
|||
show-display
|
||||
]
|
||||
|
||||
recipe print screen:address:screen, s:address:array:character -> screen:address:screen [
|
||||
recipe print screen:address:shared:screen, s:address:shared:array:character -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
color:number, color-found?:boolean <- next-ingredient
|
||||
|
@ -641,11 +641,11 @@ recipe print screen:address:screen, s:address:array:character -> screen:address:
|
|||
|
||||
scenario print-text-stops-at-right-margin [
|
||||
run [
|
||||
1:address:screen <- new-fake-screen 3/width, 2/height
|
||||
2:address:array:character <- new [abcd]
|
||||
1:address:screen <- print 1:address:screen, 2:address:array:character
|
||||
3:address:array:screen-cell <- get *1:address:screen, data:offset
|
||||
4:array:screen-cell <- copy *3:address:array:screen-cell
|
||||
1:address:shared:screen <- new-fake-screen 3/width, 2/height
|
||||
2:address:shared:array:character <- new [abcd]
|
||||
1:address:shared:screen <- print 1:address:shared:screen, 2:address:shared:array:character
|
||||
3:address:shared:array:screen-cell <- get *1:address:shared:screen, data:offset
|
||||
4:array:screen-cell <- copy *3:address:shared:array:screen-cell
|
||||
]
|
||||
memory-should-contain [
|
||||
4 <- 6 # width*height
|
||||
|
@ -659,7 +659,7 @@ scenario print-text-stops-at-right-margin [
|
|||
]
|
||||
]
|
||||
|
||||
recipe print-integer screen:address:screen, n:number -> screen:address:screen [
|
||||
recipe print-integer screen:address:shared:screen, n:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
color:number, color-found?:boolean <- next-ingredient
|
||||
|
@ -675,12 +675,12 @@ recipe print-integer screen:address:screen, n:number -> screen:address:screen [
|
|||
bg-color <- copy 0/black
|
||||
}
|
||||
# todo: other bases besides decimal
|
||||
s:address:array:character <- to-text n
|
||||
s:address:shared:array:character <- to-text n
|
||||
screen <- print screen, s, color, bg-color
|
||||
]
|
||||
|
||||
# for now, we can only print integers
|
||||
recipe print screen:address:screen, n:number -> screen:address:screen [
|
||||
recipe print screen:address:shared:screen, n:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
screen <- print-integer screen, n
|
||||
|
|
|
@ -10,7 +10,7 @@ scenario screen-in-scenario [
|
|||
assume-screen 5/width, 3/height
|
||||
run [
|
||||
1:character <- copy 97/a
|
||||
screen:address:screen <- print screen:address:screen, 1:character/a
|
||||
screen:address:shared:screen <- print screen:address:shared:screen, 1:character/a
|
||||
]
|
||||
screen-should-contain [
|
||||
# 01234
|
||||
|
@ -25,9 +25,9 @@ scenario screen-in-scenario-unicode-color [
|
|||
assume-screen 5/width, 3/height
|
||||
run [
|
||||
1:character <- copy 955/greek-small-lambda
|
||||
screen:address:screen <- print screen:address:screen, 1:character/lambda, 1/red
|
||||
screen:address:shared:screen <- print screen:address:shared:screen, 1:character/lambda, 1/red
|
||||
2:character <- copy 97/a
|
||||
screen:address:screen <- print screen:address:screen, 2:character/a
|
||||
screen:address:shared:screen <- print screen:address:shared:screen, 2:character/a
|
||||
]
|
||||
screen-should-contain [
|
||||
# 01234
|
||||
|
@ -43,9 +43,9 @@ scenario screen-in-scenario-color [
|
|||
assume-screen 5/width, 3/height
|
||||
run [
|
||||
1:character <- copy 955/greek-small-lambda
|
||||
screen:address:screen <- print screen:address:screen, 1:character/lambda, 1/red
|
||||
screen:address:shared:screen <- print screen:address:shared:screen, 1:character/lambda, 1/red
|
||||
2:character <- copy 97/a
|
||||
screen:address:screen <- print screen:address:screen, 2:character/a, 7/white
|
||||
screen:address:shared:screen <- print screen:address:shared:screen, 2:character/a, 7/white
|
||||
]
|
||||
# screen-should-contain shows everything
|
||||
screen-should-contain [
|
||||
|
@ -78,7 +78,7 @@ scenario screen-in-scenario-error [
|
|||
assume-screen 5/width, 3/height
|
||||
run [
|
||||
1:character <- copy 97/a
|
||||
screen:address:screen <- print screen:address:screen, 1:character/a
|
||||
screen:address:shared:screen <- print screen:address:shared:screen, 1:character/a
|
||||
]
|
||||
screen-should-contain [
|
||||
# 01234
|
||||
|
@ -97,7 +97,7 @@ scenario screen-in-scenario-color [
|
|||
assume-screen 5/width, 3/height
|
||||
run [
|
||||
1:character <- copy 97/a
|
||||
screen:address:screen <- print screen:address:screen, 1:character/a, 1/red
|
||||
screen:address:shared:screen <- print screen:address:shared:screen, 1:character/a, 1/red
|
||||
]
|
||||
screen-should-contain-in-color 2/green, [
|
||||
# 01234
|
||||
|
@ -146,11 +146,11 @@ Name[r]["screen"] = SCREEN;
|
|||
|
||||
:(before "End Rewrite Instruction(curr, recipe result)")
|
||||
// rewrite `assume-screen width, height` to
|
||||
// `screen:address:screen <- new-fake-screen width, height`
|
||||
// `screen:address:shared:screen <- new-fake-screen width, height`
|
||||
if (curr.name == "assume-screen") {
|
||||
curr.name = "new-fake-screen";
|
||||
assert(curr.products.empty());
|
||||
curr.products.push_back(reagent("screen:address:screen"));
|
||||
curr.products.push_back(reagent("screen:address:shared:screen"));
|
||||
curr.products.at(0).set_value(SCREEN);
|
||||
}
|
||||
|
||||
|
@ -210,7 +210,7 @@ void check_screen(const string& expected_contents, const int color) {
|
|||
long long int screen_location = get_or_insert(Memory, SCREEN);
|
||||
int data_offset = find_element_name(get(Type_ordinal, "screen"), "data", "");
|
||||
assert(data_offset >= 0);
|
||||
long long int screen_data_location = screen_location+data_offset; // type: address:array:character
|
||||
long long int screen_data_location = screen_location+data_offset; // type: address:shared:array:character
|
||||
long long int screen_data_start = get_or_insert(Memory, screen_data_location); // type: array:character
|
||||
int width_offset = find_element_name(get(Type_ordinal, "screen"), "num-columns", "");
|
||||
long long int screen_width = get_or_insert(Memory, screen_location+width_offset);
|
||||
|
@ -349,7 +349,7 @@ void dump_screen() {
|
|||
long long int screen_height = get_or_insert(Memory, screen_location+height_offset);
|
||||
int data_offset = find_element_name(get(Type_ordinal, "screen"), "data", "");
|
||||
assert(data_offset >= 0);
|
||||
long long int screen_data_location = screen_location+data_offset; // type: address:array:character
|
||||
long long int screen_data_location = screen_location+data_offset; // type: address:shared:array:character
|
||||
long long int screen_data_start = get_or_insert(Memory, screen_data_location); // type: array:character
|
||||
assert(get_or_insert(Memory, screen_data_start) == screen_width*screen_height);
|
||||
long long int curr = screen_data_start+1; // skip length
|
||||
|
|
|
@ -4,7 +4,7 @@ scenario print-character-at-top-left-2 [
|
|||
assume-screen 3/width, 2/height
|
||||
run [
|
||||
1:character <- copy 97/a
|
||||
screen:address:screen <- print screen:address:screen, 1:character/a
|
||||
screen:address:shared:screen <- print screen:address:shared:screen, 1:character/a
|
||||
]
|
||||
screen-should-contain [
|
||||
.a .
|
||||
|
@ -17,11 +17,11 @@ scenario clear-line-erases-printed-characters-2 [
|
|||
run [
|
||||
# print a character
|
||||
1:character <- copy 97/a
|
||||
screen:address:screen <- print screen:address:screen, 1:character/a
|
||||
screen:address:shared:screen <- print screen:address:shared:screen, 1:character/a
|
||||
# move cursor to start of line
|
||||
screen:address:screen <- move-cursor screen:address:screen, 0/row, 0/column
|
||||
screen:address:shared:screen <- move-cursor screen:address:shared:screen, 0/row, 0/column
|
||||
# clear line
|
||||
screen:address:screen <- clear-line screen:address:screen
|
||||
screen:address:shared:screen <- clear-line screen:address:shared:screen
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
|
|
@ -22,31 +22,31 @@ container resize-event [
|
|||
|
||||
container console [
|
||||
current-event-index:number
|
||||
events:address:array:event
|
||||
events:address:shared:array:event
|
||||
]
|
||||
|
||||
recipe new-fake-console events:address:array:event -> result:address:console [
|
||||
recipe new-fake-console events:address:shared:array:event -> result:address:shared:console [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result:address:console <- new console:type
|
||||
buf:address:address:array:event <- get-address *result, events:offset
|
||||
result:address:shared:console <- new console:type
|
||||
buf:address:address:shared:array:event <- get-address *result, events:offset
|
||||
*buf <- copy events
|
||||
idx:address:number <- get-address *result, current-event-index:offset
|
||||
*idx <- copy 0
|
||||
]
|
||||
|
||||
recipe read-event console:address:console -> result:event, console:address:console, found?:boolean, quit?:boolean [
|
||||
recipe read-event console:address:shared:console -> result:event, console:address:shared:console, found?:boolean, quit?:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
break-unless console
|
||||
current-event-index:address:number <- get-address *console, current-event-index:offset
|
||||
buf:address:array:event <- get *console, events:offset
|
||||
buf:address:shared:array:event <- get *console, events:offset
|
||||
{
|
||||
max:number <- length *buf
|
||||
done?:boolean <- greater-or-equal *current-event-index, max
|
||||
break-unless done?
|
||||
dummy:address:event <- new event:type
|
||||
dummy:address:shared:event <- new event:type
|
||||
reply *dummy, console/same-as-ingredient:0, 1/found, 1/quit
|
||||
}
|
||||
result <- index *buf, *current-event-index
|
||||
|
@ -61,7 +61,7 @@ recipe read-event console:address:console -> result:event, console:address:conso
|
|||
# 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..
|
||||
recipe read-key console:address:console -> result:character, console:address:console, found?:boolean, quit?:boolean [
|
||||
recipe read-key console:address:shared:console -> result:character, console:address:shared:console, found?:boolean, quit?:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:event, console, found?:boolean, quit?:boolean <- read-event console
|
||||
|
@ -72,7 +72,7 @@ recipe read-key console:address:console -> result:character, console:address:con
|
|||
reply *c, console/same-as-ingredient:0, 1/found, 0/quit
|
||||
]
|
||||
|
||||
recipe send-keys-to-channel console:address:console, chan:address:channel, screen:address:screen -> console:address:console, chan:address:channel, screen:address:screen [
|
||||
recipe send-keys-to-channel console:address:shared:console, chan:address:shared:channel, screen:address:shared:screen -> console:address:shared:console, chan:address:shared:channel, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -86,7 +86,7 @@ recipe send-keys-to-channel console:address:console, chan:address:channel, scree
|
|||
}
|
||||
]
|
||||
|
||||
recipe wait-for-event console:address:console -> console:address:console [
|
||||
recipe wait-for-event console:address:shared:console -> console:address:shared:console [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -96,7 +96,7 @@ recipe wait-for-event console:address:console -> console:address:console [
|
|||
]
|
||||
|
||||
# use this helper to skip rendering if there's lots of other events queued up
|
||||
recipe has-more-events? console:address:console -> result:boolean [
|
||||
recipe has-more-events? console:address:shared:console -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
|
|
@ -11,10 +11,10 @@ scenario keyboard-in-scenario [
|
|||
type [abc]
|
||||
]
|
||||
run [
|
||||
1:character, console:address:console, 2:boolean <- read-key console:address:console
|
||||
3:character, console:address:console, 4:boolean <- read-key console:address:console
|
||||
5:character, console:address:console, 6:boolean <- read-key console:address:console
|
||||
7:character, console:address:console, 8:boolean, 9:boolean <- read-key console:address:console
|
||||
1:character, console:address:shared:console, 2:boolean <- read-key console:address:shared:console
|
||||
3:character, console:address:shared:console, 4:boolean <- read-key console:address:shared:console
|
||||
5:character, console:address:shared:console, 6:boolean <- read-key console:address:shared:console
|
||||
7:character, console:address:shared:console, 8:boolean, 9:boolean <- read-key console:address:shared:console
|
||||
]
|
||||
memory-should-contain [
|
||||
1 <- 97 # 'a'
|
||||
|
@ -184,15 +184,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:address:shared:console
|
||||
5:event <- read-event console:address:shared:console
|
||||
9:event <- read-event console:address:shared:console
|
||||
# mouse click
|
||||
13:event <- read-event console:address:console
|
||||
13:event <- read-event console:address:shared:console
|
||||
# non-character keycode
|
||||
17:event <- read-event console:address:console
|
||||
17:event <- read-event console:address:shared:console
|
||||
# final keyboard event
|
||||
21:event <- read-event console:address:console
|
||||
21:event <- read-event console:address:shared:console
|
||||
]
|
||||
memory-should-contain [
|
||||
1 <- 0 # 'text'
|
||||
|
|
|
@ -7,10 +7,10 @@ scenario read-key-in-mu [
|
|||
type [abc]
|
||||
]
|
||||
run [
|
||||
1:character, console:address:console, 2:boolean <- read-key console:address:console
|
||||
3:character, console:address:console, 4:boolean <- read-key console:address:console
|
||||
5:character, console:address:console, 6:boolean <- read-key console:address:console
|
||||
7:character, console:address:console, 8:boolean <- read-key console:address:console
|
||||
1:character, console:address:shared:console, 2:boolean <- read-key console:address:shared:console
|
||||
3:character, console:address:shared:console, 4:boolean <- read-key console:address:shared:console
|
||||
5:character, console:address:shared:console, 6:boolean <- read-key console:address:shared:console
|
||||
7:character, console:address:shared:console, 8:boolean <- read-key console:address:shared:console
|
||||
]
|
||||
memory-should-contain [
|
||||
1 <- 97 # 'a'
|
||||
|
|
|
@ -4,16 +4,16 @@
|
|||
:(scenario run_interactive_code)
|
||||
recipe main [
|
||||
1:number/raw <- copy 0
|
||||
2:address:array:character <- new [1:number/raw <- copy 34]
|
||||
run-interactive 2:address:array:character
|
||||
2:address:shared:array:character <- new [1:number/raw <- copy 34]
|
||||
run-interactive 2:address:shared:array:character
|
||||
3:number/raw <- copy 1:number/raw
|
||||
]
|
||||
+mem: storing 34 in location 3
|
||||
|
||||
:(scenario run_interactive_empty)
|
||||
recipe main [
|
||||
1:address:array:character <- copy 0/unsafe
|
||||
2:address:array:character <- run-interactive 1:address:array:character
|
||||
1:address:shared:array:character <- copy 0/unsafe
|
||||
2:address:shared:array:character <- run-interactive 1:address:shared:array:character
|
||||
]
|
||||
# result is null
|
||||
+mem: storing 0 in location 2
|
||||
|
@ -88,7 +88,7 @@ bool run_interactive(long long int address) {
|
|||
// call run(string) but without the scheduling
|
||||
load(string("recipe! interactive [\n") +
|
||||
"local-scope\n" +
|
||||
"screen:address:screen <- next-ingredient\n" +
|
||||
"screen:address:shared:screen <- next-ingredient\n" +
|
||||
"$start-tracking-products\n" +
|
||||
command + "\n" +
|
||||
"$stop-tracking-products\n" +
|
||||
|
@ -153,15 +153,15 @@ load(string(
|
|||
"]\n" +
|
||||
"recipe sandbox [\n" +
|
||||
"local-scope\n" +
|
||||
"screen:address:screen/shared <- new-fake-screen 30, 5\n" +
|
||||
"screen:address:shared:screen <- new-fake-screen 30, 5\n" +
|
||||
"r:number/routine_id <- start-running interactive, screen\n" +
|
||||
"limit-time r, 100000/instructions\n" +
|
||||
"wait-for-routine r\n" +
|
||||
"sandbox-state:number <- routine-state r/routine_id\n" +
|
||||
"completed?:boolean <- equal sandbox-state, 1/completed\n" +
|
||||
"output:address:array:character <- $most-recent-products\n" +
|
||||
"warnings:address:array:character <- save-errors-warnings\n" +
|
||||
"stashes:address:array:character <- save-app-trace\n" +
|
||||
"output:address:shared:array:character <- $most-recent-products\n" +
|
||||
"warnings:address:shared:array:character <- save-errors-warnings\n" +
|
||||
"stashes:address:shared:array:character <- save-app-trace\n" +
|
||||
"$cleanup-run-interactive\n" +
|
||||
"reply output, warnings, screen, stashes, completed?\n" +
|
||||
"]\n");
|
||||
|
@ -174,10 +174,10 @@ Recently_added_recipes.clear();
|
|||
|
||||
:(scenario run_interactive_comments)
|
||||
recipe main [
|
||||
1:address:array:character <- new [# ab
|
||||
1:address:shared:array:character <- new [# ab
|
||||
add 2, 2]
|
||||
2:address:array:character <- run-interactive 1:address:array:character
|
||||
3:array:character <- copy *2:address:array:character
|
||||
2:address:shared:array:character <- run-interactive 1:address:shared:array:character
|
||||
3:array:character <- copy *2:address:shared:array:character
|
||||
]
|
||||
+mem: storing 52 in location 4
|
||||
|
||||
|
@ -271,9 +271,9 @@ case _CLEANUP_RUN_INTERACTIVE: {
|
|||
:(scenario "run_interactive_converts_result_to_text")
|
||||
recipe main [
|
||||
# try to interactively add 2 and 2
|
||||
1:address:array:character <- new [add 2, 2]
|
||||
2:address:array:character <- run-interactive 1:address:array:character
|
||||
10:array:character <- copy 2:address:array:character/lookup
|
||||
1:address:shared:array:character <- new [add 2, 2]
|
||||
2:address:shared:array:character <- run-interactive 1:address:shared:array:character
|
||||
10:array:character <- copy 2:address:shared:array:character/lookup
|
||||
]
|
||||
# first letter in the output should be '4' in unicode
|
||||
+mem: storing 52 in location 11
|
||||
|
@ -281,13 +281,13 @@ recipe main [
|
|||
:(scenario "run_interactive_returns_text")
|
||||
recipe main [
|
||||
# try to interactively add 2 and 2
|
||||
1:address:array:character <- new [
|
||||
x:address:array:character <- new [a]
|
||||
y:address:array:character <- new [b]
|
||||
z:address:array:character <- append x:address:array:character, y:address:array:character
|
||||
1:address:shared:array:character <- new [
|
||||
x:address:shared:array:character <- new [a]
|
||||
y:address:shared:array:character <- new [b]
|
||||
z:address:shared:array:character <- append x:address:shared:array:character, y:address:shared:array:character
|
||||
]
|
||||
2:address:array:character <- run-interactive 1:address:array:character
|
||||
10:array:character <- copy 2:address:array:character/lookup
|
||||
2:address:shared:array:character <- run-interactive 1:address:shared:array:character
|
||||
10:array:character <- copy 2:address:shared:array:character/lookup
|
||||
]
|
||||
# output contains "ab"
|
||||
+mem: storing 97 in location 11
|
||||
|
@ -296,10 +296,10 @@ recipe main [
|
|||
:(scenario "run_interactive_returns_errors")
|
||||
recipe main [
|
||||
# run a command that generates an error
|
||||
1:address:array:character <- new [x:number <- copy 34
|
||||
1:address:shared:array:character <- new [x:number <- copy 34
|
||||
get x:number, foo:offset]
|
||||
2:address:array:character, 3:address:array:character <- run-interactive 1:address:array:character
|
||||
10:array:character <- copy 3:address:array:character/lookup
|
||||
2:address:shared:array:character, 3:address:shared:array:character <- run-interactive 1:address:shared:array:character
|
||||
10:array:character <- copy 3:address:shared:array:character/lookup
|
||||
]
|
||||
# error should be "unknown element foo in container number"
|
||||
+mem: storing 117 in location 11
|
||||
|
@ -311,10 +311,10 @@ get x:number, foo:offset]
|
|||
:(scenario run_interactive_with_comment)
|
||||
recipe main [
|
||||
# 2 instructions, with a comment after the first
|
||||
1:address:array:number <- new [a:number <- copy 0 # abc
|
||||
1:address:shared:array:number <- new [a:number <- copy 0 # abc
|
||||
b:number <- copy 0
|
||||
]
|
||||
2:address:array:character, 3:address:array:character <- run-interactive 1:address:array:character
|
||||
2:address:shared:array:character, 3:address:shared:array:character <- run-interactive 1:address:shared:array:character
|
||||
]
|
||||
# no errors
|
||||
+mem: storing 0 in location 3
|
||||
|
@ -331,8 +331,8 @@ void test_run_interactive_cleans_up_any_created_specializations() {
|
|||
// run-interactive a call that specializes this recipe
|
||||
run("recipe main [\n"
|
||||
" 1:number/raw <- copy 0\n"
|
||||
" 2:address:array:character <- new [foo 1:number/raw]\n"
|
||||
" run-interactive 2:address:array:character\n"
|
||||
" 2:address:shared:array:character <- new [foo 1:number/raw]\n"
|
||||
" run-interactive 2:address:shared:array:character\n"
|
||||
"]\n");
|
||||
assert(SIZE(Recently_added_recipes) == 2); // foo, main
|
||||
// check that number of variants doesn't change
|
||||
|
@ -504,7 +504,7 @@ case RELOAD: {
|
|||
:(scenario reload_continues_past_error)
|
||||
recipe main [
|
||||
local-scope
|
||||
x:address:array:character <- new [recipe foo [
|
||||
x:address:shared:array:character <- new [recipe foo [
|
||||
get 1234:number, foo:offset
|
||||
]]
|
||||
reload x
|
||||
|
@ -520,7 +520,7 @@ void test_reload_cleans_up_any_created_specializations() {
|
|||
// a call that specializes this recipe
|
||||
run("recipe main [\n"
|
||||
" local-scope\n"
|
||||
" x:address:array:character <- new [recipe foo x:_elem -> n:number [\n"
|
||||
" x:address:shared:array:character <- new [recipe foo x:_elem -> n:number [\n"
|
||||
"local-scope\n"
|
||||
"load-ingredients\n"
|
||||
"reply 34\n"
|
||||
|
|
10
channel.mu
10
channel.mu
|
@ -1,6 +1,6 @@
|
|||
# example program: communicating between routines using channels
|
||||
|
||||
recipe producer chan:address:channel -> chan:address:channel [
|
||||
recipe producer chan:address:shared:channel -> chan:address:shared:channel [
|
||||
# produce characters 1 to 5 on a channel
|
||||
local-scope
|
||||
load-ingredients
|
||||
|
@ -12,19 +12,19 @@ recipe producer chan:address:channel -> chan:address:channel [
|
|||
# other threads might get between these prints
|
||||
$print [produce: ], n, [
|
||||
]
|
||||
chan:address:channel <- write chan, n
|
||||
chan:address:shared:channel <- write chan, n
|
||||
n <- add n, 1
|
||||
loop
|
||||
}
|
||||
]
|
||||
|
||||
recipe consumer chan:address:channel -> chan:address:channel [
|
||||
recipe consumer chan:address:shared:channel -> chan:address:shared:channel [
|
||||
# consume and print integers from a channel
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
# read an integer from the channel
|
||||
n:character, chan:address:channel <- read chan
|
||||
n:character, chan:address:shared:channel <- read chan
|
||||
# other threads might get between these prints
|
||||
$print [consume: ], n:character, [
|
||||
]
|
||||
|
@ -34,7 +34,7 @@ recipe consumer chan:address:channel -> chan:address:channel [
|
|||
|
||||
recipe main [
|
||||
local-scope
|
||||
chan:address:channel <- new-channel 3
|
||||
chan:address:shared:channel <- new-channel 3
|
||||
# create two background 'routines' that communicate by a channel
|
||||
routine1:number <- start-running producer, chan
|
||||
routine2:number <- start-running consumer, chan
|
||||
|
|
119
chessboard.mu
119
chessboard.mu
|
@ -34,7 +34,7 @@ scenario print-board-and-read-move [
|
|||
]
|
||||
]
|
||||
run [
|
||||
screen:address:screen, console:address:console <- chessboard screen:address:screen, console:address:console
|
||||
screen:address:shared:screen, console:address:shared:console <- chessboard screen:address:shared:screen, console:address:shared:console
|
||||
# icon for the cursor
|
||||
screen <- print screen, 9251/␣
|
||||
]
|
||||
|
@ -66,18 +66,18 @@ scenario print-board-and-read-move [
|
|||
|
||||
## Here's how 'chessboard' is implemented.
|
||||
|
||||
recipe chessboard screen:address:screen, console:address:console -> screen:address:screen, console:address:console [
|
||||
recipe chessboard screen:address:shared:screen, console:address:shared:console -> screen:address:shared:screen, console:address:shared:console [
|
||||
local-scope
|
||||
load-ingredients
|
||||
board:address:array:address:array:character <- initial-position
|
||||
board:address:shared:array:address:shared:array:character <- initial-position
|
||||
# hook up stdin
|
||||
stdin:address:channel <- new-channel 10/capacity
|
||||
stdin:address:shared:channel <- new-channel 10/capacity
|
||||
start-running send-keys-to-channel, console, stdin, screen
|
||||
# buffer lines in stdin
|
||||
buffered-stdin:address:channel <- new-channel 10/capacity
|
||||
buffered-stdin:address:shared:channel <- new-channel 10/capacity
|
||||
start-running buffer-lines, stdin, buffered-stdin
|
||||
{
|
||||
msg:address:array:character <- new [Stupid text-mode chessboard. White pieces in uppercase; black pieces in lowercase. No checking for legal moves.
|
||||
msg:address:shared:array:character <- new [Stupid text-mode chessboard. White pieces in uppercase; black pieces in lowercase. No checking for legal moves.
|
||||
]
|
||||
print screen, msg
|
||||
cursor-to-next-line screen
|
||||
|
@ -94,7 +94,7 @@ recipe chessboard screen:address:screen, console:address:console -> screen:addre
|
|||
cursor-to-next-line screen
|
||||
msg <- new [move: ]
|
||||
screen <- print screen, msg
|
||||
m:address:move, quit:boolean, error:boolean <- read-move buffered-stdin, screen
|
||||
m:address:shared:move, quit:boolean, error:boolean <- read-move buffered-stdin, screen
|
||||
break-if quit, +quit:label
|
||||
buffered-stdin <- clear-channel buffered-stdin # cleanup after error. todo: test this?
|
||||
loop-if error
|
||||
|
@ -103,12 +103,13 @@ recipe chessboard screen:address:screen, console:address:console -> screen:addre
|
|||
screen <- clear-screen screen
|
||||
loop
|
||||
}
|
||||
msg <- copy 0
|
||||
+quit
|
||||
]
|
||||
|
||||
## a board is an array of files, a file is an array of characters (squares)
|
||||
|
||||
recipe new-board initial-position:address:array:character -> board:address:array:address:array:character [
|
||||
recipe new-board initial-position:address:shared:array:character -> board:address:shared:array:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# assert(length(initial-position) == 64)
|
||||
|
@ -116,19 +117,19 @@ recipe new-board initial-position:address:array:character -> board:address:array
|
|||
correct-length?:boolean <- equal len, 64
|
||||
assert correct-length?, [chessboard had incorrect size]
|
||||
# board is an array of pointers to files; file is an array of characters
|
||||
board <- new {(address array character): type}, 8
|
||||
board <- new {(address shared array character): type}, 8
|
||||
col:number <- copy 0
|
||||
{
|
||||
done?:boolean <- equal col, 8
|
||||
break-if done?
|
||||
file:address:address:array:character <- index-address *board, col
|
||||
file:address:address:shared:array:character <- index-address *board, col
|
||||
*file <- new-file initial-position, col
|
||||
col <- add col, 1
|
||||
loop
|
||||
}
|
||||
]
|
||||
|
||||
recipe new-file position:address:array:character, index:number -> result:address:array:character [
|
||||
recipe new-file position:address:shared:array:character, index:number -> result:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
index <- multiply index, 8
|
||||
|
@ -145,7 +146,7 @@ recipe new-file position:address:array:character, index:number -> result:address
|
|||
}
|
||||
]
|
||||
|
||||
recipe print-board screen:address:screen, board:address:array:address:array:character -> screen:address:screen [
|
||||
recipe print-board screen:address:shared:screen, board:address:shared:array:address:shared:array:character -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
row:number <- copy 7 # start printing from the top of the board
|
||||
|
@ -157,14 +158,14 @@ recipe print-board screen:address:screen, board:address:array:address:array:char
|
|||
# print rank number as a legend
|
||||
rank:number <- add row, 1
|
||||
print-integer screen, rank
|
||||
s:address:array:character <- new [ | ]
|
||||
s:address:shared:array:character <- new [ | ]
|
||||
print screen, s
|
||||
# print each square in the row
|
||||
col:number <- copy 0
|
||||
{
|
||||
done?:boolean <- equal col:number, 8
|
||||
break-if done?:boolean
|
||||
f:address:array:character <- index *board, col
|
||||
f:address:shared:array:character <- index *board, col
|
||||
c:character <- index *f, row
|
||||
print screen, c
|
||||
print screen, space
|
||||
|
@ -184,7 +185,7 @@ recipe print-board screen:address:screen, board:address:array:address:array:char
|
|||
screen <- cursor-to-next-line screen
|
||||
]
|
||||
|
||||
recipe initial-position -> board:address:array:address:array:character [
|
||||
recipe initial-position -> board:address:shared:array:address:shared:array:character [
|
||||
local-scope
|
||||
# layout in memory (in raster order):
|
||||
# R P _ _ _ _ p r
|
||||
|
@ -195,7 +196,7 @@ recipe initial-position -> board:address:array:address:array:character [
|
|||
# B P _ _ _ _ p B
|
||||
# N P _ _ _ _ p n
|
||||
# R P _ _ _ _ p r
|
||||
initial-position:address:array:character <- 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:address:shared:array:character <- 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,
|
||||
|
@ -210,8 +211,8 @@ recipe initial-position -> board:address:array:address:array:character [
|
|||
scenario printing-the-board [
|
||||
assume-screen 30/width, 12/height
|
||||
run [
|
||||
1:address:array:address:array:character/board <- initial-position
|
||||
screen:address:screen <- print-board screen:address:screen, 1:address:array:address:array:character/board
|
||||
1:address:shared:array:address:shared:array:character/board <- initial-position
|
||||
screen:address:shared:screen <- print-board screen:address:shared:screen, 1:address:shared:array:address:shared:array:character/board
|
||||
]
|
||||
screen-should-contain [
|
||||
# 012345678901234567890123456789
|
||||
|
@ -241,14 +242,14 @@ container move [
|
|||
]
|
||||
|
||||
# prints only error messages to screen
|
||||
recipe read-move stdin:address:channel, screen:address:screen -> result:address:move, quit?:boolean, error?:boolean, stdin:address:channel, screen:address:screen [
|
||||
recipe read-move stdin:address:shared:channel, screen:address:shared:screen -> result:address:shared:move, quit?:boolean, error?:boolean, stdin:address:shared:channel, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
from-file:number, quit?:boolean, error?:boolean <- read-file stdin, screen
|
||||
reply-if quit?, 0/dummy, quit?, error?
|
||||
reply-if error?, 0/dummy, quit?, error?
|
||||
# construct the move object
|
||||
result:address:move <- new move:type
|
||||
result:address:shared:move <- new move:type
|
||||
x:address:number <- get-address *result, from-file:offset
|
||||
*x <- copy from-file
|
||||
x <- get-address *result, from-rank:offset
|
||||
|
@ -271,7 +272,7 @@ recipe read-move stdin:address:channel, screen:address:screen -> result:address:
|
|||
]
|
||||
|
||||
# valid values for file: 0-7
|
||||
recipe read-file stdin:address:channel, screen:address:screen -> file:number, quit:boolean, error:boolean, stdin:address:channel, screen:address:screen [
|
||||
recipe read-file stdin:address:shared:channel, screen:address:shared:screen -> file:number, quit:boolean, error:boolean, stdin:address:shared:channel, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
c:character, stdin <- read stdin
|
||||
|
@ -293,7 +294,7 @@ recipe read-file stdin:address:channel, screen:address:screen -> file:number, qu
|
|||
{
|
||||
newline?:boolean <- equal c, 10/newline
|
||||
break-unless newline?
|
||||
error-message:address:array:character <- new [that's not enough]
|
||||
error-message:address:shared:array:character <- new [that's not enough]
|
||||
print screen, error-message
|
||||
reply 0/dummy, 0/quit, 1/error
|
||||
}
|
||||
|
@ -302,7 +303,7 @@ recipe read-file stdin:address:channel, screen:address:screen -> file:number, qu
|
|||
{
|
||||
above-min:boolean <- greater-or-equal file, 0
|
||||
break-if above-min
|
||||
error-message:address:array:character <- new [file too low: ]
|
||||
error-message:address:shared:array:character <- new [file too low: ]
|
||||
print screen, error-message
|
||||
print screen, c
|
||||
cursor-to-next-line screen
|
||||
|
@ -320,7 +321,7 @@ recipe read-file stdin:address:channel, screen:address:screen -> file:number, qu
|
|||
]
|
||||
|
||||
# valid values: 0-7, -1 (quit), -2 (error)
|
||||
recipe read-rank stdin:address:channel, screen:address:screen -> rank:number, quit?:boolean, error?:boolean, stdin:address:channel, screen:address:screen [
|
||||
recipe read-rank stdin:address:shared:channel, screen:address:shared:screen -> rank:number, quit?:boolean, error?:boolean, stdin:address:shared:channel, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
c:character, stdin <- read stdin
|
||||
|
@ -337,7 +338,7 @@ recipe read-rank stdin:address:channel, screen:address:screen -> rank:number, qu
|
|||
{
|
||||
newline?:boolean <- equal c, 10 # newline
|
||||
break-unless newline?
|
||||
error-message:address:array:character <- new [that's not enough]
|
||||
error-message:address:shared:array:character <- new [that's not enough]
|
||||
print screen, error-message
|
||||
reply 0/dummy, 0/quit, 1/error
|
||||
}
|
||||
|
@ -364,14 +365,14 @@ recipe read-rank stdin:address:channel, screen:address:screen -> rank:number, qu
|
|||
|
||||
# read a character from the given channel and check that it's what we expect
|
||||
# return true on error
|
||||
recipe expect-from-channel stdin:address:channel, expected:character, screen:address:screen -> result:boolean, stdin:address:channel, screen:address:screen [
|
||||
recipe expect-from-channel stdin:address:shared:channel, expected:character, screen:address:shared:screen -> result:boolean, stdin:address:shared:channel, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
c:character, stdin <- read stdin
|
||||
{
|
||||
match?:boolean <- equal c, expected
|
||||
break-if match?
|
||||
s:address:array:character <- new [expected character not found]
|
||||
s:address:shared:array:character <- new [expected character not found]
|
||||
print screen, s
|
||||
}
|
||||
result <- not match?
|
||||
|
@ -380,8 +381,8 @@ recipe expect-from-channel stdin:address:channel, expected:character, screen:add
|
|||
scenario read-move-blocking [
|
||||
assume-screen 20/width, 2/height
|
||||
run [
|
||||
1:address:channel <- new-channel 2
|
||||
2:number/routine <- start-running read-move, 1:address:channel, screen:address:screen
|
||||
1:address:shared:channel <- new-channel 2
|
||||
2:number/routine <- start-running read-move, 1:address:shared:channel, screen:address:shared:screen
|
||||
# 'read-move' is waiting for input
|
||||
wait-for-routine 2:number
|
||||
3:number <- routine-state 2:number/id
|
||||
|
@ -389,7 +390,7 @@ scenario read-move-blocking [
|
|||
assert 4:boolean/waiting?, [
|
||||
F read-move-blocking: routine failed to pause after coming up (before any keys were pressed)]
|
||||
# press 'a'
|
||||
1:address:channel <- write 1:address:channel, 97/a
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 97/a
|
||||
restart 2:number/routine
|
||||
# 'read-move' still waiting for input
|
||||
wait-for-routine 2:number
|
||||
|
@ -398,7 +399,7 @@ F read-move-blocking: routine failed to pause after coming up (before any keys w
|
|||
assert 4:boolean/waiting?, [
|
||||
F read-move-blocking: routine failed to pause after rank 'a']
|
||||
# press '2'
|
||||
1:address:channel <- write 1:address:channel, 50/'2'
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 50/'2'
|
||||
restart 2:number/routine
|
||||
# 'read-move' still waiting for input
|
||||
wait-for-routine 2:number
|
||||
|
@ -407,7 +408,7 @@ F read-move-blocking: routine failed to pause after rank 'a']
|
|||
assert 4:boolean/waiting?, [
|
||||
F read-move-blocking: routine failed to pause after file 'a2']
|
||||
# press '-'
|
||||
1:address:channel <- write 1:address:channel, 45/'-'
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 45/'-'
|
||||
restart 2:number/routine
|
||||
# 'read-move' still waiting for input
|
||||
wait-for-routine 2:number
|
||||
|
@ -416,7 +417,7 @@ F read-move-blocking: routine failed to pause after file 'a2']
|
|||
assert 4:boolean/waiting?/routine-state, [
|
||||
F read-move-blocking: routine failed to pause after hyphen 'a2-']
|
||||
# press 'a'
|
||||
1:address:channel <- write 1:address:channel, 97/a
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 97/a
|
||||
restart 2:number/routine
|
||||
# 'read-move' still waiting for input
|
||||
wait-for-routine 2:number
|
||||
|
@ -425,7 +426,7 @@ F read-move-blocking: routine failed to pause after hyphen 'a2-']
|
|||
assert 4:boolean/waiting?/routine-state, [
|
||||
F read-move-blocking: routine failed to pause after rank 'a2-a']
|
||||
# press '4'
|
||||
1:address:channel <- write 1:address:channel, 52/'4'
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 52/'4'
|
||||
restart 2:number/routine
|
||||
# 'read-move' still waiting for input
|
||||
wait-for-routine 2:number
|
||||
|
@ -434,7 +435,7 @@ F read-move-blocking: routine failed to pause after rank 'a2-a']
|
|||
assert 4:boolean/waiting?, [
|
||||
F read-move-blocking: routine failed to pause after file 'a2-a4']
|
||||
# press 'newline'
|
||||
1:address:channel <- write 1:address:channel, 10 # newline
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 10 # newline
|
||||
restart 2:number/routine
|
||||
# 'read-move' now completes
|
||||
wait-for-routine 2:number
|
||||
|
@ -452,8 +453,8 @@ F read-move-blocking: routine failed to terminate on newline]
|
|||
scenario read-move-quit [
|
||||
assume-screen 20/width, 2/height
|
||||
run [
|
||||
1:address:channel <- new-channel 2
|
||||
2:number/routine <- start-running read-move, 1:address:channel, screen:address:screen
|
||||
1:address:shared:channel <- new-channel 2
|
||||
2:number/routine <- start-running read-move, 1:address:shared:channel, screen:address:shared:screen
|
||||
# 'read-move' is waiting for input
|
||||
wait-for-routine 2:number
|
||||
3:number <- routine-state 2:number/id
|
||||
|
@ -461,7 +462,7 @@ scenario read-move-quit [
|
|||
assert 4:boolean/waiting?, [
|
||||
F read-move-quit: routine failed to pause after coming up (before any keys were pressed)]
|
||||
# press 'q'
|
||||
1:address:channel <- write 1:address:channel, 113/q
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 113/q
|
||||
restart 2:number/routine
|
||||
# 'read-move' completes
|
||||
wait-for-routine 2:number
|
||||
|
@ -479,15 +480,15 @@ F read-move-quit: routine failed to terminate on 'q']
|
|||
scenario read-move-illegal-file [
|
||||
assume-screen 20/width, 2/height
|
||||
run [
|
||||
1:address:channel <- new-channel 2
|
||||
2:number/routine <- start-running read-move, 1:address:channel, screen:address:screen
|
||||
1:address:shared:channel <- new-channel 2
|
||||
2:number/routine <- start-running read-move, 1:address:shared:channel, screen:address:shared:screen
|
||||
# 'read-move' is waiting for input
|
||||
wait-for-routine 2:number
|
||||
3:number <- routine-state 2:number/id
|
||||
4:boolean/waiting? <- equal 3:number/routine-state, 3/waiting
|
||||
assert 4:boolean/waiting?, [
|
||||
F read-move-file: routine failed to pause after coming up (before any keys were pressed)]
|
||||
1:address:channel <- write 1:address:channel, 50/'2'
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 50/'2'
|
||||
restart 2:number/routine
|
||||
wait-for-routine 2:number
|
||||
]
|
||||
|
@ -500,16 +501,16 @@ F read-move-file: routine failed to pause after coming up (before any keys were
|
|||
scenario read-move-illegal-rank [
|
||||
assume-screen 20/width, 2/height
|
||||
run [
|
||||
1:address:channel <- new-channel 2
|
||||
2:number/routine <- start-running read-move, 1:address:channel, screen:address:screen
|
||||
1:address:shared:channel <- new-channel 2
|
||||
2:number/routine <- start-running read-move, 1:address:shared:channel, screen:address:shared:screen
|
||||
# 'read-move' is waiting for input
|
||||
wait-for-routine 2:number
|
||||
3:number <- routine-state 2:number/id
|
||||
4:boolean/waiting? <- equal 3:number/routine-state, 3/waiting
|
||||
assert 4:boolean/waiting?, [
|
||||
F read-move-file: routine failed to pause after coming up (before any keys were pressed)]
|
||||
1:address:channel <- write 1:address:channel, 97/a
|
||||
1:address:channel <- write 1:address:channel, 97/a
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 97/a
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 97/a
|
||||
restart 2:number/routine
|
||||
wait-for-routine 2:number
|
||||
]
|
||||
|
@ -522,16 +523,16 @@ F read-move-file: routine failed to pause after coming up (before any keys were
|
|||
scenario read-move-empty [
|
||||
assume-screen 20/width, 2/height
|
||||
run [
|
||||
1:address:channel <- new-channel 2
|
||||
2:number/routine <- start-running read-move, 1:address:channel, screen:address:screen
|
||||
1:address:shared:channel <- new-channel 2
|
||||
2:number/routine <- start-running read-move, 1:address:shared:channel, screen:address:shared:screen
|
||||
# 'read-move' is waiting for input
|
||||
wait-for-routine 2:number
|
||||
3:number <- routine-state 2:number/id
|
||||
4:boolean/waiting? <- equal 3:number/routine-state, 3/waiting
|
||||
assert 4:boolean/waiting?, [
|
||||
F read-move-file: routine failed to pause after coming up (before any keys were pressed)]
|
||||
1:address:channel <- write 1:address:channel, 10/newline
|
||||
1:address:channel <- write 1:address:channel, 97/a
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 10/newline
|
||||
1:address:shared:channel <- write 1:address:shared:channel, 97/a
|
||||
restart 2:number/routine
|
||||
wait-for-routine 2:number
|
||||
]
|
||||
|
@ -541,14 +542,14 @@ F read-move-file: routine failed to pause after coming up (before any keys were
|
|||
]
|
||||
]
|
||||
|
||||
recipe make-move board:address:array:address:array:character, m:address:move -> board:address:array:address:array:character [
|
||||
recipe make-move board:address:shared:array:address:shared:array:character, m:address:shared:move -> board:address:shared:array:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
from-file:number <- get *m, from-file:offset
|
||||
from-rank:number <- get *m, from-rank:offset
|
||||
to-file:number <- get *m, to-file:offset
|
||||
to-rank:number <- get *m, to-rank:offset
|
||||
f:address:array:character <- index *board, from-file
|
||||
f:address:shared:array:character <- index *board, from-file
|
||||
src:address:character/square <- index-address *f, from-rank
|
||||
f <- index *board, to-file
|
||||
dest:address:character/square <- index-address *f, to-rank
|
||||
|
@ -559,18 +560,18 @@ recipe make-move board:address:array:address:array:character, m:address:move ->
|
|||
scenario making-a-move [
|
||||
assume-screen 30/width, 12/height
|
||||
run [
|
||||
2:address:array:address:array:character/board <- initial-position
|
||||
3:address:move <- new move:type
|
||||
4:address:number <- get-address *3:address:move, from-file:offset
|
||||
2:address:shared:array:address:shared:array:character/board <- initial-position
|
||||
3:address:shared:move <- new move:type
|
||||
4:address:number <- get-address *3:address:shared:move, from-file:offset
|
||||
*4:address:number <- copy 6/g
|
||||
5:address:number <- get-address *3:address:move, from-rank:offset
|
||||
5:address:number <- get-address *3:address:shared:move, from-rank:offset
|
||||
*5:address:number <- copy 1/'2'
|
||||
6:address:number <- get-address *3:address:move, to-file:offset
|
||||
6:address:number <- get-address *3:address:shared:move, to-file:offset
|
||||
*6:address:number <- copy 6/g
|
||||
7:address:number <- get-address *3:address:move, to-rank:offset
|
||||
7:address:number <- get-address *3:address:shared:move, to-rank:offset
|
||||
*7:address:number <- copy 3/'4'
|
||||
2:address:array:address:array:character/board <- make-move 2:address:array:address:array:character/board, 3:address:move
|
||||
screen:address:screen <- print-board screen:address:screen, 2:address:array:address:array:character/board
|
||||
2:address:shared:array:address:shared:array:character/board <- make-move 2:address:shared:array:address:shared:array:character/board, 3:address:shared:move
|
||||
screen:address:shared:screen <- print-board screen:address:shared:screen, 2:address:shared:array:address:shared:array:character/board
|
||||
]
|
||||
screen-should-contain [
|
||||
# 012345678901234567890123456789
|
||||
|
|
10
counters.mu
10
counters.mu
|
@ -1,24 +1,24 @@
|
|||
# example program: maintain multiple counters with isolated lexical scopes
|
||||
# (spaces)
|
||||
|
||||
recipe new-counter n:number -> default-space:address:array:location [
|
||||
recipe new-counter n:number -> default-space:address:shared:array:location [
|
||||
default-space <- new location:type, 30
|
||||
load-ingredients
|
||||
]
|
||||
|
||||
recipe increment-counter outer:address:array:location/names:new-counter, x:number -> n:number/space:1 [
|
||||
recipe increment-counter outer:address:shared:array:location/names:new-counter, x:number -> n:number/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:address:shared:array:location/names:new-counter <- copy outer # setup outer space; it *must* come from 'new-counter'
|
||||
n/space:1 <- add n/space:1, x
|
||||
]
|
||||
|
||||
recipe main [
|
||||
local-scope
|
||||
# counter A
|
||||
a:address:array:location <- new-counter 34
|
||||
a:address:shared:array:location <- new-counter 34
|
||||
# counter B
|
||||
b:address:array:location <- new-counter 23
|
||||
b:address:shared:array:location <- new-counter 23
|
||||
# increment both by 2 but in different ways
|
||||
increment-counter a, 1
|
||||
b-value:number <- increment-counter b, 2
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# temporary main for this layer: just render the given text at the given
|
||||
# screen dimensions, then stop
|
||||
recipe! main text:address:array:character [
|
||||
recipe! main text:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
open-console
|
||||
|
@ -16,8 +16,8 @@ recipe! main text:address:array:character [
|
|||
scenario editor-initially-prints-text-to-screen [
|
||||
assume-screen 10/width, 5/height
|
||||
run [
|
||||
1:address:array:character <- new [abc]
|
||||
new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
1:address:shared:array:character <- new [abc]
|
||||
new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
]
|
||||
screen-should-contain [
|
||||
# top line of screen reserved for menu
|
||||
|
@ -29,11 +29,11 @@ scenario editor-initially-prints-text-to-screen [
|
|||
|
||||
container editor-data [
|
||||
# editable text: doubly linked list of characters (head contains a special sentinel)
|
||||
data:address:duplex-list:character
|
||||
top-of-screen:address:duplex-list:character
|
||||
bottom-of-screen:address:duplex-list:character
|
||||
data:address:shared:duplex-list:character
|
||||
top-of-screen:address:shared:duplex-list:character
|
||||
bottom-of-screen:address:shared:duplex-list:character
|
||||
# location before cursor inside data
|
||||
before-cursor:address:duplex-list:character
|
||||
before-cursor:address:shared:duplex-list:character
|
||||
|
||||
# raw bounds of display area on screen
|
||||
# always displays from row 1 (leaving row 0 for a menu) and at most until bottom of screen
|
||||
|
@ -47,7 +47,7 @@ container editor-data [
|
|||
# creates a new editor widget and renders its initial appearance to screen
|
||||
# top/left/right constrain the screen area available to the new editor
|
||||
# right is exclusive
|
||||
recipe new-editor s:address:array:character, screen:address:screen, left:number, right:number -> result:address:editor-data, screen:address:screen [
|
||||
recipe new-editor s:address:shared:array:character, screen:address:shared:screen, left:number, right:number -> result:address:shared:editor-data, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# no clipping of bounds
|
||||
|
@ -63,11 +63,11 @@ recipe new-editor s:address:array:character, screen:address:screen, left:number,
|
|||
*x <- copy 1/top
|
||||
x <- get-address *result, cursor-column:offset
|
||||
*x <- copy left
|
||||
init:address:address:duplex-list:character <- get-address *result, data:offset
|
||||
init:address:address:shared:duplex-list:character <- get-address *result, data:offset
|
||||
*init <- push 167/§, 0/tail
|
||||
top-of-screen:address:address:duplex-list:character <- get-address *result, top-of-screen:offset
|
||||
top-of-screen:address:address:shared:duplex-list:character <- get-address *result, top-of-screen:offset
|
||||
*top-of-screen <- copy *init
|
||||
y:address:address:duplex-list:character <- get-address *result, before-cursor:offset
|
||||
y:address:address:shared:duplex-list:character <- get-address *result, before-cursor:offset
|
||||
*y <- copy *init
|
||||
result <- insert-text result, s
|
||||
# initialize cursor to top of screen
|
||||
|
@ -78,7 +78,7 @@ recipe new-editor s:address:array:character, screen:address:screen, left:number,
|
|||
<editor-initialization>
|
||||
]
|
||||
|
||||
recipe insert-text editor:address:editor-data, text:address:array:character -> editor:address:editor-data [
|
||||
recipe insert-text editor:address:shared:editor-data, text:address:shared:array:character -> editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# early exit if text is empty
|
||||
|
@ -87,7 +87,7 @@ recipe insert-text editor:address:editor-data, text:address:array:character -> e
|
|||
reply-unless len, editor/same-as-ingredient:0
|
||||
idx:number <- copy 0
|
||||
# now we can start appending the rest, character by character
|
||||
curr:address:duplex-list:character <- get *editor, data:offset
|
||||
curr:address:shared:duplex-list:character <- get *editor, data:offset
|
||||
{
|
||||
done?:boolean <- greater-or-equal idx, len
|
||||
break-if done?
|
||||
|
@ -104,8 +104,8 @@ recipe insert-text editor:address:editor-data, text:address:array:character -> e
|
|||
scenario editor-initializes-without-data [
|
||||
assume-screen 5/width, 3/height
|
||||
run [
|
||||
1:address:editor-data <- new-editor 0/data, screen:address:screen, 2/left, 5/right
|
||||
2:editor-data <- copy *1:address:editor-data
|
||||
1:address:shared:editor-data <- new-editor 0/data, screen:address:shared:screen, 2/left, 5/right
|
||||
2:editor-data <- copy *1:address:shared:editor-data
|
||||
]
|
||||
memory-should-contain [
|
||||
# 2 (data) <- just the § sentinel
|
||||
|
@ -127,7 +127,7 @@ scenario editor-initializes-without-data [
|
|||
# Assumes cursor should be at coordinates (cursor-row, cursor-column) and
|
||||
# updates before-cursor to match. Might also move coordinates if they're
|
||||
# outside text.
|
||||
recipe render screen:address:screen, editor:address:editor-data -> last-row:number, last-column:number, screen:address:screen, editor:address:editor-data [
|
||||
recipe render screen:address:shared:screen, editor:address:shared:editor-data -> last-row:number, last-column:number, screen:address:shared:screen, editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless editor, 1/top, 0/left, screen/same-as-ingredient:0, editor/same-as-ingredient:1
|
||||
|
@ -135,8 +135,8 @@ recipe render screen:address:screen, editor:address:editor-data -> last-row:numb
|
|||
screen-height:number <- screen-height screen
|
||||
right:number <- get *editor, right:offset
|
||||
# traversing editor
|
||||
curr:address:duplex-list:character <- get *editor, top-of-screen:offset
|
||||
prev:address:duplex-list:character <- copy curr # just in case curr becomes null and we can't compute prev
|
||||
curr:address:shared:duplex-list:character <- get *editor, top-of-screen:offset
|
||||
prev:address:shared:duplex-list:character <- copy curr # just in case curr becomes null and we can't compute prev
|
||||
curr <- next curr
|
||||
# traversing screen
|
||||
+render-loop-initialization
|
||||
|
@ -145,7 +145,7 @@ recipe render screen:address:screen, editor:address:editor-data -> last-row:numb
|
|||
column:number <- copy left
|
||||
cursor-row:address:number <- get-address *editor, cursor-row:offset
|
||||
cursor-column:address:number <- get-address *editor, cursor-column:offset
|
||||
before-cursor:address:address:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
screen <- move-cursor screen, row, column
|
||||
{
|
||||
+next-character
|
||||
|
@ -208,7 +208,7 @@ recipe render screen:address:screen, editor:address:editor-data -> last-row:numb
|
|||
loop
|
||||
}
|
||||
# save first character off-screen
|
||||
bottom-of-screen:address:address:duplex-list:character <- get-address *editor, bottom-of-screen:offset
|
||||
bottom-of-screen:address:address:shared:duplex-list:character <- get-address *editor, bottom-of-screen:offset
|
||||
*bottom-of-screen <- copy curr
|
||||
# is cursor to the right of the last line? move to end
|
||||
{
|
||||
|
@ -225,7 +225,7 @@ recipe render screen:address:screen, editor:address:editor-data -> last-row:numb
|
|||
reply row, column, screen/same-as-ingredient:0, editor/same-as-ingredient:1
|
||||
]
|
||||
|
||||
recipe clear-line-delimited screen:address:screen, column:number, right:number -> screen:address:screen [
|
||||
recipe clear-line-delimited screen:address:shared:screen, column:number, right:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
space:character <- copy 32/space
|
||||
|
@ -238,7 +238,7 @@ recipe clear-line-delimited screen:address:screen, column:number, right:number -
|
|||
}
|
||||
]
|
||||
|
||||
recipe clear-screen-from screen:address:screen, row:number, column:number, left:number, right:number -> screen:address:screen [
|
||||
recipe clear-screen-from screen:address:shared:screen, row:number, column:number, left:number, right:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if it's the real screen, use the optimized primitive
|
||||
|
@ -254,7 +254,7 @@ recipe clear-screen-from screen:address:screen, row:number, column:number, left:
|
|||
reply screen/same-as-ingredient:0
|
||||
]
|
||||
|
||||
recipe clear-rest-of-screen screen:address:screen, row:number, left:number, right:number -> screen:address:screen [
|
||||
recipe clear-rest-of-screen screen:address:shared:screen, row:number, left:number, right:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
row <- add row, 1
|
||||
|
@ -273,9 +273,9 @@ recipe clear-rest-of-screen screen:address:screen, row:number, left:number, righ
|
|||
scenario editor-initially-prints-multiple-lines [
|
||||
assume-screen 5/width, 5/height
|
||||
run [
|
||||
s:address:array:character <- new [abc
|
||||
s:address:shared:array:character <- new [abc
|
||||
def]
|
||||
new-editor s:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
new-editor s:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -288,8 +288,8 @@ def]
|
|||
scenario editor-initially-handles-offsets [
|
||||
assume-screen 5/width, 5/height
|
||||
run [
|
||||
s:address:array:character <- new [abc]
|
||||
new-editor s:address:array:character, screen:address:screen, 1/left, 5/right
|
||||
s:address:shared:array:character <- new [abc]
|
||||
new-editor s:address:shared:array:character, screen:address:shared:screen, 1/left, 5/right
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -301,9 +301,9 @@ scenario editor-initially-handles-offsets [
|
|||
scenario editor-initially-prints-multiple-lines-at-offset [
|
||||
assume-screen 5/width, 5/height
|
||||
run [
|
||||
s:address:array:character <- new [abc
|
||||
s:address:shared:array:character <- new [abc
|
||||
def]
|
||||
new-editor s:address:array:character, screen:address:screen, 1/left, 5/right
|
||||
new-editor s:address:shared:array:character, screen:address:shared:screen, 1/left, 5/right
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -316,8 +316,8 @@ def]
|
|||
scenario editor-initially-wraps-long-lines [
|
||||
assume-screen 5/width, 5/height
|
||||
run [
|
||||
s:address:array:character <- new [abc def]
|
||||
new-editor s:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
s:address:shared:array:character <- new [abc def]
|
||||
new-editor s:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -336,8 +336,8 @@ scenario editor-initially-wraps-long-lines [
|
|||
scenario editor-initially-wraps-barely-long-lines [
|
||||
assume-screen 5/width, 5/height
|
||||
run [
|
||||
s:address:array:character <- new [abcde]
|
||||
new-editor s:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
s:address:shared:array:character <- new [abcde]
|
||||
new-editor s:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
]
|
||||
# still wrap, even though the line would fit. We need room to click on the
|
||||
# end of the line
|
||||
|
@ -358,10 +358,10 @@ scenario editor-initially-wraps-barely-long-lines [
|
|||
scenario editor-initializes-empty-text [
|
||||
assume-screen 5/width, 5/height
|
||||
run [
|
||||
1:address:array:character <- new []
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
1:address:shared:array:character <- new []
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -379,10 +379,10 @@ scenario editor-initializes-empty-text [
|
|||
scenario render-colors-comments [
|
||||
assume-screen 5/width, 5/height
|
||||
run [
|
||||
s:address:array:character <- new [abc
|
||||
s:address:shared:array:character <- new [abc
|
||||
# de
|
||||
f]
|
||||
new-editor s:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
new-editor s:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -460,10 +460,10 @@ recipe get-color color:number, c:character -> color:number [
|
|||
scenario render-colors-assignment [
|
||||
assume-screen 8/width, 5/height
|
||||
run [
|
||||
s:address:array:character <- new [abc
|
||||
s:address:shared:array:character <- new [abc
|
||||
d <- e
|
||||
f]
|
||||
new-editor s:address:array:character, screen:address:screen, 0/left, 8/right
|
||||
new-editor s:address:shared:array:character, screen:address:shared:screen, 0/left, 8/right
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
|
||||
# temporary main: interactive editor
|
||||
# hit ctrl-c to exit
|
||||
recipe! main text:address:array:character [
|
||||
recipe! main text:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
open-console
|
||||
editor:address:editor-data <- new-editor text, 0/screen, 5/left, 45/right
|
||||
editor:address:shared:editor-data <- new-editor text, 0/screen, 5/left, 45/right
|
||||
editor-event-loop 0/screen, 0/console, editor
|
||||
close-console
|
||||
]
|
||||
|
||||
recipe editor-event-loop screen:address:screen, console:address:console, editor:address:editor-data -> screen:address:screen, console:address:console, editor:address:editor-data [
|
||||
recipe editor-event-loop screen:address:shared:screen, console:address:shared:console, editor:address:shared:editor-data -> screen:address:shared:screen, console:address:shared:console, editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -20,7 +20,7 @@ recipe editor-event-loop screen:address:screen, console:address:console, editor:
|
|||
cursor-row:number <- get *editor, cursor-row:offset
|
||||
cursor-column:number <- get *editor, cursor-column:offset
|
||||
screen <- move-cursor screen, cursor-row, cursor-column
|
||||
e:event, console:address:console, found?:boolean, quit?:boolean <- read-event console
|
||||
e:event, console:address:shared:console, found?:boolean, quit?:boolean <- read-event console
|
||||
loop-unless found?
|
||||
break-if quit? # only in tests
|
||||
trace 10, [app], [next-event]
|
||||
|
@ -45,7 +45,7 @@ recipe editor-event-loop screen:address:screen, console:address:console, editor:
|
|||
]
|
||||
|
||||
# process click, return if it was on current editor
|
||||
recipe move-cursor-in-editor screen:address:screen, editor:address:editor-data, t:touch-event -> in-focus?:boolean, editor:address:editor-data [
|
||||
recipe move-cursor-in-editor screen:address:shared:screen, editor:address:shared:editor-data, t:touch-event -> in-focus?:boolean, editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless editor, 0/false
|
||||
|
@ -70,7 +70,7 @@ recipe move-cursor-in-editor screen:address:screen, editor:address:editor-data,
|
|||
# Variant of 'render' that only moves the cursor (coordinates and
|
||||
# before-cursor). If it's past the end of a line, it 'slides' it left. If it's
|
||||
# past the last line it positions at end of last line.
|
||||
recipe snap-cursor screen:address:screen, editor:address:editor-data, target-row:number, target-column:number -> editor:address:editor-data [
|
||||
recipe snap-cursor screen:address:shared:screen, editor:address:shared:editor-data, target-row:number, target-column:number -> editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless editor
|
||||
|
@ -78,8 +78,8 @@ recipe snap-cursor screen:address:screen, editor:address:editor-data, target-row
|
|||
right:number <- get *editor, right:offset
|
||||
screen-height:number <- screen-height screen
|
||||
# count newlines until screen row
|
||||
curr:address:duplex-list:character <- get *editor, top-of-screen:offset
|
||||
prev:address:duplex-list:character <- copy curr # just in case curr becomes null and we can't compute prev
|
||||
curr:address:shared:duplex-list:character <- get *editor, top-of-screen:offset
|
||||
prev:address:shared:duplex-list:character <- copy curr # just in case curr becomes null and we can't compute prev
|
||||
curr <- next curr
|
||||
row:number <- copy 1/top
|
||||
column:number <- copy left
|
||||
|
@ -87,7 +87,7 @@ recipe snap-cursor screen:address:screen, editor:address:editor-data, target-row
|
|||
*cursor-row <- copy target-row
|
||||
cursor-column:address:number <- get-address *editor, cursor-column:offset
|
||||
*cursor-column <- copy target-column
|
||||
before-cursor:address:address:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
{
|
||||
+next-character
|
||||
break-unless curr
|
||||
|
@ -155,7 +155,7 @@ recipe snap-cursor screen:address:screen, editor:address:editor-data, target-row
|
|||
|
||||
# Process an event 'e' and try to minimally update the screen.
|
||||
# Set 'go-render?' to true to indicate the caller must perform a non-minimal update.
|
||||
recipe handle-keyboard-event screen:address:screen, editor:address:editor-data, e:event -> screen:address:screen, editor:address:editor-data, go-render?:boolean [
|
||||
recipe handle-keyboard-event screen:address:shared:screen, editor:address:shared:editor-data, e:event -> screen:address:shared:screen, editor:address:shared:editor-data, go-render?:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
go-render? <- copy 0/false
|
||||
|
@ -164,7 +164,7 @@ recipe handle-keyboard-event screen:address:screen, editor:address:editor-data,
|
|||
screen-height:number <- screen-height screen
|
||||
left:number <- get *editor, left:offset
|
||||
right:number <- get *editor, right:offset
|
||||
before-cursor:address:address:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
cursor-row:address:number <- get-address *editor, cursor-row:offset
|
||||
cursor-column:address:number <- get-address *editor, cursor-column:offset
|
||||
save-row:number <- copy *cursor-row
|
||||
|
@ -195,10 +195,10 @@ recipe handle-keyboard-event screen:address:screen, editor:address:editor-data,
|
|||
reply
|
||||
]
|
||||
|
||||
recipe insert-at-cursor editor:address:editor-data, c:character, screen:address:screen -> editor:address:editor-data, screen:address:screen, go-render?:boolean [
|
||||
recipe insert-at-cursor editor:address:shared:editor-data, c:character, screen:address:shared:screen -> editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
before-cursor:address:address:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
insert c, *before-cursor
|
||||
*before-cursor <- next *before-cursor
|
||||
cursor-row:address:number <- get-address *editor, cursor-row:offset
|
||||
|
@ -213,7 +213,7 @@ recipe insert-at-cursor editor:address:editor-data, c:character, screen:address:
|
|||
<insert-character-special-case>
|
||||
# but mostly we'll just move the cursor right
|
||||
*cursor-column <- add *cursor-column, 1
|
||||
next:address:duplex-list:character <- next *before-cursor
|
||||
next:address:shared:duplex-list:character <- next *before-cursor
|
||||
{
|
||||
# at end of all text? no need to scroll? just print the character and leave
|
||||
at-end?:boolean <- equal next, 0/null
|
||||
|
@ -233,7 +233,7 @@ recipe insert-at-cursor editor:address:editor-data, c:character, screen:address:
|
|||
break-unless next
|
||||
at-right?:boolean <- greater-or-equal *cursor-column, screen-width
|
||||
break-if at-right?
|
||||
curr:address:duplex-list:character <- copy *before-cursor
|
||||
curr:address:shared:duplex-list:character <- copy *before-cursor
|
||||
move-cursor screen, save-row, save-column
|
||||
curr-column:number <- copy save-column
|
||||
{
|
||||
|
@ -259,7 +259,7 @@ recipe insert-at-cursor editor:address:editor-data, c:character, screen:address:
|
|||
]
|
||||
|
||||
# helper for tests
|
||||
recipe editor-render screen:address:screen, editor:address:editor-data -> screen:address:screen, editor:address:editor-data [
|
||||
recipe editor-render screen:address:shared:screen, editor:address:shared:editor-data -> screen:address:shared:screen, editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
left:number <- get *editor, left:offset
|
||||
|
@ -274,12 +274,12 @@ recipe editor-render screen:address:screen, editor:address:editor-data -> screen
|
|||
|
||||
scenario editor-handles-empty-event-queue [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
assume-console []
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -291,17 +291,17 @@ scenario editor-handles-empty-event-queue [
|
|||
|
||||
scenario editor-handles-mouse-clicks [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 1, 1 # on the 'b'
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -318,16 +318,16 @@ scenario editor-handles-mouse-clicks [
|
|||
|
||||
scenario editor-handles-mouse-clicks-outside-text [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 1, 7 # last line, to the right of text
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
memory-should-contain [
|
||||
3 <- 1 # cursor row
|
||||
|
@ -338,17 +338,17 @@ scenario editor-handles-mouse-clicks-outside-text [
|
|||
|
||||
scenario editor-handles-mouse-clicks-outside-text-2 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc
|
||||
1:address:shared:array:character <- new [abc
|
||||
def]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 1, 7 # interior line, to the right of text
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
memory-should-contain [
|
||||
3 <- 1 # cursor row
|
||||
|
@ -359,17 +359,17 @@ def]
|
|||
|
||||
scenario editor-handles-mouse-clicks-outside-text-3 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc
|
||||
1:address:shared:array:character <- new [abc
|
||||
def]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 3, 7 # below text
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
memory-should-contain [
|
||||
3 <- 2 # cursor row
|
||||
|
@ -380,19 +380,19 @@ def]
|
|||
|
||||
scenario editor-handles-mouse-clicks-outside-column [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
1:address:shared:array:character <- new [abc]
|
||||
# editor occupies only left half of screen
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
# click on right half of screen
|
||||
left-click 3, 8
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -409,18 +409,18 @@ scenario editor-handles-mouse-clicks-outside-column [
|
|||
|
||||
scenario editor-handles-mouse-clicks-in-menu-area [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
# click on first, 'menu' row
|
||||
left-click 0, 3
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
# no change to cursor
|
||||
memory-should-contain [
|
||||
|
@ -431,15 +431,15 @@ scenario editor-handles-mouse-clicks-in-menu-area [
|
|||
|
||||
scenario editor-inserts-characters-into-empty-editor [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new []
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new []
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
type [abc]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -452,9 +452,9 @@ scenario editor-inserts-characters-into-empty-editor [
|
|||
|
||||
scenario editor-inserts-characters-at-cursor [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
# type two letters at different places
|
||||
assume-console [
|
||||
|
@ -463,7 +463,7 @@ scenario editor-inserts-characters-at-cursor [
|
|||
type [d]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -476,16 +476,16 @@ scenario editor-inserts-characters-at-cursor [
|
|||
|
||||
scenario editor-inserts-characters-at-cursor-2 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 1, 5 # right of last line
|
||||
type [d]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -498,17 +498,17 @@ scenario editor-inserts-characters-at-cursor-2 [
|
|||
|
||||
scenario editor-inserts-characters-at-cursor-5 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc
|
||||
1:address:shared:array:character <- new [abc
|
||||
d]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 1, 5 # right of non-last line
|
||||
type [e]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -522,16 +522,16 @@ d]
|
|||
|
||||
scenario editor-inserts-characters-at-cursor-3 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 3, 5 # below all text
|
||||
type [d]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -544,17 +544,17 @@ scenario editor-inserts-characters-at-cursor-3 [
|
|||
|
||||
scenario editor-inserts-characters-at-cursor-4 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc
|
||||
1:address:shared:array:character <- new [abc
|
||||
d]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 3, 5 # below all text
|
||||
type [e]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -568,17 +568,17 @@ d]
|
|||
|
||||
scenario editor-inserts-characters-at-cursor-6 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc
|
||||
1:address:shared:array:character <- new [abc
|
||||
d]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 3, 5 # below all text
|
||||
type [ef]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -592,14 +592,14 @@ d]
|
|||
|
||||
scenario editor-moves-cursor-after-inserting-characters [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [ab]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new [ab]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
assume-console [
|
||||
type [01]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -613,15 +613,15 @@ scenario editor-moves-cursor-after-inserting-characters [
|
|||
|
||||
scenario editor-wraps-line-on-insert [
|
||||
assume-screen 5/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
# type a letter
|
||||
assume-console [
|
||||
type [e]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
# no wrap yet
|
||||
screen-should-contain [
|
||||
|
@ -636,7 +636,7 @@ scenario editor-wraps-line-on-insert [
|
|||
type [f]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
# now wrap
|
||||
screen-should-contain [
|
||||
|
@ -651,19 +651,19 @@ scenario editor-wraps-line-on-insert [
|
|||
scenario editor-wraps-line-on-insert-2 [
|
||||
# create an editor with some text
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abcdefg
|
||||
1:address:shared:array:character <- new [abcdefg
|
||||
defg]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
# type more text at the start
|
||||
assume-console [
|
||||
left-click 3, 0
|
||||
type [abc]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
# cursor is not wrapped
|
||||
memory-should-contain [
|
||||
|
@ -703,16 +703,16 @@ after <insert-character-special-case> [
|
|||
|
||||
scenario editor-wraps-cursor-after-inserting-characters [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abcde]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
1:address:shared:array:character <- new [abcde]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
assume-console [
|
||||
left-click 1, 4 # line is full; no wrap icon yet
|
||||
type [f]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -729,16 +729,16 @@ scenario editor-wraps-cursor-after-inserting-characters [
|
|||
|
||||
scenario editor-wraps-cursor-after-inserting-characters-2 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abcde]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
1:address:shared:array:character <- new [abcde]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
assume-console [
|
||||
left-click 1, 3 # right before the wrap icon
|
||||
type [f]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -755,16 +755,16 @@ scenario editor-wraps-cursor-after-inserting-characters-2 [
|
|||
|
||||
scenario editor-wraps-cursor-to-left-margin [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abcde]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 2/left, 7/right
|
||||
1:address:shared:array:character <- new [abcde]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 2/left, 7/right
|
||||
assume-console [
|
||||
left-click 1, 5 # line is full; no wrap icon yet
|
||||
type [01]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -792,14 +792,14 @@ after <editor-initialization> [
|
|||
|
||||
scenario editor-moves-cursor-down-after-inserting-newline [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
assume-console [
|
||||
type [0
|
||||
1]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -822,12 +822,12 @@ after <handle-special-character> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe insert-new-line-and-indent editor:address:editor-data, screen:address:screen -> editor:address:editor-data, screen:address:screen, go-render?:boolean [
|
||||
recipe insert-new-line-and-indent editor:address:shared:editor-data, screen:address:shared:screen -> editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
cursor-row:address:number <- get-address *editor, cursor-row:offset
|
||||
cursor-column:address:number <- get-address *editor, cursor-column:offset
|
||||
before-cursor:address:address:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
left:number <- get *editor, left:offset
|
||||
right:number <- get *editor, right:offset
|
||||
screen-height:number <- screen-height screen
|
||||
|
@ -847,8 +847,8 @@ recipe insert-new-line-and-indent editor:address:editor-data, screen:address:scr
|
|||
# indent if necessary
|
||||
indent?:boolean <- get *editor, indent?:offset
|
||||
reply-unless indent?
|
||||
d:address:duplex-list:character <- get *editor, data:offset
|
||||
end-of-previous-line:address:duplex-list:character <- prev *before-cursor
|
||||
d:address:shared:duplex-list:character <- get *editor, data:offset
|
||||
end-of-previous-line:address:shared:duplex-list:character <- prev *before-cursor
|
||||
indent:number <- line-indent end-of-previous-line, d
|
||||
i:number <- copy 0
|
||||
{
|
||||
|
@ -862,7 +862,7 @@ recipe insert-new-line-and-indent editor:address:editor-data, screen:address:scr
|
|||
|
||||
# takes a pointer 'curr' into the doubly-linked list and its sentinel, counts
|
||||
# the number of spaces at the start of the line containing 'curr'.
|
||||
recipe line-indent curr:address:duplex-list:character, start:address:duplex-list:character -> result:number [
|
||||
recipe line-indent curr:address:shared:duplex-list:character, start:address:shared:duplex-list:character -> result:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result:number <- copy 0
|
||||
|
@ -894,14 +894,14 @@ recipe line-indent curr:address:duplex-list:character, start:address:duplex-list
|
|||
|
||||
scenario editor-moves-cursor-down-after-inserting-newline-2 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 1/left, 10/right
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 1/left, 10/right
|
||||
assume-console [
|
||||
type [0
|
||||
1]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -914,8 +914,8 @@ scenario editor-moves-cursor-down-after-inserting-newline-2 [
|
|||
|
||||
scenario editor-clears-previous-line-completely-after-inserting-newline [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abcde]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
1:address:shared:array:character <- new [abcde]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
assume-console [
|
||||
press enter
|
||||
]
|
||||
|
@ -927,7 +927,7 @@ scenario editor-clears-previous-line-completely-after-inserting-newline [
|
|||
. .
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
# line should be fully cleared
|
||||
screen-should-contain [
|
||||
|
@ -941,10 +941,10 @@ scenario editor-clears-previous-line-completely-after-inserting-newline [
|
|||
|
||||
scenario editor-inserts-indent-after-newline [
|
||||
assume-screen 10/width, 10/height
|
||||
1:address:array:character <- new [ab
|
||||
1:address:shared:array:character <- new [ab
|
||||
cd
|
||||
ef]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
# position cursor after 'cd' and hit 'newline'
|
||||
assume-console [
|
||||
left-click 2, 8
|
||||
|
@ -952,9 +952,9 @@ ef]
|
|||
]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
# cursor should be below start of previous line
|
||||
memory-should-contain [
|
||||
|
@ -965,10 +965,10 @@ ef]
|
|||
|
||||
scenario editor-skips-indent-around-paste [
|
||||
assume-screen 10/width, 10/height
|
||||
1:address:array:character <- new [ab
|
||||
1:address:shared:array:character <- new [ab
|
||||
cd
|
||||
ef]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
# position cursor after 'cd' and hit 'newline' surrounded by paste markers
|
||||
assume-console [
|
||||
left-click 2, 8
|
||||
|
@ -977,9 +977,9 @@ ef]
|
|||
press 65506 # end paste
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
# cursor should be below start of previous line
|
||||
memory-should-contain [
|
||||
|
@ -1012,7 +1012,7 @@ after <handle-special-key> [
|
|||
|
||||
## helpers
|
||||
|
||||
recipe draw-horizontal screen:address:screen, row:number, x:number, right:number -> screen:address:screen [
|
||||
recipe draw-horizontal screen:address:shared:screen, row:number, x:number, right:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
style:character, style-found?:boolean <- next-ingredient
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,22 +6,22 @@
|
|||
recipe! main [
|
||||
local-scope
|
||||
open-console
|
||||
initial-recipe:address:array:character <- restore [recipes.mu]
|
||||
initial-sandbox:address:array:character <- new []
|
||||
initial-recipe:address:shared:array:character <- restore [recipes.mu]
|
||||
initial-sandbox:address:shared:array:character <- new []
|
||||
hide-screen 0/screen
|
||||
env:address:programming-environment-data <- new-programming-environment 0/screen, initial-recipe, initial-sandbox
|
||||
env:address:shared:programming-environment-data <- new-programming-environment 0/screen, initial-recipe, initial-sandbox
|
||||
render-all 0/screen, env
|
||||
event-loop 0/screen, 0/console, env
|
||||
# never gets here
|
||||
]
|
||||
|
||||
container programming-environment-data [
|
||||
recipes:address:editor-data
|
||||
current-sandbox:address:editor-data
|
||||
recipes:address:shared:editor-data
|
||||
current-sandbox:address:shared:editor-data
|
||||
sandbox-in-focus?:boolean # false => cursor in recipes; true => cursor in current-sandbox
|
||||
]
|
||||
|
||||
recipe new-programming-environment screen:address:screen, initial-recipe-contents:address:array:character, initial-sandbox-contents:address:array:character -> result:address:programming-environment-data, screen:address:screen [
|
||||
recipe new-programming-environment screen:address:shared:screen, initial-recipe-contents:address:shared:array:character, initial-sandbox-contents:address:shared:array:character -> result:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
width:number <- screen-width screen
|
||||
|
@ -33,25 +33,25 @@ recipe new-programming-environment screen:address:screen, initial-recipe-content
|
|||
button-on-screen?:boolean <- greater-or-equal button-start, 0
|
||||
assert button-on-screen?, [screen too narrow for menu]
|
||||
screen <- move-cursor screen, 0/row, button-start
|
||||
run-button:address:array:character <- new [ run (F4) ]
|
||||
run-button:address:shared:array:character <- new [ run (F4) ]
|
||||
print screen, run-button, 255/white, 161/reddish
|
||||
# dotted line down the middle
|
||||
divider:number, _ <- divide-with-remainder width, 2
|
||||
draw-vertical screen, divider, 1/top, height, 9482/vertical-dotted
|
||||
# recipe editor on the left
|
||||
recipes:address:address:editor-data <- get-address *result, recipes:offset
|
||||
recipes:address:address:shared:editor-data <- get-address *result, recipes:offset
|
||||
*recipes <- new-editor initial-recipe-contents, screen, 0/left, divider/right
|
||||
# sandbox editor on the right
|
||||
new-left:number <- add divider, 1
|
||||
current-sandbox:address:address:editor-data <- get-address *result, current-sandbox:offset
|
||||
current-sandbox:address:address:shared:editor-data <- get-address *result, current-sandbox:offset
|
||||
*current-sandbox <- new-editor initial-sandbox-contents, screen, new-left, width/right
|
||||
]
|
||||
|
||||
recipe event-loop screen:address:screen, console:address:console, env:address:programming-environment-data -> screen:address:screen, console:address:console, env:address:programming-environment-data [
|
||||
recipe event-loop screen:address:shared:screen, console:address:shared:console, env:address:shared:programming-environment-data -> screen:address:shared:screen, console:address:shared:console, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
recipes:address:editor-data <- get *env, recipes:offset
|
||||
current-sandbox:address:editor-data <- get *env, current-sandbox:offset
|
||||
recipes:address:shared:editor-data <- get *env, recipes:offset
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
sandbox-in-focus?:address:boolean <- get-address *env, sandbox-in-focus?:offset
|
||||
# if we fall behind we'll stop updating the screen, but then we have to
|
||||
# render the entire screen when we catch up.
|
||||
|
@ -179,14 +179,14 @@ recipe event-loop screen:address:screen, console:address:console, env:address:pr
|
|||
}
|
||||
]
|
||||
|
||||
recipe resize screen:address:screen, env:address:programming-environment-data -> env:address:programming-environment-data, screen:address:screen [
|
||||
recipe resize screen:address:shared:screen, env:address:shared:programming-environment-data -> env:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
clear-screen screen # update screen dimensions
|
||||
width:number <- screen-width screen
|
||||
divider:number, _ <- divide-with-remainder width, 2
|
||||
# update recipe editor
|
||||
recipes:address:editor-data <- get *env, recipes:offset
|
||||
recipes:address:shared:editor-data <- get *env, recipes:offset
|
||||
right:address:number <- get-address *recipes, right:offset
|
||||
*right <- subtract divider, 1
|
||||
# reset cursor (later we'll try to preserve its position)
|
||||
|
@ -195,7 +195,7 @@ recipe resize screen:address:screen, env:address:programming-environment-data ->
|
|||
cursor-column:address:number <- get-address *recipes, cursor-column:offset
|
||||
*cursor-column <- copy 0
|
||||
# update sandbox editor
|
||||
current-sandbox:address:editor-data <- get *env, current-sandbox:offset
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
left:address:number <- get-address *current-sandbox, left:offset
|
||||
right:address:number <- get-address *current-sandbox, right:offset
|
||||
*left <- add divider, 1
|
||||
|
@ -211,9 +211,9 @@ scenario point-at-multiple-editors [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 30/width, 5/height
|
||||
# initialize both halves of screen
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:array:character <- new [def]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:array:character <- new [def]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
# focus on both sides
|
||||
assume-console [
|
||||
left-click 1, 1
|
||||
|
@ -221,11 +221,11 @@ scenario point-at-multiple-editors [
|
|||
]
|
||||
# check cursor column in each
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
4:address:editor-data <- get *3:address:programming-environment-data, recipes:offset
|
||||
5:number <- get *4:address:editor-data, cursor-column:offset
|
||||
6:address:editor-data <- get *3:address:programming-environment-data, current-sandbox:offset
|
||||
7:number <- get *6:address:editor-data, cursor-column:offset
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
4:address:shared:editor-data <- get *3:address:shared:programming-environment-data, recipes:offset
|
||||
5:number <- get *4:address:shared:editor-data, cursor-column:offset
|
||||
6:address:shared:editor-data <- get *3:address:shared:programming-environment-data, current-sandbox:offset
|
||||
7:number <- get *6:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
memory-should-contain [
|
||||
5 <- 1
|
||||
|
@ -237,10 +237,10 @@ scenario edit-multiple-editors [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 30/width, 5/height
|
||||
# initialize both halves of screen
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:array:character <- new [def]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
render-all screen, 3:address:programming-environment-data
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:array:character <- new [def]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
render-all screen, 3:address:shared:programming-environment-data
|
||||
# type one letter in each of them
|
||||
assume-console [
|
||||
left-click 1, 1
|
||||
|
@ -249,11 +249,11 @@ scenario edit-multiple-editors [
|
|||
type [1]
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
4:address:editor-data <- get *3:address:programming-environment-data, recipes:offset
|
||||
5:number <- get *4:address:editor-data, cursor-column:offset
|
||||
6:address:editor-data <- get *3:address:programming-environment-data, current-sandbox:offset
|
||||
7:number <- get *6:address:editor-data, cursor-column:offset
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
4:address:shared:editor-data <- get *3:address:shared:programming-environment-data, recipes:offset
|
||||
5:number <- get *4:address:shared:editor-data, cursor-column:offset
|
||||
6:address:shared:editor-data <- get *3:address:shared:programming-environment-data, current-sandbox:offset
|
||||
7:number <- get *6:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
screen-should-contain [
|
||||
. run (F4) . # this line has a different background, but we don't test that yet
|
||||
|
@ -268,7 +268,7 @@ scenario edit-multiple-editors [
|
|||
# show the cursor at the right window
|
||||
run [
|
||||
8:character/cursor <- copy 9251/␣
|
||||
print screen:address:screen, 8:character/cursor
|
||||
print screen:address:shared:screen, 8:character/cursor
|
||||
]
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
|
@ -282,10 +282,10 @@ scenario multiple-editors-cover-only-their-own-areas [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 60/width, 10/height
|
||||
run [
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:array:character <- new [def]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
render-all screen, 3:address:programming-environment-data
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:array:character <- new [def]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
render-all screen, 3:address:shared:programming-environment-data
|
||||
]
|
||||
# divider isn't messed up
|
||||
screen-should-contain [
|
||||
|
@ -300,16 +300,16 @@ scenario multiple-editors-cover-only-their-own-areas [
|
|||
scenario editor-in-focus-keeps-cursor [
|
||||
trace-until 100/app # trace too long
|
||||
assume-screen 30/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:array:character <- new [def]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
render-all screen, 3:address:programming-environment-data
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:array:character <- new [def]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
render-all screen, 3:address:shared:programming-environment-data
|
||||
# initialize programming environment and highlight cursor
|
||||
assume-console []
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
4:character/cursor <- copy 9251/␣
|
||||
print screen:address:screen, 4:character/cursor
|
||||
print screen:address:shared:screen, 4:character/cursor
|
||||
]
|
||||
# is cursor at the right place?
|
||||
screen-should-contain [
|
||||
|
@ -323,9 +323,9 @@ scenario editor-in-focus-keeps-cursor [
|
|||
type [z]
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
4:character/cursor <- copy 9251/␣
|
||||
print screen:address:screen, 4:character/cursor
|
||||
print screen:address:shared:screen, 4:character/cursor
|
||||
]
|
||||
# cursor should still be right
|
||||
screen-should-contain [
|
||||
|
@ -340,11 +340,11 @@ scenario backspace-in-sandbox-editor-joins-lines [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 30/width, 5/height
|
||||
# initialize sandbox side with two lines
|
||||
1:address:array:character <- new []
|
||||
2:address:array:character <- new [abc
|
||||
1:address:shared:array:character <- new []
|
||||
2:address:shared:array:character <- new [abc
|
||||
def]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
render-all screen, 3:address:programming-environment-data
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
render-all screen, 3:address:shared:programming-environment-data
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
. ┊abc .
|
||||
|
@ -358,9 +358,9 @@ def]
|
|||
press backspace
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
4:character/cursor <- copy 9251/␣
|
||||
print screen:address:screen, 4:character/cursor
|
||||
print screen:address:shared:screen, 4:character/cursor
|
||||
]
|
||||
# cursor moves to end of old line
|
||||
screen-should-contain [
|
||||
|
@ -371,7 +371,7 @@ def]
|
|||
]
|
||||
]
|
||||
|
||||
recipe render-all screen:address:screen, env:address:programming-environment-data -> screen:address:screen [
|
||||
recipe render-all screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
trace 10, [app], [render all]
|
||||
|
@ -384,7 +384,7 @@ recipe render-all screen:address:screen, env:address:programming-environment-dat
|
|||
button-on-screen?:boolean <- greater-or-equal button-start, 0
|
||||
assert button-on-screen?, [screen too narrow for menu]
|
||||
screen <- move-cursor screen, 0/row, button-start
|
||||
run-button:address:array:character <- new [ run (F4) ]
|
||||
run-button:address:shared:array:character <- new [ run (F4) ]
|
||||
print screen, run-button, 255/white, 161/reddish
|
||||
# dotted line down the middle
|
||||
trace 11, [app], [render divider]
|
||||
|
@ -396,19 +396,19 @@ recipe render-all screen:address:screen, env:address:programming-environment-dat
|
|||
screen <- render-sandbox-side screen, env
|
||||
<render-components-end>
|
||||
#
|
||||
recipes:address:editor-data <- get *env, recipes:offset
|
||||
current-sandbox:address:editor-data <- get *env, current-sandbox:offset
|
||||
recipes:address:shared:editor-data <- get *env, recipes:offset
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
sandbox-in-focus?:boolean <- get *env, sandbox-in-focus?:offset
|
||||
screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?
|
||||
#
|
||||
show-screen screen
|
||||
]
|
||||
|
||||
recipe render-recipes screen:address:screen, env:address:programming-environment-data -> screen:address:screen [
|
||||
recipe render-recipes screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
trace 11, [app], [render recipes]
|
||||
recipes:address:editor-data <- get *env, recipes:offset
|
||||
recipes:address:shared:editor-data <- get *env, recipes:offset
|
||||
# render recipes
|
||||
left:number <- get *recipes, left:offset
|
||||
right:number <- get *recipes, right:offset
|
||||
|
@ -423,10 +423,10 @@ recipe render-recipes screen:address:screen, env:address:programming-environment
|
|||
]
|
||||
|
||||
# replaced in a later layer
|
||||
recipe render-sandbox-side screen:address:screen, env:address:programming-environment-data -> screen:address:screen [
|
||||
recipe render-sandbox-side screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
current-sandbox:address:editor-data <- get *env, current-sandbox:offset
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
left:number <- get *current-sandbox, left:offset
|
||||
right:number <- get *current-sandbox, right:offset
|
||||
row:number, column:number, screen, current-sandbox <- render screen, current-sandbox
|
||||
|
@ -438,7 +438,7 @@ recipe render-sandbox-side screen:address:screen, env:address:programming-enviro
|
|||
clear-screen-from screen, row, left, left, right
|
||||
]
|
||||
|
||||
recipe update-cursor screen:address:screen, recipes:address:editor-data, current-sandbox:address:editor-data, sandbox-in-focus?:boolean -> screen:address:screen [
|
||||
recipe update-cursor screen:address:shared:screen, recipes:address:shared:editor-data, current-sandbox:address:shared:editor-data, sandbox-in-focus?:boolean -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -456,7 +456,7 @@ recipe update-cursor screen:address:screen, recipes:address:editor-data, current
|
|||
|
||||
# print a text 's' to 'editor' in 'color' starting at 'row'
|
||||
# clear rest of last line, move cursor to next line
|
||||
recipe render screen:address:screen, s:address:array:character, left:number, right:number, color:number, row:number -> row:number, screen:address:screen [
|
||||
recipe render screen:address:shared:screen, s:address:shared:array:character, left:number, right:number, color:number, row:number -> row:number, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless s
|
||||
|
@ -517,7 +517,7 @@ recipe render screen:address:screen, s:address:array:character, left:number, rig
|
|||
]
|
||||
|
||||
# like 'render' for texts, but with colorization for comments like in the editor
|
||||
recipe render-code screen:address:screen, s:address:array:character, left:number, right:number, row:number -> row:number, screen:address:screen [
|
||||
recipe render-code screen:address:shared:screen, s:address:shared:array:character, left:number, right:number, row:number -> row:number, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless s
|
||||
|
@ -585,7 +585,7 @@ after <global-type> [
|
|||
{
|
||||
redraw-screen?:boolean <- equal *c, 12/ctrl-l
|
||||
break-unless redraw-screen?
|
||||
screen <- render-all screen, env:address:programming-environment-data
|
||||
screen <- render-all screen, env:address:shared:programming-environment-data
|
||||
sync-screen screen
|
||||
loop +next-event:label
|
||||
}
|
||||
|
@ -606,7 +606,7 @@ after <global-type> [
|
|||
|
||||
## helpers
|
||||
|
||||
recipe draw-vertical screen:address:screen, col:number, y:number, bottom:number -> screen:address:screen [
|
||||
recipe draw-vertical screen:address:shared:screen, col:number, y:number, bottom:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
style:character, style-found?:boolean <- next-ingredient
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
recipe! main [
|
||||
local-scope
|
||||
open-console
|
||||
initial-recipe:address:array:character <- restore [recipes.mu]
|
||||
initial-sandbox:address:array:character <- new []
|
||||
initial-recipe:address:shared:array:character <- restore [recipes.mu]
|
||||
initial-sandbox:address:shared:array:character <- new []
|
||||
hide-screen 0/screen
|
||||
env:address:programming-environment-data <- new-programming-environment 0/screen, initial-recipe, initial-sandbox
|
||||
env:address:shared:programming-environment-data <- new-programming-environment 0/screen, initial-recipe, initial-sandbox
|
||||
env <- restore-sandboxes env
|
||||
render-all 0/screen, env
|
||||
event-loop 0/screen, 0/console, env
|
||||
|
@ -18,35 +18,35 @@ recipe! main [
|
|||
]
|
||||
|
||||
container programming-environment-data [
|
||||
sandbox:address:sandbox-data # list of sandboxes, from top to bottom
|
||||
sandbox:address:shared:sandbox-data # list of sandboxes, from top to bottom
|
||||
]
|
||||
|
||||
container sandbox-data [
|
||||
data:address:array:character
|
||||
response:address:array:character
|
||||
expected-response:address:array:character
|
||||
data:address:shared:array:character
|
||||
response:address:shared:array:character
|
||||
expected-response:address:shared:array:character
|
||||
# coordinates to track clicks
|
||||
starting-row-on-screen:number
|
||||
code-ending-row-on-screen:number # past end of code
|
||||
response-starting-row-on-screen:number
|
||||
screen:address:screen # prints in the sandbox go here
|
||||
next-sandbox:address:sandbox-data
|
||||
screen:address:shared:screen # prints in the sandbox go here
|
||||
next-sandbox:address:shared:sandbox-data
|
||||
]
|
||||
|
||||
scenario run-and-show-results [
|
||||
trace-until 100/app # trace too long
|
||||
assume-screen 100/width, 15/height
|
||||
# recipe editor is empty
|
||||
1:address:array:character <- new []
|
||||
1:address:shared:array:character <- new []
|
||||
# sandbox editor contains an instruction without storing outputs
|
||||
2:address:array:character <- new [divide-with-remainder 11, 3]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
2:address:shared:array:character <- new [divide-with-remainder 11, 3]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
# run the code in the editors
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
# check that screen prints the results
|
||||
screen-should-contain [
|
||||
|
@ -89,7 +89,7 @@ scenario run-and-show-results [
|
|||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
# check that screen prints the results
|
||||
screen-should-contain [
|
||||
|
@ -115,14 +115,14 @@ after <global-keypress> [
|
|||
do-run?:boolean <- equal *k, 65532/F4
|
||||
break-unless do-run?
|
||||
#? $log [F4 pressed]
|
||||
status:address:array:character <- new [running... ]
|
||||
status:address:shared:array:character <- new [running... ]
|
||||
screen <- update-status screen, status, 245/grey
|
||||
error?:boolean, env, screen <- run-sandboxes env, screen
|
||||
# F4 might update warnings and results on both sides
|
||||
screen <- render-all screen, env
|
||||
{
|
||||
break-if error?
|
||||
status:address:array:character <- new [ ]
|
||||
status:address:shared:array:character <- new [ ]
|
||||
screen <- update-status screen, status, 245/grey
|
||||
}
|
||||
screen <- update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?
|
||||
|
@ -130,36 +130,36 @@ after <global-keypress> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe run-sandboxes env:address:programming-environment-data, screen:address:screen -> errors-found?:boolean, env:address:programming-environment-data, screen:address:screen [
|
||||
recipe run-sandboxes env:address:shared:programming-environment-data, screen:address:shared:screen -> errors-found?:boolean, env:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
errors-found?:boolean, env, screen <- update-recipes env, screen
|
||||
reply-if errors-found?
|
||||
# check contents of right editor (sandbox)
|
||||
current-sandbox:address:editor-data <- get *env, current-sandbox:offset
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
{
|
||||
sandbox-contents:address:array:character <- editor-contents current-sandbox
|
||||
sandbox-contents:address:shared:array:character <- editor-contents current-sandbox
|
||||
break-unless sandbox-contents
|
||||
# if contents exist, first save them
|
||||
# run them and turn them into a new sandbox-data
|
||||
new-sandbox:address:sandbox-data <- new sandbox-data:type
|
||||
data:address:address:array:character <- get-address *new-sandbox, data:offset
|
||||
new-sandbox:address:shared:sandbox-data <- new sandbox-data:type
|
||||
data:address:address:shared:array:character <- get-address *new-sandbox, data:offset
|
||||
*data <- copy sandbox-contents
|
||||
# push to head of sandbox list
|
||||
dest:address:address:sandbox-data <- get-address *env, sandbox:offset
|
||||
next:address:address:sandbox-data <- get-address *new-sandbox, next-sandbox:offset
|
||||
dest:address:address:shared:sandbox-data <- get-address *env, sandbox:offset
|
||||
next:address:address:shared:sandbox-data <- get-address *new-sandbox, next-sandbox:offset
|
||||
*next <- copy *dest
|
||||
*dest <- copy new-sandbox
|
||||
# clear sandbox editor
|
||||
init:address:address:duplex-list:character <- get-address *current-sandbox, data:offset
|
||||
init:address:address:shared:duplex-list:character <- get-address *current-sandbox, data:offset
|
||||
*init <- push 167/§, 0/tail
|
||||
top-of-screen:address:address:duplex-list:character <- get-address *current-sandbox, top-of-screen:offset
|
||||
top-of-screen:address:address:shared:duplex-list:character <- get-address *current-sandbox, top-of-screen:offset
|
||||
*top-of-screen <- copy *init
|
||||
}
|
||||
# save all sandboxes before running, just in case we die when running
|
||||
save-sandboxes env
|
||||
# run all sandboxes
|
||||
curr:address:sandbox-data <- get *env, sandbox:offset
|
||||
curr:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
{
|
||||
break-unless curr
|
||||
curr <- update-sandbox curr
|
||||
|
@ -171,49 +171,49 @@ recipe run-sandboxes env:address:programming-environment-data, screen:address:sc
|
|||
|
||||
# copy code from recipe editor, persist, load into mu
|
||||
# replaced in a later layer (whereupon errors-found? will actually be set)
|
||||
recipe update-recipes env:address:programming-environment-data, screen:address:screen -> errors-found?:boolean, env:address:programming-environment-data, screen:address:screen [
|
||||
recipe update-recipes env:address:shared:programming-environment-data, screen:address:shared:screen -> errors-found?:boolean, env:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
recipes:address:editor-data <- get *env, recipes:offset
|
||||
in:address:array:character <- editor-contents recipes
|
||||
recipes:address:shared:editor-data <- get *env, recipes:offset
|
||||
in:address:shared:array:character <- editor-contents recipes
|
||||
save [recipes.mu], in # newlayer: persistence
|
||||
reload in
|
||||
errors-found? <- copy 0/false
|
||||
]
|
||||
|
||||
# replaced in a later layer
|
||||
recipe update-sandbox sandbox:address:sandbox-data -> sandbox:address:sandbox-data [
|
||||
recipe update-sandbox sandbox:address:shared:sandbox-data -> sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
data:address:array:character <- get *sandbox, data:offset
|
||||
response:address:address:array:character <- get-address *sandbox, response:offset
|
||||
fake-screen:address:address:screen <- get-address *sandbox, screen:offset
|
||||
data:address:shared:array:character <- get *sandbox, data:offset
|
||||
response:address:address:shared:array:character <- get-address *sandbox, response:offset
|
||||
fake-screen:address:address:shared:screen <- get-address *sandbox, screen:offset
|
||||
*response, _, *fake-screen <- run-interactive data
|
||||
]
|
||||
|
||||
recipe update-status screen:address:screen, msg:address:array:character, color:number -> screen:address:screen [
|
||||
recipe update-status screen:address:shared:screen, msg:address:shared:array:character, color:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
screen <- move-cursor screen, 0, 2
|
||||
screen <- print screen, msg, color, 238/grey/background
|
||||
]
|
||||
|
||||
recipe save-sandboxes env:address:programming-environment-data [
|
||||
recipe save-sandboxes env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
current-sandbox:address:editor-data <- get *env, current-sandbox:offset
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
# first clear previous versions, in case we deleted some sandbox
|
||||
$system [rm lesson/[0-9]* >/dev/null 2>/dev/null] # some shells can't handle '>&'
|
||||
curr:address:sandbox-data <- get *env, sandbox:offset
|
||||
suffix:address:array:character <- new [.out]
|
||||
curr:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
suffix:address:shared:array:character <- new [.out]
|
||||
idx:number <- copy 0
|
||||
{
|
||||
break-unless curr
|
||||
data:address:array:character <- get *curr, data:offset
|
||||
filename:address:array:character <- to-text idx
|
||||
data:address:shared:array:character <- get *curr, data:offset
|
||||
filename:address:shared:array:character <- to-text idx
|
||||
save filename, data
|
||||
{
|
||||
expected-response:address:array:character <- get *curr, expected-response:offset
|
||||
expected-response:address:shared:array:character <- get *curr, expected-response:offset
|
||||
break-unless expected-response
|
||||
filename <- append filename, suffix
|
||||
save filename, expected-response
|
||||
|
@ -224,24 +224,24 @@ recipe save-sandboxes env:address:programming-environment-data [
|
|||
}
|
||||
]
|
||||
|
||||
recipe! render-sandbox-side screen:address:screen, env:address:programming-environment-data -> screen:address:screen [
|
||||
recipe! render-sandbox-side screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
#? $log [render sandbox side]
|
||||
trace 11, [app], [render sandbox side]
|
||||
current-sandbox:address:editor-data <- get *env, current-sandbox:offset
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
left:number <- get *current-sandbox, left:offset
|
||||
right:number <- get *current-sandbox, right:offset
|
||||
row:number, column:number, screen, current-sandbox <- render screen, current-sandbox
|
||||
clear-screen-from screen, row, column, left, right
|
||||
row <- add row, 1
|
||||
draw-horizontal screen, row, left, right, 9473/horizontal-double
|
||||
sandbox:address:sandbox-data <- get *env, sandbox:offset
|
||||
sandbox:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
row, screen <- render-sandboxes screen, sandbox, left, right, row
|
||||
clear-rest-of-screen screen, row, left, left, right
|
||||
]
|
||||
|
||||
recipe render-sandboxes screen:address:screen, sandbox:address:sandbox-data, left:number, right:number, row:number -> row:number, screen:address:screen, sandbox:address:sandbox-data [
|
||||
recipe render-sandboxes screen:address:shared:screen, sandbox:address:shared:sandbox-data, left:number, right:number, row:number -> row:number, screen:address:shared:screen, sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
#? $log [render sandbox]
|
||||
|
@ -261,16 +261,16 @@ recipe render-sandboxes screen:address:screen, sandbox:address:sandbox-data, lef
|
|||
# render sandbox contents
|
||||
row <- add row, 1
|
||||
screen <- move-cursor screen, row, left
|
||||
sandbox-data:address:array:character <- get *sandbox, data:offset
|
||||
sandbox-data:address:shared:array:character <- get *sandbox, data:offset
|
||||
row, screen <- render-code screen, sandbox-data, left, right, row
|
||||
code-ending-row:address:number <- get-address *sandbox, code-ending-row-on-screen:offset
|
||||
*code-ending-row <- copy row
|
||||
# render sandbox warnings, screen or response, in that order
|
||||
response-starting-row:address:number <- get-address *sandbox, response-starting-row-on-screen:offset
|
||||
sandbox-response:address:array:character <- get *sandbox, response:offset
|
||||
sandbox-response:address:shared:array:character <- get *sandbox, response:offset
|
||||
<render-sandbox-results>
|
||||
{
|
||||
sandbox-screen:address:screen <- get *sandbox, screen:offset
|
||||
sandbox-screen:address:shared:screen <- get *sandbox, screen:offset
|
||||
empty-screen?:boolean <- fake-screen-is-empty? sandbox-screen
|
||||
break-if empty-screen?
|
||||
row, screen <- render-screen screen, sandbox-screen, left, right, row
|
||||
|
@ -287,32 +287,32 @@ recipe render-sandboxes screen:address:screen, sandbox:address:sandbox-data, lef
|
|||
# draw solid line after sandbox
|
||||
draw-horizontal screen, row, left, right, 9473/horizontal-double
|
||||
# draw next sandbox
|
||||
next-sandbox:address:sandbox-data <- get *sandbox, next-sandbox:offset
|
||||
next-sandbox:address:shared:sandbox-data <- get *sandbox, next-sandbox:offset
|
||||
row, screen <- render-sandboxes screen, next-sandbox, left, right, row
|
||||
]
|
||||
|
||||
# assumes programming environment has no sandboxes; restores them from previous session
|
||||
recipe restore-sandboxes env:address:programming-environment-data -> env:address:programming-environment-data [
|
||||
recipe restore-sandboxes env:address:shared:programming-environment-data -> env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# read all scenarios, pushing them to end of a list of scenarios
|
||||
suffix:address:array:character <- new [.out]
|
||||
suffix:address:shared:array:character <- new [.out]
|
||||
idx:number <- copy 0
|
||||
curr:address:address:sandbox-data <- get-address *env, sandbox:offset
|
||||
curr:address:address:shared:sandbox-data <- get-address *env, sandbox:offset
|
||||
{
|
||||
filename:address:array:character <- to-text idx
|
||||
contents:address:array:character <- restore filename
|
||||
filename:address:shared:array:character <- to-text idx
|
||||
contents:address:shared:array:character <- restore filename
|
||||
break-unless contents # stop at first error; assuming file didn't exist
|
||||
# create new sandbox for file
|
||||
*curr <- new sandbox-data:type
|
||||
data:address:address:array:character <- get-address **curr, data:offset
|
||||
data:address:address:shared:array:character <- get-address **curr, data:offset
|
||||
*data <- copy contents
|
||||
# restore expected output for sandbox if it exists
|
||||
{
|
||||
filename <- append filename, suffix
|
||||
contents <- restore filename
|
||||
break-unless contents
|
||||
expected-response:address:address:array:character <- get-address **curr, expected-response:offset
|
||||
expected-response:address:address:shared:array:character <- get-address **curr, expected-response:offset
|
||||
*expected-response <- copy contents
|
||||
}
|
||||
+continue
|
||||
|
@ -324,19 +324,19 @@ recipe restore-sandboxes env:address:programming-environment-data -> env:address
|
|||
|
||||
# print the fake sandbox screen to 'screen' with appropriate delimiters
|
||||
# leave cursor at start of next line
|
||||
recipe render-screen screen:address:screen, sandbox-screen:address:screen, left:number, right:number, row:number -> row:number, screen:address:screen [
|
||||
recipe render-screen screen:address:shared:screen, sandbox-screen:address:shared:screen, left:number, right:number, row:number -> row:number, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless sandbox-screen
|
||||
# print 'screen:'
|
||||
header:address:array:character <- new [screen:]
|
||||
header:address:shared:array:character <- new [screen:]
|
||||
row <- render screen, header, left, right, 245/grey, row
|
||||
screen <- move-cursor screen, row, left
|
||||
# start printing sandbox-screen
|
||||
column:number <- copy left
|
||||
s-width:number <- screen-width sandbox-screen
|
||||
s-height:number <- screen-height sandbox-screen
|
||||
buf:address:array:screen-cell <- get *sandbox-screen, data:offset
|
||||
buf:address:shared:array:screen-cell <- get *sandbox-screen, data:offset
|
||||
stop-printing:number <- add left, s-width, 3
|
||||
max-column:number <- min stop-printing, right
|
||||
i:number <- copy 0
|
||||
|
@ -394,19 +394,19 @@ scenario run-updates-results [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 100/width, 12/height
|
||||
# define a recipe (no indent for the 'add' line below so column numbers are more obvious)
|
||||
1:address:array:character <- new [
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
z:number <- add 2, 2
|
||||
reply z
|
||||
]]
|
||||
# sandbox editor contains an instruction without storing outputs
|
||||
2:address:array:character <- new [foo]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
2:address:shared:array:character <- new [foo]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
# run the code in the editors
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
. ┊ .
|
||||
|
@ -425,7 +425,7 @@ reply z
|
|||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
# check that screen updates the result on the right
|
||||
screen-should-contain [
|
||||
|
@ -444,16 +444,16 @@ scenario run-instruction-manages-screen-per-sandbox [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 100/width, 20/height
|
||||
# left editor is empty
|
||||
1:address:array:character <- new []
|
||||
1:address:shared:array:character <- new []
|
||||
# right editor contains an instruction
|
||||
2:address:array:character <- new [print-integer screen, 4]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
2:address:shared:array:character <- new [print-integer screen, 4]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
# run the code in the editor
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
# check that it prints a little toy screen
|
||||
screen-should-contain [
|
||||
|
@ -473,11 +473,11 @@ scenario run-instruction-manages-screen-per-sandbox [
|
|||
]
|
||||
]
|
||||
|
||||
recipe editor-contents editor:address:editor-data -> result:address:array:character [
|
||||
recipe editor-contents editor:address:shared:editor-data -> result:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
buf:address:buffer <- new-buffer 80
|
||||
curr:address:duplex-list:character <- get *editor, data:offset
|
||||
buf:address:shared:buffer <- new-buffer 80
|
||||
curr:address:shared:duplex-list:character <- get *editor, data:offset
|
||||
# skip § sentinel
|
||||
assert curr, [editor without data is illegal; must have at least a sentinel]
|
||||
curr <- next curr
|
||||
|
@ -494,16 +494,16 @@ recipe editor-contents editor:address:editor-data -> result:address:array:charac
|
|||
|
||||
scenario editor-provides-edited-contents [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
assume-console [
|
||||
left-click 1, 2
|
||||
type [def]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:address:array:character <- editor-contents 2:address:editor-data
|
||||
4:array:character <- copy *3:address:array:character
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:address:shared:array:character <- editor-contents 2:address:shared:editor-data
|
||||
4:array:character <- copy *3:address:shared:array:character
|
||||
]
|
||||
memory-should-contain [
|
||||
4:array:character <- [abdefc]
|
||||
|
|
|
@ -4,17 +4,17 @@ scenario clicking-on-a-sandbox-moves-it-to-editor [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 40/width, 10/height
|
||||
# basic recipe
|
||||
1:address:array:character <- new [
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
reply 4
|
||||
]]
|
||||
# run it
|
||||
2:address:array:character <- new [foo]
|
||||
2:address:shared:array:character <- new [foo]
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
. ┊ .
|
||||
|
@ -30,7 +30,7 @@ recipe foo [
|
|||
left-click 3, 30
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
# it pops back into editor
|
||||
screen-should-contain [
|
||||
|
@ -48,7 +48,7 @@ recipe foo [
|
|||
type [0]
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
|
@ -69,7 +69,7 @@ after <global-touch> [
|
|||
click-column:number <- get *t, column:offset
|
||||
on-sandbox-side?:boolean <- greater-or-equal click-column, sandbox-left-margin
|
||||
break-unless on-sandbox-side?
|
||||
first-sandbox:address:sandbox-data <- get *env, sandbox:offset
|
||||
first-sandbox:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
break-unless first-sandbox
|
||||
first-sandbox-begins:number <- get *first-sandbox, starting-row-on-screen:offset
|
||||
click-row:number <- get *t, row:offset
|
||||
|
@ -78,8 +78,8 @@ after <global-touch> [
|
|||
empty-sandbox-editor?:boolean <- empty-editor? current-sandbox
|
||||
break-unless empty-sandbox-editor? # don't clobber existing contents
|
||||
# identify the sandbox to edit and remove it from the sandbox list
|
||||
sandbox:address:sandbox-data <- extract-sandbox env, click-row
|
||||
text:address:array:character <- get *sandbox, data:offset
|
||||
sandbox:address:shared:sandbox-data <- extract-sandbox env, click-row
|
||||
text:address:shared:array:character <- get *sandbox, data:offset
|
||||
current-sandbox <- insert-text current-sandbox, text
|
||||
hide-screen screen
|
||||
screen <- render-sandbox-side screen, env
|
||||
|
@ -89,24 +89,24 @@ after <global-touch> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe empty-editor? editor:address:editor-data -> result:boolean [
|
||||
recipe empty-editor? editor:address:shared:editor-data -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
head:address:duplex-list:character <- get *editor, data:offset
|
||||
first:address:duplex-list:character <- next head
|
||||
head:address:shared:duplex-list:character <- get *editor, data:offset
|
||||
first:address:shared:duplex-list:character <- next head
|
||||
result <- not first
|
||||
]
|
||||
|
||||
recipe extract-sandbox env:address:programming-environment-data, click-row:number -> result:address:sandbox-data, env:address:programming-environment-data [
|
||||
recipe extract-sandbox env:address:shared:programming-environment-data, click-row:number -> result:address:shared:sandbox-data, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# assert click-row >= sandbox.starting-row-on-screen
|
||||
sandbox:address:address:sandbox-data <- get-address *env, sandbox:offset
|
||||
sandbox:address:address:shared:sandbox-data <- get-address *env, sandbox:offset
|
||||
start:number <- get **sandbox, starting-row-on-screen:offset
|
||||
clicked-on-sandboxes?:boolean <- greater-or-equal click-row, start
|
||||
assert clicked-on-sandboxes?, [extract-sandbox called on click to sandbox editor]
|
||||
{
|
||||
next-sandbox:address:sandbox-data <- get **sandbox, next-sandbox:offset
|
||||
next-sandbox:address:shared:sandbox-data <- get **sandbox, next-sandbox:offset
|
||||
break-unless next-sandbox
|
||||
# if click-row < sandbox.next-sandbox.starting-row-on-screen, break
|
||||
next-start:number <- get *next-sandbox, starting-row-on-screen:offset
|
||||
|
@ -127,15 +127,15 @@ scenario sandbox-with-print-can-be-edited [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 100/width, 20/height
|
||||
# left editor is empty
|
||||
1:address:array:character <- new []
|
||||
1:address:shared:array:character <- new []
|
||||
# right editor contains an instruction
|
||||
2:address:array:character <- new [print-integer screen, 4]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
2:address:shared:array:character <- new [print-integer screen, 4]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
# run the sandbox
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
. ┊ .
|
||||
|
@ -156,7 +156,7 @@ scenario sandbox-with-print-can-be-edited [
|
|||
left-click 3, 70
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
scenario deleting-sandboxes [
|
||||
trace-until 100/app # trace too long
|
||||
assume-screen 100/width, 15/height
|
||||
1:address:array:character <- new []
|
||||
2:address:array:character <- new []
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
1:address:shared:array:character <- new []
|
||||
2:address:shared:array:character <- new []
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
# run a few commands
|
||||
assume-console [
|
||||
left-click 1, 80
|
||||
|
@ -14,7 +14,7 @@ scenario deleting-sandboxes [
|
|||
type [add 2, 2]
|
||||
press F4
|
||||
]
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
. ┊ .
|
||||
|
@ -35,7 +35,7 @@ scenario deleting-sandboxes [
|
|||
left-click 7, 99
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
|
@ -53,7 +53,7 @@ scenario deleting-sandboxes [
|
|||
left-click 3, 99
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
|
@ -77,17 +77,17 @@ after <global-touch> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe delete-sandbox t:touch-event, env:address:programming-environment-data -> was-delete?:boolean, env:address:programming-environment-data [
|
||||
recipe delete-sandbox t:touch-event, env:address:shared:programming-environment-data -> was-delete?:boolean, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
click-column:number <- get t, column:offset
|
||||
current-sandbox:address:editor-data <- get *env, current-sandbox:offset
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
right:number <- get *current-sandbox, right:offset
|
||||
at-right?:boolean <- equal click-column, right
|
||||
reply-unless at-right?, 0/false
|
||||
click-row:number <- get t, row:offset
|
||||
prev:address:address:sandbox-data <- get-address *env, sandbox:offset
|
||||
curr:address:sandbox-data <- get *env, sandbox:offset
|
||||
prev:address:address:shared:sandbox-data <- get-address *env, sandbox:offset
|
||||
curr:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
{
|
||||
break-unless curr
|
||||
# more sandboxes to check
|
||||
|
|
|
@ -4,17 +4,17 @@ scenario sandbox-click-on-result-toggles-color-to-green [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 40/width, 10/height
|
||||
# basic recipe
|
||||
1:address:array:character <- new [
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
reply 4
|
||||
]]
|
||||
# run it
|
||||
2:address:array:character <- new [foo]
|
||||
2:address:shared:array:character <- new [foo]
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
. ┊ .
|
||||
|
@ -30,7 +30,7 @@ recipe foo [
|
|||
left-click 5, 21
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
# color toggles to green
|
||||
screen-should-contain-in-color 2/green, [
|
||||
|
@ -46,7 +46,7 @@ recipe foo [
|
|||
# cursor should remain unmoved
|
||||
run [
|
||||
4:character/cursor <- copy 9251/␣
|
||||
print screen:address:screen, 4:character/cursor
|
||||
print screen:address:shared:screen, 4:character/cursor
|
||||
]
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
|
@ -67,7 +67,7 @@ recipe foo [
|
|||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
# result turns red
|
||||
screen-should-contain-in-color 1/red, [
|
||||
|
@ -90,14 +90,14 @@ after <global-touch> [
|
|||
click-column:number <- get *t, column:offset
|
||||
on-sandbox-side?:boolean <- greater-or-equal click-column, sandbox-left-margin
|
||||
break-unless on-sandbox-side?
|
||||
first-sandbox:address:sandbox-data <- get *env, sandbox:offset
|
||||
first-sandbox:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
break-unless first-sandbox
|
||||
first-sandbox-begins:number <- get *first-sandbox, starting-row-on-screen:offset
|
||||
click-row:number <- get *t, row:offset
|
||||
below-sandbox-editor?:boolean <- greater-or-equal click-row, first-sandbox-begins
|
||||
break-unless below-sandbox-editor?
|
||||
# identify the sandbox whose output is being clicked on
|
||||
sandbox:address:sandbox-data <- find-click-in-sandbox-output env, click-row
|
||||
sandbox:address:shared:sandbox-data <- find-click-in-sandbox-output env, click-row
|
||||
break-unless sandbox
|
||||
# toggle its expected-response, and save session
|
||||
sandbox <- toggle-expected-response sandbox
|
||||
|
@ -111,17 +111,17 @@ after <global-touch> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe find-click-in-sandbox-output env:address:programming-environment-data, click-row:number -> sandbox:address:sandbox-data [
|
||||
recipe find-click-in-sandbox-output env:address:shared:programming-environment-data, click-row:number -> sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# assert click-row >= sandbox.starting-row-on-screen
|
||||
sandbox:address:sandbox-data <- get *env, sandbox:offset
|
||||
sandbox:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
start:number <- get *sandbox, starting-row-on-screen:offset
|
||||
clicked-on-sandboxes?:boolean <- greater-or-equal click-row, start
|
||||
assert clicked-on-sandboxes?, [extract-sandbox called on click to sandbox editor]
|
||||
# while click-row < sandbox.next-sandbox.starting-row-on-screen
|
||||
{
|
||||
next-sandbox:address:sandbox-data <- get *sandbox, next-sandbox:offset
|
||||
next-sandbox:address:shared:sandbox-data <- get *sandbox, next-sandbox:offset
|
||||
break-unless next-sandbox
|
||||
next-start:number <- get *next-sandbox, starting-row-on-screen:offset
|
||||
found?:boolean <- lesser-than click-row, next-start
|
||||
|
@ -137,10 +137,10 @@ recipe find-click-in-sandbox-output env:address:programming-environment-data, cl
|
|||
reply sandbox
|
||||
]
|
||||
|
||||
recipe toggle-expected-response sandbox:address:sandbox-data -> sandbox:address:sandbox-data [
|
||||
recipe toggle-expected-response sandbox:address:shared:sandbox-data -> sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
expected-response:address:address:array:character <- get-address *sandbox, expected-response:offset
|
||||
expected-response:address:address:shared:array:character <- get-address *sandbox, expected-response:offset
|
||||
{
|
||||
# if expected-response is set, reset
|
||||
break-unless *expected-response
|
||||
|
@ -148,7 +148,7 @@ recipe toggle-expected-response sandbox:address:sandbox-data -> sandbox:address:
|
|||
reply sandbox/same-as-ingredient:0
|
||||
}
|
||||
# if not, current response is the expected response
|
||||
response:address:array:character <- get *sandbox, response:offset
|
||||
response:address:shared:array:character <- get *sandbox, response:offset
|
||||
*expected-response <- copy response
|
||||
]
|
||||
|
||||
|
@ -156,7 +156,7 @@ recipe toggle-expected-response sandbox:address:sandbox-data -> sandbox:address:
|
|||
after <render-sandbox-response> [
|
||||
{
|
||||
break-unless sandbox-response
|
||||
expected-response:address:array:character <- get *sandbox, expected-response:offset
|
||||
expected-response:address:shared:array:character <- get *sandbox, expected-response:offset
|
||||
break-unless expected-response # fall-through to print in grey
|
||||
response-is-expected?:boolean <- equal expected-response, sandbox-response
|
||||
{
|
||||
|
|
|
@ -4,17 +4,17 @@ scenario sandbox-click-on-code-toggles-app-trace [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 40/width, 10/height
|
||||
# basic recipe
|
||||
1:address:array:character <- new [
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
stash [abc]
|
||||
]]
|
||||
# run it
|
||||
2:address:array:character <- new [foo]
|
||||
2:address:shared:array:character <- new [foo]
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
. ┊ .
|
||||
|
@ -29,9 +29,9 @@ recipe foo [
|
|||
left-click 4, 21
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
4:character/cursor-icon <- copy 9251/␣
|
||||
print screen:address:screen, 4:character/cursor-icon
|
||||
print screen:address:shared:screen, 4:character/cursor-icon
|
||||
]
|
||||
# trace now printed and cursor shouldn't have budged
|
||||
screen-should-contain [
|
||||
|
@ -59,8 +59,8 @@ recipe foo [
|
|||
left-click 4, 25
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
print screen:address:screen, 4:character/cursor-icon
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
print screen:address:shared:screen, 4:character/cursor-icon
|
||||
]
|
||||
# trace hidden again
|
||||
screen-should-contain [
|
||||
|
@ -78,18 +78,18 @@ scenario sandbox-shows-app-trace-and-result [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 40/width, 10/height
|
||||
# basic recipe
|
||||
1:address:array:character <- new [
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
stash [abc]
|
||||
reply 4
|
||||
]]
|
||||
# run it
|
||||
2:address:array:character <- new [foo]
|
||||
2:address:shared:array:character <- new [foo]
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
. ┊ .
|
||||
|
@ -105,7 +105,7 @@ recipe foo [
|
|||
left-click 4, 21
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
# trace now printed above result
|
||||
screen-should-contain [
|
||||
|
@ -122,18 +122,18 @@ recipe foo [
|
|||
]
|
||||
|
||||
container sandbox-data [
|
||||
trace:address:array:character
|
||||
trace:address:shared:array:character
|
||||
display-trace?:boolean
|
||||
]
|
||||
|
||||
# replaced in a later layer
|
||||
recipe! update-sandbox sandbox:address:sandbox-data -> sandbox:address:sandbox-data [
|
||||
recipe! update-sandbox sandbox:address:shared:sandbox-data -> sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
data:address:array:character <- get *sandbox, data:offset
|
||||
response:address:address:array:character <- get-address *sandbox, response:offset
|
||||
trace:address:address:array:character <- get-address *sandbox, trace:offset
|
||||
fake-screen:address:address:screen <- get-address *sandbox, screen:offset
|
||||
data:address:shared:array:character <- get *sandbox, data:offset
|
||||
response:address:address:shared:array:character <- get-address *sandbox, response:offset
|
||||
trace:address:address:shared:array:character <- get-address *sandbox, trace:offset
|
||||
fake-screen:address:address:shared:screen <- get-address *sandbox, screen:offset
|
||||
*response, _, *fake-screen, *trace <- run-interactive data
|
||||
]
|
||||
|
||||
|
@ -145,14 +145,14 @@ after <global-touch> [
|
|||
click-column:number <- get *t, column:offset
|
||||
on-sandbox-side?:boolean <- greater-or-equal click-column, sandbox-left-margin
|
||||
break-unless on-sandbox-side?
|
||||
first-sandbox:address:sandbox-data <- get *env, sandbox:offset
|
||||
first-sandbox:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
break-unless first-sandbox
|
||||
first-sandbox-begins:number <- get *first-sandbox, starting-row-on-screen:offset
|
||||
click-row:number <- get *t, row:offset
|
||||
below-sandbox-editor?:boolean <- greater-or-equal click-row, first-sandbox-begins
|
||||
break-unless below-sandbox-editor?
|
||||
# identify the sandbox whose code is being clicked on
|
||||
sandbox:address:sandbox-data <- find-click-in-sandbox-code env, click-row
|
||||
sandbox:address:shared:sandbox-data <- find-click-in-sandbox-code env, click-row
|
||||
break-unless sandbox
|
||||
# toggle its display-trace? property
|
||||
x:address:boolean <- get-address *sandbox, display-trace?:offset
|
||||
|
@ -166,7 +166,7 @@ after <global-touch> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe find-click-in-sandbox-code env:address:programming-environment-data, click-row:number -> sandbox:address:sandbox-data [
|
||||
recipe find-click-in-sandbox-code env:address:shared:programming-environment-data, click-row:number -> sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# assert click-row >= sandbox.starting-row-on-screen
|
||||
|
@ -176,7 +176,7 @@ recipe find-click-in-sandbox-code env:address:programming-environment-data, clic
|
|||
assert clicked-on-sandboxes?, [extract-sandbox called on click to sandbox editor]
|
||||
# while click-row < sandbox.next-sandbox.starting-row-on-screen
|
||||
{
|
||||
next-sandbox:address:sandbox-data <- get *sandbox, next-sandbox:offset
|
||||
next-sandbox:address:shared:sandbox-data <- get *sandbox, next-sandbox:offset
|
||||
break-unless next-sandbox
|
||||
next-start:number <- get *next-sandbox, starting-row-on-screen:offset
|
||||
found?:boolean <- lesser-than click-row, next-start
|
||||
|
@ -202,7 +202,7 @@ after <render-sandbox-results> [
|
|||
{
|
||||
display-trace?:boolean <- get *sandbox, display-trace?:offset
|
||||
break-unless display-trace?
|
||||
sandbox-trace:address:array:character <- get *sandbox, trace:offset
|
||||
sandbox-trace:address:shared:array:character <- get *sandbox, trace:offset
|
||||
break-unless sandbox-trace # nothing to print; move on
|
||||
row, screen <- render screen, sandbox-trace, left, right, 245/grey, row
|
||||
}
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
## handling malformed programs
|
||||
|
||||
container programming-environment-data [
|
||||
recipe-warnings:address:array:character
|
||||
recipe-warnings:address:shared:array:character
|
||||
]
|
||||
|
||||
# copy code from recipe editor, persist, load into mu, save any warnings
|
||||
recipe! update-recipes env:address:programming-environment-data, screen:address:screen -> errors-found?:boolean, env:address:programming-environment-data, screen:address:screen [
|
||||
recipe! update-recipes env:address:shared:programming-environment-data, screen:address:shared:screen -> errors-found?:boolean, env:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
#? $log [update recipes]
|
||||
recipes:address:editor-data <- get *env, recipes:offset
|
||||
in:address:array:character <- editor-contents recipes
|
||||
recipes:address:shared:editor-data <- get *env, recipes:offset
|
||||
in:address:shared:array:character <- editor-contents recipes
|
||||
save [recipes.mu], in
|
||||
recipe-warnings:address:address:array:character <- get-address *env, recipe-warnings:offset
|
||||
recipe-warnings:address:address:shared:array:character <- get-address *env, recipe-warnings:offset
|
||||
*recipe-warnings <- reload in
|
||||
# if recipe editor has errors, stop
|
||||
{
|
||||
break-unless *recipe-warnings
|
||||
status:address:array:character <- new [errors found]
|
||||
status:address:shared:array:character <- new [errors found]
|
||||
update-status screen, status, 1/red
|
||||
errors-found? <- copy 1/true
|
||||
reply
|
||||
|
@ -27,35 +27,35 @@ recipe! update-recipes env:address:programming-environment-data, screen:address:
|
|||
|
||||
before <render-components-end> [
|
||||
trace 11, [app], [render status]
|
||||
recipe-warnings:address:array:character <- get *env, recipe-warnings:offset
|
||||
recipe-warnings:address:shared:array:character <- get *env, recipe-warnings:offset
|
||||
{
|
||||
break-unless recipe-warnings
|
||||
status:address:array:character <- new [errors found]
|
||||
status:address:shared:array:character <- new [errors found]
|
||||
update-status screen, status, 1/red
|
||||
}
|
||||
]
|
||||
|
||||
before <render-recipe-components-end> [
|
||||
{
|
||||
recipe-warnings:address:array:character <- get *env, recipe-warnings:offset
|
||||
recipe-warnings:address:shared:array:character <- get *env, recipe-warnings:offset
|
||||
break-unless recipe-warnings
|
||||
row, screen <- render screen, recipe-warnings, left, right, 1/red, row
|
||||
}
|
||||
]
|
||||
|
||||
container sandbox-data [
|
||||
warnings:address:array:character
|
||||
warnings:address:shared:array:character
|
||||
]
|
||||
|
||||
recipe! update-sandbox sandbox:address:sandbox-data -> sandbox:address:sandbox-data [
|
||||
recipe! update-sandbox sandbox:address:shared:sandbox-data -> sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
#? $log [update sandbox]
|
||||
data:address:array:character <- get *sandbox, data:offset
|
||||
response:address:address:array:character <- get-address *sandbox, response:offset
|
||||
warnings:address:address:array:character <- get-address *sandbox, warnings:offset
|
||||
trace:address:address:array:character <- get-address *sandbox, trace:offset
|
||||
fake-screen:address:address:screen <- get-address *sandbox, screen:offset
|
||||
data:address:shared:array:character <- get *sandbox, data:offset
|
||||
response:address:address:shared:array:character <- get-address *sandbox, response:offset
|
||||
warnings:address:address:shared:array:character <- get-address *sandbox, warnings:offset
|
||||
trace:address:address:shared:array:character <- get-address *sandbox, trace:offset
|
||||
fake-screen:address:address:shared:screen <- get-address *sandbox, screen:offset
|
||||
#? $print [run-interactive], 10/newline
|
||||
*response, *warnings, *fake-screen, *trace, completed?:boolean <- run-interactive data
|
||||
{
|
||||
|
@ -70,7 +70,7 @@ recipe! update-sandbox sandbox:address:sandbox-data -> sandbox:address:sandbox-d
|
|||
# make sure we render any trace
|
||||
after <render-sandbox-trace-done> [
|
||||
{
|
||||
sandbox-warnings:address:array:character <- get *sandbox, warnings:offset
|
||||
sandbox-warnings:address:shared:array:character <- get *sandbox, warnings:offset
|
||||
break-unless sandbox-warnings
|
||||
*response-starting-row <- copy 0 # no response
|
||||
row, screen <- render screen, sandbox-warnings, left, right, 1/red, row
|
||||
|
@ -82,17 +82,17 @@ after <render-sandbox-trace-done> [
|
|||
scenario run-shows-warnings-in-get [
|
||||
trace-until 100/app # trace too long
|
||||
assume-screen 100/width, 15/height
|
||||
1:address:array:character <- new [
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
get 123:number, foo:offset
|
||||
]]
|
||||
2:address:array:character <- new [foo]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
2:address:shared:array:character <- new [foo]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. errors found run (F4) .
|
||||
|
@ -122,14 +122,14 @@ recipe foo [
|
|||
scenario run-hides-warnings-from-past-sandboxes [
|
||||
trace-until 100/app # trace too long
|
||||
assume-screen 100/width, 15/height
|
||||
1:address:array:character <- new []
|
||||
2:address:array:character <- new [get foo, x:offset] # invalid
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
1:address:shared:array:character <- new []
|
||||
2:address:shared:array:character <- new [get foo, x:offset] # invalid
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
assume-console [
|
||||
press F4 # generate error
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
assume-console [
|
||||
left-click 3, 80
|
||||
|
@ -138,7 +138,7 @@ scenario run-hides-warnings-from-past-sandboxes [
|
|||
press F4 # error should disappear
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
|
@ -156,18 +156,18 @@ scenario run-updates-warnings-for-shape-shifting-recipes [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 100/width, 15/height
|
||||
# define a shape-shifting recipe with an error
|
||||
1:address:array:character <- new [recipe foo x:_elem -> z:_elem [
|
||||
1:address:shared:array:character <- new [recipe foo x:_elem -> z:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z <- add x, [a]
|
||||
]]
|
||||
2:address:array:character <- new [foo 2]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
2:address:shared:array:character <- new [foo 2]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
|
@ -185,7 +185,7 @@ z <- add x, [a]
|
|||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
# error should remain unchanged
|
||||
screen-should-contain [
|
||||
|
@ -205,24 +205,24 @@ scenario run-avoids-spurious-warnings-on-reloading-shape-shifting-recipes [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 100/width, 15/height
|
||||
# overload a well-known shape-shifting recipe
|
||||
1:address:array:character <- new [recipe length l:address:list:_elem -> n:number [
|
||||
1:address:shared:array:character <- new [recipe length l:address:shared:list:_elem -> n:number [
|
||||
]]
|
||||
# call code that uses other variants of it, but not it itself
|
||||
2:address:array:character <- new [x:address:list:number <- copy 0
|
||||
2:address:shared:array:character <- new [x:address:shared:list:number <- copy 0
|
||||
to-text x]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
# run it once
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
# no errors anywhere on screen (can't check anything else, since to-text will return an address)
|
||||
screen-should-contain-in-color 1/red, [
|
||||
. .
|
||||
. .
|
||||
. .
|
||||
. .
|
||||
. <- .
|
||||
. <- .
|
||||
. .
|
||||
. .
|
||||
. .
|
||||
|
@ -239,7 +239,7 @@ to-text x]
|
|||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
# still no errors
|
||||
screen-should-contain-in-color 1/red, [
|
||||
|
@ -247,7 +247,7 @@ to-text x]
|
|||
. .
|
||||
. .
|
||||
. .
|
||||
. <- .
|
||||
. <- .
|
||||
. .
|
||||
. .
|
||||
. .
|
||||
|
@ -264,17 +264,17 @@ to-text x]
|
|||
scenario run-shows-missing-type-warnings [
|
||||
trace-until 100/app # trace too long
|
||||
assume-screen 100/width, 15/height
|
||||
1:address:array:character <- new [
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
x <- copy 0
|
||||
]]
|
||||
2:address:array:character <- new [foo]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
2:address:shared:array:character <- new [foo]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. errors found run (F4) .
|
||||
|
@ -290,18 +290,18 @@ scenario run-shows-unbalanced-bracket-warnings [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 100/width, 15/height
|
||||
# recipe is incomplete (unbalanced '[')
|
||||
1:address:array:character <- new [
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo «
|
||||
x <- copy 0
|
||||
]
|
||||
replace 1:address:array:character, 171/«, 91 # '['
|
||||
2:address:array:character <- new [foo]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
replace 1:address:shared:array:character, 171/«, 91 # '['
|
||||
2:address:shared:array:character <- new [foo]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. errors found run (F4) .
|
||||
|
@ -318,28 +318,28 @@ recipe foo «
|
|||
scenario run-shows-get-on-non-container-warnings [
|
||||
trace-until 100/app # trace too long
|
||||
assume-screen 100/width, 15/height
|
||||
1:address:array:character <- new [
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
x:address:point <- new point:type
|
||||
get x:address:point, 1:offset
|
||||
x:address:shared:point <- new point:type
|
||||
get x:address:shared:point, 1:offset
|
||||
]]
|
||||
2:address:array:character <- new [foo]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
2:address:shared:array:character <- new [foo]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. errors found run (F4) .
|
||||
. ┊foo .
|
||||
.recipe foo [ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.
|
||||
. x:address:point <- new point:type ┊ .
|
||||
. get x:address:point, 1:offset ┊ .
|
||||
. x:address:shared:point <- new point:type ┊ .
|
||||
. get x:address:shared:point, 1:offset ┊ .
|
||||
.] ┊ .
|
||||
.foo: first ingredient of 'get' should be a contai↩┊ .
|
||||
.ner, but got x:address:point ┊ .
|
||||
.ner, but got x:address:shared:point ┊ .
|
||||
.┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ .
|
||||
. ┊ .
|
||||
]
|
||||
|
@ -348,27 +348,27 @@ recipe foo [
|
|||
scenario run-shows-non-literal-get-argument-warnings [
|
||||
trace-until 100/app # trace too long
|
||||
assume-screen 100/width, 15/height
|
||||
1:address:array:character <- new [
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
x:number <- copy 0
|
||||
y:address:point <- new point:type
|
||||
get *y:address:point, x:number
|
||||
y:address:shared:point <- new point:type
|
||||
get *y:address:shared:point, x:number
|
||||
]]
|
||||
2:address:array:character <- new [foo]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
2:address:shared:array:character <- new [foo]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. errors found run (F4) .
|
||||
. ┊foo .
|
||||
.recipe foo [ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.
|
||||
. x:number <- copy 0 ┊ .
|
||||
. y:address:point <- new point:type ┊ .
|
||||
. get *y:address:point, x:number ┊ .
|
||||
. y:address:shared:point <- new point:type ┊ .
|
||||
. get *y:address:shared:point, x:number ┊ .
|
||||
.] ┊ .
|
||||
.foo: expected ingredient 1 of 'get' to have type ↩┊ .
|
||||
.'offset'; got x:number ┊ .
|
||||
|
@ -383,17 +383,17 @@ scenario run-shows-warnings-everytime [
|
|||
trace-until 100/app # trace too long
|
||||
# try to run a file with an error
|
||||
assume-screen 100/width, 15/height
|
||||
1:address:array:character <- new [
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
x:number <- copy y:number
|
||||
]]
|
||||
2:address:array:character <- new [foo]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
2:address:shared:array:character <- new [foo]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. errors found run (F4) .
|
||||
|
@ -410,7 +410,7 @@ recipe foo [
|
|||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. errors found run (F4) .
|
||||
|
@ -428,16 +428,16 @@ scenario run-instruction-and-print-warnings [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 100/width, 10/height
|
||||
# left editor is empty
|
||||
1:address:array:character <- new []
|
||||
1:address:shared:array:character <- new []
|
||||
# right editor contains an illegal instruction
|
||||
2:address:array:character <- new [get 1234:number, foo:offset]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
2:address:shared:array:character <- new [get 1234:number, foo:offset]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
# run the code in the editors
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
# check that screen prints error message in red
|
||||
screen-should-contain [
|
||||
|
@ -491,17 +491,17 @@ scenario run-instruction-and-print-warnings-only-once [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 100/width, 10/height
|
||||
# left editor is empty
|
||||
1:address:array:character <- new []
|
||||
1:address:shared:array:character <- new []
|
||||
# right editor contains an illegal instruction
|
||||
2:address:array:character <- new [get 1234:number, foo:offset]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
2:address:shared:array:character <- new [get 1234:number, foo:offset]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
# run the code in the editors multiple times
|
||||
assume-console [
|
||||
press F4
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
# check that screen prints error message just once
|
||||
screen-should-contain [
|
||||
|
@ -522,20 +522,20 @@ scenario sandbox-can-handle-infinite-loop [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 100/width, 20/height
|
||||
# left editor is empty
|
||||
1:address:array:character <- new [recipe foo [
|
||||
1:address:shared:array:character <- new [recipe foo [
|
||||
{
|
||||
loop
|
||||
}
|
||||
]]
|
||||
# right editor contains an instruction
|
||||
2:address:array:character <- new [foo]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
2:address:shared:array:character <- new [foo]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
# run the sandbox
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
|
@ -553,7 +553,7 @@ scenario sandbox-with-warnings-shows-trace [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 100/width, 10/height
|
||||
# generate a stash and a warning
|
||||
1:address:array:character <- new [recipe foo [
|
||||
1:address:shared:array:character <- new [recipe foo [
|
||||
local-scope
|
||||
a:number <- next-ingredient
|
||||
b:number <- next-ingredient
|
||||
|
@ -561,13 +561,13 @@ stash [dividing by], b
|
|||
_, c:number <- divide-with-remainder a, b
|
||||
reply b
|
||||
]]
|
||||
2:address:array:character <- new [foo 4, 0]
|
||||
3:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character, 2:address:array:character
|
||||
2:address:shared:array:character <- new [foo 4, 0]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character, 2:address:shared:array:character
|
||||
# run
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
# screen prints error message
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
|
@ -585,7 +585,7 @@ reply b
|
|||
left-click 4, 55
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 3:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 3:address:shared:programming-environment-data
|
||||
]
|
||||
# screen should expand trace
|
||||
screen-should-contain [
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,7 +2,7 @@
|
|||
|
||||
recipe main [
|
||||
# allocate 5 locations for globals
|
||||
global-space:address:array:location <- new location:type, 5
|
||||
global-space:address:shared:array:location <- new location:type, 5
|
||||
# read to globals by using /space:global
|
||||
1:number/space:global <- copy 3
|
||||
foo
|
||||
|
@ -10,5 +10,5 @@ recipe main [
|
|||
|
||||
recipe foo [
|
||||
# ditto for writing to globals
|
||||
$print 1:number/space:global
|
||||
$print 1:number/space:global, 10/newline
|
||||
]
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# temporary main for this layer: just render the given text at the given
|
||||
# screen dimensions, then stop
|
||||
recipe! main text:address:array:character [
|
||||
recipe! main text:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
open-console
|
||||
|
@ -16,8 +16,8 @@ recipe! main text:address:array:character [
|
|||
scenario editor-initially-prints-text-to-screen [
|
||||
assume-screen 10/width, 5/height
|
||||
run [
|
||||
1:address:array:character <- new [abc]
|
||||
new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
1:address:shared:array:character <- new [abc]
|
||||
new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
]
|
||||
screen-should-contain [
|
||||
# top line of screen reserved for menu
|
||||
|
@ -29,11 +29,11 @@ scenario editor-initially-prints-text-to-screen [
|
|||
|
||||
container editor-data [
|
||||
# editable text: doubly linked list of characters (head contains a special sentinel)
|
||||
data:address:duplex-list:character
|
||||
top-of-screen:address:duplex-list:character
|
||||
bottom-of-screen:address:duplex-list:character
|
||||
data:address:shared:duplex-list:character
|
||||
top-of-screen:address:shared:duplex-list:character
|
||||
bottom-of-screen:address:shared:duplex-list:character
|
||||
# location before cursor inside data
|
||||
before-cursor:address:duplex-list:character
|
||||
before-cursor:address:shared:duplex-list:character
|
||||
|
||||
# raw bounds of display area on screen
|
||||
# always displays from row 1 (leaving row 0 for a menu) and at most until bottom of screen
|
||||
|
@ -47,7 +47,7 @@ container editor-data [
|
|||
# creates a new editor widget and renders its initial appearance to screen
|
||||
# top/left/right constrain the screen area available to the new editor
|
||||
# right is exclusive
|
||||
recipe new-editor s:address:array:character, screen:address:screen, left:number, right:number -> result:address:editor-data, screen:address:screen [
|
||||
recipe new-editor s:address:shared:array:character, screen:address:shared:screen, left:number, right:number -> result:address:shared:editor-data, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# no clipping of bounds
|
||||
|
@ -63,11 +63,11 @@ recipe new-editor s:address:array:character, screen:address:screen, left:number,
|
|||
*x <- copy 1/top
|
||||
x <- get-address *result, cursor-column:offset
|
||||
*x <- copy left
|
||||
init:address:address:duplex-list:character <- get-address *result, data:offset
|
||||
init:address:address:shared:duplex-list:character <- get-address *result, data:offset
|
||||
*init <- push 167/§, 0/tail
|
||||
top-of-screen:address:address:duplex-list:character <- get-address *result, top-of-screen:offset
|
||||
top-of-screen:address:address:shared:duplex-list:character <- get-address *result, top-of-screen:offset
|
||||
*top-of-screen <- copy *init
|
||||
y:address:address:duplex-list:character <- get-address *result, before-cursor:offset
|
||||
y:address:address:shared:duplex-list:character <- get-address *result, before-cursor:offset
|
||||
*y <- copy *init
|
||||
result <- insert-text result, s
|
||||
# initialize cursor to top of screen
|
||||
|
@ -78,7 +78,7 @@ recipe new-editor s:address:array:character, screen:address:screen, left:number,
|
|||
<editor-initialization>
|
||||
]
|
||||
|
||||
recipe insert-text editor:address:editor-data, text:address:array:character -> editor:address:editor-data [
|
||||
recipe insert-text editor:address:shared:editor-data, text:address:shared:array:character -> editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# early exit if text is empty
|
||||
|
@ -87,7 +87,7 @@ recipe insert-text editor:address:editor-data, text:address:array:character -> e
|
|||
reply-unless len, editor/same-as-ingredient:0
|
||||
idx:number <- copy 0
|
||||
# now we can start appending the rest, character by character
|
||||
curr:address:duplex-list:character <- get *editor, data:offset
|
||||
curr:address:shared:duplex-list:character <- get *editor, data:offset
|
||||
{
|
||||
done?:boolean <- greater-or-equal idx, len
|
||||
break-if done?
|
||||
|
@ -104,8 +104,8 @@ recipe insert-text editor:address:editor-data, text:address:array:character -> e
|
|||
scenario editor-initializes-without-data [
|
||||
assume-screen 5/width, 3/height
|
||||
run [
|
||||
1:address:editor-data <- new-editor 0/data, screen:address:screen, 2/left, 5/right
|
||||
2:editor-data <- copy *1:address:editor-data
|
||||
1:address:shared:editor-data <- new-editor 0/data, screen:address:shared:screen, 2/left, 5/right
|
||||
2:editor-data <- copy *1:address:shared:editor-data
|
||||
]
|
||||
memory-should-contain [
|
||||
# 2 (data) <- just the § sentinel
|
||||
|
@ -127,7 +127,7 @@ scenario editor-initializes-without-data [
|
|||
# Assumes cursor should be at coordinates (cursor-row, cursor-column) and
|
||||
# updates before-cursor to match. Might also move coordinates if they're
|
||||
# outside text.
|
||||
recipe render screen:address:screen, editor:address:editor-data -> last-row:number, last-column:number, screen:address:screen, editor:address:editor-data [
|
||||
recipe render screen:address:shared:screen, editor:address:shared:editor-data -> last-row:number, last-column:number, screen:address:shared:screen, editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless editor, 1/top, 0/left, screen/same-as-ingredient:0, editor/same-as-ingredient:1
|
||||
|
@ -135,8 +135,8 @@ recipe render screen:address:screen, editor:address:editor-data -> last-row:numb
|
|||
screen-height:number <- screen-height screen
|
||||
right:number <- get *editor, right:offset
|
||||
# traversing editor
|
||||
curr:address:duplex-list:character <- get *editor, top-of-screen:offset
|
||||
prev:address:duplex-list:character <- copy curr # just in case curr becomes null and we can't compute prev
|
||||
curr:address:shared:duplex-list:character <- get *editor, top-of-screen:offset
|
||||
prev:address:shared:duplex-list:character <- copy curr # just in case curr becomes null and we can't compute prev
|
||||
curr <- next curr
|
||||
# traversing screen
|
||||
+render-loop-initialization
|
||||
|
@ -145,7 +145,7 @@ recipe render screen:address:screen, editor:address:editor-data -> last-row:numb
|
|||
column:number <- copy left
|
||||
cursor-row:address:number <- get-address *editor, cursor-row:offset
|
||||
cursor-column:address:number <- get-address *editor, cursor-column:offset
|
||||
before-cursor:address:address:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
screen <- move-cursor screen, row, column
|
||||
{
|
||||
+next-character
|
||||
|
@ -208,7 +208,7 @@ recipe render screen:address:screen, editor:address:editor-data -> last-row:numb
|
|||
loop
|
||||
}
|
||||
# save first character off-screen
|
||||
bottom-of-screen:address:address:duplex-list:character <- get-address *editor, bottom-of-screen:offset
|
||||
bottom-of-screen:address:address:shared:duplex-list:character <- get-address *editor, bottom-of-screen:offset
|
||||
*bottom-of-screen <- copy curr
|
||||
# is cursor to the right of the last line? move to end
|
||||
{
|
||||
|
@ -225,7 +225,7 @@ recipe render screen:address:screen, editor:address:editor-data -> last-row:numb
|
|||
reply row, column, screen/same-as-ingredient:0, editor/same-as-ingredient:1
|
||||
]
|
||||
|
||||
recipe clear-line-delimited screen:address:screen, column:number, right:number -> screen:address:screen [
|
||||
recipe clear-line-delimited screen:address:shared:screen, column:number, right:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
space:character <- copy 32/space
|
||||
|
@ -238,7 +238,7 @@ recipe clear-line-delimited screen:address:screen, column:number, right:number -
|
|||
}
|
||||
]
|
||||
|
||||
recipe clear-screen-from screen:address:screen, row:number, column:number, left:number, right:number -> screen:address:screen [
|
||||
recipe clear-screen-from screen:address:shared:screen, row:number, column:number, left:number, right:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if it's the real screen, use the optimized primitive
|
||||
|
@ -254,7 +254,7 @@ recipe clear-screen-from screen:address:screen, row:number, column:number, left:
|
|||
reply screen/same-as-ingredient:0
|
||||
]
|
||||
|
||||
recipe clear-rest-of-screen screen:address:screen, row:number, left:number, right:number -> screen:address:screen [
|
||||
recipe clear-rest-of-screen screen:address:shared:screen, row:number, left:number, right:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
row <- add row, 1
|
||||
|
@ -273,9 +273,9 @@ recipe clear-rest-of-screen screen:address:screen, row:number, left:number, righ
|
|||
scenario editor-initially-prints-multiple-lines [
|
||||
assume-screen 5/width, 5/height
|
||||
run [
|
||||
s:address:array:character <- new [abc
|
||||
s:address:shared:array:character <- new [abc
|
||||
def]
|
||||
new-editor s:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
new-editor s:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -288,8 +288,8 @@ def]
|
|||
scenario editor-initially-handles-offsets [
|
||||
assume-screen 5/width, 5/height
|
||||
run [
|
||||
s:address:array:character <- new [abc]
|
||||
new-editor s:address:array:character, screen:address:screen, 1/left, 5/right
|
||||
s:address:shared:array:character <- new [abc]
|
||||
new-editor s:address:shared:array:character, screen:address:shared:screen, 1/left, 5/right
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -301,9 +301,9 @@ scenario editor-initially-handles-offsets [
|
|||
scenario editor-initially-prints-multiple-lines-at-offset [
|
||||
assume-screen 5/width, 5/height
|
||||
run [
|
||||
s:address:array:character <- new [abc
|
||||
s:address:shared:array:character <- new [abc
|
||||
def]
|
||||
new-editor s:address:array:character, screen:address:screen, 1/left, 5/right
|
||||
new-editor s:address:shared:array:character, screen:address:shared:screen, 1/left, 5/right
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -316,8 +316,8 @@ def]
|
|||
scenario editor-initially-wraps-long-lines [
|
||||
assume-screen 5/width, 5/height
|
||||
run [
|
||||
s:address:array:character <- new [abc def]
|
||||
new-editor s:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
s:address:shared:array:character <- new [abc def]
|
||||
new-editor s:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -336,8 +336,8 @@ scenario editor-initially-wraps-long-lines [
|
|||
scenario editor-initially-wraps-barely-long-lines [
|
||||
assume-screen 5/width, 5/height
|
||||
run [
|
||||
s:address:array:character <- new [abcde]
|
||||
new-editor s:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
s:address:shared:array:character <- new [abcde]
|
||||
new-editor s:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
]
|
||||
# still wrap, even though the line would fit. We need room to click on the
|
||||
# end of the line
|
||||
|
@ -358,10 +358,10 @@ scenario editor-initially-wraps-barely-long-lines [
|
|||
scenario editor-initializes-empty-text [
|
||||
assume-screen 5/width, 5/height
|
||||
run [
|
||||
1:address:array:character <- new []
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
1:address:shared:array:character <- new []
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -379,10 +379,10 @@ scenario editor-initializes-empty-text [
|
|||
scenario render-colors-comments [
|
||||
assume-screen 5/width, 5/height
|
||||
run [
|
||||
s:address:array:character <- new [abc
|
||||
s:address:shared:array:character <- new [abc
|
||||
# de
|
||||
f]
|
||||
new-editor s:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
new-editor s:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -460,10 +460,10 @@ recipe get-color color:number, c:character -> color:number [
|
|||
scenario render-colors-assignment [
|
||||
assume-screen 8/width, 5/height
|
||||
run [
|
||||
s:address:array:character <- new [abc
|
||||
s:address:shared:array:character <- new [abc
|
||||
d <- e
|
||||
f]
|
||||
new-editor s:address:array:character, screen:address:screen, 0/left, 8/right
|
||||
new-editor s:address:shared:array:character, screen:address:shared:screen, 0/left, 8/right
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
|
||||
# temporary main: interactive editor
|
||||
# hit ctrl-c to exit
|
||||
recipe! main text:address:array:character [
|
||||
recipe! main text:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
open-console
|
||||
editor:address:editor-data <- new-editor text, 0/screen, 5/left, 45/right
|
||||
editor:address:shared:editor-data <- new-editor text, 0/screen, 5/left, 45/right
|
||||
editor-event-loop 0/screen, 0/console, editor
|
||||
close-console
|
||||
]
|
||||
|
||||
recipe editor-event-loop screen:address:screen, console:address:console, editor:address:editor-data -> screen:address:screen, console:address:console, editor:address:editor-data [
|
||||
recipe editor-event-loop screen:address:shared:screen, console:address:shared:console, editor:address:shared:editor-data -> screen:address:shared:screen, console:address:shared:console, editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -20,7 +20,7 @@ recipe editor-event-loop screen:address:screen, console:address:console, editor:
|
|||
cursor-row:number <- get *editor, cursor-row:offset
|
||||
cursor-column:number <- get *editor, cursor-column:offset
|
||||
screen <- move-cursor screen, cursor-row, cursor-column
|
||||
e:event, console:address:console, found?:boolean, quit?:boolean <- read-event console
|
||||
e:event, console:address:shared:console, found?:boolean, quit?:boolean <- read-event console
|
||||
loop-unless found?
|
||||
break-if quit? # only in tests
|
||||
trace 10, [app], [next-event]
|
||||
|
@ -45,7 +45,7 @@ recipe editor-event-loop screen:address:screen, console:address:console, editor:
|
|||
]
|
||||
|
||||
# process click, return if it was on current editor
|
||||
recipe move-cursor-in-editor screen:address:screen, editor:address:editor-data, t:touch-event -> in-focus?:boolean, editor:address:editor-data [
|
||||
recipe move-cursor-in-editor screen:address:shared:screen, editor:address:shared:editor-data, t:touch-event -> in-focus?:boolean, editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless editor, 0/false
|
||||
|
@ -70,7 +70,7 @@ recipe move-cursor-in-editor screen:address:screen, editor:address:editor-data,
|
|||
# Variant of 'render' that only moves the cursor (coordinates and
|
||||
# before-cursor). If it's past the end of a line, it 'slides' it left. If it's
|
||||
# past the last line it positions at end of last line.
|
||||
recipe snap-cursor screen:address:screen, editor:address:editor-data, target-row:number, target-column:number -> editor:address:editor-data [
|
||||
recipe snap-cursor screen:address:shared:screen, editor:address:shared:editor-data, target-row:number, target-column:number -> editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless editor
|
||||
|
@ -78,8 +78,8 @@ recipe snap-cursor screen:address:screen, editor:address:editor-data, target-row
|
|||
right:number <- get *editor, right:offset
|
||||
screen-height:number <- screen-height screen
|
||||
# count newlines until screen row
|
||||
curr:address:duplex-list:character <- get *editor, top-of-screen:offset
|
||||
prev:address:duplex-list:character <- copy curr # just in case curr becomes null and we can't compute prev
|
||||
curr:address:shared:duplex-list:character <- get *editor, top-of-screen:offset
|
||||
prev:address:shared:duplex-list:character <- copy curr # just in case curr becomes null and we can't compute prev
|
||||
curr <- next curr
|
||||
row:number <- copy 1/top
|
||||
column:number <- copy left
|
||||
|
@ -87,7 +87,7 @@ recipe snap-cursor screen:address:screen, editor:address:editor-data, target-row
|
|||
*cursor-row <- copy target-row
|
||||
cursor-column:address:number <- get-address *editor, cursor-column:offset
|
||||
*cursor-column <- copy target-column
|
||||
before-cursor:address:address:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
{
|
||||
+next-character
|
||||
break-unless curr
|
||||
|
@ -155,7 +155,7 @@ recipe snap-cursor screen:address:screen, editor:address:editor-data, target-row
|
|||
|
||||
# Process an event 'e' and try to minimally update the screen.
|
||||
# Set 'go-render?' to true to indicate the caller must perform a non-minimal update.
|
||||
recipe handle-keyboard-event screen:address:screen, editor:address:editor-data, e:event -> screen:address:screen, editor:address:editor-data, go-render?:boolean [
|
||||
recipe handle-keyboard-event screen:address:shared:screen, editor:address:shared:editor-data, e:event -> screen:address:shared:screen, editor:address:shared:editor-data, go-render?:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
go-render? <- copy 0/false
|
||||
|
@ -164,7 +164,7 @@ recipe handle-keyboard-event screen:address:screen, editor:address:editor-data,
|
|||
screen-height:number <- screen-height screen
|
||||
left:number <- get *editor, left:offset
|
||||
right:number <- get *editor, right:offset
|
||||
before-cursor:address:address:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
cursor-row:address:number <- get-address *editor, cursor-row:offset
|
||||
cursor-column:address:number <- get-address *editor, cursor-column:offset
|
||||
save-row:number <- copy *cursor-row
|
||||
|
@ -195,10 +195,10 @@ recipe handle-keyboard-event screen:address:screen, editor:address:editor-data,
|
|||
reply
|
||||
]
|
||||
|
||||
recipe insert-at-cursor editor:address:editor-data, c:character, screen:address:screen -> editor:address:editor-data, screen:address:screen, go-render?:boolean [
|
||||
recipe insert-at-cursor editor:address:shared:editor-data, c:character, screen:address:shared:screen -> editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
before-cursor:address:address:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
insert c, *before-cursor
|
||||
*before-cursor <- next *before-cursor
|
||||
cursor-row:address:number <- get-address *editor, cursor-row:offset
|
||||
|
@ -213,7 +213,7 @@ recipe insert-at-cursor editor:address:editor-data, c:character, screen:address:
|
|||
<insert-character-special-case>
|
||||
# but mostly we'll just move the cursor right
|
||||
*cursor-column <- add *cursor-column, 1
|
||||
next:address:duplex-list:character <- next *before-cursor
|
||||
next:address:shared:duplex-list:character <- next *before-cursor
|
||||
{
|
||||
# at end of all text? no need to scroll? just print the character and leave
|
||||
at-end?:boolean <- equal next, 0/null
|
||||
|
@ -233,7 +233,7 @@ recipe insert-at-cursor editor:address:editor-data, c:character, screen:address:
|
|||
break-unless next
|
||||
at-right?:boolean <- greater-or-equal *cursor-column, screen-width
|
||||
break-if at-right?
|
||||
curr:address:duplex-list:character <- copy *before-cursor
|
||||
curr:address:shared:duplex-list:character <- copy *before-cursor
|
||||
move-cursor screen, save-row, save-column
|
||||
curr-column:number <- copy save-column
|
||||
{
|
||||
|
@ -259,7 +259,7 @@ recipe insert-at-cursor editor:address:editor-data, c:character, screen:address:
|
|||
]
|
||||
|
||||
# helper for tests
|
||||
recipe editor-render screen:address:screen, editor:address:editor-data -> screen:address:screen, editor:address:editor-data [
|
||||
recipe editor-render screen:address:shared:screen, editor:address:shared:editor-data -> screen:address:shared:screen, editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
left:number <- get *editor, left:offset
|
||||
|
@ -274,12 +274,12 @@ recipe editor-render screen:address:screen, editor:address:editor-data -> screen
|
|||
|
||||
scenario editor-handles-empty-event-queue [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
assume-console []
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -291,17 +291,17 @@ scenario editor-handles-empty-event-queue [
|
|||
|
||||
scenario editor-handles-mouse-clicks [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 1, 1 # on the 'b'
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -318,16 +318,16 @@ scenario editor-handles-mouse-clicks [
|
|||
|
||||
scenario editor-handles-mouse-clicks-outside-text [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 1, 7 # last line, to the right of text
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
memory-should-contain [
|
||||
3 <- 1 # cursor row
|
||||
|
@ -338,17 +338,17 @@ scenario editor-handles-mouse-clicks-outside-text [
|
|||
|
||||
scenario editor-handles-mouse-clicks-outside-text-2 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc
|
||||
1:address:shared:array:character <- new [abc
|
||||
def]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 1, 7 # interior line, to the right of text
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
memory-should-contain [
|
||||
3 <- 1 # cursor row
|
||||
|
@ -359,17 +359,17 @@ def]
|
|||
|
||||
scenario editor-handles-mouse-clicks-outside-text-3 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc
|
||||
1:address:shared:array:character <- new [abc
|
||||
def]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 3, 7 # below text
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
memory-should-contain [
|
||||
3 <- 2 # cursor row
|
||||
|
@ -380,19 +380,19 @@ def]
|
|||
|
||||
scenario editor-handles-mouse-clicks-outside-column [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
1:address:shared:array:character <- new [abc]
|
||||
# editor occupies only left half of screen
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
# click on right half of screen
|
||||
left-click 3, 8
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -409,18 +409,18 @@ scenario editor-handles-mouse-clicks-outside-column [
|
|||
|
||||
scenario editor-handles-mouse-clicks-in-menu-area [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
# click on first, 'menu' row
|
||||
left-click 0, 3
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
# no change to cursor
|
||||
memory-should-contain [
|
||||
|
@ -431,15 +431,15 @@ scenario editor-handles-mouse-clicks-in-menu-area [
|
|||
|
||||
scenario editor-inserts-characters-into-empty-editor [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new []
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new []
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
type [abc]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -452,9 +452,9 @@ scenario editor-inserts-characters-into-empty-editor [
|
|||
|
||||
scenario editor-inserts-characters-at-cursor [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
# type two letters at different places
|
||||
assume-console [
|
||||
|
@ -463,7 +463,7 @@ scenario editor-inserts-characters-at-cursor [
|
|||
type [d]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -476,16 +476,16 @@ scenario editor-inserts-characters-at-cursor [
|
|||
|
||||
scenario editor-inserts-characters-at-cursor-2 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 1, 5 # right of last line
|
||||
type [d]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -498,17 +498,17 @@ scenario editor-inserts-characters-at-cursor-2 [
|
|||
|
||||
scenario editor-inserts-characters-at-cursor-5 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc
|
||||
1:address:shared:array:character <- new [abc
|
||||
d]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 1, 5 # right of non-last line
|
||||
type [e]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -522,16 +522,16 @@ d]
|
|||
|
||||
scenario editor-inserts-characters-at-cursor-3 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 3, 5 # below all text
|
||||
type [d]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -544,17 +544,17 @@ scenario editor-inserts-characters-at-cursor-3 [
|
|||
|
||||
scenario editor-inserts-characters-at-cursor-4 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc
|
||||
1:address:shared:array:character <- new [abc
|
||||
d]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 3, 5 # below all text
|
||||
type [e]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -568,17 +568,17 @@ d]
|
|||
|
||||
scenario editor-inserts-characters-at-cursor-6 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc
|
||||
1:address:shared:array:character <- new [abc
|
||||
d]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
$clear-trace
|
||||
assume-console [
|
||||
left-click 3, 5 # below all text
|
||||
type [ef]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -592,14 +592,14 @@ d]
|
|||
|
||||
scenario editor-moves-cursor-after-inserting-characters [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [ab]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new [ab]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
assume-console [
|
||||
type [01]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -613,15 +613,15 @@ scenario editor-moves-cursor-after-inserting-characters [
|
|||
|
||||
scenario editor-wraps-line-on-insert [
|
||||
assume-screen 5/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
# type a letter
|
||||
assume-console [
|
||||
type [e]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
# no wrap yet
|
||||
screen-should-contain [
|
||||
|
@ -636,7 +636,7 @@ scenario editor-wraps-line-on-insert [
|
|||
type [f]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
# now wrap
|
||||
screen-should-contain [
|
||||
|
@ -651,19 +651,19 @@ scenario editor-wraps-line-on-insert [
|
|||
scenario editor-wraps-line-on-insert-2 [
|
||||
# create an editor with some text
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abcdefg
|
||||
1:address:shared:array:character <- new [abcdefg
|
||||
defg]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:editor-data
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
editor-render screen, 2:address:shared:editor-data
|
||||
# type more text at the start
|
||||
assume-console [
|
||||
left-click 3, 0
|
||||
type [abc]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
# cursor is not wrapped
|
||||
memory-should-contain [
|
||||
|
@ -703,16 +703,16 @@ after <insert-character-special-case> [
|
|||
|
||||
scenario editor-wraps-cursor-after-inserting-characters [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abcde]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
1:address:shared:array:character <- new [abcde]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
assume-console [
|
||||
left-click 1, 4 # line is full; no wrap icon yet
|
||||
type [f]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -729,16 +729,16 @@ scenario editor-wraps-cursor-after-inserting-characters [
|
|||
|
||||
scenario editor-wraps-cursor-after-inserting-characters-2 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abcde]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
1:address:shared:array:character <- new [abcde]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
assume-console [
|
||||
left-click 1, 3 # right before the wrap icon
|
||||
type [f]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -755,16 +755,16 @@ scenario editor-wraps-cursor-after-inserting-characters-2 [
|
|||
|
||||
scenario editor-wraps-cursor-to-left-margin [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abcde]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 2/left, 7/right
|
||||
1:address:shared:array:character <- new [abcde]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 2/left, 7/right
|
||||
assume-console [
|
||||
left-click 1, 5 # line is full; no wrap icon yet
|
||||
type [01]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -792,14 +792,14 @@ after <editor-initialization> [
|
|||
|
||||
scenario editor-moves-cursor-down-after-inserting-newline [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
assume-console [
|
||||
type [0
|
||||
1]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -822,12 +822,12 @@ after <handle-special-character> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe insert-new-line-and-indent editor:address:editor-data, screen:address:screen -> editor:address:editor-data, screen:address:screen, go-render?:boolean [
|
||||
recipe insert-new-line-and-indent editor:address:shared:editor-data, screen:address:shared:screen -> editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
cursor-row:address:number <- get-address *editor, cursor-row:offset
|
||||
cursor-column:address:number <- get-address *editor, cursor-column:offset
|
||||
before-cursor:address:address:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
left:number <- get *editor, left:offset
|
||||
right:number <- get *editor, right:offset
|
||||
screen-height:number <- screen-height screen
|
||||
|
@ -847,8 +847,8 @@ recipe insert-new-line-and-indent editor:address:editor-data, screen:address:scr
|
|||
# indent if necessary
|
||||
indent?:boolean <- get *editor, indent?:offset
|
||||
reply-unless indent?
|
||||
d:address:duplex-list:character <- get *editor, data:offset
|
||||
end-of-previous-line:address:duplex-list:character <- prev *before-cursor
|
||||
d:address:shared:duplex-list:character <- get *editor, data:offset
|
||||
end-of-previous-line:address:shared:duplex-list:character <- prev *before-cursor
|
||||
indent:number <- line-indent end-of-previous-line, d
|
||||
i:number <- copy 0
|
||||
{
|
||||
|
@ -862,7 +862,7 @@ recipe insert-new-line-and-indent editor:address:editor-data, screen:address:scr
|
|||
|
||||
# takes a pointer 'curr' into the doubly-linked list and its sentinel, counts
|
||||
# the number of spaces at the start of the line containing 'curr'.
|
||||
recipe line-indent curr:address:duplex-list:character, start:address:duplex-list:character -> result:number [
|
||||
recipe line-indent curr:address:shared:duplex-list:character, start:address:shared:duplex-list:character -> result:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result:number <- copy 0
|
||||
|
@ -894,14 +894,14 @@ recipe line-indent curr:address:duplex-list:character, start:address:duplex-list
|
|||
|
||||
scenario editor-moves-cursor-down-after-inserting-newline-2 [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 1/left, 10/right
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 1/left, 10/right
|
||||
assume-console [
|
||||
type [0
|
||||
1]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. .
|
||||
|
@ -914,8 +914,8 @@ scenario editor-moves-cursor-down-after-inserting-newline-2 [
|
|||
|
||||
scenario editor-clears-previous-line-completely-after-inserting-newline [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abcde]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 5/right
|
||||
1:address:shared:array:character <- new [abcde]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 5/right
|
||||
assume-console [
|
||||
press enter
|
||||
]
|
||||
|
@ -927,7 +927,7 @@ scenario editor-clears-previous-line-completely-after-inserting-newline [
|
|||
. .
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
]
|
||||
# line should be fully cleared
|
||||
screen-should-contain [
|
||||
|
@ -941,10 +941,10 @@ scenario editor-clears-previous-line-completely-after-inserting-newline [
|
|||
|
||||
scenario editor-inserts-indent-after-newline [
|
||||
assume-screen 10/width, 10/height
|
||||
1:address:array:character <- new [ab
|
||||
1:address:shared:array:character <- new [ab
|
||||
cd
|
||||
ef]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
# position cursor after 'cd' and hit 'newline'
|
||||
assume-console [
|
||||
left-click 2, 8
|
||||
|
@ -952,9 +952,9 @@ ef]
|
|||
]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
# cursor should be below start of previous line
|
||||
memory-should-contain [
|
||||
|
@ -965,10 +965,10 @@ ef]
|
|||
|
||||
scenario editor-skips-indent-around-paste [
|
||||
assume-screen 10/width, 10/height
|
||||
1:address:array:character <- new [ab
|
||||
1:address:shared:array:character <- new [ab
|
||||
cd
|
||||
ef]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
# position cursor after 'cd' and hit 'newline' surrounded by paste markers
|
||||
assume-console [
|
||||
left-click 2, 8
|
||||
|
@ -977,9 +977,9 @@ ef]
|
|||
press 65506 # end paste
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:number <- get *2:address:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:editor-data, cursor-column:offset
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:number <- get *2:address:shared:editor-data, cursor-row:offset
|
||||
4:number <- get *2:address:shared:editor-data, cursor-column:offset
|
||||
]
|
||||
# cursor should be below start of previous line
|
||||
memory-should-contain [
|
||||
|
@ -1012,7 +1012,7 @@ after <handle-special-key> [
|
|||
|
||||
## helpers
|
||||
|
||||
recipe draw-horizontal screen:address:screen, row:number, x:number, right:number -> screen:address:screen [
|
||||
recipe draw-horizontal screen:address:shared:screen, row:number, x:number, right:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
style:character, style-found?:boolean <- next-ingredient
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,12 +3,12 @@
|
|||
recipe! main [
|
||||
local-scope
|
||||
open-console
|
||||
initial-sandbox:address:array:character <- new []
|
||||
initial-sandbox:address:shared:array:character <- new []
|
||||
hide-screen 0/screen
|
||||
env:address:programming-environment-data <- new-programming-environment 0/screen, initial-sandbox
|
||||
env:address:shared:programming-environment-data <- new-programming-environment 0/screen, initial-sandbox
|
||||
env <- restore-sandboxes env
|
||||
render-sandbox-side 0/screen, env
|
||||
current-sandbox:address:editor-data <- get *env, current-sandbox:offset
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
update-cursor 0/screen, current-sandbox
|
||||
show-screen 0/screen
|
||||
event-loop 0/screen, 0/console, env
|
||||
|
@ -16,10 +16,10 @@ recipe! main [
|
|||
]
|
||||
|
||||
container programming-environment-data [
|
||||
current-sandbox:address:editor-data
|
||||
current-sandbox:address:shared:editor-data
|
||||
]
|
||||
|
||||
recipe new-programming-environment screen:address:screen, initial-sandbox-contents:address:array:character -> result:address:programming-environment-data, screen:address:screen [
|
||||
recipe new-programming-environment screen:address:shared:screen, initial-sandbox-contents:address:shared:array:character -> result:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
width:number <- screen-width screen
|
||||
|
@ -31,17 +31,17 @@ recipe new-programming-environment screen:address:screen, initial-sandbox-conten
|
|||
button-on-screen?:boolean <- greater-or-equal button-start, 0
|
||||
assert button-on-screen?, [screen too narrow for menu]
|
||||
screen <- move-cursor screen, 0/row, button-start
|
||||
run-button:address:array:character <- new [ run (F4) ]
|
||||
run-button:address:shared:array:character <- new [ run (F4) ]
|
||||
print screen, run-button, 255/white, 161/reddish
|
||||
# sandbox editor
|
||||
current-sandbox:address:address:editor-data <- get-address *result, current-sandbox:offset
|
||||
current-sandbox:address:address:shared:editor-data <- get-address *result, current-sandbox:offset
|
||||
*current-sandbox <- new-editor initial-sandbox-contents, screen, 0, width/right
|
||||
]
|
||||
|
||||
recipe event-loop screen:address:screen, console:address:console, env:address:programming-environment-data -> screen:address:screen, console:address:console, env:address:programming-environment-data [
|
||||
recipe event-loop screen:address:shared:screen, console:address:shared:console, env:address:shared:programming-environment-data -> screen:address:shared:screen, console:address:shared:console, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
current-sandbox:address:editor-data <- get *env, current-sandbox:offset
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
# if we fall behind we'll stop updating the screen, but then we have to
|
||||
# render the entire screen when we catch up.
|
||||
# todo: test this
|
||||
|
@ -56,18 +56,18 @@ recipe event-loop screen:address:screen, console:address:console, env:address:pr
|
|||
<handle-event>
|
||||
# check for global events that will trigger regardless of which editor has focus
|
||||
{
|
||||
k:address:number <- maybe-convert e:event, keycode:variant
|
||||
k:address:shared:number <- maybe-convert e:event, keycode:variant
|
||||
break-unless k
|
||||
<global-keypress>
|
||||
}
|
||||
{
|
||||
c:address:character <- maybe-convert e:event, text:variant
|
||||
c:address:shared:character <- maybe-convert e:event, text:variant
|
||||
break-unless c
|
||||
<global-type>
|
||||
}
|
||||
# 'touch' event
|
||||
{
|
||||
t:address:touch-event <- maybe-convert e:event, touch:variant
|
||||
t:address:shared:touch-event <- maybe-convert e:event, touch:variant
|
||||
break-unless t
|
||||
# ignore all but 'left-click' events for now
|
||||
# todo: test this
|
||||
|
@ -83,7 +83,7 @@ recipe event-loop screen:address:screen, console:address:console, env:address:pr
|
|||
# 'resize' event - redraw editor
|
||||
# todo: test this after supporting resize in assume-console
|
||||
{
|
||||
r:address:resize-event <- maybe-convert e:event, resize:variant
|
||||
r:address:shared:resize-event <- maybe-convert e:event, resize:variant
|
||||
break-unless r
|
||||
# if more events, we're still resizing; wait until we stop
|
||||
more-events?:boolean <- has-more-events? console
|
||||
|
@ -135,13 +135,13 @@ recipe event-loop screen:address:screen, console:address:console, env:address:pr
|
|||
}
|
||||
]
|
||||
|
||||
recipe resize screen:address:screen, env:address:programming-environment-data -> env:address:programming-environment-data, screen:address:screen [
|
||||
recipe resize screen:address:shared:screen, env:address:shared:programming-environment-data -> env:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
clear-screen screen # update screen dimensions
|
||||
width:number <- screen-width screen
|
||||
# update sandbox editor
|
||||
current-sandbox:address:editor-data <- get *env, current-sandbox:offset
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
right:address:number <- get-address *current-sandbox, right:offset
|
||||
*right <- subtract width, 1
|
||||
# reset cursor
|
||||
|
@ -151,7 +151,7 @@ recipe resize screen:address:screen, env:address:programming-environment-data ->
|
|||
*cursor-column <- copy 0
|
||||
]
|
||||
|
||||
recipe render-all screen:address:screen, env:address:programming-environment-data -> screen:address:screen [
|
||||
recipe render-all screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
trace 10, [app], [render all]
|
||||
|
@ -164,23 +164,23 @@ recipe render-all screen:address:screen, env:address:programming-environment-dat
|
|||
button-on-screen?:boolean <- greater-or-equal button-start, 0
|
||||
assert button-on-screen?, [screen too narrow for menu]
|
||||
screen <- move-cursor screen, 0/row, button-start
|
||||
run-button:address:array:character <- new [ run (F4) ]
|
||||
run-button:address:shared:array:character <- new [ run (F4) ]
|
||||
print screen, run-button, 255/white, 161/reddish
|
||||
#
|
||||
screen <- render-sandbox-side screen, env
|
||||
<render-components-end>
|
||||
#
|
||||
current-sandbox:address:editor-data <- get *env, current-sandbox:offset
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
screen <- update-cursor screen, current-sandbox
|
||||
#
|
||||
show-screen screen
|
||||
]
|
||||
|
||||
# replaced in a later layer
|
||||
recipe render-sandbox-side screen:address:screen, env:address:programming-environment-data -> screen:address:screen [
|
||||
recipe render-sandbox-side screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
current-sandbox:address:editor-data <- get *env, current-sandbox:offset
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
left:number <- get *current-sandbox, left:offset
|
||||
right:number <- get *current-sandbox, right:offset
|
||||
row:number, column:number, screen, current-sandbox <- render screen, current-sandbox
|
||||
|
@ -192,7 +192,7 @@ recipe render-sandbox-side screen:address:screen, env:address:programming-enviro
|
|||
clear-screen-from screen, row, left, left, right
|
||||
]
|
||||
|
||||
recipe update-cursor screen:address:screen, current-sandbox:address:editor-data -> screen:address:screen [
|
||||
recipe update-cursor screen:address:shared:screen, current-sandbox:address:shared:editor-data -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
cursor-row:number <- get *current-sandbox, cursor-row:offset
|
||||
|
@ -202,7 +202,7 @@ recipe update-cursor screen:address:screen, current-sandbox:address:editor-data
|
|||
|
||||
# print a text 's' to 'editor' in 'color' starting at 'row'
|
||||
# clear rest of last line, move cursor to next line
|
||||
recipe render screen:address:screen, s:address:array:character, left:number, right:number, color:number, row:number -> row:number, screen:address:screen [
|
||||
recipe render screen:address:shared:screen, s:address:shared:array:character, left:number, right:number, color:number, row:number -> row:number, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless s
|
||||
|
@ -263,7 +263,7 @@ recipe render screen:address:screen, s:address:array:character, left:number, rig
|
|||
]
|
||||
|
||||
# like 'render' for texts, but with colorization for comments like in the editor
|
||||
recipe render-code screen:address:screen, s:address:array:character, left:number, right:number, row:number -> row:number, screen:address:screen [
|
||||
recipe render-code screen:address:shared:screen, s:address:shared:array:character, left:number, right:number, row:number -> row:number, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless s
|
||||
|
@ -331,8 +331,13 @@ after <global-type> [
|
|||
{
|
||||
redraw-screen?:boolean <- equal *c, 12/ctrl-l
|
||||
break-unless redraw-screen?
|
||||
screen <- render-all screen, env:address:programming-environment-data
|
||||
screen <- render-all screen, env:address:shared:programming-environment-data
|
||||
sync-screen screen
|
||||
loop +next-event:label
|
||||
}
|
||||
]
|
||||
|
||||
# dummy
|
||||
recipe restore-sandboxes env:address:shared:programming-environment-data -> env:address:shared:programming-environment-data [
|
||||
# do nothing; redefined later
|
||||
]
|
||||
|
|
|
@ -5,33 +5,33 @@
|
|||
# few other things.
|
||||
|
||||
container programming-environment-data [
|
||||
sandbox:address:sandbox-data # list of sandboxes, from top to bottom
|
||||
sandbox:address:shared:sandbox-data # list of sandboxes, from top to bottom
|
||||
]
|
||||
|
||||
container sandbox-data [
|
||||
data:address:array:character
|
||||
response:address:array:character
|
||||
expected-response:address:array:character
|
||||
data:address:shared:array:character
|
||||
response:address:shared:array:character
|
||||
expected-response:address:shared:array:character
|
||||
# coordinates to track clicks
|
||||
starting-row-on-screen:number
|
||||
code-ending-row-on-screen:number # past end of code
|
||||
response-starting-row-on-screen:number
|
||||
screen:address:screen # prints in the sandbox go here
|
||||
next-sandbox:address:sandbox-data
|
||||
screen:address:shared:screen # prints in the sandbox go here
|
||||
next-sandbox:address:shared:sandbox-data
|
||||
]
|
||||
|
||||
scenario run-and-show-results [
|
||||
trace-until 100/app # trace too long
|
||||
assume-screen 50/width, 15/height
|
||||
# sandbox editor contains an instruction without storing outputs
|
||||
1:address:array:character <- new [divide-with-remainder 11, 3]
|
||||
2:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character
|
||||
1:address:shared:array:character <- new [divide-with-remainder 11, 3]
|
||||
2:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character
|
||||
# run the code in the editors
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
]
|
||||
# check that screen prints the results
|
||||
screen-should-contain [
|
||||
|
@ -74,7 +74,7 @@ scenario run-and-show-results [
|
|||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
]
|
||||
# check that screen prints both sandboxes
|
||||
screen-should-contain [
|
||||
|
@ -99,14 +99,14 @@ after <global-keypress> [
|
|||
{
|
||||
do-run?:boolean <- equal *k, 65532/F4
|
||||
break-unless do-run?
|
||||
status:address:array:character <- new [running... ]
|
||||
status:address:shared:array:character <- new [running... ]
|
||||
screen <- update-status screen, status, 245/grey
|
||||
error?:boolean, env, screen <- run-sandboxes env, screen
|
||||
# F4 might update warnings and results on both sides
|
||||
screen <- render-all screen, env
|
||||
{
|
||||
break-if error?
|
||||
status:address:array:character <- new [ ]
|
||||
status:address:shared:array:character <- new [ ]
|
||||
screen <- update-status screen, status, 245/grey
|
||||
}
|
||||
screen <- update-cursor screen, current-sandbox
|
||||
|
@ -114,36 +114,36 @@ after <global-keypress> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe run-sandboxes env:address:programming-environment-data, screen:address:screen -> errors-found?:boolean, env:address:programming-environment-data, screen:address:screen [
|
||||
recipe run-sandboxes env:address:shared:programming-environment-data, screen:address:shared:screen -> errors-found?:boolean, env:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
errors-found?:boolean, env, screen <- update-recipes env, screen
|
||||
reply-if errors-found?
|
||||
# check contents of editor
|
||||
current-sandbox:address:editor-data <- get *env, current-sandbox:offset
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
{
|
||||
sandbox-contents:address:array:character <- editor-contents current-sandbox
|
||||
sandbox-contents:address:shared:array:character <- editor-contents current-sandbox
|
||||
break-unless sandbox-contents
|
||||
# if contents exist, first save them
|
||||
# run them and turn them into a new sandbox-data
|
||||
new-sandbox:address:sandbox-data <- new sandbox-data:type
|
||||
data:address:address:array:character <- get-address *new-sandbox, data:offset
|
||||
new-sandbox:address:shared:sandbox-data <- new sandbox-data:type
|
||||
data:address:address:shared:array:character <- get-address *new-sandbox, data:offset
|
||||
*data <- copy sandbox-contents
|
||||
# push to head of sandbox list
|
||||
dest:address:address:sandbox-data <- get-address *env, sandbox:offset
|
||||
next:address:address:sandbox-data <- get-address *new-sandbox, next-sandbox:offset
|
||||
dest:address:address:shared:sandbox-data <- get-address *env, sandbox:offset
|
||||
next:address:address:shared:sandbox-data <- get-address *new-sandbox, next-sandbox:offset
|
||||
*next <- copy *dest
|
||||
*dest <- copy new-sandbox
|
||||
# clear sandbox editor
|
||||
init:address:address:duplex-list:character <- get-address *current-sandbox, data:offset
|
||||
init:address:address:shared:duplex-list:character <- get-address *current-sandbox, data:offset
|
||||
*init <- push 167/§, 0/tail
|
||||
top-of-screen:address:address:duplex-list:character <- get-address *current-sandbox, top-of-screen:offset
|
||||
top-of-screen:address:address:shared:duplex-list:character <- get-address *current-sandbox, top-of-screen:offset
|
||||
*top-of-screen <- copy *init
|
||||
}
|
||||
# save all sandboxes before running, just in case we die when running
|
||||
save-sandboxes env
|
||||
# run all sandboxes
|
||||
curr:address:sandbox-data <- get *env, sandbox:offset
|
||||
curr:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
{
|
||||
break-unless curr
|
||||
curr <- update-sandbox curr, env
|
||||
|
@ -155,47 +155,47 @@ recipe run-sandboxes env:address:programming-environment-data, screen:address:sc
|
|||
|
||||
# load code from recipes.mu
|
||||
# replaced in a later layer (whereupon errors-found? will actually be set)
|
||||
recipe update-recipes env:address:programming-environment-data, screen:address:screen -> errors-found?:boolean, env:address:programming-environment-data, screen:address:screen [
|
||||
recipe update-recipes env:address:shared:programming-environment-data, screen:address:shared:screen -> errors-found?:boolean, env:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
in:address:array:character <- restore [recipes.mu] # newlayer: persistence
|
||||
in:address:shared:array:character <- restore [recipes.mu] # newlayer: persistence
|
||||
reload in
|
||||
errors-found? <- copy 0/false
|
||||
]
|
||||
|
||||
# replaced in a later layer
|
||||
recipe update-sandbox sandbox:address:sandbox-data -> sandbox:address:sandbox-data [
|
||||
recipe update-sandbox sandbox:address:shared:sandbox-data -> sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
data:address:array:character <- get *sandbox, data:offset
|
||||
response:address:address:array:character <- get-address *sandbox, response:offset
|
||||
fake-screen:address:address:screen <- get-address *sandbox, screen:offset
|
||||
data:address:shared:array:character <- get *sandbox, data:offset
|
||||
response:address:address:shared:array:character <- get-address *sandbox, response:offset
|
||||
fake-screen:address:address:shared:screen <- get-address *sandbox, screen:offset
|
||||
*response, _, *fake-screen <- run-interactive data
|
||||
]
|
||||
|
||||
recipe update-status screen:address:screen, msg:address:array:character, color:number -> screen:address:screen [
|
||||
recipe update-status screen:address:shared:screen, msg:address:shared:array:character, color:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
screen <- move-cursor screen, 0, 2
|
||||
screen <- print screen, msg, color, 238/grey/background
|
||||
]
|
||||
|
||||
recipe save-sandboxes env:address:programming-environment-data [
|
||||
recipe save-sandboxes env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
current-sandbox:address:editor-data <- get *env, current-sandbox:offset
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
# first clear previous versions, in case we deleted some sandbox
|
||||
$system [rm lesson/[0-9]* >/dev/null 2>/dev/null] # some shells can't handle '>&'
|
||||
curr:address:sandbox-data <- get *env, sandbox:offset
|
||||
suffix:address:array:character <- new [.out]
|
||||
curr:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
suffix:address:shared:array:character <- new [.out]
|
||||
idx:number <- copy 0
|
||||
{
|
||||
break-unless curr
|
||||
data:address:array:character <- get *curr, data:offset
|
||||
filename:address:array:character <- to-text idx
|
||||
data:address:shared:array:character <- get *curr, data:offset
|
||||
filename:address:shared:array:character <- to-text idx
|
||||
save filename, data
|
||||
{
|
||||
expected-response:address:array:character <- get *curr, expected-response:offset
|
||||
expected-response:address:shared:array:character <- get *curr, expected-response:offset
|
||||
break-unless expected-response
|
||||
filename <- append filename, suffix
|
||||
save filename, expected-response
|
||||
|
@ -206,26 +206,26 @@ recipe save-sandboxes env:address:programming-environment-data [
|
|||
}
|
||||
]
|
||||
|
||||
recipe! render-sandbox-side screen:address:screen, env:address:programming-environment-data -> screen:address:screen [
|
||||
recipe! render-sandbox-side screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
trace 11, [app], [render sandbox side]
|
||||
current-sandbox:address:editor-data <- get *env, current-sandbox:offset
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
left:number <- get *current-sandbox, left:offset
|
||||
right:number <- get *current-sandbox, right:offset
|
||||
row:number, column:number, screen, current-sandbox <- render screen, current-sandbox
|
||||
clear-screen-from screen, row, column, left, right
|
||||
row <- add row, 1
|
||||
draw-horizontal screen, row, left, right, 9473/horizontal-double
|
||||
sandbox:address:sandbox-data <- get *env, sandbox:offset
|
||||
sandbox:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
row, screen <- render-sandboxes screen, sandbox, left, right, row, env
|
||||
clear-rest-of-screen screen, row, left, left, right
|
||||
]
|
||||
|
||||
recipe render-sandboxes screen:address:screen, sandbox:address:sandbox-data, left:number, right:number, row:number -> row:number, screen:address:screen, sandbox:address:sandbox-data [
|
||||
recipe render-sandboxes screen:address:shared:screen, sandbox:address:shared:sandbox-data, left:number, right:number, row:number -> row:number, screen:address:shared:screen, sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
env:address:programming-environment-data, _/optional <- next-ingredient
|
||||
env:address:shared:programming-environment-data, _/optional <- next-ingredient
|
||||
reply-unless sandbox
|
||||
screen-height:number <- screen-height screen
|
||||
at-bottom?:boolean <- greater-or-equal row, screen-height
|
||||
|
@ -242,16 +242,16 @@ recipe render-sandboxes screen:address:screen, sandbox:address:sandbox-data, lef
|
|||
# render sandbox contents
|
||||
row <- add row, 1
|
||||
screen <- move-cursor screen, row, left
|
||||
sandbox-data:address:array:character <- get *sandbox, data:offset
|
||||
sandbox-data:address:shared:array:character <- get *sandbox, data:offset
|
||||
row, screen <- render-code screen, sandbox-data, left, right, row
|
||||
code-ending-row:address:number <- get-address *sandbox, code-ending-row-on-screen:offset
|
||||
*code-ending-row <- copy row
|
||||
# render sandbox warnings, screen or response, in that order
|
||||
response-starting-row:address:number <- get-address *sandbox, response-starting-row-on-screen:offset
|
||||
sandbox-response:address:array:character <- get *sandbox, response:offset
|
||||
sandbox-response:address:shared:array:character <- get *sandbox, response:offset
|
||||
<render-sandbox-results>
|
||||
{
|
||||
sandbox-screen:address:screen <- get *sandbox, screen:offset
|
||||
sandbox-screen:address:shared:screen <- get *sandbox, screen:offset
|
||||
empty-screen?:boolean <- fake-screen-is-empty? sandbox-screen
|
||||
break-if empty-screen?
|
||||
row, screen <- render-screen screen, sandbox-screen, left, right, row
|
||||
|
@ -268,32 +268,32 @@ recipe render-sandboxes screen:address:screen, sandbox:address:sandbox-data, lef
|
|||
# draw solid line after sandbox
|
||||
draw-horizontal screen, row, left, right, 9473/horizontal-double
|
||||
# draw next sandbox
|
||||
next-sandbox:address:sandbox-data <- get *sandbox, next-sandbox:offset
|
||||
next-sandbox:address:shared:sandbox-data <- get *sandbox, next-sandbox:offset
|
||||
row, screen <- render-sandboxes screen, next-sandbox, left, right, row
|
||||
]
|
||||
|
||||
# assumes programming environment has no sandboxes; restores them from previous session
|
||||
recipe restore-sandboxes env:address:programming-environment-data -> env:address:programming-environment-data [
|
||||
recipe! restore-sandboxes env:address:shared:programming-environment-data -> env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# read all scenarios, pushing them to end of a list of scenarios
|
||||
suffix:address:array:character <- new [.out]
|
||||
suffix:address:shared:array:character <- new [.out]
|
||||
idx:number <- copy 0
|
||||
curr:address:address:sandbox-data <- get-address *env, sandbox:offset
|
||||
curr:address:address:shared:sandbox-data <- get-address *env, sandbox:offset
|
||||
{
|
||||
filename:address:array:character <- to-text idx
|
||||
contents:address:array:character <- restore filename
|
||||
filename:address:shared:array:character <- to-text idx
|
||||
contents:address:shared:array:character <- restore filename
|
||||
break-unless contents # stop at first error; assuming file didn't exist
|
||||
# create new sandbox for file
|
||||
*curr <- new sandbox-data:type
|
||||
data:address:address:array:character <- get-address **curr, data:offset
|
||||
data:address:address:shared:array:character <- get-address **curr, data:offset
|
||||
*data <- copy contents
|
||||
# restore expected output for sandbox if it exists
|
||||
{
|
||||
filename <- append filename, suffix
|
||||
contents <- restore filename
|
||||
break-unless contents
|
||||
expected-response:address:address:array:character <- get-address **curr, expected-response:offset
|
||||
expected-response:address:address:shared:array:character <- get-address **curr, expected-response:offset
|
||||
*expected-response <- copy contents
|
||||
}
|
||||
+continue
|
||||
|
@ -305,19 +305,19 @@ recipe restore-sandboxes env:address:programming-environment-data -> env:address
|
|||
|
||||
# print the fake sandbox screen to 'screen' with appropriate delimiters
|
||||
# leave cursor at start of next line
|
||||
recipe render-screen screen:address:screen, sandbox-screen:address:screen, left:number, right:number, row:number -> row:number, screen:address:screen [
|
||||
recipe render-screen screen:address:shared:screen, sandbox-screen:address:shared:screen, left:number, right:number, row:number -> row:number, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless sandbox-screen
|
||||
# print 'screen:'
|
||||
header:address:array:character <- new [screen:]
|
||||
header:address:shared:array:character <- new [screen:]
|
||||
row <- render screen, header, left, right, 245/grey, row
|
||||
screen <- move-cursor screen, row, left
|
||||
# start printing sandbox-screen
|
||||
column:number <- copy left
|
||||
s-width:number <- screen-width sandbox-screen
|
||||
s-height:number <- screen-height sandbox-screen
|
||||
buf:address:array:screen-cell <- get *sandbox-screen, data:offset
|
||||
buf:address:shared:array:screen-cell <- get *sandbox-screen, data:offset
|
||||
stop-printing:number <- add left, s-width, 3
|
||||
max-column:number <- min stop-printing, right
|
||||
i:number <- copy 0
|
||||
|
@ -375,14 +375,14 @@ scenario run-instruction-manages-screen-per-sandbox [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 50/width, 20/height
|
||||
# editor contains an instruction
|
||||
1:address:array:character <- new [print-integer screen, 4]
|
||||
2:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character
|
||||
1:address:shared:array:character <- new [print-integer screen, 4]
|
||||
2:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character
|
||||
# run the code in the editor
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
]
|
||||
# check that it prints a little toy screen
|
||||
screen-should-contain [
|
||||
|
@ -402,11 +402,11 @@ scenario run-instruction-manages-screen-per-sandbox [
|
|||
]
|
||||
]
|
||||
|
||||
recipe editor-contents editor:address:editor-data -> result:address:array:character [
|
||||
recipe editor-contents editor:address:shared:editor-data -> result:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
buf:address:buffer <- new-buffer 80
|
||||
curr:address:duplex-list:character <- get *editor, data:offset
|
||||
buf:address:shared:buffer <- new-buffer 80
|
||||
curr:address:shared:duplex-list:character <- get *editor, data:offset
|
||||
# skip § sentinel
|
||||
assert curr, [editor without data is illegal; must have at least a sentinel]
|
||||
curr <- next curr
|
||||
|
@ -423,16 +423,16 @@ recipe editor-contents editor:address:editor-data -> result:address:array:charac
|
|||
|
||||
scenario editor-provides-edited-contents [
|
||||
assume-screen 10/width, 5/height
|
||||
1:address:array:character <- new [abc]
|
||||
2:address:editor-data <- new-editor 1:address:array:character, screen:address:screen, 0/left, 10/right
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
|
||||
assume-console [
|
||||
left-click 1, 2
|
||||
type [def]
|
||||
]
|
||||
run [
|
||||
editor-event-loop screen:address:screen, console:address:console, 2:address:editor-data
|
||||
3:address:array:character <- editor-contents 2:address:editor-data
|
||||
4:array:character <- copy *3:address:array:character
|
||||
editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
|
||||
3:address:shared:array:character <- editor-contents 2:address:shared:editor-data
|
||||
4:array:character <- copy *3:address:shared:array:character
|
||||
]
|
||||
memory-should-contain [
|
||||
4:array:character <- [abdefc]
|
||||
|
|
|
@ -4,12 +4,12 @@ scenario clicking-on-a-sandbox-moves-it-to-editor [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 40/width, 10/height
|
||||
# run something
|
||||
1:address:array:character <- new [add 2, 2]
|
||||
1:address:shared:array:character <- new [add 2, 2]
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
2:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
2:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
. .
|
||||
|
@ -27,7 +27,7 @@ scenario clicking-on-a-sandbox-moves-it-to-editor [
|
|||
left-click 3, 0
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
]
|
||||
# it pops back into editor
|
||||
screen-should-contain [
|
||||
|
@ -47,7 +47,7 @@ scenario clicking-on-a-sandbox-moves-it-to-editor [
|
|||
type [0]
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
|
@ -70,7 +70,7 @@ after <global-touch> [
|
|||
click-column:number <- get *t, column:offset
|
||||
on-sandbox-side?:boolean <- greater-or-equal click-column, sandbox-left-margin
|
||||
break-unless on-sandbox-side?
|
||||
first-sandbox:address:sandbox-data <- get *env, sandbox:offset
|
||||
first-sandbox:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
break-unless first-sandbox
|
||||
first-sandbox-begins:number <- get *first-sandbox, starting-row-on-screen:offset
|
||||
click-row:number <- get *t, row:offset
|
||||
|
@ -79,8 +79,8 @@ after <global-touch> [
|
|||
empty-sandbox-editor?:boolean <- empty-editor? current-sandbox
|
||||
break-unless empty-sandbox-editor? # make the user hit F4 before editing a new sandbox
|
||||
# identify the sandbox to edit and remove it from the sandbox list
|
||||
sandbox:address:sandbox-data <- extract-sandbox env, click-row
|
||||
text:address:array:character <- get *sandbox, data:offset
|
||||
sandbox:address:shared:sandbox-data <- extract-sandbox env, click-row
|
||||
text:address:shared:array:character <- get *sandbox, data:offset
|
||||
current-sandbox <- insert-text current-sandbox, text
|
||||
hide-screen screen
|
||||
screen <- render-sandbox-side screen, env
|
||||
|
@ -90,24 +90,24 @@ after <global-touch> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe empty-editor? editor:address:editor-data -> result:boolean [
|
||||
recipe empty-editor? editor:address:shared:editor-data -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
head:address:duplex-list:character <- get *editor, data:offset
|
||||
first:address:duplex-list:character <- next head
|
||||
head:address:shared:duplex-list:character <- get *editor, data:offset
|
||||
first:address:shared:duplex-list:character <- next head
|
||||
result <- not first
|
||||
]
|
||||
|
||||
recipe extract-sandbox env:address:programming-environment-data, click-row:number -> result:address:sandbox-data, env:address:programming-environment-data [
|
||||
recipe extract-sandbox env:address:shared:programming-environment-data, click-row:number -> result:address:shared:sandbox-data, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# assert click-row >= sandbox.starting-row-on-screen
|
||||
sandbox:address:address:sandbox-data <- get-address *env, sandbox:offset
|
||||
sandbox:address:address:shared:sandbox-data <- get-address *env, sandbox:offset
|
||||
start:number <- get **sandbox, starting-row-on-screen:offset
|
||||
clicked-on-sandboxes?:boolean <- greater-or-equal click-row, start
|
||||
assert clicked-on-sandboxes?, [extract-sandbox called on click to sandbox editor]
|
||||
{
|
||||
next-sandbox:address:sandbox-data <- get **sandbox, next-sandbox:offset
|
||||
next-sandbox:address:shared:sandbox-data <- get **sandbox, next-sandbox:offset
|
||||
break-unless next-sandbox
|
||||
# if click-row < sandbox.next-sandbox.starting-row-on-screen, break
|
||||
next-start:number <- get *next-sandbox, starting-row-on-screen:offset
|
||||
|
@ -125,14 +125,14 @@ scenario sandbox-with-print-can-be-edited [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 50/width, 20/height
|
||||
# run a print instruction
|
||||
1:address:array:character <- new [print-integer screen, 4]
|
||||
2:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character
|
||||
1:address:shared:array:character <- new [print-integer screen, 4]
|
||||
2:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character
|
||||
# run the sandbox
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
|
@ -161,7 +161,7 @@ scenario sandbox-with-print-can-be-edited [
|
|||
left-click 3, 70
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
scenario deleting-sandboxes [
|
||||
trace-until 100/app # trace too long
|
||||
assume-screen 50/width, 15/height
|
||||
1:address:array:character <- new []
|
||||
2:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character
|
||||
1:address:shared:array:character <- new []
|
||||
2:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character
|
||||
# run a few commands
|
||||
assume-console [
|
||||
left-click 1, 0
|
||||
|
@ -13,7 +13,7 @@ scenario deleting-sandboxes [
|
|||
type [add 2, 2]
|
||||
press F4
|
||||
]
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
. .
|
||||
|
@ -34,7 +34,7 @@ scenario deleting-sandboxes [
|
|||
left-click 7, 49
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
|
@ -52,7 +52,7 @@ scenario deleting-sandboxes [
|
|||
left-click 3, 49
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
|
@ -76,17 +76,17 @@ after <global-touch> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe delete-sandbox t:touch-event, env:address:programming-environment-data -> was-delete?:boolean, env:address:programming-environment-data [
|
||||
recipe delete-sandbox t:touch-event, env:address:shared:programming-environment-data -> was-delete?:boolean, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
click-column:number <- get t, column:offset
|
||||
current-sandbox:address:editor-data <- get *env, current-sandbox:offset
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
right:number <- get *current-sandbox, right:offset
|
||||
at-right?:boolean <- equal click-column, right
|
||||
reply-unless at-right?, 0/false
|
||||
click-row:number <- get t, row:offset
|
||||
prev:address:address:sandbox-data <- get-address *env, sandbox:offset
|
||||
curr:address:sandbox-data <- get *env, sandbox:offset
|
||||
prev:address:address:shared:sandbox-data <- get-address *env, sandbox:offset
|
||||
curr:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
{
|
||||
break-unless curr
|
||||
# more sandboxes to check
|
||||
|
|
|
@ -10,14 +10,14 @@ after <global-touch> [
|
|||
click-column:number <- get *t, column:offset
|
||||
on-sandbox-side?:boolean <- greater-or-equal click-column, sandbox-left-margin
|
||||
break-unless on-sandbox-side?
|
||||
first-sandbox:address:sandbox-data <- get *env, sandbox:offset
|
||||
first-sandbox:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
break-unless first-sandbox
|
||||
first-sandbox-begins:number <- get *first-sandbox, starting-row-on-screen:offset
|
||||
click-row:number <- get *t, row:offset
|
||||
below-sandbox-editor?:boolean <- greater-or-equal click-row, first-sandbox-begins
|
||||
break-unless below-sandbox-editor?
|
||||
# identify the sandbox whose output is being clicked on
|
||||
sandbox:address:sandbox-data <- find-click-in-sandbox-output env, click-row
|
||||
sandbox:address:shared:sandbox-data <- find-click-in-sandbox-output env, click-row
|
||||
break-unless sandbox
|
||||
# toggle its expected-response, and save session
|
||||
sandbox <- toggle-expected-response sandbox
|
||||
|
@ -31,17 +31,17 @@ after <global-touch> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe find-click-in-sandbox-output env:address:programming-environment-data, click-row:number -> sandbox:address:sandbox-data [
|
||||
recipe find-click-in-sandbox-output env:address:shared:programming-environment-data, click-row:number -> sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# assert click-row >= sandbox.starting-row-on-screen
|
||||
sandbox:address:sandbox-data <- get *env, sandbox:offset
|
||||
sandbox:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
start:number <- get *sandbox, starting-row-on-screen:offset
|
||||
clicked-on-sandboxes?:boolean <- greater-or-equal click-row, start
|
||||
assert clicked-on-sandboxes?, [extract-sandbox called on click to sandbox editor]
|
||||
# while click-row < sandbox.next-sandbox.starting-row-on-screen
|
||||
{
|
||||
next-sandbox:address:sandbox-data <- get *sandbox, next-sandbox:offset
|
||||
next-sandbox:address:shared:sandbox-data <- get *sandbox, next-sandbox:offset
|
||||
break-unless next-sandbox
|
||||
next-start:number <- get *next-sandbox, starting-row-on-screen:offset
|
||||
found?:boolean <- lesser-than click-row, next-start
|
||||
|
@ -57,10 +57,10 @@ recipe find-click-in-sandbox-output env:address:programming-environment-data, cl
|
|||
reply sandbox
|
||||
]
|
||||
|
||||
recipe toggle-expected-response sandbox:address:sandbox-data -> sandbox:address:sandbox-data [
|
||||
recipe toggle-expected-response sandbox:address:shared:sandbox-data -> sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
expected-response:address:address:array:character <- get-address *sandbox, expected-response:offset
|
||||
expected-response:address:address:shared:array:character <- get-address *sandbox, expected-response:offset
|
||||
{
|
||||
# if expected-response is set, reset
|
||||
break-unless *expected-response
|
||||
|
@ -68,7 +68,7 @@ recipe toggle-expected-response sandbox:address:sandbox-data -> sandbox:address:
|
|||
reply sandbox/same-as-ingredient:0
|
||||
}
|
||||
# if not, current response is the expected response
|
||||
response:address:array:character <- get *sandbox, response:offset
|
||||
response:address:shared:array:character <- get *sandbox, response:offset
|
||||
*expected-response <- copy response
|
||||
]
|
||||
|
||||
|
@ -76,7 +76,7 @@ recipe toggle-expected-response sandbox:address:sandbox-data -> sandbox:address:
|
|||
after <render-sandbox-response> [
|
||||
{
|
||||
break-unless sandbox-response
|
||||
expected-response:address:array:character <- get *sandbox, expected-response:offset
|
||||
expected-response:address:shared:array:character <- get *sandbox, expected-response:offset
|
||||
break-unless expected-response # fall-through to print in grey
|
||||
response-is-expected?:boolean <- equal expected-response, sandbox-response
|
||||
{
|
||||
|
|
|
@ -4,12 +4,12 @@ scenario sandbox-click-on-code-toggles-app-trace [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 40/width, 10/height
|
||||
# run a stash instruction
|
||||
1:address:array:character <- new [stash [abc]]
|
||||
1:address:shared:array:character <- new [stash [abc]]
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
2:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
2:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
. .
|
||||
|
@ -24,9 +24,9 @@ scenario sandbox-click-on-code-toggles-app-trace [
|
|||
left-click 4, 21
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
4:character/cursor-icon <- copy 9251/␣
|
||||
print screen:address:screen, 4:character/cursor-icon
|
||||
print screen:address:shared:screen, 4:character/cursor-icon
|
||||
]
|
||||
# trace now printed and cursor shouldn't have budged
|
||||
screen-should-contain [
|
||||
|
@ -54,8 +54,8 @@ scenario sandbox-click-on-code-toggles-app-trace [
|
|||
left-click 4, 25
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
print screen:address:screen, 4:character/cursor-icon
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
print screen:address:shared:screen, 4:character/cursor-icon
|
||||
]
|
||||
# trace hidden again
|
||||
screen-should-contain [
|
||||
|
@ -73,13 +73,13 @@ scenario sandbox-shows-app-trace-and-result [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 40/width, 10/height
|
||||
# run a stash instruction and some code
|
||||
1:address:array:character <- new [stash [abc]
|
||||
1:address:shared:array:character <- new [stash [abc]
|
||||
add 2, 2]
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
2:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
2:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
. .
|
||||
|
@ -96,7 +96,7 @@ add 2, 2]
|
|||
left-click 4, 21
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
]
|
||||
# trace now printed above result
|
||||
screen-should-contain [
|
||||
|
@ -114,18 +114,18 @@ add 2, 2]
|
|||
]
|
||||
|
||||
container sandbox-data [
|
||||
trace:address:array:character
|
||||
trace:address:shared:array:character
|
||||
display-trace?:boolean
|
||||
]
|
||||
|
||||
# replaced in a later layer
|
||||
recipe! update-sandbox sandbox:address:sandbox-data -> sandbox:address:sandbox-data [
|
||||
recipe! update-sandbox sandbox:address:shared:sandbox-data -> sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
data:address:array:character <- get *sandbox, data:offset
|
||||
response:address:address:array:character <- get-address *sandbox, response:offset
|
||||
trace:address:address:array:character <- get-address *sandbox, trace:offset
|
||||
fake-screen:address:address:screen <- get-address *sandbox, screen:offset
|
||||
data:address:shared:array:character <- get *sandbox, data:offset
|
||||
response:address:address:shared:array:character <- get-address *sandbox, response:offset
|
||||
trace:address:address:shared:array:character <- get-address *sandbox, trace:offset
|
||||
fake-screen:address:address:shared:screen <- get-address *sandbox, screen:offset
|
||||
*response, _, *fake-screen, *trace <- run-interactive data
|
||||
]
|
||||
|
||||
|
@ -137,14 +137,14 @@ after <global-touch> [
|
|||
click-column:number <- get *t, column:offset
|
||||
on-sandbox-side?:boolean <- greater-or-equal click-column, sandbox-left-margin
|
||||
break-unless on-sandbox-side?
|
||||
first-sandbox:address:sandbox-data <- get *env, sandbox:offset
|
||||
first-sandbox:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
break-unless first-sandbox
|
||||
first-sandbox-begins:number <- get *first-sandbox, starting-row-on-screen:offset
|
||||
click-row:number <- get *t, row:offset
|
||||
below-sandbox-editor?:boolean <- greater-or-equal click-row, first-sandbox-begins
|
||||
break-unless below-sandbox-editor?
|
||||
# identify the sandbox whose code is being clicked on
|
||||
sandbox:address:sandbox-data <- find-click-in-sandbox-code env, click-row
|
||||
sandbox:address:shared:sandbox-data <- find-click-in-sandbox-code env, click-row
|
||||
break-unless sandbox
|
||||
# toggle its display-trace? property
|
||||
x:address:boolean <- get-address *sandbox, display-trace?:offset
|
||||
|
@ -158,7 +158,7 @@ after <global-touch> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe find-click-in-sandbox-code env:address:programming-environment-data, click-row:number -> sandbox:address:sandbox-data [
|
||||
recipe find-click-in-sandbox-code env:address:shared:programming-environment-data, click-row:number -> sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# assert click-row >= sandbox.starting-row-on-screen
|
||||
|
@ -168,7 +168,7 @@ recipe find-click-in-sandbox-code env:address:programming-environment-data, clic
|
|||
assert clicked-on-sandboxes?, [extract-sandbox called on click to sandbox editor]
|
||||
# while click-row < sandbox.next-sandbox.starting-row-on-screen
|
||||
{
|
||||
next-sandbox:address:sandbox-data <- get *sandbox, next-sandbox:offset
|
||||
next-sandbox:address:shared:sandbox-data <- get *sandbox, next-sandbox:offset
|
||||
break-unless next-sandbox
|
||||
next-start:number <- get *next-sandbox, starting-row-on-screen:offset
|
||||
found?:boolean <- lesser-than click-row, next-start
|
||||
|
@ -194,7 +194,7 @@ after <render-sandbox-results> [
|
|||
{
|
||||
display-trace?:boolean <- get *sandbox, display-trace?:offset
|
||||
break-unless display-trace?
|
||||
sandbox-trace:address:array:character <- get *sandbox, trace:offset
|
||||
sandbox-trace:address:shared:array:character <- get *sandbox, trace:offset
|
||||
break-unless sandbox-trace # nothing to print; move on
|
||||
row, screen <- render screen, sandbox-trace, left, right, 245/grey, row
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
## handling malformed programs
|
||||
|
||||
container programming-environment-data [
|
||||
recipe-warnings:address:array:character
|
||||
recipe-warnings:address:shared:array:character
|
||||
]
|
||||
|
||||
# copy code from recipe editor, persist, load into mu, save any warnings
|
||||
recipe! update-recipes env:address:programming-environment-data, screen:address:screen -> errors-found?:boolean, env:address:programming-environment-data, screen:address:screen [
|
||||
recipe! update-recipes env:address:shared:programming-environment-data, screen:address:shared:screen -> errors-found?:boolean, env:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
in:address:array:character <- restore [recipes.mu]
|
||||
recipe-warnings:address:address:array:character <- get-address *env, recipe-warnings:offset
|
||||
in:address:shared:array:character <- restore [recipes.mu]
|
||||
recipe-warnings:address:address:shared:array:character <- get-address *env, recipe-warnings:offset
|
||||
*recipe-warnings <- reload in
|
||||
# if recipe editor has errors, stop
|
||||
{
|
||||
break-unless *recipe-warnings
|
||||
status:address:array:character <- new [errors found]
|
||||
status:address:shared:array:character <- new [errors found]
|
||||
update-status screen, status, 1/red
|
||||
}
|
||||
errors-found? <- copy 0/false
|
||||
|
@ -22,27 +22,27 @@ recipe! update-recipes env:address:programming-environment-data, screen:address:
|
|||
|
||||
before <render-components-end> [
|
||||
trace 11, [app], [render status]
|
||||
recipe-warnings:address:array:character <- get *env, recipe-warnings:offset
|
||||
recipe-warnings:address:shared:array:character <- get *env, recipe-warnings:offset
|
||||
{
|
||||
break-unless recipe-warnings
|
||||
status:address:array:character <- new [errors found]
|
||||
status:address:shared:array:character <- new [errors found]
|
||||
update-status screen, status, 1/red
|
||||
}
|
||||
]
|
||||
|
||||
container sandbox-data [
|
||||
warnings:address:array:character
|
||||
warnings:address:shared:array:character
|
||||
]
|
||||
|
||||
recipe! update-sandbox sandbox:address:sandbox-data, env:address:programming-environment-data -> sandbox:address:sandbox-data [
|
||||
recipe! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data -> sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
data:address:array:character <- get *sandbox, data:offset
|
||||
response:address:address:array:character <- get-address *sandbox, response:offset
|
||||
warnings:address:address:array:character <- get-address *sandbox, warnings:offset
|
||||
trace:address:address:array:character <- get-address *sandbox, trace:offset
|
||||
fake-screen:address:address:screen <- get-address *sandbox, screen:offset
|
||||
recipe-warnings:address:array:character <- get *env, recipe-warnings:offset
|
||||
data:address:shared:array:character <- get *sandbox, data:offset
|
||||
response:address:address:shared:array:character <- get-address *sandbox, response:offset
|
||||
warnings:address:address:shared:array:character <- get-address *sandbox, warnings:offset
|
||||
trace:address:address:shared:array:character <- get-address *sandbox, trace:offset
|
||||
fake-screen:address:address:shared:screen <- get-address *sandbox, screen:offset
|
||||
recipe-warnings:address:shared:array:character <- get *env, recipe-warnings:offset
|
||||
{
|
||||
break-unless recipe-warnings
|
||||
*warnings <- copy recipe-warnings
|
||||
|
@ -60,12 +60,12 @@ recipe! update-sandbox sandbox:address:sandbox-data, env:address:programming-env
|
|||
# make sure we render any trace
|
||||
after <render-sandbox-trace-done> [
|
||||
{
|
||||
sandbox-warnings:address:array:character <- get *sandbox, warnings:offset
|
||||
sandbox-warnings:address:shared:array:character <- get *sandbox, warnings:offset
|
||||
break-unless sandbox-warnings
|
||||
*response-starting-row <- copy 0 # no response
|
||||
{
|
||||
break-unless env
|
||||
recipe-warnings:address:array:character <- get *env, recipe-warnings:offset
|
||||
recipe-warnings:address:shared:array:character <- get *env, recipe-warnings:offset
|
||||
row, screen <- render screen, recipe-warnings, left, right, 1/red, row
|
||||
}
|
||||
row, screen <- render screen, sandbox-warnings, left, right, 1/red, row
|
||||
|
@ -77,22 +77,22 @@ after <render-sandbox-trace-done> [
|
|||
scenario run-instruction-and-print-warnings [
|
||||
trace-until 100/app # trace too long
|
||||
assume-screen 50/width, 15/height
|
||||
1:address:array:character <- new [get 1:address:point, 1:offset]
|
||||
2:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character
|
||||
1:address:shared:array:character <- new [get 1:address:shared:point, 1:offset]
|
||||
2:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
. .
|
||||
.━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.
|
||||
. x.
|
||||
.get 1:address:point, 1:offset .
|
||||
.get 1:address:shared:point, 1:offset .
|
||||
.first ingredient of 'get' should be a container, ↩.
|
||||
.but got 1:address:point .
|
||||
.but got 1:address:shared:point .
|
||||
.━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.
|
||||
. .
|
||||
]
|
||||
|
@ -103,7 +103,7 @@ scenario run-instruction-and-print-warnings [
|
|||
. .
|
||||
. .
|
||||
.first ingredient of 'get' should be a container, .
|
||||
.but got 1:address:point .
|
||||
.but got 1:address:shared:point .
|
||||
. .
|
||||
. .
|
||||
]
|
||||
|
@ -115,15 +115,15 @@ scenario run-instruction-and-print-warnings-only-once [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 50/width, 10/height
|
||||
# editor contains an illegal instruction
|
||||
1:address:array:character <- new [get 1234:number, foo:offset]
|
||||
2:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character
|
||||
1:address:shared:array:character <- new [get 1234:number, foo:offset]
|
||||
2:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character
|
||||
# run the code in the editors multiple times
|
||||
assume-console [
|
||||
press F4
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
]
|
||||
# check that screen prints error message just once
|
||||
screen-should-contain [
|
||||
|
@ -144,16 +144,16 @@ scenario sandbox-can-handle-infinite-loop [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 50/width, 20/height
|
||||
# editor contains an infinite loop
|
||||
1:address:array:character <- new [{
|
||||
1:address:shared:array:character <- new [{
|
||||
loop
|
||||
}]
|
||||
2:address:programming-environment-data <- new-programming-environment screen:address:screen, 1:address:array:character
|
||||
2:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 1:address:shared:array:character
|
||||
# run the sandbox
|
||||
assume-console [
|
||||
press F4
|
||||
]
|
||||
run [
|
||||
event-loop screen:address:screen, console:address:console, 2:address:programming-environment-data
|
||||
event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:programming-environment-data
|
||||
]
|
||||
screen-should-contain [
|
||||
. run (F4) .
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user