Periodic cleanup to replace 'reply' with 'return' everywhere in the
repo.

I use 'reply' for students to help reinforce the metaphor of function
calls as being like messages through a pipe. But that causes 'reply' to
get into my muscle memory when writing Mu code for myself, and I worry
that that makes Mu seem unnecessarily alien to anybody reading on
Github.

Perhaps I should just give it up? I'll try using 'return' with my next
student.
This commit is contained in:
Kartik K. Agaram 2016-11-10 10:24:14 -08:00
parent b771d375d3
commit f116818c7c
20 changed files with 92 additions and 79 deletions

View File

@ -4,10 +4,23 @@
def main [
1:num, 2:num <- f 34
]
def f [
12:num <- next-ingredient
13:num <- add 1, 12:num
return 12:num, 13:num
]
+mem: storing 34 in location 1
+mem: storing 35 in location 2
:(scenario reply)
def main [
1:num, 2:num <- f 34
]
def f [
12:num <- next-ingredient
13:num <- add 1, 12:num
reply 12:num, 13:num
$dump-trace
]
+mem: storing 34 in location 1
+mem: storing 35 in location 2
@ -25,7 +38,7 @@ case RETURN: {
case RETURN: {
// Starting Reply
if (Trace_stream) {
trace(9999, "trace") << "reply: decrementing callstack depth from " << Trace_stream->callstack_depth << end();
trace(9999, "trace") << current_instruction().name << ": decrementing callstack depth from " << Trace_stream->callstack_depth << end();
--Trace_stream->callstack_depth;
if (Trace_stream->callstack_depth < 0) {
Current_routine->calls.clear();
@ -37,20 +50,20 @@ case RETURN: {
if (Current_routine->calls.empty()) goto stop_running_current_routine;
for (int i = 0; i < SIZE(ingredients); ++i)
trace(9998, "run") << "result " << i << " is " << to_string(ingredients.at(i)) << end();
// make reply products available to caller
// make return products available to caller
copy(ingredients.begin(), ingredients.end(), inserter(products, products.begin()));
// End Reply
break; // continue to process rest of *caller* instruction
}
//: Types in reply instructions are checked ahead of time.
//: Types in return instructions are checked ahead of time.
:(before "End Checks")
Transform.push_back(check_types_of_reply_instructions); // idempotent
Transform.push_back(check_types_of_return_instructions); // idempotent
:(code)
void check_types_of_reply_instructions(const recipe_ordinal r) {
void check_types_of_return_instructions(const recipe_ordinal r) {
const recipe& caller = get(Recipe, r);
trace(9991, "transform") << "--- check types of reply instructions in recipe " << caller.name << end();
trace(9991, "transform") << "--- check types of return instructions in recipe " << caller.name << end();
for (int i = 0; i < SIZE(caller.steps); ++i) {
const instruction& caller_instruction = caller.steps.at(i);
if (caller_instruction.is_label) continue;
@ -58,43 +71,43 @@ void check_types_of_reply_instructions(const recipe_ordinal r) {
if (caller_instruction.operation < MAX_PRIMITIVE_RECIPES) continue;
const recipe& callee = get(Recipe, caller_instruction.operation);
for (int i = 0; i < SIZE(callee.steps); ++i) {
const instruction& reply_inst = callee.steps.at(i);
if (reply_inst.operation != RETURN) continue;
const instruction& return_inst = callee.steps.at(i);
if (return_inst.operation != RETURN) continue;
// check types with the caller
if (SIZE(caller_instruction.products) > SIZE(reply_inst.ingredients)) {
if (SIZE(caller_instruction.products) > SIZE(return_inst.ingredients)) {
raise << maybe(caller.name) << "too few values returned from " << callee.name << '\n' << end();
break;
}
for (int i = 0; i < SIZE(caller_instruction.products); ++i) {
reagent/*copy*/ lhs = reply_inst.ingredients.at(i);
reagent/*copy*/ lhs = return_inst.ingredients.at(i);
reagent/*copy*/ rhs = caller_instruction.products.at(i);
// End Check RETURN Copy(lhs, rhs)
if (!types_coercible(rhs, lhs)) {
raise << maybe(callee.name) << reply_inst.name << " ingredient '" << lhs.original_string << "' can't be saved in '" << rhs.original_string << "'\n" << end();
raise << maybe(callee.name) << return_inst.name << " ingredient '" << lhs.original_string << "' can't be saved in '" << rhs.original_string << "'\n" << end();
raise << " ['" << to_string(lhs.type) << "' vs '" << to_string(rhs.type) << "']\n" << end();
goto finish_reply_check;
goto finish_return_check;
}
}
// check that any reply ingredients with /same-as-ingredient connect up
// check that any return ingredients with /same-as-ingredient connect up
// the corresponding ingredient and product in the caller.
for (int i = 0; i < SIZE(caller_instruction.products); ++i) {
if (has_property(reply_inst.ingredients.at(i), "same-as-ingredient")) {
string_tree* tmp = property(reply_inst.ingredients.at(i), "same-as-ingredient");
if (has_property(return_inst.ingredients.at(i), "same-as-ingredient")) {
string_tree* tmp = property(return_inst.ingredients.at(i), "same-as-ingredient");
if (!tmp || !tmp->atom) {
raise << maybe(caller.name) << "'same-as-ingredient' metadata should take exactly one value in '" << to_original_string(reply_inst) << "'\n" << end();
goto finish_reply_check;
raise << maybe(caller.name) << "'same-as-ingredient' metadata should take exactly one value in '" << to_original_string(return_inst) << "'\n" << end();
goto finish_return_check;
}
int ingredient_index = to_integer(tmp->value);
if (ingredient_index >= SIZE(caller_instruction.ingredients)) {
raise << maybe(caller.name) << "too few ingredients in '" << to_original_string(caller_instruction) << "'\n" << end();
goto finish_reply_check;
goto finish_return_check;
}
if (!is_dummy(caller_instruction.products.at(i)) && !is_literal(caller_instruction.ingredients.at(ingredient_index)) && caller_instruction.products.at(i).name != caller_instruction.ingredients.at(ingredient_index).name) {
raise << maybe(caller.name) << "'" << to_original_string(caller_instruction) << "' should write to '" << caller_instruction.ingredients.at(ingredient_index).original_string << "' rather than '" << caller_instruction.products.at(i).original_string << "'\n" << end();
}
}
}
finish_reply_check:;
finish_return_check:;
}
}
}
@ -114,7 +127,7 @@ def f [
//: In Mu we'd like to assume that any instruction doesn't modify its
//: ingredients unless they're also products. The /same-as-ingredient inside
//: the recipe's 'reply' indicates that an ingredient is intended to be
//: the recipe's 'return' indicates that an ingredient is intended to be
//: modified in place, and will help catch accidental misuse of such
//: 'ingredient-products' (sometimes called in-out parameters in other
//: languages).

View File

@ -5,7 +5,7 @@
//: units (containers or arrays) that may contain many different primitives at
//: once. Containers and arrays can grow quite large in complex programs, and
//: we'd like some way to efficiently share them between recipes without
//: constantly having to make copies. Right now 'next-ingredient' and 'reply'
//: constantly having to make copies. Right now 'next-ingredient' and 'return'
//: copy data across recipe boundaries. To avoid copying large quantities of
//: data around, we'll use *addresses*. An address is a bookmark to some
//: arbitrary quantity of data (the *payload*). It's a primitive, so it's as

View File

@ -222,7 +222,7 @@ if (curr.name == "local-scope") {
rewrite_default_space_instruction(curr);
}
//: todo: do this in a transform, rather than magically in the reply instruction
//: todo: do this in a transform, rather than magically in the return instruction
:(after "Falling Through End Of Recipe")
try_reclaim_locals();
:(after "Starting Reply")
@ -259,7 +259,7 @@ void try_reclaim_locals() {
}
:(code)
// is this reagent one of the values returned by the current (reply) instruction?
// is this reagent one of the values returned by the current (return) instruction?
// is the corresponding ingredient saved in the caller?
bool escaping(const reagent& r) {
assert(Current_routine); // run-time only
@ -370,7 +370,7 @@ def main [
def f [
local-scope
x:&:num <- new number:type
reply x:&:num
return x:&:num
]
def main [
f # doesn't save result

View File

@ -322,13 +322,13 @@ def add2 x:num, y:num -> z:num [
+error: add2: replied with the wrong type at 'return z'
:(before "End Checks")
Transform.push_back(check_reply_instructions_against_header); // idempotent
Transform.push_back(check_return_instructions_against_header); // idempotent
:(code)
void check_reply_instructions_against_header(const recipe_ordinal r) {
void check_return_instructions_against_header(const recipe_ordinal r) {
const recipe& caller_recipe = get(Recipe, r);
if (!caller_recipe.has_header) return;
trace(9991, "transform") << "--- checking reply instructions against header for " << caller_recipe.name << end();
trace(9991, "transform") << "--- checking return instructions against header for " << caller_recipe.name << end();
for (int i = 0; i < SIZE(caller_recipe.steps); ++i) {
const instruction& inst = caller_recipe.steps.at(i);
if (inst.name != "reply" && inst.name != "return") continue;
@ -373,7 +373,7 @@ void check_header_ingredients(const recipe_ordinal r) {
recipe& caller_recipe = get(Recipe, r);
if (caller_recipe.products.empty()) return;
caller_recipe.ingredient_index.clear();
trace(9991, "transform") << "--- checking reply instructions against header for " << caller_recipe.name << end();
trace(9991, "transform") << "--- checking return instructions against header for " << caller_recipe.name << end();
for (int i = 0; i < SIZE(caller_recipe.ingredients); ++i) {
if (contains_key(caller_recipe.ingredient_index, caller_recipe.ingredients.at(i).name))
raise << maybe(caller_recipe.name) << "'" << caller_recipe.ingredients.at(i).name << "' can't repeat in the ingredients\n" << end();
@ -454,24 +454,24 @@ def add2 x:num, y:num -> z:num [
+mem: storing 8 in location 1
:(after "Transform.push_back(check_header_ingredients)")
Transform.push_back(fill_in_reply_ingredients); // idempotent
Transform.push_back(fill_in_return_ingredients); // idempotent
:(code)
void fill_in_reply_ingredients(const recipe_ordinal r) {
void fill_in_return_ingredients(const recipe_ordinal r) {
recipe& caller_recipe = get(Recipe, r);
if (!caller_recipe.has_header) return;
trace(9991, "transform") << "--- fill in reply ingredients from header for recipe " << caller_recipe.name << end();
trace(9991, "transform") << "--- fill in return ingredients from header for recipe " << caller_recipe.name << end();
for (int i = 0; i < SIZE(caller_recipe.steps); ++i) {
instruction& inst = caller_recipe.steps.at(i);
if (inst.name == "reply" || inst.name == "return")
add_header_products(inst, caller_recipe);
}
// fall through reply
// fall through return
if (caller_recipe.steps.empty()) return; // error will be raised elsewhere if there's a product in the header; just give up
const instruction& final_instruction = caller_recipe.steps.at(SIZE(caller_recipe.steps)-1);
if (final_instruction.name != "reply" && final_instruction.name != "return") {
instruction inst;
inst.name = "reply";
inst.name = "return";
add_header_products(inst, caller_recipe);
caller_recipe.steps.push_back(inst);
}
@ -493,7 +493,7 @@ void add_header_products(instruction& inst, const recipe& caller_recipe) {
}
}
:(scenario explicit_reply_ignores_header)
:(scenario explicit_return_ignores_header)
def main [
1:num/raw, 2:num/raw <- add2 3, 5
]
@ -516,7 +516,7 @@ def add2 x:num, y:num -> z:num [
load-ingredients
z <- add x, y
]
+transform: instruction: reply {z: "number"}
+transform: instruction: return {z: "number"}
+mem: storing 8 in location 1
:(scenario return_on_fallthrough_already_exists)
@ -530,10 +530,10 @@ def add2 x:num, y:num -> z:num [
return z
]
+transform: instruction: return {z: ()}
-transform: instruction: reply z:num
-transform: instruction: return z:num
+mem: storing 8 in location 1
:(scenario return_after_conditional_reply_based_on_header)
:(scenario return_after_conditional_return_based_on_header)
def main [
1:num/raw <- add2 3, 5
]

View File

@ -244,7 +244,7 @@ def main [
+run: {6: ("foo" "point")} <- merge {1: "literal", "y": ()}, {23: "literal"}
+mem: storing 1 in location 6
+mem: storing 23 in location 7
+run: reply
+run: return
# no other stores
% CHECK_EQ(trace_count_prefix("mem", "storing"), 7);

View File

@ -56,7 +56,7 @@ def foo p:&:d1 -> q:num [
load-ingredients
x:&:d1 <- new d1:type
*x <- put *x, p:offset, 34 # ignore this 'p'
reply 36
return 36
]
container d1 [
p:num

View File

@ -13,7 +13,7 @@ def push x:_elem, l:&:list:_elem -> l:&:list:_elem [
load-ingredients
result:&:list:_elem <- new {(list _elem): type}
*result <- merge x, l
reply result
return result
]
def first in:&:list:_elem -> result:_elem [
@ -264,7 +264,7 @@ scenario removing-from-singleton-list [
def reverse list:&:list:_elem temp:&:list:_elem/contained-in:result -> result:&:list:_elem [
local-scope
load-ingredients
reply-unless list, temp
return-unless list, temp
object:_elem <- first, list
list <- rest list
temp <- push object, temp

View File

@ -5,7 +5,7 @@ def random generator:&:stream:num -> result:num, fail?:bool, generator:&:stream:
break-if generator
# generator is 0? use real random-number generator
result <- real-random
reply result, 0/false
return result, 0/false
}
result, fail?, generator <- read generator
]

View File

@ -324,7 +324,7 @@ def use-space [
n:&:num/space:1 <- next-ingredient # should decrement refcount
*n/space:1 <- copy 34
n2:num <- add *n/space:1, 1
reply n2
return n2
]
def main [
local-scope
@ -665,7 +665,7 @@ def f2 [
20:num <- copy 1
]
# f2 runs an extra instruction for the implicit return added by the
# fill_in_reply_ingredients transform
# fill_in_return_ingredients transform
+mem: storing 3 in location 11
:(scenario number_of_instructions_across_multiple_scheduling_intervals)
@ -685,7 +685,7 @@ def f2 [
20:num <- copy 1
]
# f2 runs an extra instruction for the implicit return added by the
# fill_in_reply_ingredients transform
# fill_in_return_ingredients transform
+mem: storing 5 in location 11
//:: make sure that each routine gets a different alloc to start

View File

@ -607,7 +607,7 @@ def screen-height screen:&:screen -> height:num [
def hide-cursor screen:&:screen -> screen:&:screen [
local-scope
load-ingredients
reply-if screen # fake screen; do nothing
return-if screen # fake screen; do nothing
# real screen
hide-cursor-on-display
]
@ -615,7 +615,7 @@ def hide-cursor screen:&:screen -> screen:&:screen [
def show-cursor screen:&:screen -> screen:&:screen [
local-scope
load-ingredients
reply-if screen # fake screen; do nothing
return-if screen # fake screen; do nothing
# real screen
show-cursor-on-display
]
@ -623,7 +623,7 @@ def show-cursor screen:&:screen -> screen:&:screen [
def hide-screen screen:&:screen -> screen:&:screen [
local-scope
load-ingredients
reply-if screen # fake screen; do nothing
return-if screen # fake screen; do nothing
# real screen
hide-display
]
@ -631,7 +631,7 @@ def hide-screen screen:&:screen -> screen:&:screen [
def show-screen screen:&:screen -> screen:&:screen [
local-scope
load-ingredients
reply-if screen # fake screen; do nothing
return-if screen # fake screen; do nothing
# real screen
show-display
]

View File

@ -86,7 +86,7 @@ def start-writing resources:&:resources, filename:text -> sink:&:sink:char, rout
break-unless resources
# fake file system
routine-id <- start-running transmit-to-fake-file resources, filename, source
reply
return
}
# real file system
file:num <- $open-file-for-writing filename
@ -136,7 +136,7 @@ def transmit-to-fake-file resources:&:resources, filename:text, source:&:source:
loop-unless found?
put-index *data, i, new-resource
reset lock
reply
return
}
# if file didn't already exist, make room for it
new-len:num <- add len, 1

View File

@ -26,7 +26,7 @@ F - example-server-test: $open-server-socket failed]
def example-handler query:text -> response:text [
local-scope
load-ingredients
reply [abc]
return [abc]
]
# To test client operations, use `assume-resources` with a filename that

View File

@ -146,7 +146,7 @@ def should-attempt-copy? click-row:num, click-column:num, env:&:environment -> r
load-ingredients
# are we below the sandbox editor?
click-sandbox-area?:bool <- click-on-sandbox-area? click-row, click-column, env
reply-unless click-sandbox-area?, 0/false
return-unless click-sandbox-area?, 0/false
# narrower, is the click in the columns spanning the 'copy' button?
first-sandbox:&:editor <- get *env, current-sandbox:offset
assert first-sandbox, [!!]
@ -154,7 +154,7 @@ def should-attempt-copy? click-row:num, click-column:num, env:&:environment -> r
sandbox-right-margin:num <- get *first-sandbox, right:offset
_, _, copy-button-left:num, copy-button-right:num, _ <- sandbox-menu-columns sandbox-left-margin, sandbox-right-margin
copy-button-vertical-area?:bool <- within-range? click-column, copy-button-left, copy-button-right
reply-unless copy-button-vertical-area?, 0/false
return-unless copy-button-vertical-area?, 0/false
# finally, is sandbox editor empty?
current-sandbox:&:editor <- get *env, current-sandbox:offset
result <- empty-editor? current-sandbox

View File

@ -84,7 +84,7 @@ def should-attempt-delete? click-row:num, click-column:num, env:&:environment ->
load-ingredients
# are we below the sandbox editor?
click-sandbox-area?:bool <- click-on-sandbox-area? click-row, click-column, env
reply-unless click-sandbox-area?, 0/false
return-unless click-sandbox-area?, 0/false
# narrower, is the click in the columns spanning the 'copy' button?
first-sandbox:&:editor <- get *env, current-sandbox:offset
assert first-sandbox, [!!]

View File

@ -141,7 +141,7 @@ def should-attempt-edit? click-row:num, click-column:num, env:&:environment -> r
load-ingredients
# are we below the sandbox editor?
click-sandbox-area?:bool <- click-on-sandbox-area? click-row, click-column, env
reply-unless click-sandbox-area?, 0/false
return-unless click-sandbox-area?, 0/false
# narrower, is the click in the columns spanning the 'edit' button?
first-sandbox:&:editor <- get *env, current-sandbox:offset
assert first-sandbox, [!!]
@ -149,7 +149,7 @@ def should-attempt-edit? click-row:num, click-column:num, env:&:environment -> r
sandbox-right-margin:num <- get *first-sandbox, right:offset
edit-button-left:num, edit-button-right:num, _ <- sandbox-menu-columns sandbox-left-margin, sandbox-right-margin
edit-button-vertical-area?:bool <- within-range? click-column, edit-button-left, edit-button-right
reply-unless edit-button-vertical-area?, 0/false
return-unless edit-button-vertical-area?, 0/false
# finally, is sandbox editor empty?
current-sandbox:&:editor <- get *env, current-sandbox:offset
result <- empty-editor? current-sandbox

View File

@ -50,14 +50,14 @@ def new-pair a:&:cell, b:&:cell -> result:&:cell [
def is-atom? x:&:cell -> result:bool [
local-scope
load-ingredients
reply-unless x, 0/false
return-unless x, 0/false
_, result <- maybe-convert *x, atom:variant
]
def is-pair? x:&:cell -> result:bool [
local-scope
load-ingredients
reply-unless x, 0/false
return-unless x, 0/false
_, result <- maybe-convert *x, pair:variant
]
@ -91,7 +91,7 @@ def atom-match? x:&:cell, pat:text -> result:bool [
local-scope
load-ingredients
s:text, is-atom?:bool <- maybe-convert *x, atom:variant
reply-unless is-atom?, 0/false
return-unless is-atom?, 0/false
result <- equal pat, s
]
@ -108,7 +108,7 @@ def first x:&:cell -> result:&:cell [
local-scope
load-ingredients
pair:pair, pair?:bool <- maybe-convert *x, pair:variant
reply-unless pair?, 0/nil
return-unless pair?, 0/nil
result <- get pair, first:offset
]
@ -116,7 +116,7 @@ def rest x:&:cell -> result:&:cell [
local-scope
load-ingredients
pair:pair, pair?:bool <- maybe-convert *x, pair:variant
reply-unless pair?, 0/nil
return-unless pair?, 0/nil
result <- get pair, rest:offset
]
@ -124,7 +124,7 @@ def set-first base:&:cell, new-first:&:cell -> base:&:cell [
local-scope
load-ingredients
pair:pair, is-pair?:bool <- maybe-convert *base, pair:variant
reply-unless is-pair?
return-unless is-pair?
pair <- put pair, first:offset, new-first
*base <- merge 1/pair, pair
]
@ -133,7 +133,7 @@ def set-rest base:&:cell, new-rest:&:cell -> base:&:cell [
local-scope
load-ingredients
pair:pair, is-pair?:bool <- maybe-convert *base, pair:variant
reply-unless is-pair?
return-unless is-pair?
pair <- put pair, rest:offset, new-rest
*base <- merge 1/pair, pair
]
@ -181,7 +181,7 @@ def parse in:&:stream:char -> out:&:cell, in:&:stream:char [
# skip whitespace
in <- skip-whitespace in
c:char, eof?:bool <- peek in
reply-if eof?, 0/nil
return-if eof?, 0/nil
pair?:bool <- equal c, 40/open-paren
{
break-if pair?
@ -270,7 +270,7 @@ def skip-whitespace in:&:stream:char -> in:&:stream:char [
load-ingredients
{
done?:bool <- end-of-stream? in
reply-if done?, 0/null
return-if done?, 0/null
c:char <- peek in
space?:bool <- space? c
break-unless space?
@ -294,14 +294,14 @@ def to-buffer x:&:cell, buf:&:buffer -> buf:&:buffer [
{
break-if x
buf <- append buf, [<>]
reply
return
}
# base case: atom
{
s:text, atom?:bool <- maybe-convert *x, atom:variant
break-unless atom?
buf <- append buf, s
reply
return
}
# recursive case: pair
buf <- append buf, [< ]

View File

@ -49,9 +49,9 @@ def conflict? curr:square, queens:&:list:square -> result:bool [
local-scope
load-ingredients
result1:bool <- conflicting-file? curr, queens
reply-if result1, result1
return-if result1, result1
result2:bool <- conflicting-diagonal? curr, queens
reply result2
return result2
]
def conflicting-file? curr:square, queens:&:list:square -> result:bool [
@ -63,11 +63,11 @@ def conflicting-file? curr:square, queens:&:list:square -> result:bool [
q:square <- first queens
qfile:num <- get q, file:offset
file-match?:bool <- equal curr-file, qfile
reply-if file-match?, 1/conflict-found
return-if file-match?, 1/conflict-found
queens <- rest queens
loop
}
reply 0/no-conflict-found
return 0/no-conflict-found
]
def conflicting-diagonal? curr:square, queens:&:list:square -> result:bool [
@ -85,11 +85,11 @@ def conflicting-diagonal? curr:square, queens:&:list:square -> result:bool [
rank-delta <- abs rank-delta
file-delta <- abs file-delta
diagonal-match?:bool <- equal rank-delta, file-delta
reply-if diagonal-match?, 1/conflict-found
return-if diagonal-match?, 1/conflict-found
queens <- rest queens
loop
}
reply 0/no-conflict-found
return 0/no-conflict-found
]
def main [

View File

@ -146,7 +146,7 @@ def should-attempt-copy? click-row:num, click-column:num, env:&:environment -> r
load-ingredients
# are we below the sandbox editor?
click-sandbox-area?:bool <- click-on-sandbox-area? click-row, env
reply-unless click-sandbox-area?, 0/false
return-unless click-sandbox-area?, 0/false
# narrower, is the click in the columns spanning the 'copy' button?
first-sandbox:&:editor <- get *env, current-sandbox:offset
assert first-sandbox, [!!]
@ -154,7 +154,7 @@ def should-attempt-copy? click-row:num, click-column:num, env:&:environment -> r
sandbox-right-margin:num <- get *first-sandbox, right:offset
_, _, copy-button-left:num, copy-button-right:num, _ <- sandbox-menu-columns sandbox-left-margin, sandbox-right-margin
copy-button-vertical-area?:bool <- within-range? click-column, copy-button-left, copy-button-right
reply-unless copy-button-vertical-area?, 0/false
return-unless copy-button-vertical-area?, 0/false
# finally, is sandbox editor empty?
current-sandbox:&:editor <- get *env, current-sandbox:offset
result <- empty-editor? current-sandbox

View File

@ -81,7 +81,7 @@ def should-attempt-delete? click-row:num, click-column:num, env:&:environment ->
load-ingredients
# are we below the sandbox editor?
click-sandbox-area?:bool <- click-on-sandbox-area? click-row, env
reply-unless click-sandbox-area?, 0/false
return-unless click-sandbox-area?, 0/false
# narrower, is the click in the columns spanning the 'copy' button?
first-sandbox:&:editor <- get *env, current-sandbox:offset
assert first-sandbox, [!!]

View File

@ -70,7 +70,7 @@ def should-attempt-edit? click-row:num, click-column:num, env:&:environment -> r
load-ingredients
# are we below the sandbox editor?
click-sandbox-area?:bool <- click-on-sandbox-area? click-row, env
reply-unless click-sandbox-area?, 0/false
return-unless click-sandbox-area?, 0/false
# narrower, is the click in the columns spanning the 'edit' button?
first-sandbox:&:editor <- get *env, current-sandbox:offset
assert first-sandbox, [!!]
@ -78,7 +78,7 @@ def should-attempt-edit? click-row:num, click-column:num, env:&:environment -> r
sandbox-right-margin:num <- get *first-sandbox, right:offset
edit-button-left:num, edit-button-right:num, _ <- sandbox-menu-columns sandbox-left-margin, sandbox-right-margin
edit-button-vertical-area?:bool <- within-range? click-column, edit-button-left, edit-button-right
reply-unless edit-button-vertical-area?, 0/false
return-unless edit-button-vertical-area?, 0/false
# finally, is sandbox editor empty?
current-sandbox:&:editor <- get *env, current-sandbox:offset
result <- empty-editor? current-sandbox