2735 - define recipes using 'def'
I'm dropping all mention of 'recipe' terminology from the Readme. That way I hope to avoid further bike-shedding discussions while I very slowly decide on the right terminology with my students. I could be smarter in my error messages and use 'recipe' when code uses it and 'function' otherwise. But what about other words like ingredient? It would all add complexity that I'm not yet sure is worthwhile. But I do want separate experiences for veteran programmers reading about Mu on github and for people learning programming using Mu.
41
011load.cc
|
@ -2,7 +2,7 @@
|
|||
|
||||
:(scenarios load) // use 'load' instead of 'run' in all scenarios in this layer
|
||||
:(scenario first_recipe)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 23
|
||||
]
|
||||
+parse: instruction: copy
|
||||
|
@ -24,10 +24,10 @@ vector<recipe_ordinal> load(istream& in) {
|
|||
if (!has_data(in)) break;
|
||||
string command = next_word(in);
|
||||
// Command Handlers
|
||||
if (command == "recipe") {
|
||||
if (command == "recipe" || command == "def") {
|
||||
result.push_back(slurp_recipe(in));
|
||||
}
|
||||
else if (command == "recipe!") {
|
||||
else if (command == "recipe!" || command == "def!") {
|
||||
Disable_redefine_checks = true;
|
||||
result.push_back(slurp_recipe(in));
|
||||
Disable_redefine_checks = false;
|
||||
|
@ -248,9 +248,10 @@ void clear_recently_added_recipes() {
|
|||
|
||||
:(scenario parse_comment_outside_recipe)
|
||||
# this comment will be dropped by the tangler, so we need a dummy recipe to stop that
|
||||
recipe f1 [ ]
|
||||
def f1 [
|
||||
]
|
||||
# this comment will go through to 'load'
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 23
|
||||
]
|
||||
+parse: instruction: copy
|
||||
|
@ -258,7 +259,7 @@ recipe main [
|
|||
+parse: product: 1: "number"
|
||||
|
||||
:(scenario parse_comment_amongst_instruction)
|
||||
recipe main [
|
||||
def main [
|
||||
# comment
|
||||
1:number <- copy 23
|
||||
]
|
||||
|
@ -267,7 +268,7 @@ recipe main [
|
|||
+parse: product: 1: "number"
|
||||
|
||||
:(scenario parse_comment_amongst_instruction_2)
|
||||
recipe main [
|
||||
def main [
|
||||
# comment
|
||||
1:number <- copy 23
|
||||
# comment
|
||||
|
@ -277,7 +278,7 @@ recipe main [
|
|||
+parse: product: 1: "number"
|
||||
|
||||
:(scenario parse_comment_amongst_instruction_3)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 23
|
||||
# comment
|
||||
2:number <- copy 23
|
||||
|
@ -290,7 +291,7 @@ recipe main [
|
|||
+parse: product: 2: "number"
|
||||
|
||||
:(scenario parse_comment_after_instruction)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 23 # comment
|
||||
]
|
||||
+parse: instruction: copy
|
||||
|
@ -298,19 +299,19 @@ recipe main [
|
|||
+parse: product: 1: "number"
|
||||
|
||||
:(scenario parse_label)
|
||||
recipe main [
|
||||
def main [
|
||||
+foo
|
||||
]
|
||||
+parse: label: +foo
|
||||
|
||||
:(scenario parse_dollar_as_recipe_name)
|
||||
recipe main [
|
||||
def main [
|
||||
$foo
|
||||
]
|
||||
+parse: instruction: $foo
|
||||
|
||||
:(scenario parse_multiple_properties)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 23/foo:bar:baz
|
||||
]
|
||||
+parse: instruction: copy
|
||||
|
@ -318,7 +319,7 @@ recipe main [
|
|||
+parse: product: 1: "number"
|
||||
|
||||
:(scenario parse_multiple_products)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number, 2:number <- copy 23
|
||||
]
|
||||
+parse: instruction: copy
|
||||
|
@ -327,7 +328,7 @@ recipe main [
|
|||
+parse: product: 2: "number"
|
||||
|
||||
:(scenario parse_multiple_ingredients)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number, 2:number <- copy 23, 4:number
|
||||
]
|
||||
+parse: instruction: copy
|
||||
|
@ -337,7 +338,7 @@ recipe main [
|
|||
+parse: product: 2: "number"
|
||||
|
||||
:(scenario parse_multiple_types)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number, 2:address:number <- copy 23, 4:number
|
||||
]
|
||||
+parse: instruction: copy
|
||||
|
@ -347,7 +348,7 @@ recipe main [
|
|||
+parse: product: 2: ("address" "number")
|
||||
|
||||
:(scenario parse_properties)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:number/lookup <- copy 23
|
||||
]
|
||||
+parse: product: 1: ("address" "number"), {"lookup": ()}
|
||||
|
@ -365,19 +366,19 @@ void test_parse_comment_terminated_by_eof() {
|
|||
|
||||
:(scenario forbid_redefining_recipes)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 23
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 24
|
||||
]
|
||||
+error: redefining recipe main
|
||||
|
||||
:(scenario permit_forcibly_redefining_recipes)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 23
|
||||
]
|
||||
recipe! main [
|
||||
def! main [
|
||||
1:number <- copy 24
|
||||
]
|
||||
-error: redefining recipe main
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
:(scenarios load)
|
||||
:(scenario string_literal)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:array:character <- copy [abc def] # copy can't really take a string
|
||||
]
|
||||
+parse: ingredient: "abc def": "literal-string"
|
||||
|
||||
:(scenario string_literal_with_colons)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:array:character <- copy [abc:def/ghi]
|
||||
]
|
||||
+parse: ingredient: "abc:def/ghi": "literal-string"
|
||||
|
@ -145,26 +145,26 @@ void strip_last(string& s) {
|
|||
}
|
||||
|
||||
:(scenario string_literal_nested)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:array:character <- copy [abc [def]]
|
||||
]
|
||||
+parse: ingredient: "abc [def]": "literal-string"
|
||||
|
||||
:(scenario string_literal_escaped)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:array:character <- copy [abc \[def]
|
||||
]
|
||||
+parse: ingredient: "abc [def": "literal-string"
|
||||
|
||||
:(scenario string_literal_escaped_comment_aware)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:array:character <- copy [
|
||||
abc \\\[def]
|
||||
]
|
||||
+parse: ingredient: "\nabc \[def": "literal-string"
|
||||
|
||||
:(scenario string_literal_and_comment)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:array:character <- copy [abc] # comment
|
||||
]
|
||||
+parse: --- defining main
|
||||
|
@ -174,14 +174,14 @@ recipe main [
|
|||
+parse: product: 1: ("address" "array" "character")
|
||||
|
||||
:(scenario string_literal_escapes_newlines_in_trace)
|
||||
recipe main [
|
||||
def main [
|
||||
copy [abc
|
||||
def]
|
||||
]
|
||||
+parse: ingredient: "abc\ndef": "literal-string"
|
||||
|
||||
:(scenario string_literal_can_skip_past_comments)
|
||||
recipe main [
|
||||
def main [
|
||||
copy [
|
||||
# ']' inside comment
|
||||
bar
|
||||
|
@ -190,7 +190,7 @@ recipe main [
|
|||
+parse: ingredient: "\n # ']' inside comment\n bar\n ": "literal-string"
|
||||
|
||||
:(scenario string_literal_empty)
|
||||
recipe main [
|
||||
def main [
|
||||
copy []
|
||||
]
|
||||
+parse: ingredient: "": "literal-string"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
:(scenarios load)
|
||||
:(scenario noninteger_literal)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 3.14159
|
||||
]
|
||||
+parse: ingredient: 3.14159: "literal-fractional-number"
|
||||
|
|
20
020run.cc
|
@ -10,14 +10,14 @@
|
|||
//: another. Later layers will add more primitives.
|
||||
|
||||
:(scenario copy_literal)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 23
|
||||
]
|
||||
+run: 1:number <- copy 23
|
||||
+mem: storing 23 in location 1
|
||||
|
||||
:(scenario copy)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 23
|
||||
2:number <- copy 1:number
|
||||
]
|
||||
|
@ -26,7 +26,7 @@ recipe main [
|
|||
+mem: storing 23 in location 2
|
||||
|
||||
:(scenario copy_multiple)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number, 2:number <- copy 23, 24
|
||||
]
|
||||
+mem: storing 23 in location 1
|
||||
|
@ -330,7 +330,7 @@ void run(string form) {
|
|||
}
|
||||
|
||||
:(scenario run_label)
|
||||
recipe main [
|
||||
def main [
|
||||
+foo
|
||||
1:number <- copy 23
|
||||
2:number <- copy 1:number
|
||||
|
@ -340,14 +340,14 @@ recipe main [
|
|||
-run: +foo
|
||||
|
||||
:(scenario run_dummy)
|
||||
recipe main [
|
||||
def main [
|
||||
_ <- copy 0
|
||||
]
|
||||
+run: _ <- copy 0
|
||||
|
||||
:(scenario write_to_0_disallowed)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
0:number <- copy 34
|
||||
]
|
||||
-mem: storing 34 in location 0
|
||||
|
@ -356,25 +356,25 @@ recipe main [
|
|||
//: to put spaces around the '<-'.
|
||||
|
||||
:(scenario comma_without_space)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number, 2:number <- copy 2,2
|
||||
]
|
||||
+mem: storing 2 in location 1
|
||||
|
||||
:(scenario space_without_comma)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number, 2:number <- copy 2 2
|
||||
]
|
||||
+mem: storing 2 in location 1
|
||||
|
||||
:(scenario comma_before_space)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number, 2:number <- copy 2, 2
|
||||
]
|
||||
+mem: storing 2 in location 1
|
||||
|
||||
:(scenario comma_after_space)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number, 2:number <- copy 2 ,2
|
||||
]
|
||||
+mem: storing 2 in location 1
|
||||
|
|
|
@ -46,34 +46,34 @@ void check_instruction(const recipe_ordinal r) {
|
|||
|
||||
:(scenario copy_checks_reagent_count)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34, 35
|
||||
]
|
||||
+error: ingredients and products should match in '1:number <- copy 34, 35'
|
||||
|
||||
:(scenario write_scalar_to_array_disallowed)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:array:number <- copy 34
|
||||
]
|
||||
+error: main: can't copy 34 to 1:array:number; types don't match
|
||||
|
||||
:(scenario write_scalar_to_array_disallowed_2)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:number, 2:array:number <- copy 34, 35
|
||||
]
|
||||
+error: main: can't copy 35 to 2:array:number; types don't match
|
||||
|
||||
:(scenario write_scalar_to_address_disallowed)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:number <- copy 34
|
||||
]
|
||||
+error: main: can't copy 34 to 1:address:number; types don't match
|
||||
|
||||
:(scenario write_address_to_number_allowed)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:number <- copy 12/unsafe
|
||||
2:number <- copy 1:address:number
|
||||
]
|
||||
|
@ -81,7 +81,7 @@ recipe main [
|
|||
$error: 0
|
||||
|
||||
:(scenario write_boolean_to_number_allowed)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- copy 1/true
|
||||
2:number <- copy 1:boolean
|
||||
]
|
||||
|
@ -89,7 +89,7 @@ recipe main [
|
|||
$error: 0
|
||||
|
||||
:(scenario write_number_to_boolean_allowed)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:boolean <- copy 1:number
|
||||
]
|
||||
|
|
|
@ -35,13 +35,13 @@ case ADD: {
|
|||
}
|
||||
|
||||
:(scenario add_literal)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- add 23, 34
|
||||
]
|
||||
+mem: storing 57 in location 1
|
||||
|
||||
:(scenario add)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 23
|
||||
2:number <- copy 34
|
||||
3:number <- add 1:number, 2:number
|
||||
|
@ -49,21 +49,21 @@ recipe main [
|
|||
+mem: storing 57 in location 3
|
||||
|
||||
:(scenario add_multiple)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- add 3, 4, 5
|
||||
]
|
||||
+mem: storing 12 in location 1
|
||||
|
||||
:(scenario add_checks_type)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- add 2:boolean, 1
|
||||
]
|
||||
+error: main: 'add' requires number ingredients, but got 2:boolean
|
||||
|
||||
:(scenario add_checks_return_type)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:number <- add 2, 2
|
||||
]
|
||||
+error: main: 'add' should yield a number, but got 1:address:number
|
||||
|
@ -110,13 +110,13 @@ bool is_raw(const reagent& r) {
|
|||
}
|
||||
|
||||
:(scenario subtract_literal)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- subtract 5, 2
|
||||
]
|
||||
+mem: storing 3 in location 1
|
||||
|
||||
:(scenario subtract)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 23
|
||||
2:number <- copy 34
|
||||
3:number <- subtract 1:number, 2:number
|
||||
|
@ -124,7 +124,7 @@ recipe main [
|
|||
+mem: storing -11 in location 3
|
||||
|
||||
:(scenario subtract_multiple)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- subtract 6, 3, 2
|
||||
]
|
||||
+mem: storing 1 in location 1
|
||||
|
@ -163,13 +163,13 @@ case MULTIPLY: {
|
|||
}
|
||||
|
||||
:(scenario multiply_literal)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- multiply 2, 3
|
||||
]
|
||||
+mem: storing 6 in location 1
|
||||
|
||||
:(scenario multiply)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 4
|
||||
2:number <- copy 6
|
||||
3:number <- multiply 1:number, 2:number
|
||||
|
@ -177,7 +177,7 @@ recipe main [
|
|||
+mem: storing 24 in location 3
|
||||
|
||||
:(scenario multiply_multiple)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- multiply 2, 3, 4
|
||||
]
|
||||
+mem: storing 24 in location 1
|
||||
|
@ -219,13 +219,13 @@ case DIVIDE: {
|
|||
}
|
||||
|
||||
:(scenario divide_literal)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- divide 8, 2
|
||||
]
|
||||
+mem: storing 4 in location 1
|
||||
|
||||
:(scenario divide)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 27
|
||||
2:number <- copy 3
|
||||
3:number <- divide 1:number, 2:number
|
||||
|
@ -233,7 +233,7 @@ recipe main [
|
|||
+mem: storing 9 in location 3
|
||||
|
||||
:(scenario divide_multiple)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- divide 12, 3, 2
|
||||
]
|
||||
+mem: storing 2 in location 1
|
||||
|
@ -287,14 +287,14 @@ case DIVIDE_WITH_REMAINDER: {
|
|||
}
|
||||
|
||||
:(scenario divide_with_remainder_literal)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number, 2:number <- divide-with-remainder 9, 2
|
||||
]
|
||||
+mem: storing 4 in location 1
|
||||
+mem: storing 1 in location 2
|
||||
|
||||
:(scenario divide_with_remainder)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 27
|
||||
2:number <- copy 11
|
||||
3:number, 4:number <- divide-with-remainder 1:number, 2:number
|
||||
|
@ -303,20 +303,20 @@ recipe main [
|
|||
+mem: storing 5 in location 4
|
||||
|
||||
:(scenario divide_with_decimal_point)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- divide 5, 2
|
||||
]
|
||||
+mem: storing 2.5 in location 1
|
||||
|
||||
:(scenario divide_by_zero)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- divide 4, 0
|
||||
]
|
||||
+mem: storing inf in location 1
|
||||
|
||||
:(scenario divide_by_zero_2)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- divide-with-remainder 4, 0
|
||||
]
|
||||
# integer division can't return floating-point infinity
|
||||
|
@ -364,32 +364,32 @@ case SHIFT_LEFT: {
|
|||
}
|
||||
|
||||
:(scenario shift_left_by_zero)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- shift-left 1, 0
|
||||
]
|
||||
+mem: storing 1 in location 1
|
||||
|
||||
:(scenario shift_left_1)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- shift-left 1, 4
|
||||
]
|
||||
+mem: storing 16 in location 1
|
||||
|
||||
:(scenario shift_left_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- shift-left 3, 2
|
||||
]
|
||||
+mem: storing 12 in location 1
|
||||
|
||||
:(scenario shift_left_by_negative)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- shift-left 3, -1
|
||||
]
|
||||
+error: main: second ingredient can't be negative in '1:number <- shift-left 3, -1'
|
||||
|
||||
:(scenario shift_left_ignores_fractional_part)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- divide 3, 2
|
||||
2:number <- shift-left 1:number, 1
|
||||
]
|
||||
|
@ -435,32 +435,32 @@ case SHIFT_RIGHT: {
|
|||
}
|
||||
|
||||
:(scenario shift_right_by_zero)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- shift-right 1, 0
|
||||
]
|
||||
+mem: storing 1 in location 1
|
||||
|
||||
:(scenario shift_right_1)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- shift-right 1024, 1
|
||||
]
|
||||
+mem: storing 512 in location 1
|
||||
|
||||
:(scenario shift_right_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- shift-right 3, 1
|
||||
]
|
||||
+mem: storing 1 in location 1
|
||||
|
||||
:(scenario shift_right_by_negative)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- shift-right 4, -1
|
||||
]
|
||||
+error: main: second ingredient can't be negative in '1:number <- shift-right 4, -1'
|
||||
|
||||
:(scenario shift_right_ignores_fractional_part)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- divide 3, 2
|
||||
2:number <- shift-right 1:number, 1
|
||||
]
|
||||
|
@ -501,25 +501,25 @@ case AND_BITS: {
|
|||
}
|
||||
|
||||
:(scenario and_bits_1)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- and-bits 8, 3
|
||||
]
|
||||
+mem: storing 0 in location 1
|
||||
|
||||
:(scenario and_bits_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- and-bits 3, 2
|
||||
]
|
||||
+mem: storing 2 in location 1
|
||||
|
||||
:(scenario and_bits_3)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- and-bits 14, 3
|
||||
]
|
||||
+mem: storing 2 in location 1
|
||||
|
||||
:(scenario and_bits_negative)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- and-bits -3, 4
|
||||
]
|
||||
+mem: storing 4 in location 1
|
||||
|
@ -559,19 +559,19 @@ case OR_BITS: {
|
|||
}
|
||||
|
||||
:(scenario or_bits_1)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- or-bits 3, 8
|
||||
]
|
||||
+mem: storing 11 in location 1
|
||||
|
||||
:(scenario or_bits_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- or-bits 3, 10
|
||||
]
|
||||
+mem: storing 11 in location 1
|
||||
|
||||
:(scenario or_bits_3)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- or-bits 4, 6
|
||||
]
|
||||
+mem: storing 6 in location 1
|
||||
|
@ -611,19 +611,19 @@ case XOR_BITS: {
|
|||
}
|
||||
|
||||
:(scenario xor_bits_1)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- xor-bits 3, 8
|
||||
]
|
||||
+mem: storing 11 in location 1
|
||||
|
||||
:(scenario xor_bits_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- xor-bits 3, 10
|
||||
]
|
||||
+mem: storing 9 in location 1
|
||||
|
||||
:(scenario xor_bits_3)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- xor-bits 4, 6
|
||||
]
|
||||
+mem: storing 2 in location 1
|
||||
|
@ -662,25 +662,25 @@ case FLIP_BITS: {
|
|||
}
|
||||
|
||||
:(scenario flip_bits_zero)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- flip-bits 0
|
||||
]
|
||||
+mem: storing -1 in location 1
|
||||
|
||||
:(scenario flip_bits_negative)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- flip-bits -1
|
||||
]
|
||||
+mem: storing 0 in location 1
|
||||
|
||||
:(scenario flip_bits_1)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- flip-bits 3
|
||||
]
|
||||
+mem: storing -4 in location 1
|
||||
|
||||
:(scenario flip_bits_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- flip-bits 12
|
||||
]
|
||||
+mem: storing -13 in location 1
|
||||
|
|
|
@ -33,7 +33,7 @@ case AND: {
|
|||
}
|
||||
|
||||
:(scenario and)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- copy 1
|
||||
2:boolean <- copy 0
|
||||
3:boolean <- and 1:boolean, 2:boolean
|
||||
|
@ -41,19 +41,19 @@ recipe main [
|
|||
+mem: storing 0 in location 3
|
||||
|
||||
:(scenario and_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- and 1, 1
|
||||
]
|
||||
+mem: storing 1 in location 1
|
||||
|
||||
:(scenario and_multiple)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- and 1, 1, 0
|
||||
]
|
||||
+mem: storing 0 in location 1
|
||||
|
||||
:(scenario and_multiple_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- and 1, 1, 1
|
||||
]
|
||||
+mem: storing 1 in location 1
|
||||
|
@ -91,7 +91,7 @@ case OR: {
|
|||
}
|
||||
|
||||
:(scenario or)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- copy 1
|
||||
2:boolean <- copy 0
|
||||
3:boolean <- or 1:boolean, 2:boolean
|
||||
|
@ -99,19 +99,19 @@ recipe main [
|
|||
+mem: storing 1 in location 3
|
||||
|
||||
:(scenario or_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- or 0, 0
|
||||
]
|
||||
+mem: storing 0 in location 1
|
||||
|
||||
:(scenario or_multiple)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- and 0, 0, 0
|
||||
]
|
||||
+mem: storing 0 in location 1
|
||||
|
||||
:(scenario or_multiple_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- or 0, 0, 1
|
||||
]
|
||||
+mem: storing 1 in location 1
|
||||
|
@ -151,14 +151,14 @@ case NOT: {
|
|||
}
|
||||
|
||||
:(scenario not)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- copy 1
|
||||
2:boolean <- not 1:boolean
|
||||
]
|
||||
+mem: storing 0 in location 2
|
||||
|
||||
:(scenario not_multiple)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean, 2:boolean, 3:boolean <- not 1, 0, 1
|
||||
]
|
||||
+mem: storing 0 in location 1
|
||||
|
|
12
024jump.cc
|
@ -1,7 +1,7 @@
|
|||
//: Jump primitives
|
||||
|
||||
:(scenario jump_can_skip_instructions)
|
||||
recipe main [
|
||||
def main [
|
||||
jump 1:offset
|
||||
1:number <- copy 1
|
||||
]
|
||||
|
@ -38,7 +38,7 @@ case JUMP: {
|
|||
put(Type_ordinal, "offset", 0);
|
||||
|
||||
:(scenario jump_backward)
|
||||
recipe main [
|
||||
def main [
|
||||
jump 1:offset # 0 -+
|
||||
jump 3:offset # | +-+ 1
|
||||
# \/ /\ |
|
||||
|
@ -81,7 +81,7 @@ case JUMP_IF: {
|
|||
}
|
||||
|
||||
:(scenario jump_if)
|
||||
recipe main [
|
||||
def main [
|
||||
jump-if 999, 1:offset
|
||||
123:number <- copy 1
|
||||
]
|
||||
|
@ -91,7 +91,7 @@ recipe main [
|
|||
-mem: storing 1 in location 123
|
||||
|
||||
:(scenario jump_if_fallthrough)
|
||||
recipe main [
|
||||
def main [
|
||||
jump-if 0, 1:offset
|
||||
123:number <- copy 1
|
||||
]
|
||||
|
@ -133,7 +133,7 @@ case JUMP_UNLESS: {
|
|||
}
|
||||
|
||||
:(scenario jump_unless)
|
||||
recipe main [
|
||||
def main [
|
||||
jump-unless 0, 1:offset
|
||||
123:number <- copy 1
|
||||
]
|
||||
|
@ -143,7 +143,7 @@ recipe main [
|
|||
-mem: storing 1 in location 123
|
||||
|
||||
:(scenario jump_unless_fallthrough)
|
||||
recipe main [
|
||||
def main [
|
||||
jump-unless 999, 1:offset
|
||||
123:number <- copy 1
|
||||
]
|
||||
|
|
|
@ -36,7 +36,7 @@ case EQUAL: {
|
|||
}
|
||||
|
||||
:(scenario equal)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:number <- copy 33
|
||||
3:boolean <- equal 1:number, 2:number
|
||||
|
@ -46,7 +46,7 @@ recipe main [
|
|||
+mem: storing 0 in location 3
|
||||
|
||||
:(scenario equal_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:number <- copy 34
|
||||
3:boolean <- equal 1:number, 2:number
|
||||
|
@ -56,13 +56,13 @@ recipe main [
|
|||
+mem: storing 1 in location 3
|
||||
|
||||
:(scenario equal_multiple)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- equal 34, 34, 34
|
||||
]
|
||||
+mem: storing 1 in location 1
|
||||
|
||||
:(scenario equal_multiple_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- equal 34, 34, 35
|
||||
]
|
||||
+mem: storing 0 in location 1
|
||||
|
@ -107,7 +107,7 @@ case GREATER_THAN: {
|
|||
}
|
||||
|
||||
:(scenario greater_than)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:number <- copy 33
|
||||
3:boolean <- greater-than 1:number, 2:number
|
||||
|
@ -115,7 +115,7 @@ recipe main [
|
|||
+mem: storing 1 in location 3
|
||||
|
||||
:(scenario greater_than_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:number <- copy 34
|
||||
3:boolean <- greater-than 1:number, 2:number
|
||||
|
@ -123,13 +123,13 @@ recipe main [
|
|||
+mem: storing 0 in location 3
|
||||
|
||||
:(scenario greater_than_multiple)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- greater-than 36, 35, 34
|
||||
]
|
||||
+mem: storing 1 in location 1
|
||||
|
||||
:(scenario greater_than_multiple_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- greater-than 36, 35, 35
|
||||
]
|
||||
+mem: storing 0 in location 1
|
||||
|
@ -174,7 +174,7 @@ case LESSER_THAN: {
|
|||
}
|
||||
|
||||
:(scenario lesser_than)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 32
|
||||
2:number <- copy 33
|
||||
3:boolean <- lesser-than 1:number, 2:number
|
||||
|
@ -182,7 +182,7 @@ recipe main [
|
|||
+mem: storing 1 in location 3
|
||||
|
||||
:(scenario lesser_than_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:number <- copy 33
|
||||
3:boolean <- lesser-than 1:number, 2:number
|
||||
|
@ -190,13 +190,13 @@ recipe main [
|
|||
+mem: storing 0 in location 3
|
||||
|
||||
:(scenario lesser_than_multiple)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- lesser-than 34, 35, 36
|
||||
]
|
||||
+mem: storing 1 in location 1
|
||||
|
||||
:(scenario lesser_than_multiple_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- lesser-than 34, 35, 35
|
||||
]
|
||||
+mem: storing 0 in location 1
|
||||
|
@ -241,7 +241,7 @@ case GREATER_OR_EQUAL: {
|
|||
}
|
||||
|
||||
:(scenario greater_or_equal)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:number <- copy 33
|
||||
3:boolean <- greater-or-equal 1:number, 2:number
|
||||
|
@ -249,7 +249,7 @@ recipe main [
|
|||
+mem: storing 1 in location 3
|
||||
|
||||
:(scenario greater_or_equal_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:number <- copy 34
|
||||
3:boolean <- greater-or-equal 1:number, 2:number
|
||||
|
@ -257,7 +257,7 @@ recipe main [
|
|||
+mem: storing 1 in location 3
|
||||
|
||||
:(scenario greater_or_equal_3)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:number <- copy 35
|
||||
3:boolean <- greater-or-equal 1:number, 2:number
|
||||
|
@ -265,13 +265,13 @@ recipe main [
|
|||
+mem: storing 0 in location 3
|
||||
|
||||
:(scenario greater_or_equal_multiple)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- greater-or-equal 36, 35, 35
|
||||
]
|
||||
+mem: storing 1 in location 1
|
||||
|
||||
:(scenario greater_or_equal_multiple_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- greater-or-equal 36, 35, 36
|
||||
]
|
||||
+mem: storing 0 in location 1
|
||||
|
@ -316,7 +316,7 @@ case LESSER_OR_EQUAL: {
|
|||
}
|
||||
|
||||
:(scenario lesser_or_equal)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 32
|
||||
2:number <- copy 33
|
||||
3:boolean <- lesser-or-equal 1:number, 2:number
|
||||
|
@ -324,7 +324,7 @@ recipe main [
|
|||
+mem: storing 1 in location 3
|
||||
|
||||
:(scenario lesser_or_equal_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 33
|
||||
2:number <- copy 33
|
||||
3:boolean <- lesser-or-equal 1:number, 2:number
|
||||
|
@ -332,7 +332,7 @@ recipe main [
|
|||
+mem: storing 1 in location 3
|
||||
|
||||
:(scenario lesser_or_equal_3)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:number <- copy 33
|
||||
3:boolean <- lesser-or-equal 1:number, 2:number
|
||||
|
@ -340,13 +340,13 @@ recipe main [
|
|||
+mem: storing 0 in location 3
|
||||
|
||||
:(scenario lesser_or_equal_multiple)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- lesser-or-equal 34, 35, 35
|
||||
]
|
||||
+mem: storing 1 in location 1
|
||||
|
||||
:(scenario lesser_or_equal_multiple_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:boolean <- lesser-or-equal 34, 35, 34
|
||||
]
|
||||
+mem: storing 0 in location 1
|
||||
|
|
10
029tools.cc
|
@ -1,7 +1,7 @@
|
|||
//: Allow mu programs to log facts just like we've been doing in C++ so far.
|
||||
|
||||
:(scenario trace)
|
||||
recipe main [
|
||||
def main [
|
||||
trace 1, [foo], [this is a trace in mu]
|
||||
]
|
||||
+foo: this is a trace in mu
|
||||
|
@ -59,19 +59,19 @@ case STASH: {
|
|||
}
|
||||
|
||||
:(scenario stash_literal_string)
|
||||
recipe main [
|
||||
def main [
|
||||
stash [foo]
|
||||
]
|
||||
+app: foo
|
||||
|
||||
:(scenario stash_literal_number)
|
||||
recipe main [
|
||||
def main [
|
||||
stash [foo:], 4
|
||||
]
|
||||
+app: foo: 4
|
||||
|
||||
:(scenario stash_number)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
stash [foo:], 1:number
|
||||
]
|
||||
|
@ -187,7 +187,7 @@ case _SAVE_TRACE: {
|
|||
|
||||
:(scenario assert)
|
||||
% Hide_errors = true; // '%' lines insert arbitrary C code into tests before calling 'run' with the lines below. Must be immediately after :(scenario) line.
|
||||
recipe main [
|
||||
def main [
|
||||
assert 0, [this is an assert in mu]
|
||||
]
|
||||
+error: this is an assert in mu
|
||||
|
|
|
@ -16,7 +16,7 @@ get(Type, point).elements.push_back(reagent("y:number"));
|
|||
//: container. Don't do this in general. I'm tagging exceptions with /raw to
|
||||
//: avoid errors.
|
||||
:(scenario copy_multiple_locations)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:number <- copy 35
|
||||
3:point <- copy 1:point/unsafe
|
||||
|
@ -27,7 +27,7 @@ recipe main [
|
|||
//: trying to copy to a differently-typed destination will fail
|
||||
:(scenario copy_checks_size)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
2:point <- copy 1:number
|
||||
]
|
||||
+error: main: can't copy 1:number to 2:point; types don't match
|
||||
|
@ -43,7 +43,7 @@ get(Type, point_number).elements.push_back(reagent("xy:point"));
|
|||
get(Type, point_number).elements.push_back(reagent("z:number"));
|
||||
|
||||
:(scenario copy_handles_nested_container_elements)
|
||||
recipe main [
|
||||
def main [
|
||||
12:number <- copy 34
|
||||
13:number <- copy 35
|
||||
14:number <- copy 36
|
||||
|
@ -55,7 +55,7 @@ recipe main [
|
|||
//: numbers, no matter how large they are.
|
||||
|
||||
:(scenario compare_multiple_locations)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34 # first
|
||||
2:number <- copy 35
|
||||
3:number <- copy 36
|
||||
|
@ -67,7 +67,7 @@ recipe main [
|
|||
+mem: storing 1 in location 7
|
||||
|
||||
:(scenario compare_multiple_locations_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34 # first
|
||||
2:number <- copy 35
|
||||
3:number <- copy 36
|
||||
|
@ -109,7 +109,7 @@ if (t.kind == CONTAINER) {
|
|||
}
|
||||
|
||||
:(scenario stash_container)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34 # first
|
||||
2:number <- copy 35
|
||||
3:number <- copy 36
|
||||
|
@ -119,7 +119,7 @@ recipe main [
|
|||
|
||||
//:: To access elements of a container, use 'get'
|
||||
:(scenario get)
|
||||
recipe main [
|
||||
def main [
|
||||
12:number <- copy 34
|
||||
13:number <- copy 35
|
||||
15:number <- get 12:point/raw, 1:offset # unsafe
|
||||
|
@ -205,7 +205,7 @@ const reagent element_type(const reagent& canonized_base, long long int offset_v
|
|||
}
|
||||
|
||||
:(scenario get_handles_nested_container_elements)
|
||||
recipe main [
|
||||
def main [
|
||||
12:number <- copy 34
|
||||
13:number <- copy 35
|
||||
14:number <- copy 36
|
||||
|
@ -215,7 +215,7 @@ recipe main [
|
|||
|
||||
:(scenario get_out_of_bounds)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
12:number <- copy 34
|
||||
13:number <- copy 35
|
||||
14:number <- copy 36
|
||||
|
@ -225,7 +225,7 @@ recipe main [
|
|||
|
||||
:(scenario get_out_of_bounds_2)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
12:number <- copy 34
|
||||
13:number <- copy 35
|
||||
14:number <- copy 36
|
||||
|
@ -235,7 +235,7 @@ recipe main [
|
|||
|
||||
:(scenario get_product_type_mismatch)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
12:number <- copy 34
|
||||
13:number <- copy 35
|
||||
14:number <- copy 36
|
||||
|
@ -246,7 +246,7 @@ recipe main [
|
|||
//: we might want to call 'get' without saving the results, say in a sandbox
|
||||
|
||||
:(scenario get_without_product)
|
||||
recipe main [
|
||||
def main [
|
||||
12:number <- copy 34
|
||||
13:number <- copy 35
|
||||
get 12:point/raw, 1:offset # unsafe
|
||||
|
@ -256,7 +256,7 @@ recipe main [
|
|||
//:: To write to elements of containers, you need their address.
|
||||
|
||||
:(scenario get_address)
|
||||
recipe main [
|
||||
def main [
|
||||
12:number <- copy 34
|
||||
13:number <- copy 35
|
||||
15:address:number <- get-address 12:point/raw, 1:offset # unsafe
|
||||
|
@ -333,7 +333,7 @@ case GET_ADDRESS: {
|
|||
|
||||
:(scenario get_address_out_of_bounds)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
12:number <- copy 34
|
||||
13:number <- copy 35
|
||||
14:number <- copy 36
|
||||
|
@ -343,7 +343,7 @@ recipe main [
|
|||
|
||||
:(scenario get_address_out_of_bounds_2)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
12:number <- copy 34
|
||||
13:number <- copy 35
|
||||
14:number <- copy 36
|
||||
|
@ -357,7 +357,7 @@ container boolbool [
|
|||
x:boolean
|
||||
y:boolean
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
12:boolean <- copy 1
|
||||
13:boolean <- copy 0
|
||||
15:boolean <- get-address 12:boolbool, 1:offset
|
||||
|
@ -466,7 +466,7 @@ container foo [
|
|||
y:number
|
||||
]
|
||||
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:number <- copy 35
|
||||
3:number <- get 1:foo, 0:offset
|
||||
|
@ -515,14 +515,14 @@ Next_type_ordinal = 1000;
|
|||
|
||||
:(scenario run_complains_on_unknown_types)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
# integer is not a type
|
||||
1:integer <- copy 0
|
||||
]
|
||||
+error: main: unknown type integer in '1:integer <- copy 0'
|
||||
|
||||
:(scenario run_allows_type_definition_after_use)
|
||||
recipe main [
|
||||
def main [
|
||||
1:bar <- copy 0/unsafe
|
||||
]
|
||||
|
||||
|
@ -616,7 +616,7 @@ container foo [
|
|||
y:number
|
||||
]
|
||||
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo <- merge 3, 4
|
||||
]
|
||||
+mem: storing 3 in location 1
|
||||
|
@ -643,21 +643,21 @@ case MERGE: {
|
|||
//: type-check 'merge' to avoid interpreting numbers as addresses
|
||||
|
||||
:(scenario merge_check)
|
||||
recipe main [
|
||||
def main [
|
||||
1:point <- merge 3, 4
|
||||
]
|
||||
$error: 0
|
||||
|
||||
:(scenario merge_check_missing_element)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:point <- merge 3
|
||||
]
|
||||
+error: main: too few ingredients in '1:point <- merge 3'
|
||||
|
||||
:(scenario merge_check_extra_element)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:point <- merge 3, 4, 5
|
||||
]
|
||||
+error: main: too many ingredients in '1:point <- merge 3, 4, 5'
|
||||
|
@ -668,7 +668,7 @@ recipe main [
|
|||
//: container fields.
|
||||
|
||||
:(scenario merge_check_recursive_containers)
|
||||
recipe main [
|
||||
def main [
|
||||
1:point <- merge 3, 4
|
||||
1:point-number <- merge 1:point, 5
|
||||
]
|
||||
|
@ -676,21 +676,21 @@ $error: 0
|
|||
|
||||
:(scenario merge_check_recursive_containers_2)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:point <- merge 3, 4
|
||||
2:point-number <- merge 1:point
|
||||
]
|
||||
+error: main: too few ingredients in '2:point-number <- merge 1:point'
|
||||
|
||||
:(scenario merge_check_recursive_containers_3)
|
||||
recipe main [
|
||||
def main [
|
||||
1:point-number <- merge 3, 4, 5
|
||||
]
|
||||
$error: 0
|
||||
|
||||
:(scenario merge_check_recursive_containers_4)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:point-number <- merge 3, 4
|
||||
]
|
||||
+error: main: too few ingredients in '1:point-number <- merge 3, 4'
|
||||
|
@ -807,7 +807,7 @@ void check_merge_call(const vector<reagent>& ingredients, const reagent& product
|
|||
|
||||
:(scenario merge_check_product)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- merge 3
|
||||
]
|
||||
+error: main: 'merge' should yield a container in '1:number <- merge 3'
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//: 'lookup' property.
|
||||
|
||||
:(scenario copy_indirect)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:number <- copy 2/unsafe
|
||||
2:number <- copy 34
|
||||
# This loads location 1 as an address and looks up *that* location.
|
||||
|
@ -16,7 +16,7 @@ canonize(x);
|
|||
//: similarly, write to addresses pointing at other locations using the
|
||||
//: 'lookup' property
|
||||
:(scenario store_indirect)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:number <- copy 2/unsafe
|
||||
1:address:number/lookup <- copy 34
|
||||
]
|
||||
|
@ -32,7 +32,7 @@ if (x.value == 0) {
|
|||
//: writes to address 0 always loudly fail
|
||||
:(scenario store_to_0_fails)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:number <- copy 0
|
||||
1:address:number/lookup <- copy 34
|
||||
]
|
||||
|
@ -66,7 +66,7 @@ void lookup_memory(reagent& x) {
|
|||
|
||||
:(scenario canonize_non_pointer_fails_without_crashing)
|
||||
% Hide_errors = true;
|
||||
recipe foo [
|
||||
def foo [
|
||||
1:address:number <- get-address *p, x:offset
|
||||
]
|
||||
# don't crash
|
||||
|
@ -130,7 +130,7 @@ void drop_one_lookup(reagent& r) {
|
|||
|
||||
//:: 'get' can read from container address
|
||||
:(scenario get_indirect)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 2
|
||||
2:number <- copy 34
|
||||
3:number <- copy 35
|
||||
|
@ -139,7 +139,7 @@ recipe main [
|
|||
+mem: storing 34 in location 4
|
||||
|
||||
:(scenario get_indirect2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 2
|
||||
2:number <- copy 34
|
||||
3:number <- copy 35
|
||||
|
@ -149,7 +149,7 @@ recipe main [
|
|||
+mem: storing 34 in location 5
|
||||
|
||||
:(scenario include_nonlookup_properties)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 2
|
||||
2:number <- copy 34
|
||||
3:number <- copy 35
|
||||
|
@ -166,7 +166,7 @@ canonize(base);
|
|||
|
||||
:(scenario get_address_indirect)
|
||||
# 'get' can read from container address
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 2
|
||||
2:number <- copy 34
|
||||
3:number <- copy 35
|
||||
|
@ -184,7 +184,7 @@ canonize(base);
|
|||
//:: abbreviation for '/lookup': a prefix '*'
|
||||
|
||||
:(scenario lookup_abbreviation)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:number <- copy 2/unsafe
|
||||
2:number <- copy 34
|
||||
3:number <- copy *1:address:number
|
||||
|
|
32
032array.cc
|
@ -7,7 +7,7 @@
|
|||
|
||||
//: You can create arrays using 'create-array'.
|
||||
:(scenario create_array)
|
||||
recipe main [
|
||||
def main [
|
||||
# create an array occupying locations 1 (for the size) and 2-4 (for the elements)
|
||||
1:array:number:3 <- create-array
|
||||
]
|
||||
|
@ -67,7 +67,7 @@ case CREATE_ARRAY: {
|
|||
:(scenario copy_array)
|
||||
# Arrays can be copied around with a single instruction just like numbers,
|
||||
# no matter how large they are.
|
||||
recipe main [
|
||||
def main [
|
||||
1:array:number:3 <- create-array
|
||||
2:number <- copy 14
|
||||
3:number <- copy 15
|
||||
|
@ -80,7 +80,7 @@ recipe main [
|
|||
+mem: storing 16 in location 8
|
||||
|
||||
:(scenario copy_array_indirect)
|
||||
recipe main [
|
||||
def main [
|
||||
1:array:number:3 <- create-array
|
||||
2:number <- copy 14
|
||||
3:number <- copy 15
|
||||
|
@ -94,7 +94,7 @@ recipe main [
|
|||
+mem: storing 16 in location 9
|
||||
|
||||
:(scenario stash_array)
|
||||
recipe main [
|
||||
def main [
|
||||
1:array:number:3 <- create-array
|
||||
2:number <- copy 14
|
||||
3:number <- copy 15
|
||||
|
@ -149,7 +149,7 @@ container foo [
|
|||
//:: To access elements of an array, use 'index'
|
||||
|
||||
:(scenario index)
|
||||
recipe main [
|
||||
def main [
|
||||
1:array:number:3 <- create-array
|
||||
2:number <- copy 14
|
||||
3:number <- copy 15
|
||||
|
@ -159,7 +159,7 @@ recipe main [
|
|||
+mem: storing 14 in location 5
|
||||
|
||||
:(scenario index_direct_offset)
|
||||
recipe main [
|
||||
def main [
|
||||
1:array:number:3 <- create-array
|
||||
2:number <- copy 14
|
||||
3:number <- copy 15
|
||||
|
@ -234,7 +234,7 @@ type_tree* array_element(const type_tree* type) {
|
|||
}
|
||||
|
||||
:(scenario index_indirect)
|
||||
recipe main [
|
||||
def main [
|
||||
1:array:number:3 <- create-array
|
||||
2:number <- copy 14
|
||||
3:number <- copy 15
|
||||
|
@ -246,7 +246,7 @@ recipe main [
|
|||
|
||||
:(scenario index_out_of_bounds)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:array:number:3 <- create-array
|
||||
2:number <- copy 14
|
||||
3:number <- copy 15
|
||||
|
@ -261,7 +261,7 @@ recipe main [
|
|||
|
||||
:(scenario index_out_of_bounds_2)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:array:point:3 <- create-array
|
||||
2:number <- copy 14
|
||||
3:number <- copy 15
|
||||
|
@ -276,7 +276,7 @@ recipe main [
|
|||
|
||||
:(scenario index_product_type_mismatch)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:array:point:3 <- create-array
|
||||
2:number <- copy 14
|
||||
3:number <- copy 15
|
||||
|
@ -292,7 +292,7 @@ recipe main [
|
|||
//: we might want to call 'index' without saving the results, say in a sandbox
|
||||
|
||||
:(scenario index_without_product)
|
||||
recipe main [
|
||||
def main [
|
||||
1:array:number:3 <- create-array
|
||||
2:number <- copy 14
|
||||
3:number <- copy 15
|
||||
|
@ -304,7 +304,7 @@ recipe main [
|
|||
//:: To write to elements of containers, you need their address.
|
||||
|
||||
:(scenario index_address)
|
||||
recipe main [
|
||||
def main [
|
||||
1:array:number:3 <- create-array
|
||||
2:number <- copy 14
|
||||
3:number <- copy 15
|
||||
|
@ -366,7 +366,7 @@ case INDEX_ADDRESS: {
|
|||
|
||||
:(scenario index_address_out_of_bounds)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:array:point:3 <- create-array
|
||||
2:number <- copy 14
|
||||
3:number <- copy 15
|
||||
|
@ -381,7 +381,7 @@ recipe main [
|
|||
|
||||
:(scenario index_address_out_of_bounds_2)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:array:point:3 <- create-array
|
||||
2:number <- copy 14
|
||||
3:number <- copy 15
|
||||
|
@ -396,7 +396,7 @@ recipe main [
|
|||
|
||||
:(scenario index_address_product_type_mismatch)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:array:point:3 <- create-array
|
||||
2:number <- copy 14
|
||||
3:number <- copy 15
|
||||
|
@ -412,7 +412,7 @@ recipe main [
|
|||
//:: compute the length of an array
|
||||
|
||||
:(scenario array_length)
|
||||
recipe main [
|
||||
def main [
|
||||
1:array:number:3 <- create-array
|
||||
2:number <- copy 14
|
||||
3:number <- copy 15
|
||||
|
|
|
@ -20,7 +20,7 @@ get(Type, tmp).elements.push_back(reagent("p:point"));
|
|||
//: avoid errors.
|
||||
:(scenario copy_exclusive_container)
|
||||
# Copying exclusive containers copies all their contents and an extra location for the tag.
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 1 # 'point' variant
|
||||
2:number <- copy 34
|
||||
3:number <- copy 35
|
||||
|
@ -56,7 +56,7 @@ if (t.kind == EXCLUSIVE_CONTAINER) {
|
|||
put(Type_ordinal, "variant", 0);
|
||||
|
||||
:(scenario maybe_convert)
|
||||
recipe main [
|
||||
def main [
|
||||
12:number <- copy 1
|
||||
13:number <- copy 35
|
||||
14:number <- copy 36
|
||||
|
@ -65,7 +65,7 @@ recipe main [
|
|||
+mem: storing 13 in location 20
|
||||
|
||||
:(scenario maybe_convert_fail)
|
||||
recipe main [
|
||||
def main [
|
||||
12:number <- copy 1
|
||||
13:number <- copy 35
|
||||
14:number <- copy 36
|
||||
|
@ -147,7 +147,7 @@ const reagent variant_type(const reagent& canonized_base, long long int tag) {
|
|||
|
||||
:(scenario maybe_convert_product_type_mismatch)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
12:number <- copy 1
|
||||
13:number <- copy 35
|
||||
14:number <- copy 36
|
||||
|
@ -194,7 +194,7 @@ exclusive-container foo [
|
|||
y:number
|
||||
]
|
||||
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:foo <- merge 0/x, 1:number # tag must be a literal when merging exclusive containers
|
||||
4:foo <- merge 1/y, 1:number
|
||||
|
@ -214,7 +214,7 @@ exclusive-container foo [
|
|||
container bar [
|
||||
z:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo <- merge 0/x, 34
|
||||
]
|
||||
+mem: storing 0 in location 1
|
||||
|
@ -230,7 +230,7 @@ exclusive-container foo [
|
|||
container bar [
|
||||
z:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
1:number <- copy 0
|
||||
2:foo <- merge 1:number, 34
|
||||
|
@ -269,7 +269,7 @@ exclusive-container bar [
|
|||
x:number
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo <- merge 23, 1/y, 34
|
||||
]
|
||||
+mem: storing 23 in location 1
|
||||
|
@ -287,7 +287,7 @@ exclusive-container bar [
|
|||
x:number
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo <- merge 23, 1/y, 34, 35
|
||||
]
|
||||
+error: main: too many ingredients in '1:foo <- merge 23, 1/y, 34, 35'
|
||||
|
@ -301,7 +301,7 @@ container bar [
|
|||
x:number
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo <- merge 1/y, 23, 34
|
||||
]
|
||||
+mem: storing 1 in location 1
|
||||
|
@ -318,7 +318,7 @@ container bar [
|
|||
x:number
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo <- merge 0/x, 23
|
||||
]
|
||||
$error: 0
|
||||
|
@ -333,7 +333,7 @@ container bar [
|
|||
x:number
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo <- merge 1/y, 23
|
||||
]
|
||||
+error: main: too few ingredients in '1:foo <- merge 1/y, 23'
|
||||
|
@ -362,7 +362,7 @@ exclusive-container bar [
|
|||
y:foo
|
||||
]
|
||||
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:number <- copy 35
|
||||
3:bar <- merge 0/x, 1:number
|
||||
|
|
12
034call.cc
|
@ -1,22 +1,22 @@
|
|||
//: So far the recipes we define can't run each other. Let's fix that.
|
||||
|
||||
:(scenario calling_recipe)
|
||||
recipe main [
|
||||
def main [
|
||||
f
|
||||
]
|
||||
recipe f [
|
||||
def f [
|
||||
3:number <- add 2, 2
|
||||
]
|
||||
+mem: storing 4 in location 3
|
||||
|
||||
:(scenario return_on_fallthrough)
|
||||
recipe main [
|
||||
def main [
|
||||
f
|
||||
1:number <- copy 0
|
||||
2:number <- copy 0
|
||||
3:number <- copy 0
|
||||
]
|
||||
recipe f [
|
||||
def f [
|
||||
4:number <- copy 0
|
||||
5:number <- copy 0
|
||||
]
|
||||
|
@ -125,14 +125,14 @@ void finish_call_housekeeping(const instruction& call_instruction, const vector<
|
|||
|
||||
:(scenario calling_undefined_recipe_fails)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
foo
|
||||
]
|
||||
+error: main: undefined operation in 'foo '
|
||||
|
||||
:(scenario calling_undefined_recipe_handles_missing_result)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
x:number <- foo
|
||||
]
|
||||
+error: main: undefined operation in 'x:number <- foo '
|
||||
|
|
|
@ -2,20 +2,20 @@
|
|||
//: ingredients, use 'next-ingredient'.
|
||||
|
||||
:(scenario next_ingredient)
|
||||
recipe main [
|
||||
def main [
|
||||
f 2
|
||||
]
|
||||
recipe f [
|
||||
def f [
|
||||
12:number <- next-ingredient
|
||||
13:number <- add 1, 12:number
|
||||
]
|
||||
+mem: storing 3 in location 13
|
||||
|
||||
:(scenario next_ingredient_missing)
|
||||
recipe main [
|
||||
def main [
|
||||
f
|
||||
]
|
||||
recipe f [
|
||||
def f [
|
||||
_, 12:number <- next-ingredient
|
||||
]
|
||||
+mem: storing 0 in location 12
|
||||
|
@ -86,19 +86,19 @@ case NEXT_INGREDIENT: {
|
|||
|
||||
:(scenario next_ingredient_fail_on_missing)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
f
|
||||
]
|
||||
recipe f [
|
||||
def f [
|
||||
11:number <- next-ingredient
|
||||
]
|
||||
+error: f: no ingredient to save in 11:number
|
||||
|
||||
:(scenario rewind_ingredients)
|
||||
recipe main [
|
||||
def main [
|
||||
f 2
|
||||
]
|
||||
recipe f [
|
||||
def f [
|
||||
12:number <- next-ingredient # consume ingredient
|
||||
_, 1:boolean <- next-ingredient # will not find any ingredients
|
||||
rewind-ingredients
|
||||
|
@ -124,10 +124,10 @@ case REWIND_INGREDIENTS: {
|
|||
}
|
||||
|
||||
:(scenario ingredient)
|
||||
recipe main [
|
||||
def main [
|
||||
f 1, 2
|
||||
]
|
||||
recipe f [
|
||||
def f [
|
||||
12:number <- ingredient 1 # consume second ingredient first
|
||||
13:number, 1:boolean <- next-ingredient # next-ingredient tries to scan past that
|
||||
]
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//: Calls can also generate products, using 'reply'.
|
||||
//: Calls can also generate products, using 'reply' or 'return'.
|
||||
|
||||
:(scenario reply)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number, 2:number <- f 34
|
||||
]
|
||||
recipe f [
|
||||
def f [
|
||||
12:number <- next-ingredient
|
||||
13:number <- add 1, 12:number
|
||||
reply 12:number, 13:number
|
||||
|
@ -16,6 +16,7 @@ recipe f [
|
|||
REPLY,
|
||||
:(before "End Primitive Recipe Numbers")
|
||||
put(Recipe_ordinal, "reply", REPLY);
|
||||
put(Recipe_ordinal, "return", REPLY);
|
||||
:(before "End Primitive Recipe Checks")
|
||||
case REPLY: {
|
||||
break; // checks will be performed by a transform below
|
||||
|
@ -46,13 +47,13 @@ case REPLY: {
|
|||
|
||||
//: Products can include containers and exclusive containers, addresses and arrays.
|
||||
:(scenario reply_container)
|
||||
recipe main [
|
||||
def main [
|
||||
3:point <- f 2
|
||||
]
|
||||
recipe f [
|
||||
def f [
|
||||
12:number <- next-ingredient
|
||||
13:number <- copy 35
|
||||
reply 12:point/raw
|
||||
return 12:point/raw
|
||||
]
|
||||
+run: result 0 is [2, 35]
|
||||
+mem: storing 2 in location 3
|
||||
|
@ -86,7 +87,7 @@ void check_types_of_reply_instructions(recipe_ordinal r) {
|
|||
reagent rhs = caller_instruction.products.at(i);
|
||||
canonize_type(rhs);
|
||||
if (!types_coercible(rhs, lhs)) {
|
||||
raise << maybe(callee.name) << "reply ingredient " << lhs.original_string << " can't be saved in " << rhs.original_string << '\n' << end();
|
||||
raise << maybe(callee.name) << reply_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;
|
||||
}
|
||||
|
@ -117,16 +118,16 @@ void check_types_of_reply_instructions(recipe_ordinal r) {
|
|||
|
||||
:(scenario reply_type_mismatch)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
3:number <- f 2
|
||||
]
|
||||
recipe f [
|
||||
def f [
|
||||
12:number <- next-ingredient
|
||||
13:number <- copy 35
|
||||
14:point <- copy 12:point/raw
|
||||
reply 14:point
|
||||
return 14:point
|
||||
]
|
||||
+error: f: reply ingredient 14:point can't be saved in 3:number
|
||||
+error: f: return ingredient 14:point can't be saved in 3:number
|
||||
|
||||
//: 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
|
||||
|
@ -135,24 +136,24 @@ recipe f [
|
|||
|
||||
:(scenario reply_same_as_ingredient)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
2:number <- test1 1:number # call with different ingredient and product
|
||||
]
|
||||
recipe test1 [
|
||||
def test1 [
|
||||
10:number <- next-ingredient
|
||||
reply 10:number/same-as-ingredient:0
|
||||
return 10:number/same-as-ingredient:0
|
||||
]
|
||||
+error: main: '2:number <- test1 1:number' should write to 1:number rather than 2:number
|
||||
|
||||
:(scenario reply_same_as_ingredient_dummy)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
_ <- test1 1:number # call with different ingredient and product
|
||||
]
|
||||
recipe test1 [
|
||||
def test1 [
|
||||
10:number <- next-ingredient
|
||||
reply 10:number/same-as-ingredient:0
|
||||
return 10:number/same-as-ingredient:0
|
||||
]
|
||||
$error: 0
|
||||
|
||||
|
@ -176,22 +177,22 @@ string to_string(const vector<double>& in) {
|
|||
//: Conditional reply.
|
||||
|
||||
:(scenario reply_if)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- test1
|
||||
]
|
||||
recipe test1 [
|
||||
reply-if 0, 34
|
||||
reply 35
|
||||
def test1 [
|
||||
return-if 0, 34
|
||||
return 35
|
||||
]
|
||||
+mem: storing 35 in location 1
|
||||
|
||||
:(scenario reply_if_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- test1
|
||||
]
|
||||
recipe test1 [
|
||||
reply-if 1, 34
|
||||
reply 35
|
||||
def test1 [
|
||||
return-if 1, 34
|
||||
return 35
|
||||
]
|
||||
+mem: storing 34 in location 1
|
||||
|
||||
|
@ -201,7 +202,7 @@ recipe test1 [
|
|||
// jump-unless a, 1:offset
|
||||
// reply b, c, ...
|
||||
// ```
|
||||
if (curr.name == "reply-if") {
|
||||
if (curr.name == "reply-if" || curr.name == "return-if") {
|
||||
if (curr.products.empty()) {
|
||||
curr.operation = get(Recipe_ordinal, "jump-unless");
|
||||
curr.name = "jump-unless";
|
||||
|
@ -216,7 +217,7 @@ if (curr.name == "reply-if") {
|
|||
curr.ingredients.swap(results);
|
||||
}
|
||||
else {
|
||||
raise << "'reply-if' never yields any products\n" << end();
|
||||
raise << "'" << curr.name << "' never yields any products\n" << end();
|
||||
}
|
||||
}
|
||||
// rewrite `reply-unless a, b, c, ...` to
|
||||
|
@ -224,7 +225,7 @@ if (curr.name == "reply-if") {
|
|||
// jump-if a, 1:offset
|
||||
// reply b, c, ...
|
||||
// ```
|
||||
if (curr.name == "reply-unless") {
|
||||
if (curr.name == "reply-unless" || curr.name == "return-unless") {
|
||||
if (curr.products.empty()) {
|
||||
curr.operation = get(Recipe_ordinal, "jump-if");
|
||||
curr.name = "jump-if";
|
||||
|
@ -239,6 +240,6 @@ if (curr.name == "reply-unless") {
|
|||
curr.ingredients.swap(results);
|
||||
}
|
||||
else {
|
||||
raise << "'reply-unless' never yields any products\n" << end();
|
||||
raise << "'" << curr.name << "' never yields any products\n" << end();
|
||||
}
|
||||
}
|
||||
|
|
46
037new.cc
|
@ -47,7 +47,7 @@ if (r.type->name == "shared") {
|
|||
:(scenarios run)
|
||||
:(scenario new)
|
||||
# call new two times with identical arguments; you should get back different results
|
||||
recipe main [
|
||||
def main [
|
||||
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
|
||||
|
@ -229,7 +229,7 @@ void ensure_space(long long int size) {
|
|||
:(scenario new_initializes)
|
||||
% Memory_allocated_until = 10;
|
||||
% put(Memory, Memory_allocated_until, 1);
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:number <- new number:type
|
||||
2:number <- copy *1:address:shared:number
|
||||
]
|
||||
|
@ -237,13 +237,13 @@ recipe main [
|
|||
|
||||
:(scenario new_error)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:number/raw <- new number:type
|
||||
]
|
||||
+error: main: product of 'new' has incorrect type: 1:address:number/raw <- new number:type
|
||||
|
||||
:(scenario new_array)
|
||||
recipe main [
|
||||
def main [
|
||||
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
|
||||
|
@ -254,7 +254,7 @@ recipe main [
|
|||
+mem: storing 7 in location 3
|
||||
|
||||
:(scenario new_empty_array)
|
||||
recipe main [
|
||||
def main [
|
||||
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
|
||||
|
@ -267,7 +267,7 @@ recipe main [
|
|||
//: If a routine runs out of its initial allocation, it should allocate more.
|
||||
:(scenario new_overflow)
|
||||
% Initial_memory_per_routine = 3; // barely enough room for point allocation below
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:number/raw <- new number:type
|
||||
2:address:shared:point/raw <- new point:type # not enough room in initial page
|
||||
]
|
||||
|
@ -278,7 +278,7 @@ recipe main [
|
|||
//: todo: custodians, etc. Following malloc/free is a temporary hack.
|
||||
|
||||
:(scenario new_reclaim)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:number <- new number:type
|
||||
2:address:shared:number <- copy 1:address:shared:number # because 1 will get reset during abandon below
|
||||
abandon 1:address:shared:number # unsafe
|
||||
|
@ -367,7 +367,7 @@ if (get_or_insert(Free_list, size)) {
|
|||
}
|
||||
|
||||
:(scenario new_differing_size_no_reclaim)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:number <- new number:type
|
||||
2:address:shared:number <- copy 1:address:shared:number
|
||||
abandon 1:address:shared:number
|
||||
|
@ -378,7 +378,7 @@ recipe main [
|
|||
+mem: storing 0 in location 4
|
||||
|
||||
:(scenario new_reclaim_array)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:array:number <- new number:type, 2
|
||||
2:address:shared:array:number <- copy 1:address:shared:array:number
|
||||
abandon 1:address:shared:array:number # unsafe
|
||||
|
@ -389,7 +389,7 @@ recipe main [
|
|||
+mem: storing 1 in location 4
|
||||
|
||||
:(scenario reset_on_abandon)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:number <- new number:type
|
||||
abandon 1:address:shared:number
|
||||
]
|
||||
|
@ -400,7 +400,7 @@ recipe main [
|
|||
//:: Manage refcounts when copying addresses.
|
||||
|
||||
:(scenario refcounts)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:number <- copy 1000/unsafe
|
||||
2:address:shared:number <- copy 1:address:shared:number
|
||||
1:address:shared:number <- copy 0
|
||||
|
@ -458,7 +458,7 @@ if (x.type->value == get(Type_ordinal, "address")
|
|||
}
|
||||
|
||||
:(scenario refcounts_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:number <- new number:type
|
||||
# over-writing one allocation with another
|
||||
1:address:shared:number <- new number:type
|
||||
|
@ -470,13 +470,13 @@ recipe main [
|
|||
+mem: automatically abandoning 1000
|
||||
|
||||
:(scenario refcounts_3)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:number <- new number:type
|
||||
# passing in addresses to recipes increments refcount
|
||||
foo 1:address:shared:number
|
||||
1:address:shared:number <- copy 0
|
||||
]
|
||||
recipe foo [
|
||||
def foo [
|
||||
2:address:shared:number <- next-ingredient
|
||||
# return does NOT yet decrement refcount; memory must be explicitly managed
|
||||
2:address:shared:number <- copy 0
|
||||
|
@ -492,7 +492,7 @@ recipe foo [
|
|||
+mem: automatically abandoning 1000
|
||||
|
||||
:(scenario refcounts_4)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:number <- new number:type
|
||||
# idempotent copies leave refcount unchanged
|
||||
1:address:shared:number <- copy 1:address:shared:number
|
||||
|
@ -504,14 +504,14 @@ recipe main [
|
|||
+mem: incrementing refcount of 1000: 0 -> 1
|
||||
|
||||
:(scenario refcounts_5)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:number <- new number:type
|
||||
# passing in addresses to recipes increments refcount
|
||||
foo 1:address:shared:number
|
||||
# return does NOT yet decrement refcount; memory must be explicitly managed
|
||||
1:address:shared:number <- new number:type
|
||||
]
|
||||
recipe foo [
|
||||
def foo [
|
||||
2:address:shared:number <- next-ingredient
|
||||
]
|
||||
+run: 1:address:shared:number <- new number:type
|
||||
|
@ -524,7 +524,7 @@ recipe foo [
|
|||
//:: Extend 'new' to handle a unicode string literal argument.
|
||||
|
||||
:(scenario new_string)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:array:character <- new [abc def]
|
||||
2:character <- index *1:address:shared:array:character, 5
|
||||
]
|
||||
|
@ -532,7 +532,7 @@ recipe main [
|
|||
+mem: storing 101 in location 2
|
||||
|
||||
:(scenario new_string_handles_unicode)
|
||||
recipe main [
|
||||
def main [
|
||||
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
|
||||
|
@ -582,7 +582,7 @@ long long int new_mu_string(const string& contents) {
|
|||
//: stash recognizes strings
|
||||
|
||||
:(scenario stash_string)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:array:character <- new [abc]
|
||||
stash [foo:], 1:address:shared:array:character
|
||||
]
|
||||
|
@ -595,14 +595,14 @@ if (is_mu_string(r)) {
|
|||
}
|
||||
|
||||
:(scenario unicode_string)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:array:character <- new [♠]
|
||||
stash [foo:], 1:address:shared:array:character
|
||||
]
|
||||
+app: foo: ♠
|
||||
|
||||
:(scenario stash_space_after_string)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:array:character <- new [abc]
|
||||
stash 1:address:shared:array:character, [foo]
|
||||
]
|
||||
|
@ -611,7 +611,7 @@ recipe main [
|
|||
//: Allocate more to routine when initializing a literal string
|
||||
:(scenario new_string_overflow)
|
||||
% Initial_memory_per_routine = 2;
|
||||
recipe main [
|
||||
def main [
|
||||
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
|
||||
]
|
||||
|
|
34
040brace.cc
|
@ -21,7 +21,7 @@
|
|||
|
||||
:(scenarios transform)
|
||||
:(scenario brace_conversion)
|
||||
recipe main [
|
||||
def main [
|
||||
{
|
||||
break
|
||||
1:number <- copy 0
|
||||
|
@ -145,7 +145,7 @@ long long int matching_brace(long long int index, const list<pair<int, long long
|
|||
}
|
||||
|
||||
:(scenario loop)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
2:number <- copy 0
|
||||
{
|
||||
|
@ -160,7 +160,7 @@ recipe main [
|
|||
+transform: jump -2:offset
|
||||
|
||||
:(scenario break_empty_block)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
{
|
||||
break
|
||||
|
@ -171,7 +171,7 @@ recipe main [
|
|||
+transform: jump 0:offset
|
||||
|
||||
:(scenario break_cascading)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
{
|
||||
break
|
||||
|
@ -186,7 +186,7 @@ recipe main [
|
|||
+transform: jump 0:offset
|
||||
|
||||
:(scenario break_cascading_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
2:number <- copy 0
|
||||
{
|
||||
|
@ -205,7 +205,7 @@ recipe main [
|
|||
+transform: jump 0:offset
|
||||
|
||||
:(scenario break_if)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
2:number <- copy 0
|
||||
{
|
||||
|
@ -224,7 +224,7 @@ recipe main [
|
|||
+transform: jump 0:offset
|
||||
|
||||
:(scenario break_nested)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
{
|
||||
2:number <- copy 0
|
||||
|
@ -238,7 +238,7 @@ recipe main [
|
|||
+transform: jump 4:offset
|
||||
|
||||
:(scenario break_nested_degenerate)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
{
|
||||
2:number <- copy 0
|
||||
|
@ -251,7 +251,7 @@ recipe main [
|
|||
+transform: jump 3:offset
|
||||
|
||||
:(scenario break_nested_degenerate_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
{
|
||||
2:number <- copy 0
|
||||
|
@ -264,7 +264,7 @@ recipe main [
|
|||
|
||||
:(scenario break_label)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
{
|
||||
break +foo:offset
|
||||
|
@ -273,7 +273,7 @@ recipe main [
|
|||
+transform: jump +foo:offset
|
||||
|
||||
:(scenario break_unless)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
2:number <- copy 0
|
||||
{
|
||||
|
@ -288,7 +288,7 @@ recipe main [
|
|||
+transform: copy ...
|
||||
|
||||
:(scenario loop_unless)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
2:number <- copy 0
|
||||
{
|
||||
|
@ -303,7 +303,7 @@ recipe main [
|
|||
+transform: copy ...
|
||||
|
||||
:(scenario loop_nested)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
{
|
||||
2:number <- copy 0
|
||||
|
@ -318,7 +318,7 @@ recipe main [
|
|||
+transform: jump-if 4, -5:offset
|
||||
|
||||
:(scenario loop_label)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
+foo
|
||||
2:number <- copy 0
|
||||
|
@ -330,7 +330,7 @@ recipe main [
|
|||
//: test how things actually run
|
||||
:(scenarios run)
|
||||
:(scenario brace_conversion_and_run)
|
||||
recipe test-factorial [
|
||||
def test-factorial [
|
||||
1:number <- copy 5
|
||||
2:number <- copy 1
|
||||
{
|
||||
|
@ -347,14 +347,14 @@ recipe test-factorial [
|
|||
|
||||
:(scenario break_outside_braces_fails)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
break
|
||||
]
|
||||
+error: break needs a '{' before
|
||||
|
||||
:(scenario break_conditional_without_ingredient_fails)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
{
|
||||
break-if
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
//: iteration of some containing loop nest.
|
||||
|
||||
:(scenario jump_to_label)
|
||||
recipe main [
|
||||
def main [
|
||||
jump +target:label
|
||||
1:number <- copy 0
|
||||
+target
|
||||
|
@ -92,7 +92,7 @@ bool is_jump_target(string label) {
|
|||
}
|
||||
|
||||
:(scenario break_to_label)
|
||||
recipe main [
|
||||
def main [
|
||||
{
|
||||
{
|
||||
break +target:label
|
||||
|
@ -104,7 +104,7 @@ recipe main [
|
|||
-mem: storing 0 in location 1
|
||||
|
||||
:(scenario jump_if_to_label)
|
||||
recipe main [
|
||||
def main [
|
||||
{
|
||||
{
|
||||
jump-if 1, +target:label
|
||||
|
@ -116,7 +116,7 @@ recipe main [
|
|||
-mem: storing 0 in location 1
|
||||
|
||||
:(scenario loop_unless_to_label)
|
||||
recipe main [
|
||||
def main [
|
||||
{
|
||||
{
|
||||
loop-unless 0, +target:label # loop/break with a label don't care about braces
|
||||
|
@ -128,7 +128,7 @@ recipe main [
|
|||
-mem: storing 0 in location 1
|
||||
|
||||
:(scenario jump_runs_code_after_label)
|
||||
recipe main [
|
||||
def main [
|
||||
# first a few lines of padding to exercise the offset computation
|
||||
1:number <- copy 0
|
||||
2:number <- copy 0
|
||||
|
@ -143,21 +143,21 @@ recipe main [
|
|||
|
||||
:(scenario jump_fails_without_target)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
jump
|
||||
]
|
||||
+error: main: 'jump' expects an ingredient but got none
|
||||
|
||||
:(scenario jump_fails_without_target_2)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
jump-if 1/true
|
||||
]
|
||||
+error: main: 'jump-if' expects 2 ingredients but got 1
|
||||
|
||||
:(scenario recipe_fails_on_duplicate_jump_target)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
+label
|
||||
1:number <- copy 0
|
||||
+label
|
||||
|
@ -167,7 +167,7 @@ recipe main [
|
|||
|
||||
:(scenario jump_ignores_nontarget_label)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
# first a few lines of padding to exercise the offset computation
|
||||
1:number <- copy 0
|
||||
2:number <- copy 0
|
||||
|
|
22
042name.cc
|
@ -3,7 +3,7 @@
|
|||
//: convenience.
|
||||
|
||||
:(scenario transform_names)
|
||||
recipe main [
|
||||
def main [
|
||||
x:number <- copy 0
|
||||
]
|
||||
+name: assign x 1
|
||||
|
@ -12,7 +12,7 @@ recipe main [
|
|||
:(scenarios transform)
|
||||
:(scenario transform_names_fails_on_use_before_define)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
x:number <- copy y:number
|
||||
]
|
||||
+error: main: use before set: y
|
||||
|
@ -147,7 +147,7 @@ bool is_special_name(const string& s) {
|
|||
|
||||
:(scenario transform_names_passes_dummy)
|
||||
# _ is just a dummy result that never gets consumed
|
||||
recipe main [
|
||||
def main [
|
||||
_, x:number <- copy 0, 1
|
||||
]
|
||||
+name: assign x 1
|
||||
|
@ -157,7 +157,7 @@ recipe main [
|
|||
:(scenarios run)
|
||||
:(scenario transform_names_passes_raw)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
x:number/raw <- copy 0
|
||||
]
|
||||
-name: assign x 1
|
||||
|
@ -166,28 +166,28 @@ recipe main [
|
|||
:(scenarios transform)
|
||||
:(scenario transform_names_fails_when_mixing_names_and_numeric_locations)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
x:number <- copy 1:number
|
||||
]
|
||||
+error: main: mixing variable names and numeric addresses
|
||||
|
||||
:(scenario transform_names_fails_when_mixing_names_and_numeric_locations_2)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
x:number <- copy 1
|
||||
1:number <- copy x:number
|
||||
]
|
||||
+error: main: mixing variable names and numeric addresses
|
||||
|
||||
:(scenario transform_names_does_not_fail_when_mixing_names_and_raw_locations)
|
||||
recipe main [
|
||||
def main [
|
||||
x:number <- copy 1:number/raw
|
||||
]
|
||||
-error: main: mixing variable names and numeric addresses
|
||||
$error: 0
|
||||
|
||||
:(scenario transform_names_does_not_fail_when_mixing_names_and_literals)
|
||||
recipe main [
|
||||
def main [
|
||||
x:number <- copy 1
|
||||
]
|
||||
-error: main: mixing variable names and numeric addresses
|
||||
|
@ -196,7 +196,7 @@ $error: 0
|
|||
//:: Support element names for containers in 'get' and 'get-address'.
|
||||
|
||||
:(scenario transform_names_transforms_container_elements)
|
||||
recipe main [
|
||||
def main [
|
||||
p:address:point <- copy 0
|
||||
a:number <- get *p:address:point, y:offset
|
||||
b:number <- get *p:address:point, x:offset
|
||||
|
@ -226,7 +226,7 @@ if (inst.name == "get" || inst.name == "get-address") {
|
|||
//: this test is actually illegal so can't call run
|
||||
:(scenarios transform)
|
||||
:(scenario transform_names_handles_containers)
|
||||
recipe main [
|
||||
def main [
|
||||
a:point <- copy 0/unsafe
|
||||
b:number <- copy 0/unsafe
|
||||
]
|
||||
|
@ -237,7 +237,7 @@ recipe main [
|
|||
|
||||
:(scenarios run)
|
||||
:(scenario transform_names_handles_exclusive_containers)
|
||||
recipe main [
|
||||
def main [
|
||||
12:number <- copy 1
|
||||
13:number <- copy 35
|
||||
14:number <- copy 36
|
||||
|
|
20
043space.cc
|
@ -5,7 +5,7 @@
|
|||
:(scenario set_default_space)
|
||||
# if default-space is 10, and if an array of 5 locals lies from location 12 to 16 (inclusive),
|
||||
# then local 0 is really location 12, local 1 is really location 13, and so on.
|
||||
recipe main [
|
||||
def main [
|
||||
# pretend shared:array:location; in practice we'll use new
|
||||
10:number <- copy 0 # refcount
|
||||
11:number <- copy 5 # length
|
||||
|
@ -15,7 +15,7 @@ recipe main [
|
|||
+mem: storing 23 in location 13
|
||||
|
||||
:(scenario lookup_sidesteps_default_space)
|
||||
recipe main [
|
||||
def main [
|
||||
# pretend pointer from outside
|
||||
3:number <- copy 34
|
||||
# pretend shared:array:location; in practice we'll use new
|
||||
|
@ -31,7 +31,7 @@ recipe main [
|
|||
//:: first disable name conversion for 'default-space'
|
||||
:(scenario convert_names_passes_default_space)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
default-space:number, x:number <- copy 0, 1
|
||||
]
|
||||
+name: assign x 1
|
||||
|
@ -101,7 +101,7 @@ long long int address(long long int offset, long long int base) {
|
|||
}
|
||||
|
||||
:(scenario get_default_space)
|
||||
recipe main [
|
||||
def main [
|
||||
default-space:address:shared:array:location <- copy 10/unsafe
|
||||
1:address:shared:array:location/raw <- copy default-space:address:shared:array:location
|
||||
]
|
||||
|
@ -117,7 +117,7 @@ recipe main [
|
|||
//:: fix 'get'
|
||||
|
||||
:(scenario lookup_sidesteps_default_space_in_get)
|
||||
recipe main [
|
||||
def main [
|
||||
# pretend pointer to container from outside
|
||||
12:number <- copy 34
|
||||
13:number <- copy 35
|
||||
|
@ -137,7 +137,7 @@ tmp.properties.push_back(pair<string, string_tree*>("raw", NULL));
|
|||
//:: fix 'index'
|
||||
|
||||
:(scenario lookup_sidesteps_default_space_in_index)
|
||||
recipe main [
|
||||
def main [
|
||||
# pretend pointer to array from outside
|
||||
12:number <- copy 2
|
||||
13:number <- copy 34
|
||||
|
@ -159,7 +159,7 @@ tmp.properties.push_back(pair<string, string_tree*>("raw", NULL));
|
|||
//:: allocate in a default space with names
|
||||
|
||||
:(scenario new_default_space)
|
||||
recipe main [
|
||||
def main [
|
||||
new-default-space
|
||||
x:number <- copy 0
|
||||
y:number <- copy 3
|
||||
|
@ -198,15 +198,15 @@ if (curr.name == "new-default-space") {
|
|||
//:: from a recipe
|
||||
|
||||
:(scenario local_scope)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address <- foo
|
||||
2:address <- foo
|
||||
3:boolean <- equal 1:address, 2:address
|
||||
]
|
||||
recipe foo [
|
||||
def foo [
|
||||
local-scope
|
||||
x:number <- copy 34
|
||||
reply default-space:address:shared:array:location
|
||||
return default-space:address:shared:array:location
|
||||
]
|
||||
# both calls to foo should have received the same default-space
|
||||
+mem: storing 1 in location 3
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
:(scenario surrounding_space)
|
||||
# location 1 in space 1 refers to the space surrounding the default space, here 20.
|
||||
recipe main [
|
||||
def main [
|
||||
# pretend shared:array:location; in practice we'll use new
|
||||
10:number <- copy 0 # refcount
|
||||
11:number <- copy 5 # length
|
||||
|
@ -19,7 +19,7 @@ recipe main [
|
|||
1:number <- copy 32
|
||||
1:number/space:1 <- copy 33
|
||||
]
|
||||
recipe dummy [ # just for the /names: property above
|
||||
def dummy [ # just for the /names: property above
|
||||
]
|
||||
# chain space: 10 + /*skip refcount*/1 + /*skip length*/1
|
||||
+mem: storing 20 in location 12
|
||||
|
@ -57,6 +57,6 @@ long long int space_index(const reagent& x) {
|
|||
}
|
||||
|
||||
:(scenario permit_space_as_variable_name)
|
||||
recipe main [
|
||||
def main [
|
||||
space:number <- copy 0
|
||||
]
|
||||
|
|
|
@ -4,26 +4,26 @@
|
|||
//: surrounding space of the surrounding space, etc.
|
||||
|
||||
:(scenario closure)
|
||||
recipe main [
|
||||
def main [
|
||||
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 [
|
||||
def new-counter [
|
||||
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:shared:array:location
|
||||
return default-space:address:shared:array:location
|
||||
]
|
||||
|
||||
recipe increment-counter [
|
||||
def increment-counter [
|
||||
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
|
||||
return y:number/space:1
|
||||
]
|
||||
|
||||
+name: lexically surrounding space for recipe increment-counter comes from new-counter
|
||||
|
@ -152,7 +152,7 @@ bool already_transformed(const reagent& r, const map<string, long long int>& nam
|
|||
|
||||
:(scenario missing_surrounding_space)
|
||||
% Hide_errors = true;
|
||||
recipe f [
|
||||
def f [
|
||||
local-scope
|
||||
x:number/space:1 <- copy 34
|
||||
]
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
//: entirely.
|
||||
|
||||
:(scenario global_space)
|
||||
recipe main [
|
||||
def main [
|
||||
# pretend shared:array:location; in practice we'll use new
|
||||
10:number <- copy 0 # refcount
|
||||
11:number <- copy 5 # length
|
||||
|
@ -72,7 +72,7 @@ global_space = 0;
|
|||
//: don't want to make them too comfortable to use.
|
||||
|
||||
:(scenario global_space_with_names)
|
||||
recipe main [
|
||||
def main [
|
||||
global-space:address:shared:array:location <- new location:type, 10
|
||||
x:number <- copy 23
|
||||
1:number/space:global <- copy 24
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
:(scenario transform_fails_on_reusing_name_with_different_type)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
x:number <- copy 1
|
||||
x:boolean <- copy 1
|
||||
]
|
||||
|
@ -67,19 +67,19 @@ void check_type(set<reagent>& known, const reagent& x, const recipe_ordinal r) {
|
|||
}
|
||||
|
||||
:(scenario transform_fills_in_missing_types)
|
||||
recipe main [
|
||||
def main [
|
||||
x:number <- copy 1
|
||||
y:number <- add x, 1
|
||||
]
|
||||
|
||||
:(scenario transform_fills_in_missing_types_in_product)
|
||||
recipe main [
|
||||
def main [
|
||||
x:number <- copy 1
|
||||
x <- copy 2
|
||||
]
|
||||
|
||||
:(scenario transform_fills_in_missing_types_in_product_and_ingredient)
|
||||
recipe main [
|
||||
def main [
|
||||
x:number <- copy 1
|
||||
x <- add x, 1
|
||||
]
|
||||
|
@ -87,7 +87,7 @@ recipe main [
|
|||
|
||||
:(scenario transform_fails_on_missing_types_in_first_mention)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
x <- copy 1
|
||||
x:number <- copy 2
|
||||
]
|
||||
|
@ -95,7 +95,7 @@ recipe main [
|
|||
|
||||
:(scenario typo_in_address_type_fails)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
y:address:shared:charcter <- new character:type
|
||||
*y <- copy 67
|
||||
]
|
||||
|
@ -103,16 +103,16 @@ recipe main [
|
|||
|
||||
:(scenario array_type_without_size_fails)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
x:array:number <- merge 2, 12, 13
|
||||
]
|
||||
+error: main can't determine the size of array variable x. Either allocate it separately and make the type of x address:shared:..., or specify the length of the array in the type of x.
|
||||
|
||||
:(scenarios transform)
|
||||
:(scenario transform_checks_types_of_identical_reagents_in_multiple_spaces)
|
||||
recipe foo [ # dummy
|
||||
def foo [ # dummy
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
0:address:shared:array:location/names:foo <- copy 0 # specify surrounding space
|
||||
x:boolean <- copy 1/true
|
||||
|
|
|
@ -172,11 +172,11 @@ void run_mu_scenario(const scenario& s) {
|
|||
:(scenario forbid_redefining_scenario_even_if_forced)
|
||||
% Hide_errors = true;
|
||||
% Disable_redefine_checks = true;
|
||||
recipe scenario-foo [
|
||||
def scenario-foo [
|
||||
1:number <- copy 34
|
||||
]
|
||||
|
||||
recipe scenario-foo [
|
||||
def scenario-foo [
|
||||
1:number <- copy 35
|
||||
]
|
||||
+error: redefining recipe scenario-foo
|
||||
|
@ -190,7 +190,7 @@ recipe scenario-foo [
|
|||
//: 'run' interprets a string as a set of instructions
|
||||
|
||||
:(scenario run)
|
||||
recipe main [
|
||||
def main [
|
||||
run [
|
||||
1:number <- copy 13
|
||||
]
|
||||
|
@ -231,7 +231,7 @@ void bind_special_scenario_names(recipe_ordinal r) {
|
|||
}
|
||||
|
||||
:(scenario run_multiple)
|
||||
recipe main [
|
||||
def main [
|
||||
run [
|
||||
1:number <- copy 13
|
||||
]
|
||||
|
@ -253,7 +253,7 @@ Scenario_testing_scenario = false;
|
|||
:(scenario memory_check)
|
||||
% Scenario_testing_scenario = true;
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
memory-should-contain [
|
||||
1 <- 13
|
||||
]
|
||||
|
@ -389,7 +389,7 @@ void check_string(long long int address, const string& literal) {
|
|||
:(scenario memory_check_multiple)
|
||||
% Scenario_testing_scenario = true;
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
memory-should-contain [
|
||||
1 <- 0
|
||||
1 <- 0
|
||||
|
@ -400,7 +400,7 @@ recipe main [
|
|||
:(scenario memory_check_string_length)
|
||||
% Scenario_testing_scenario = true;
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 3
|
||||
2:number <- copy 97 # 'a'
|
||||
3:number <- copy 98 # 'b'
|
||||
|
@ -412,7 +412,7 @@ recipe main [
|
|||
+error: expected location 1 to contain length 2 of string [ab] but saw 3
|
||||
|
||||
:(scenario memory_check_string)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 3
|
||||
2:number <- copy 97 # 'a'
|
||||
3:number <- copy 98 # 'b'
|
||||
|
@ -429,7 +429,7 @@ recipe main [
|
|||
:(scenario memory_invalid_string_check)
|
||||
% Scenario_testing_scenario = true;
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
memory-should-contain [
|
||||
1 <- [abc]
|
||||
]
|
||||
|
@ -439,7 +439,7 @@ recipe main [
|
|||
:(scenario memory_check_with_comment)
|
||||
% Scenario_testing_scenario = true;
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
memory-should-contain [
|
||||
1 <- 34 # comment
|
||||
]
|
||||
|
@ -456,7 +456,7 @@ recipe main [
|
|||
:(scenario trace_check_fails)
|
||||
% Scenario_testing_scenario = true;
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
trace-should-contain [
|
||||
a: b
|
||||
a: d
|
||||
|
@ -515,7 +515,7 @@ vector<trace_line> parse_trace(const string& expected) {
|
|||
:(scenario trace_check_fails_in_nonfirst_line)
|
||||
% Scenario_testing_scenario = true;
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
run [
|
||||
trace 1, [a], [b]
|
||||
]
|
||||
|
@ -528,7 +528,7 @@ recipe main [
|
|||
|
||||
:(scenario trace_check_passes_silently)
|
||||
% Scenario_testing_scenario = true;
|
||||
recipe main [
|
||||
def main [
|
||||
run [
|
||||
trace 1, [a], [b]
|
||||
]
|
||||
|
@ -546,7 +546,7 @@ $error: 0
|
|||
:(scenario trace_negative_check_fails)
|
||||
% Scenario_testing_scenario = true;
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
run [
|
||||
trace 1, [a], [b]
|
||||
]
|
||||
|
@ -589,7 +589,7 @@ bool check_trace_missing(const string& in) {
|
|||
|
||||
:(scenario trace_negative_check_passes_silently)
|
||||
% Scenario_testing_scenario = true;
|
||||
recipe main [
|
||||
def main [
|
||||
trace-should-not-contain [
|
||||
a: b
|
||||
]
|
||||
|
@ -600,7 +600,7 @@ $error: 0
|
|||
:(scenario trace_negative_check_fails_on_any_unexpected_line)
|
||||
% Scenario_testing_scenario = true;
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
run [
|
||||
trace 1, [a], [d]
|
||||
]
|
||||
|
@ -612,7 +612,7 @@ recipe main [
|
|||
+error: unexpected [d] in trace with label a
|
||||
|
||||
:(scenario trace_count_check)
|
||||
recipe main [
|
||||
def main [
|
||||
run [
|
||||
trace 1, [a], [foo]
|
||||
]
|
||||
|
@ -666,7 +666,7 @@ case CHECK_TRACE_COUNT_FOR_LABEL: {
|
|||
:(scenario trace_count_check_2)
|
||||
% Scenario_testing_scenario = true;
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
run [
|
||||
trace 1, [a], [foo]
|
||||
]
|
||||
|
|
26
052tangle.cc
|
@ -7,7 +7,7 @@
|
|||
//: todo: switch recipe.steps to a more efficient data structure.
|
||||
|
||||
:(scenario tangle_before)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
<label1>
|
||||
3:number <- copy 0
|
||||
|
@ -152,7 +152,7 @@ void check_insert_fragments(unused recipe_ordinal) {
|
|||
}
|
||||
|
||||
:(scenario tangle_before_and_after)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
<label1>
|
||||
4:number <- copy 0
|
||||
|
@ -173,7 +173,7 @@ $mem: 4
|
|||
|
||||
:(scenario tangle_ignores_jump_target)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
+label1
|
||||
4:number <- copy 0
|
||||
|
@ -184,7 +184,7 @@ before +label1 [
|
|||
+error: can't tangle before label +label1
|
||||
|
||||
:(scenario tangle_keeps_labels_separate)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
<label1>
|
||||
<label2>
|
||||
|
@ -215,7 +215,7 @@ after <label2> [
|
|||
$mem: 6
|
||||
|
||||
:(scenario tangle_stacks_multiple_fragments)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
<label1>
|
||||
6:number <- copy 0
|
||||
|
@ -245,7 +245,7 @@ after <label1> [
|
|||
$mem: 6
|
||||
|
||||
:(scenario tangle_supports_fragments_with_multiple_instructions)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 0
|
||||
<label1>
|
||||
6:number <- copy 0
|
||||
|
@ -269,13 +269,13 @@ after <label1> [
|
|||
$mem: 6
|
||||
|
||||
:(scenario tangle_tangles_into_all_labels_with_same_name)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 10
|
||||
<label1>
|
||||
4:number <- copy 10
|
||||
recipe2
|
||||
]
|
||||
recipe recipe2 [
|
||||
def recipe2 [
|
||||
1:number <- copy 11
|
||||
<label1>
|
||||
4:number <- copy 11
|
||||
|
@ -301,7 +301,7 @@ after <label1> [
|
|||
$mem: 8
|
||||
|
||||
:(scenario tangle_tangles_into_all_labels_with_same_name_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 10
|
||||
<label1>
|
||||
<label1>
|
||||
|
@ -325,7 +325,7 @@ after <label1> [
|
|||
$mem: 6
|
||||
|
||||
:(scenario tangle_tangles_into_all_labels_with_same_name_3)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 10
|
||||
<label1>
|
||||
<foo>
|
||||
|
@ -352,7 +352,7 @@ after <foo> [
|
|||
$mem: 6
|
||||
|
||||
:(scenario tangle_handles_jump_target_inside_fragment)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 10
|
||||
<label1>
|
||||
4:number <- copy 10
|
||||
|
@ -373,7 +373,7 @@ before <label1> [
|
|||
$mem: 3
|
||||
|
||||
:(scenario tangle_renames_jump_target)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 10
|
||||
<label1>
|
||||
+label2
|
||||
|
@ -395,7 +395,7 @@ before <label1> [
|
|||
$mem: 3
|
||||
|
||||
:(scenario tangle_jump_to_base_recipe)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 10
|
||||
<label1>
|
||||
+label2
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
:(scenarios load)
|
||||
:(scenario dilated_reagent)
|
||||
recipe main [
|
||||
def main [
|
||||
{1: number, foo: bar} <- copy 34
|
||||
]
|
||||
+parse: product: 1: "number", {"foo": "bar"}
|
||||
|
||||
:(scenario load_trailing_space_after_curly_bracket)
|
||||
recipe main [
|
||||
def main [
|
||||
# line below has a space at the end
|
||||
{
|
||||
]
|
||||
|
@ -18,14 +18,14 @@ recipe main [
|
|||
|
||||
:(scenarios run)
|
||||
:(scenario dilated_reagent_with_comment)
|
||||
recipe main [
|
||||
def main [
|
||||
{1: number, foo: bar} <- copy 34 # test comment
|
||||
]
|
||||
+parse: product: 1: "number", {"foo": "bar"}
|
||||
$error: 0
|
||||
|
||||
:(scenario dilated_reagent_with_comment_immediately_following)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy {34: literal} # test comment
|
||||
]
|
||||
$error: 0
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// (address to array of charaters) to (list of numbers)".
|
||||
|
||||
:(scenario dilated_reagent_with_nested_brackets)
|
||||
recipe main [
|
||||
def main [
|
||||
{1: number, foo: (bar (baz quux))} <- copy 34
|
||||
]
|
||||
+parse: product: 1: "number", {"foo": ("bar" ("baz" "quux"))}
|
||||
|
@ -59,7 +59,7 @@ string_tree* parse_string_tree(istream& in) {
|
|||
|
||||
:(scenario dilated_reagent_with_type_tree)
|
||||
% Hide_errors = true; // 'map' isn't defined yet
|
||||
recipe main [
|
||||
def main [
|
||||
{1: (foo (address array character) (bar number))} <- copy 34
|
||||
]
|
||||
# just to avoid errors
|
||||
|
@ -70,7 +70,7 @@ container bar [
|
|||
+parse: product: 1: ("foo" ("address" "array" "character") ("bar" "number"))
|
||||
|
||||
:(scenario dilated_reagent_in_static_array)
|
||||
recipe main [
|
||||
def main [
|
||||
{1: (array (address shared number) 3)} <- create-array
|
||||
5:address:address:shared:number <- index-address {1: (array (address shared number) 3)}, 0
|
||||
*5:address:address:shared:number <- new number:type
|
||||
|
@ -83,7 +83,7 @@ recipe main [
|
|||
//: an exception is 'new', which takes a type tree as its ingredient *value*
|
||||
|
||||
:(scenario dilated_reagent_with_new)
|
||||
recipe main [
|
||||
def main [
|
||||
x:address:shared:address:number <- new {(address number): type}
|
||||
]
|
||||
+new: size of ("address" "number") is 1
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
//: number of ingredients and yields some fixed number of products.
|
||||
|
||||
:(scenario recipe_with_header)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number/raw <- add2 3, 5
|
||||
]
|
||||
recipe add2 x:number, y:number -> z:number [
|
||||
def add2 x:number, y:number -> z:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z:number <- add x, y
|
||||
reply z
|
||||
return z
|
||||
]
|
||||
+mem: storing 8 in location 1
|
||||
|
||||
|
@ -48,38 +48,38 @@ void load_recipe_header(istream& in, recipe& result) {
|
|||
}
|
||||
|
||||
:(scenario recipe_handles_stray_comma)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number/raw <- add2 3, 5
|
||||
]
|
||||
recipe add2 x:number, y:number -> z:number, [
|
||||
def add2 x:number, y:number -> z:number, [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z:number <- add x, y
|
||||
reply z
|
||||
return z
|
||||
]
|
||||
+mem: storing 8 in location 1
|
||||
|
||||
:(scenario recipe_handles_stray_comma_2)
|
||||
recipe main [
|
||||
def main [
|
||||
foo
|
||||
]
|
||||
recipe foo, [
|
||||
def foo, [
|
||||
1:number/raw <- add 2, 2
|
||||
]
|
||||
recipe bar [
|
||||
def bar [
|
||||
1:number/raw <- add 2, 3
|
||||
]
|
||||
+mem: storing 4 in location 1
|
||||
|
||||
:(scenario recipe_handles_missing_bracket)
|
||||
% Hide_errors = true;
|
||||
recipe main
|
||||
def main
|
||||
]
|
||||
+error: recipe body must begin with '['
|
||||
|
||||
:(scenario recipe_handles_missing_bracket_2)
|
||||
% Hide_errors = true;
|
||||
recipe main
|
||||
def main
|
||||
local-scope
|
||||
{
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ recipe main
|
|||
|
||||
:(scenario recipe_handles_missing_bracket_3)
|
||||
% Hide_errors = true;
|
||||
recipe main # comment
|
||||
def main # comment
|
||||
local-scope
|
||||
{
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ for (long long int i = 0; i < SIZE(x.products); ++i)
|
|||
//: If a recipe never mentions any ingredients or products, assume it has a header.
|
||||
|
||||
:(scenario recipe_without_ingredients_or_products_has_header)
|
||||
recipe test [
|
||||
def test [
|
||||
1:number <- copy 34
|
||||
]
|
||||
+parse: recipe test has a header
|
||||
|
@ -121,6 +121,7 @@ if (!result.has_header) {
|
|||
for (long long int i = 0; i < SIZE(result.steps); ++i) {
|
||||
const instruction& inst = result.steps.at(i);
|
||||
if ((inst.name == "reply" && !inst.ingredients.empty())
|
||||
|| (inst.name == "return" && !inst.ingredients.empty())
|
||||
|| inst.name == "next-ingredient"
|
||||
|| inst.name == "ingredient"
|
||||
|| inst.name == "rewind-ingredients") {
|
||||
|
@ -182,25 +183,25 @@ case NEXT_INGREDIENT_WITHOUT_TYPECHECKING: {
|
|||
|
||||
:(scenario show_clear_error_on_bad_call)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- foo 34
|
||||
]
|
||||
recipe foo x:point -> y:number [
|
||||
def foo x:point -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 35
|
||||
return 35
|
||||
]
|
||||
+error: main: ingredient 0 has the wrong type at '1:number <- foo 34'
|
||||
|
||||
:(scenario show_clear_error_on_bad_call_2)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:point <- foo 34
|
||||
]
|
||||
recipe foo x:number -> y:number [
|
||||
def foo x:number -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply x
|
||||
return x
|
||||
]
|
||||
+error: main: product 0 has the wrong type at '1:point <- foo 34'
|
||||
|
||||
|
@ -245,11 +246,11 @@ bool is_unique_address(reagent x) {
|
|||
|
||||
:(scenario forbid_calls_with_nonshared_addresses)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:number <- copy 0
|
||||
foo 1:address:number
|
||||
]
|
||||
recipe foo x:address:number [
|
||||
def foo x:address:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
]
|
||||
|
@ -257,10 +258,10 @@ recipe foo x:address:number [
|
|||
|
||||
:(scenario forbid_calls_with_nonshared_addresses_2)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:number <- foo
|
||||
]
|
||||
recipe foo -> x:address:number [
|
||||
def foo -> x:address:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x <- copy 0
|
||||
|
@ -272,13 +273,13 @@ recipe foo -> x:address:number [
|
|||
:(scenarios transform)
|
||||
:(scenario recipe_headers_are_checked)
|
||||
% Hide_errors = true;
|
||||
recipe add2 x:number, y:number -> z:number [
|
||||
def add2 x:number, y:number -> z:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z:address:number <- copy 0/unsafe
|
||||
reply z
|
||||
return z
|
||||
]
|
||||
+error: add2: replied with the wrong type at 'reply z'
|
||||
+error: add2: replied with the wrong type at 'return z'
|
||||
|
||||
:(before "End Checks")
|
||||
Transform.push_back(check_reply_instructions_against_header); // idempotent
|
||||
|
@ -290,7 +291,7 @@ void check_reply_instructions_against_header(const recipe_ordinal r) {
|
|||
trace(9991, "transform") << "--- checking reply instructions against header for " << caller_recipe.name << end();
|
||||
for (long long int i = 0; i < SIZE(caller_recipe.steps); ++i) {
|
||||
const instruction& inst = caller_recipe.steps.at(i);
|
||||
if (inst.name != "reply") continue;
|
||||
if (inst.name != "reply" && inst.name != "return") continue;
|
||||
if (SIZE(caller_recipe.products) != SIZE(inst.ingredients)) {
|
||||
raise << maybe(caller_recipe.name) << "replied with the wrong number of products at '" << to_string(inst) << "'\n" << end();
|
||||
continue;
|
||||
|
@ -304,20 +305,20 @@ void check_reply_instructions_against_header(const recipe_ordinal r) {
|
|||
|
||||
:(scenario recipe_headers_are_checked_2)
|
||||
% Hide_errors = true;
|
||||
recipe add2 x:number, y:number [
|
||||
def add2 x:number, y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z:address:number <- copy 0/unsafe
|
||||
reply z
|
||||
return z
|
||||
]
|
||||
+error: add2: replied with the wrong number of products at 'reply z'
|
||||
+error: add2: replied with the wrong number of products at 'return z'
|
||||
|
||||
:(scenario recipe_headers_check_for_duplicate_names)
|
||||
% Hide_errors = true;
|
||||
recipe add2 x:number, x:number -> z:number [
|
||||
def add2 x:number, x:number -> z:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply z
|
||||
return z
|
||||
]
|
||||
+error: add2: x can't repeat in the ingredients
|
||||
|
||||
|
@ -344,14 +345,14 @@ void check_header_ingredients(const recipe_ordinal r) {
|
|||
|
||||
:(scenarios run)
|
||||
:(scenario deduce_instruction_types_from_recipe_header)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number/raw <- add2 3, 5
|
||||
]
|
||||
recipe add2 x:number, y:number -> z:number [
|
||||
def add2 x:number, y:number -> z:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z <- add x, y # no type for z
|
||||
reply z
|
||||
return z
|
||||
]
|
||||
+mem: storing 8 in location 1
|
||||
|
||||
|
@ -399,14 +400,14 @@ void deduce_types_from_header(const recipe_ordinal r) {
|
|||
//: in the header.
|
||||
|
||||
:(scenario reply_based_on_header)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number/raw <- add2 3, 5
|
||||
]
|
||||
recipe add2 x:number, y:number -> z:number [
|
||||
def add2 x:number, y:number -> z:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z <- add x, y
|
||||
reply
|
||||
return
|
||||
]
|
||||
+mem: storing 8 in location 1
|
||||
|
||||
|
@ -420,11 +421,12 @@ void fill_in_reply_ingredients(recipe_ordinal r) {
|
|||
trace(9991, "transform") << "--- fill in reply ingredients from header for recipe " << caller_recipe.name << end();
|
||||
for (long long int i = 0; i < SIZE(caller_recipe.steps); ++i) {
|
||||
instruction& inst = caller_recipe.steps.at(i);
|
||||
if (inst.name == "reply")
|
||||
if (inst.name == "reply" || inst.name == "return")
|
||||
add_header_products(inst, caller_recipe);
|
||||
}
|
||||
// fall through reply
|
||||
if (caller_recipe.steps.at(SIZE(caller_recipe.steps)-1).name != "reply") {
|
||||
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";
|
||||
add_header_products(inst, caller_recipe);
|
||||
|
@ -433,7 +435,7 @@ void fill_in_reply_ingredients(recipe_ordinal r) {
|
|||
}
|
||||
|
||||
void add_header_products(instruction& inst, const recipe& caller_recipe) {
|
||||
assert(inst.name == "reply");
|
||||
assert(inst.name == "reply" || inst.name == "return");
|
||||
// collect any products with the same names as ingredients
|
||||
for (long long int i = 0; i < SIZE(caller_recipe.products); ++i) {
|
||||
// if the ingredient is missing, add it from the header
|
||||
|
@ -449,24 +451,24 @@ void add_header_products(instruction& inst, const recipe& caller_recipe) {
|
|||
}
|
||||
|
||||
:(scenario explicit_reply_ignores_header)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number/raw, 2:number/raw <- add2 3, 5
|
||||
]
|
||||
recipe add2 a:number, b:number -> y:number, z:number [
|
||||
def add2 a:number, b:number -> y:number, z:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- add a, b
|
||||
z <- subtract a, b
|
||||
reply a, z
|
||||
return a, z
|
||||
]
|
||||
+mem: storing 3 in location 1
|
||||
+mem: storing -2 in location 2
|
||||
|
||||
:(scenario reply_on_fallthrough_based_on_header)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number/raw <- add2 3, 5
|
||||
]
|
||||
recipe add2 x:number, y:number -> z:number [
|
||||
def add2 x:number, y:number -> z:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z <- add x, y
|
||||
|
@ -475,27 +477,27 @@ recipe add2 x:number, y:number -> z:number [
|
|||
+mem: storing 8 in location 1
|
||||
|
||||
:(scenario reply_on_fallthrough_already_exists)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number/raw <- add2 3, 5
|
||||
]
|
||||
recipe add2 x:number, y:number -> z:number [
|
||||
def add2 x:number, y:number -> z:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z <- add x, y # no type for z
|
||||
reply z
|
||||
return z
|
||||
]
|
||||
+transform: instruction: reply z
|
||||
+transform: instruction: return z
|
||||
-transform: instruction: reply z:number
|
||||
+mem: storing 8 in location 1
|
||||
|
||||
:(scenario recipe_headers_perform_same_ingredient_check)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:number <- copy 34
|
||||
3:number <- add2 1:number, 2:number
|
||||
]
|
||||
recipe add2 x:number, y:number -> x:number [
|
||||
def add2 x:number, y:number -> x:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
]
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
//: names like 'print' or 'length' in many mutually extensible ways.
|
||||
|
||||
:(scenario static_dispatch)
|
||||
recipe main [
|
||||
def main [
|
||||
7:number/raw <- test 3
|
||||
]
|
||||
recipe test a:number -> z:number [
|
||||
def test a:number -> z:number [
|
||||
z <- copy 1
|
||||
]
|
||||
recipe test a:number, b:number -> z:number [
|
||||
def test a:number, b:number -> z:number [
|
||||
z <- copy 2
|
||||
]
|
||||
+mem: storing 1 in location 7
|
||||
|
@ -115,13 +115,13 @@ string next_unused_recipe_name(const string& recipe_name) {
|
|||
//: call with the most suitable variant.
|
||||
|
||||
:(scenario static_dispatch_picks_most_similar_variant)
|
||||
recipe main [
|
||||
def main [
|
||||
7:number/raw <- test 3, 4, 5
|
||||
]
|
||||
recipe test a:number -> z:number [
|
||||
def test a:number -> z:number [
|
||||
z <- copy 1
|
||||
]
|
||||
recipe test a:number, b:number -> z:number [
|
||||
def test a:number, b:number -> z:number [
|
||||
z <- copy 2
|
||||
]
|
||||
+mem: storing 2 in location 7
|
||||
|
@ -336,37 +336,37 @@ bool next_stash(const call& c, instruction* stash_inst) {
|
|||
}
|
||||
|
||||
:(scenario static_dispatch_disabled_in_recipe_without_variants)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- test 3
|
||||
]
|
||||
recipe test [
|
||||
def test [
|
||||
2:number <- next-ingredient # ensure no header
|
||||
reply 34
|
||||
return 34
|
||||
]
|
||||
+mem: storing 34 in location 1
|
||||
|
||||
:(scenario static_dispatch_disabled_on_headerless_definition)
|
||||
% Hide_errors = true;
|
||||
recipe test a:number -> z:number [
|
||||
def test a:number -> z:number [
|
||||
z <- copy 1
|
||||
]
|
||||
recipe test [
|
||||
reply 34
|
||||
def test [
|
||||
return 34
|
||||
]
|
||||
+error: redefining recipe test
|
||||
|
||||
:(scenario static_dispatch_disabled_on_headerless_definition_2)
|
||||
% Hide_errors = true;
|
||||
recipe test [
|
||||
reply 34
|
||||
def test [
|
||||
return 34
|
||||
]
|
||||
recipe test a:number -> z:number [
|
||||
def test a:number -> z:number [
|
||||
z <- copy 1
|
||||
]
|
||||
+error: redefining recipe test
|
||||
|
||||
:(scenario static_dispatch_on_primitive_names)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:number <- copy 34
|
||||
3:boolean <- equal 1:number, 2:number
|
||||
|
@ -376,7 +376,7 @@ recipe main [
|
|||
]
|
||||
|
||||
# temporarily hardcode number equality to always fail
|
||||
recipe equal x:number, y:number -> z:boolean [
|
||||
def equal x:number, y:number -> z:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z <- copy 0/false
|
||||
|
@ -387,15 +387,15 @@ recipe equal x:number, y:number -> z:boolean [
|
|||
+mem: storing 1 in location 6
|
||||
|
||||
:(scenario static_dispatch_works_with_dummy_results_for_containers)
|
||||
recipe main [
|
||||
def main [
|
||||
_ <- test 3, 4
|
||||
]
|
||||
recipe test a:number -> z:point [
|
||||
def test a:number -> z:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z <- merge a, 0
|
||||
]
|
||||
recipe test a:number, b:number -> z:point [
|
||||
def test a:number, b:number -> z:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z <- merge a, b
|
||||
|
@ -403,14 +403,14 @@ recipe test a:number, b:number -> z:point [
|
|||
$error: 0
|
||||
|
||||
:(scenario static_dispatch_works_with_compound_type_containing_container_defined_after_first_use)
|
||||
recipe main [
|
||||
def main [
|
||||
x:address:shared:foo <- new foo:type
|
||||
test x
|
||||
]
|
||||
container foo [
|
||||
x:number
|
||||
]
|
||||
recipe test a:address:shared:foo -> z:number [
|
||||
def test a:address:shared:foo -> z:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z:number <- get *a, x:offset
|
||||
|
@ -418,11 +418,11 @@ recipe test a:address:shared:foo -> z:number [
|
|||
$error: 0
|
||||
|
||||
:(scenario static_dispatch_works_with_compound_type_containing_container_defined_after_second_use)
|
||||
recipe main [
|
||||
def main [
|
||||
x:address:shared:foo <- new foo:type
|
||||
test x
|
||||
]
|
||||
recipe test a:address:shared:foo -> z:number [
|
||||
def test a:address:shared:foo -> z:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
z:number <- get *a, x:offset
|
||||
|
@ -433,78 +433,78 @@ container foo [
|
|||
$error: 0
|
||||
|
||||
:(scenario static_dispatch_prefers_literals_to_be_numbers_rather_than_addresses)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- foo 0
|
||||
]
|
||||
recipe foo x:address:number -> y:number [
|
||||
reply 34
|
||||
def foo x:address:number -> y:number [
|
||||
return 34
|
||||
]
|
||||
recipe foo x:number -> y:number [
|
||||
reply 35
|
||||
def foo x:number -> y:number [
|
||||
return 35
|
||||
]
|
||||
+mem: storing 35 in location 1
|
||||
|
||||
:(scenario static_dispatch_on_non_literal_character_ignores_variant_with_numbers)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
x:character <- copy 10/newline
|
||||
1:number/raw <- foo x
|
||||
]
|
||||
recipe foo x:number -> y:number [
|
||||
def foo x:number -> y:number [
|
||||
load-ingredients
|
||||
reply 34
|
||||
return 34
|
||||
]
|
||||
+error: main: ingredient 0 has the wrong type at '1:number/raw <- foo x'
|
||||
-mem: storing 34 in location 1
|
||||
|
||||
:(scenario static_dispatch_dispatches_literal_to_boolean_before_character)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number/raw <- foo 0 # valid literal for boolean
|
||||
]
|
||||
recipe foo x:character -> y:number [
|
||||
def foo x:character -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 34
|
||||
return 34
|
||||
]
|
||||
recipe foo x:boolean -> y:number [
|
||||
def foo x:boolean -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 35
|
||||
return 35
|
||||
]
|
||||
# boolean variant is preferred
|
||||
+mem: storing 35 in location 1
|
||||
|
||||
:(scenario static_dispatch_dispatches_literal_to_character_when_out_of_boolean_range)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number/raw <- foo 97 # not a valid literal for boolean
|
||||
]
|
||||
recipe foo x:character -> y:number [
|
||||
def foo x:character -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 34
|
||||
return 34
|
||||
]
|
||||
recipe foo x:boolean -> y:number [
|
||||
def foo x:boolean -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 35
|
||||
return 35
|
||||
]
|
||||
# character variant is preferred
|
||||
+mem: storing 34 in location 1
|
||||
|
||||
:(scenario static_dispatch_dispatches_literal_to_number_if_at_all_possible)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number/raw <- foo 97
|
||||
]
|
||||
recipe foo x:character -> y:number [
|
||||
def foo x:character -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 34
|
||||
return 34
|
||||
]
|
||||
recipe foo x:number -> y:number [
|
||||
def foo x:number -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 35
|
||||
return 35
|
||||
]
|
||||
# number variant is preferred
|
||||
+mem: storing 35 in location 1
|
||||
|
@ -523,42 +523,42 @@ string header_label(recipe_ordinal r) {
|
|||
}
|
||||
|
||||
:(scenario reload_variant_retains_other_variants)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:number <- foo 1:number
|
||||
]
|
||||
recipe foo x:number -> y:number [
|
||||
def foo x:number -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 34
|
||||
return 34
|
||||
]
|
||||
recipe foo x:address:number -> y:number [
|
||||
def foo x:address:number -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 35
|
||||
return 35
|
||||
]
|
||||
recipe! foo x:address:number -> y:number [
|
||||
def! foo x:address:number -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 36
|
||||
return 36
|
||||
]
|
||||
+mem: storing 34 in location 2
|
||||
$error: 0
|
||||
|
||||
:(scenario dispatch_errors_come_after_unknown_name_errors)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
y:number <- foo x
|
||||
]
|
||||
recipe foo a:number -> b:number [
|
||||
def foo a:number -> b:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 34
|
||||
return 34
|
||||
]
|
||||
recipe foo a:boolean -> b:number [
|
||||
def foo a:boolean -> b:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 35
|
||||
return 35
|
||||
]
|
||||
+error: main: missing type for x in 'y:number <- foo x'
|
||||
+error: main: failed to find a matching call for 'y:number <- foo x'
|
||||
|
|
|
@ -5,7 +5,7 @@ container foo:_t [
|
|||
x:_t
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo:number <- merge 12, 13
|
||||
3:foo:point <- merge 14, 15, 16
|
||||
]
|
||||
|
@ -21,7 +21,7 @@ container foo:_a:_b [
|
|||
x:_a
|
||||
y:_b
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo:number:boolean <- merge 34, 1/true
|
||||
]
|
||||
$error: 0
|
||||
|
@ -31,7 +31,7 @@ container foo:_a:_b [
|
|||
x:_a
|
||||
y:_b
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:array:character <- new [abc]
|
||||
# compound types for type ingredients
|
||||
{2: (foo number (address shared array character))} <- merge 34/x, 1:address:shared:array:character/y
|
||||
|
@ -47,7 +47,7 @@ container bar:_a:_b [
|
|||
# dilated element
|
||||
{data: (foo _a (address shared _b))}
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:bar:number:array:character <- merge 34/x, 1:address:shared:array:character/y
|
||||
]
|
||||
|
@ -112,7 +112,7 @@ exclusive-container foo:_t [
|
|||
x:_t
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo:number <- merge 0/x, 34
|
||||
3:foo:point <- merge 0/x, 15, 16
|
||||
6:foo:point <- merge 1/y, 23
|
||||
|
@ -157,7 +157,7 @@ container foo:_t [
|
|||
x:_t
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo:point <- merge 14, 15, 16
|
||||
2:number <- get 1:foo:point, y:offset
|
||||
]
|
||||
|
@ -178,7 +178,7 @@ container foo:_t [
|
|||
x:_t
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo:point <- merge 14, 15, 16
|
||||
2:point <- get 1:foo:point, x:offset
|
||||
]
|
||||
|
@ -190,7 +190,7 @@ container foo:_t [
|
|||
x:_t
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo:address:point <- merge 34/unsafe, 48
|
||||
2:address:point <- get 1:foo:address:point, x:offset
|
||||
]
|
||||
|
@ -205,7 +205,7 @@ container bar [
|
|||
x:foo:point
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:bar <- merge 14, 15, 16, 17
|
||||
2:number <- get 1:bar, 1:offset
|
||||
]
|
||||
|
@ -216,7 +216,7 @@ container foo:_a:_b [
|
|||
x:_a
|
||||
y:_b
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:array:character <- new [abc]
|
||||
{2: (foo number (address shared array character))} <- merge 34/x, 1:address:shared:array:character/y
|
||||
3:address:shared:array:character <- get {2: (foo number (address shared array character))}, y:offset
|
||||
|
@ -488,7 +488,7 @@ container foo:_t [
|
|||
x:_t
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
10:foo:point <- merge 14, 15, 16
|
||||
1:number <- get 10:foo, 1:offset
|
||||
]
|
||||
|
@ -501,7 +501,7 @@ container foo:_t [
|
|||
x:_t
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
10:foo:point <- merge 14, 15, 16
|
||||
1:address:number <- get-address 10:foo:point, 1:offset
|
||||
]
|
||||
|
@ -528,7 +528,7 @@ exclusive-container bar [
|
|||
x:number
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo:bar <- merge 23, 1/y, 34
|
||||
]
|
||||
+mem: storing 23 in location 1
|
||||
|
@ -546,7 +546,7 @@ exclusive-container bar [
|
|||
x:number
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo:bar <- merge 23, 1/y, 34, 35
|
||||
]
|
||||
+error: main: too many ingredients in '1:foo:bar <- merge 23, 1/y, 34, 35'
|
||||
|
@ -560,7 +560,7 @@ container bar [
|
|||
x:number
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo:bar <- merge 1/y, 23, 34
|
||||
]
|
||||
+mem: storing 1 in location 1
|
||||
|
@ -577,7 +577,7 @@ container bar [
|
|||
x:number
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo:bar <- merge 0/x, 23
|
||||
]
|
||||
$error: 0
|
||||
|
@ -592,7 +592,7 @@ container bar [
|
|||
x:number
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo:bar <- merge 1/y, 23
|
||||
]
|
||||
+error: main: too few ingredients in '1:foo:bar <- merge 1/y, 23'
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
//:: Like container definitions, recipes too can contain type parameters.
|
||||
|
||||
:(scenario shape_shifting_recipe)
|
||||
recipe main [
|
||||
def main [
|
||||
10:point <- merge 14, 15
|
||||
11:point <- foo 10:point
|
||||
]
|
||||
# non-matching variant
|
||||
recipe foo a:number -> result:number [
|
||||
def foo a:number -> result:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- copy 34
|
||||
]
|
||||
# matching shape-shifting variant
|
||||
recipe foo a:_t -> result:_t [
|
||||
def foo a:_t -> result:_t [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- copy a
|
||||
|
@ -542,18 +542,18 @@ void ensure_all_concrete_types(/*const*/ reagent& x, const recipe& exemplar) {
|
|||
}
|
||||
|
||||
:(scenario shape_shifting_recipe_2)
|
||||
recipe main [
|
||||
def main [
|
||||
10:point <- merge 14, 15
|
||||
11:point <- foo 10:point
|
||||
]
|
||||
# non-matching shape-shifting variant
|
||||
recipe foo a:_t, b:_t -> result:number [
|
||||
def foo a:_t, b:_t -> result:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- copy 34
|
||||
]
|
||||
# matching shape-shifting variant
|
||||
recipe foo a:_t -> result:_t [
|
||||
def foo a:_t -> result:_t [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- copy a
|
||||
|
@ -562,12 +562,12 @@ recipe foo a:_t -> result:_t [
|
|||
+mem: storing 15 in location 12
|
||||
|
||||
:(scenario shape_shifting_recipe_nonroot)
|
||||
recipe main [
|
||||
def main [
|
||||
10:foo:point <- merge 14, 15, 16
|
||||
20:point/raw <- bar 10:foo:point
|
||||
]
|
||||
# shape-shifting recipe with type ingredient following some other type
|
||||
recipe bar a:foo:_t -> result:_t [
|
||||
def bar a:foo:_t -> result:_t [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- get a, x:offset
|
||||
|
@ -584,22 +584,22 @@ container c:_a:_b [
|
|||
a:_a
|
||||
b:_b
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
s:address:shared:array:character <- new [abc]
|
||||
{x: (c (address shared array character) number)} <- merge s, 34
|
||||
foo x
|
||||
]
|
||||
recipe foo x:c:_bar:_baz [
|
||||
def foo x:c:_bar:_baz [
|
||||
local-scope
|
||||
load-ingredients
|
||||
]
|
||||
|
||||
:(scenario shape_shifting_recipe_type_deduction_ignores_offsets)
|
||||
recipe main [
|
||||
def main [
|
||||
10:foo:point <- merge 14, 15, 16
|
||||
20:point/raw <- bar 10:foo:point
|
||||
]
|
||||
recipe bar a:foo:_t -> result:_t [
|
||||
def bar a:foo:_t -> result:_t [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:number <- copy 1
|
||||
|
@ -613,16 +613,16 @@ container foo:_t [
|
|||
+mem: storing 15 in location 21
|
||||
|
||||
:(scenario shape_shifting_recipe_empty)
|
||||
recipe main [
|
||||
def main [
|
||||
foo 1
|
||||
]
|
||||
# shape-shifting recipe with no body
|
||||
recipe foo a:_t [
|
||||
def foo a:_t [
|
||||
]
|
||||
# shouldn't crash
|
||||
|
||||
:(scenario shape_shifting_recipe_handles_shape_shifting_new_ingredient)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:foo:point <- bar 3
|
||||
11:foo:point <- copy *1:address:shared:foo:point
|
||||
]
|
||||
|
@ -630,7 +630,7 @@ container foo:_t [
|
|||
x:_t
|
||||
y:number
|
||||
]
|
||||
recipe bar x:number -> result:address:shared:foo:_t [
|
||||
def bar x:number -> result:address:shared:foo:_t [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# new refers to _t in its ingredient *value*
|
||||
|
@ -641,11 +641,11 @@ recipe bar x:number -> result:address:shared:foo:_t [
|
|||
+mem: storing 0 in location 13
|
||||
|
||||
:(scenario shape_shifting_recipe_handles_shape_shifting_new_ingredient_2)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:foo:point <- bar 3
|
||||
11:foo:point <- copy *1:address:shared:foo:point
|
||||
]
|
||||
recipe bar x:number -> result:address:shared:foo:_t [
|
||||
def bar x:number -> result:address:shared:foo:_t [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# new refers to _t in its ingredient *value*
|
||||
|
@ -661,14 +661,14 @@ container foo:_t [
|
|||
+mem: storing 0 in location 13
|
||||
|
||||
:(scenario shape_shifting_recipe_supports_compound_types)
|
||||
recipe main [
|
||||
def main [
|
||||
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: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 [
|
||||
def bar a:_t -> result:_t [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- copy a
|
||||
|
@ -677,26 +677,26 @@ recipe bar a:_t -> result:_t [
|
|||
|
||||
:(scenario shape_shifting_recipe_error)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
a:number <- copy 3
|
||||
b:address:shared:number <- foo a
|
||||
]
|
||||
recipe foo a:_t -> b:_t [
|
||||
def foo a:_t -> b:_t [
|
||||
load-ingredients
|
||||
b <- copy a
|
||||
]
|
||||
+error: main: no call found for 'b:address:shared:number <- foo a'
|
||||
|
||||
:(scenario specialize_inside_recipe_without_header)
|
||||
recipe main [
|
||||
def main [
|
||||
foo 3
|
||||
]
|
||||
recipe foo [
|
||||
def foo [
|
||||
local-scope
|
||||
x:number <- next-ingredient # ensure no header
|
||||
1:number/raw <- bar x # call a shape-shifting recipe
|
||||
]
|
||||
recipe bar x:_elem -> y:_elem [
|
||||
def bar x:_elem -> y:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- add x, 1
|
||||
|
@ -704,12 +704,12 @@ recipe bar x:_elem -> y:_elem [
|
|||
+mem: storing 4 in location 1
|
||||
|
||||
:(scenario specialize_with_literal)
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
# permit literal to map to number
|
||||
1:number/raw <- foo 3
|
||||
]
|
||||
recipe foo x:_elem -> y:_elem [
|
||||
def foo x:_elem -> y:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- add x, 1
|
||||
|
@ -717,12 +717,12 @@ recipe foo x:_elem -> y:_elem [
|
|||
+mem: storing 4 in location 1
|
||||
|
||||
:(scenario specialize_with_literal_2)
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
# permit literal to map to character
|
||||
1:character/raw <- foo 3
|
||||
]
|
||||
recipe foo x:_elem -> y:_elem [
|
||||
def foo x:_elem -> y:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- add x, 1
|
||||
|
@ -730,12 +730,12 @@ recipe foo x:_elem -> y:_elem [
|
|||
+mem: storing 4 in location 1
|
||||
|
||||
:(scenario specialize_with_literal_3)
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
# permit '0' to map to address to shape-shifting type-ingredient
|
||||
1:address:shared:character/raw <- foo 0
|
||||
]
|
||||
recipe foo x:address:_elem -> y:address:_elem [
|
||||
def foo x:address:_elem -> y:address:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- copy x
|
||||
|
@ -745,12 +745,12 @@ $error: 0
|
|||
|
||||
:(scenario specialize_with_literal_4)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
# ambiguous call: what's the type of its ingredient?!
|
||||
foo 0
|
||||
]
|
||||
recipe foo x:address:_elem -> y:address:_elem [
|
||||
def foo x:address:_elem -> y:address:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- copy x
|
||||
|
@ -759,10 +759,10 @@ recipe foo x:address:_elem -> y:address:_elem [
|
|||
+error: foo: failed to map a type to y
|
||||
|
||||
:(scenario specialize_with_literal_5)
|
||||
recipe main [
|
||||
def main [
|
||||
foo 3, 4 # recipe mapping two variables to literals
|
||||
]
|
||||
recipe foo x:_elem, y:_elem [
|
||||
def foo x:_elem, y:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
1:number/raw <- add x, y
|
||||
|
@ -771,22 +771,22 @@ recipe foo x:_elem, y:_elem [
|
|||
|
||||
:(scenario multiple_shape_shifting_variants)
|
||||
# try to call two different shape-shifting recipes with the same name
|
||||
recipe main [
|
||||
def main [
|
||||
e1:d1:number <- merge 3
|
||||
e2:d2:number <- merge 4, 5
|
||||
1:number/raw <- foo e1
|
||||
2:number/raw <- foo e2
|
||||
]
|
||||
# the two shape-shifting definitions
|
||||
recipe foo a:d1:_elem -> b:number [
|
||||
def foo a:d1:_elem -> b:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 34
|
||||
return 34
|
||||
]
|
||||
recipe foo a:d2:_elem -> b:number [
|
||||
def foo a:d2:_elem -> b:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 35
|
||||
return 35
|
||||
]
|
||||
# the shape-shifting containers they use
|
||||
container d1:_elem [
|
||||
|
@ -801,21 +801,21 @@ container d2:_elem [
|
|||
|
||||
:(scenario multiple_shape_shifting_variants_2)
|
||||
# static dispatch between shape-shifting variants, _including pointer lookups_
|
||||
recipe main [
|
||||
def main [
|
||||
e1:d1:number <- merge 3
|
||||
e2:address:shared:d2:number <- new {(d2 number): type}
|
||||
1:number/raw <- foo e1
|
||||
2:number/raw <- foo *e2 # different from previous scenario
|
||||
]
|
||||
recipe foo a:d1:_elem -> b:number [
|
||||
def foo a:d1:_elem -> b:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 34
|
||||
return 34
|
||||
]
|
||||
recipe foo a:d2:_elem -> b:number [
|
||||
def foo a:d2:_elem -> b:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 35
|
||||
return 35
|
||||
]
|
||||
container d1:_elem [
|
||||
x:_elem
|
||||
|
@ -829,15 +829,15 @@ container d2:_elem [
|
|||
|
||||
:(scenario missing_type_in_shape_shifting_recipe)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
a:d1:number <- merge 3
|
||||
foo a
|
||||
]
|
||||
recipe foo a:d1:_elem -> b:number [
|
||||
def foo a:d1:_elem -> b:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
copy e # no such variable
|
||||
reply 34
|
||||
return 34
|
||||
]
|
||||
container d1:_elem [
|
||||
x:_elem
|
||||
|
@ -848,15 +848,15 @@ container d1:_elem [
|
|||
|
||||
:(scenario missing_type_in_shape_shifting_recipe_2)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
a:d1:number <- merge 3
|
||||
foo a
|
||||
]
|
||||
recipe foo a:d1:_elem -> b:number [
|
||||
def foo a:d1:_elem -> b:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
get e, x:offset # unknown variable in a 'get', which does some extra checking
|
||||
reply 34
|
||||
return 34
|
||||
]
|
||||
container d1:_elem [
|
||||
x:_elem
|
||||
|
@ -867,108 +867,108 @@ container d1:_elem [
|
|||
|
||||
:(scenarios transform)
|
||||
:(scenario specialize_recursive_shape_shifting_recipe)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 34
|
||||
2:number <- foo 1:number
|
||||
]
|
||||
recipe foo x:_elem -> y:number [
|
||||
def foo x:_elem -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
break
|
||||
y:number <- foo x
|
||||
}
|
||||
reply y
|
||||
return y
|
||||
]
|
||||
+transform: new specialization: foo_2
|
||||
# transform terminates
|
||||
|
||||
:(scenarios run)
|
||||
:(scenario specialize_most_similar_variant)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:number <- new number:type
|
||||
2:number <- foo 1:address:shared:number
|
||||
]
|
||||
recipe foo x:_elem -> y:number [
|
||||
def foo x:_elem -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 34
|
||||
return 34
|
||||
]
|
||||
recipe foo x:address:shared:_elem -> y:number [
|
||||
def foo x:address:shared:_elem -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 35
|
||||
return 35
|
||||
]
|
||||
+mem: storing 35 in location 2
|
||||
|
||||
:(scenario specialize_most_similar_variant_2)
|
||||
# version with headers padded with lots of unrelated concrete types
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- copy 23
|
||||
2:address:shared:array:number <- copy 0
|
||||
3:number <- foo 2:address:shared:array:number, 1:number
|
||||
]
|
||||
# variant with concrete type
|
||||
recipe foo dummy:address:shared:array:number, x:number -> y:number, dummy:address:shared:array:number [
|
||||
def foo dummy:address:shared:array:number, x:number -> y:number, dummy:address:shared:array:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 34
|
||||
return 34
|
||||
]
|
||||
# shape-shifting variant
|
||||
recipe foo dummy:address:shared:array:number, x:_elem -> y:number, dummy:address:shared:array:number [
|
||||
def foo dummy:address:shared:array:number, x:_elem -> y:number, dummy:address:shared:array:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 35
|
||||
return 35
|
||||
]
|
||||
# prefer the concrete variant
|
||||
+mem: storing 34 in location 3
|
||||
|
||||
:(scenario specialize_most_similar_variant_3)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:array:character <- new [abc]
|
||||
foo 1:address:shared:array:character
|
||||
]
|
||||
recipe foo x:address:shared:array:character [
|
||||
def foo x:address:shared:array:character [
|
||||
2:number <- copy 34
|
||||
]
|
||||
recipe foo x:address:_elem [
|
||||
def foo x:address:_elem [
|
||||
2:number <- copy 35
|
||||
]
|
||||
# make sure the more precise version was used
|
||||
+mem: storing 34 in location 2
|
||||
|
||||
:(scenario specialize_literal_as_number)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- foo 23
|
||||
]
|
||||
recipe foo x:_elem -> y:number [
|
||||
def foo x:_elem -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 34
|
||||
return 34
|
||||
]
|
||||
recipe foo x:character -> y:number [
|
||||
def foo x:character -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 35
|
||||
return 35
|
||||
]
|
||||
+mem: storing 34 in location 1
|
||||
|
||||
:(scenario specialize_literal_as_number_2)
|
||||
# version calling with literal
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- foo 0
|
||||
]
|
||||
# variant with concrete type
|
||||
recipe foo x:number -> y:number [
|
||||
def foo x:number -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 34
|
||||
return 34
|
||||
]
|
||||
# shape-shifting variant
|
||||
recipe foo x:address:shared:_elem -> y:number [
|
||||
def foo x:address:shared:_elem -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply 35
|
||||
return 35
|
||||
]
|
||||
# prefer the concrete variant, ignore concrete types in scoring the shape-shifting variant
|
||||
+mem: storing 34 in location 1
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
//: One hole for now: variables in surrounding spaces are implicitly mutable.
|
||||
|
||||
:(scenario can_modify_value_ingredients)
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
p:address:shared:point <- new point:type
|
||||
foo *p
|
||||
]
|
||||
recipe foo p:point [
|
||||
def foo p:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:address:number <- get-address p, x:offset
|
||||
|
@ -18,12 +18,12 @@ recipe foo p:point [
|
|||
$error: 0
|
||||
|
||||
:(scenario can_modify_ingredients_that_are_also_products)
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
p:address:shared:point <- new point:type
|
||||
p <- foo p
|
||||
]
|
||||
recipe foo p:address:shared:point -> p:address:shared:point [
|
||||
def foo p:address:shared:point -> p:address:shared:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:address:number <- get-address *p, x:offset
|
||||
|
@ -32,12 +32,12 @@ recipe foo p:address:shared:point -> p:address:shared:point [
|
|||
$error: 0
|
||||
|
||||
:(scenario ignore_literal_ingredients_for_immutability_checks)
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
p:address:shared:d1 <- new d1:type
|
||||
q:number <- foo p
|
||||
]
|
||||
recipe foo p:address:shared:d1 -> q:number [
|
||||
def foo p:address:shared:d1 -> q:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:address:shared:d1 <- new d1:type
|
||||
|
@ -52,12 +52,12 @@ $error: 0
|
|||
|
||||
:(scenario cannot_modify_immutable_ingredients)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
x:address:shared:number <- new number:type
|
||||
foo x
|
||||
]
|
||||
recipe foo x:address:shared:number [
|
||||
def foo x:address:shared:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
*x <- copy 34
|
||||
|
@ -66,12 +66,12 @@ recipe foo x:address:shared:number [
|
|||
|
||||
:(scenario cannot_take_address_inside_immutable_ingredients)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
p:address:shared:point <- new point:type
|
||||
foo p
|
||||
]
|
||||
recipe foo p:address:shared:point [
|
||||
def foo p:address:shared:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:address:number <- get-address *p, x:offset
|
||||
|
@ -81,17 +81,17 @@ recipe foo p:address:shared:point [
|
|||
|
||||
:(scenario cannot_call_mutating_recipes_on_immutable_ingredients)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
p:address:shared:point <- new point:type
|
||||
foo p
|
||||
]
|
||||
recipe foo p:address:shared:point [
|
||||
def foo p:address:shared:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
bar p
|
||||
]
|
||||
recipe bar p:address:shared:point -> p:address:shared:point [
|
||||
def bar p:address:shared:point -> p:address:shared:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:address:number <- get-address *p, x:offset
|
||||
|
@ -101,12 +101,12 @@ recipe bar p:address:shared:point -> p:address:shared:point [
|
|||
|
||||
:(scenario cannot_modify_copies_of_immutable_ingredients)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
p:address:shared:point <- new point:type
|
||||
foo p
|
||||
]
|
||||
recipe foo p:address:shared:point [
|
||||
def foo p:address:shared:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
q:address:shared:point <- copy p
|
||||
|
@ -115,12 +115,12 @@ recipe foo p:address:shared:point [
|
|||
+error: 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
|
||||
|
||||
:(scenario can_modify_copies_of_mutable_ingredients)
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
p:address:shared:point <- new point:type
|
||||
foo p
|
||||
]
|
||||
recipe foo p:address:shared:point -> p:address:shared:point [
|
||||
def foo p:address:shared:point -> p:address:shared:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
q:address:shared:point <- copy p
|
||||
|
@ -133,10 +133,10 @@ $error: 0
|
|||
container foo [
|
||||
x:address:shared:array:number # contains an address
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
# don't run anything
|
||||
]
|
||||
recipe foo a:address:shared:foo [
|
||||
def foo a:address:shared:foo [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:address:shared:array:number <- get *a, x:offset # just a regular get of the container
|
||||
|
@ -149,10 +149,10 @@ recipe foo a:address:shared:foo [
|
|||
container foo [
|
||||
x:address:shared:array:number # contains an address
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
# don't run anything
|
||||
]
|
||||
recipe foo a:address:shared:foo [
|
||||
def foo a:address:shared:foo [
|
||||
local-scope
|
||||
load-ingredients
|
||||
b:foo <- merge 0 # completely unrelated to 'a'
|
||||
|
@ -167,10 +167,10 @@ $error: 0
|
|||
container foo [
|
||||
x:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
# don't run anything
|
||||
]
|
||||
recipe foo a:address:shared:array:address:number [
|
||||
def foo a:address:shared:array:address:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
x:address:number <- index *a, 0 # just a regular index of the array
|
||||
|
@ -183,10 +183,10 @@ recipe foo a:address:shared:array:address:number [
|
|||
container foo [
|
||||
x:address:shared:array:number # contains an address
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
# don't run anything
|
||||
]
|
||||
recipe foo a:address:shared:array:address:number [
|
||||
def foo a:address:shared:array:address:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
b:address:shared:array:address:number <- new {(address number): type}, 3 # completely unrelated to 'a'
|
||||
|
@ -199,17 +199,17 @@ $error: 0
|
|||
container test-list [
|
||||
next:address:shared:test-list
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
p:address:shared:test-list <- new test-list:type
|
||||
foo p
|
||||
]
|
||||
recipe foo p:address:shared:test-list [
|
||||
def foo p:address:shared:test-list [
|
||||
local-scope
|
||||
load-ingredients
|
||||
p2:address:shared:test-list <- bar p
|
||||
]
|
||||
recipe bar x:address:shared:test-list -> y:address:shared:test-list [
|
||||
def bar x:address:shared:test-list -> y:address:shared:test-list [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- get *x, next:offset
|
||||
|
@ -217,18 +217,18 @@ recipe bar x:address:shared:test-list -> y:address:shared:test-list [
|
|||
$error: 0
|
||||
|
||||
:(scenario handle_optional_ingredients_in_immutability_checks)
|
||||
recipe main [
|
||||
def main [
|
||||
k:address:shared:number <- new number:type
|
||||
test k
|
||||
]
|
||||
# recipe taking an immutable address ingredient
|
||||
recipe test k:address:shared:number [
|
||||
def test k:address:shared:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
foo k
|
||||
]
|
||||
# ..calling a recipe with an optional address ingredient
|
||||
recipe foo -> [
|
||||
def foo -> [
|
||||
local-scope
|
||||
load-ingredients
|
||||
k:address:shared:number, found?:boolean <- next-ingredient
|
||||
|
@ -237,17 +237,17 @@ $error: 0
|
|||
|
||||
//: when checking for immutable ingredients, remember to take space into account
|
||||
:(scenario check_space_of_reagents_in_immutability_checks)
|
||||
recipe main [
|
||||
def main [
|
||||
a:address:shared:array:location <- new-closure
|
||||
b:address:shared:number <- new number:type
|
||||
run-closure b:address:shared:number, a:address:shared:array:location
|
||||
]
|
||||
recipe new-closure [
|
||||
def new-closure [
|
||||
new-default-space
|
||||
x:address:shared:number <- new number:type
|
||||
reply default-space
|
||||
return default-space
|
||||
]
|
||||
recipe run-closure x:address:shared:number, s:address:shared:array:location [
|
||||
def run-closure x:address:shared:number, s:address:shared:array:location [
|
||||
local-scope
|
||||
load-ingredients
|
||||
0:address:shared:array:location/names:new-closure <- copy s
|
||||
|
@ -336,18 +336,18 @@ set<long long int> scan_contained_in_product_indices(const instruction& inst, se
|
|||
container test-list [
|
||||
next:address:shared:test-list
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
p:address:shared:test-list <- new test-list:type
|
||||
foo p
|
||||
]
|
||||
recipe foo p:address:shared:test-list [ # p is immutable
|
||||
def foo p:address:shared:test-list [ # p is immutable
|
||||
local-scope
|
||||
load-ingredients
|
||||
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:shared:test-list -> y:address:shared:test-list/contained-in:x [
|
||||
def test-next x:address:shared:test-list -> y:address:shared:test-list/contained-in:x [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- get *x, next:offset
|
||||
|
@ -447,23 +447,23 @@ set<long long int> ingredient_indices(const instruction& inst, const set<reagent
|
|||
container test-list [
|
||||
next:address:shared:test-list
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
p:address:shared:test-list <- new test-list:type
|
||||
foo p
|
||||
]
|
||||
recipe foo p:address:shared:test-list -> p:address:shared:test-list [
|
||||
def foo p:address:shared:test-list -> p:address:shared:test-list [
|
||||
local-scope
|
||||
load-ingredients
|
||||
p2:address:shared:test-list <- test-next p
|
||||
p <- test-remove p2, p
|
||||
]
|
||||
recipe test-next x:address:shared:test-list -> y:address:shared:test-list [
|
||||
def 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:shared:test-list/contained-in:from, from:address:shared:test-list -> from:address:shared:test-list [
|
||||
def 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:shared:test-list <- get-address *x, next:offset # pretend modification
|
||||
|
|
24
061recipe.cc
|
@ -5,10 +5,10 @@
|
|||
//: todo: support storing shape-shifting recipes into recipe variables and calling them
|
||||
|
||||
:(scenario call_literal_recipe)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- call f, 34
|
||||
]
|
||||
recipe f x:number -> y:number [
|
||||
def f x:number -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- copy x
|
||||
|
@ -16,11 +16,11 @@ recipe f x:number -> y:number [
|
|||
+mem: storing 34 in location 1
|
||||
|
||||
:(scenario call_variable)
|
||||
recipe main [
|
||||
def main [
|
||||
{1: (recipe number -> number)} <- copy f
|
||||
2:number <- call {1: (recipe number -> number)}, 34
|
||||
]
|
||||
recipe f x:number -> y:number [
|
||||
def f x:number -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- copy x
|
||||
|
@ -75,10 +75,10 @@ case CALL: {
|
|||
|
||||
:(scenario call_check_literal_recipe)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- call f, 34
|
||||
]
|
||||
recipe f x:point -> y:point [
|
||||
def f x:point -> y:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- copy x
|
||||
|
@ -88,11 +88,11 @@ recipe f x:point -> y:point [
|
|||
|
||||
:(scenario call_check_variable_recipe)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
{1: (recipe point -> point)} <- copy f
|
||||
2:number <- call {1: (recipe point -> point)}, 34
|
||||
]
|
||||
recipe f x:point -> y:point [
|
||||
def f x:point -> y:point [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- copy x
|
||||
|
@ -153,12 +153,12 @@ bool is_mu_recipe(reagent r) {
|
|||
|
||||
:(scenario copy_typecheck_recipe_variable)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
3:number <- copy 34 # abc def
|
||||
{1: (recipe number -> number)} <- copy f # store literal in a matching variable
|
||||
{2: (recipe boolean -> boolean)} <- copy {1: (recipe number -> number)} # mismatch between recipe variables
|
||||
]
|
||||
recipe f x:number -> y:number [
|
||||
def f x:number -> y:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- copy x
|
||||
|
@ -167,10 +167,10 @@ recipe f x:number -> y:number [
|
|||
|
||||
:(scenario copy_typecheck_recipe_variable_2)
|
||||
% Hide_errors = true;
|
||||
recipe main [
|
||||
def main [
|
||||
{1: (recipe number -> number)} <- copy f # mismatch with a recipe literal
|
||||
]
|
||||
recipe f x:boolean -> y:boolean [
|
||||
def f x:boolean -> y:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- copy x
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
//: guarantees on how the operations in each are interleaved with each other.
|
||||
|
||||
:(scenario scheduler)
|
||||
recipe f1 [
|
||||
def f1 [
|
||||
start-running f2
|
||||
# wait for f2 to run
|
||||
{
|
||||
jump-unless 1:number, -1
|
||||
}
|
||||
]
|
||||
recipe f2 [
|
||||
def f2 [
|
||||
1:number <- copy 1
|
||||
]
|
||||
+schedule: f1
|
||||
|
@ -181,7 +181,7 @@ case START_RUNNING: {
|
|||
|
||||
:(scenario scheduler_runs_single_routine)
|
||||
% Scheduling_interval = 1;
|
||||
recipe f1 [
|
||||
def f1 [
|
||||
1:number <- copy 0
|
||||
2:number <- copy 0
|
||||
]
|
||||
|
@ -192,12 +192,12 @@ recipe f1 [
|
|||
|
||||
:(scenario scheduler_interleaves_routines)
|
||||
% Scheduling_interval = 1;
|
||||
recipe f1 [
|
||||
def f1 [
|
||||
start-running f2
|
||||
1:number <- copy 0
|
||||
2:number <- copy 0
|
||||
]
|
||||
recipe f2 [
|
||||
def f2 [
|
||||
3:number <- copy 0
|
||||
4:number <- copy 0
|
||||
]
|
||||
|
@ -213,24 +213,24 @@ recipe f2 [
|
|||
+run: 2:number <- copy 0
|
||||
|
||||
:(scenario start_running_takes_ingredients)
|
||||
recipe f1 [
|
||||
def f1 [
|
||||
start-running f2, 3
|
||||
# wait for f2 to run
|
||||
{
|
||||
jump-unless 1:number, -1
|
||||
}
|
||||
]
|
||||
recipe f2 [
|
||||
def f2 [
|
||||
1:number <- next-ingredient
|
||||
2:number <- add 1:number, 1
|
||||
]
|
||||
+mem: storing 4 in location 2
|
||||
|
||||
:(scenario start_running_returns_routine_id)
|
||||
recipe f1 [
|
||||
def f1 [
|
||||
1:number <- start-running f2
|
||||
]
|
||||
recipe f2 [
|
||||
def f2 [
|
||||
12:number <- copy 44
|
||||
]
|
||||
+mem: storing 2 in location 1
|
||||
|
@ -244,7 +244,7 @@ recipe f2 [
|
|||
% Routines.push_back(new routine(f2));
|
||||
% Routines.back()->state = COMPLETED; // f2 not meant to run
|
||||
# must have at least one routine without escaping
|
||||
recipe f3 [
|
||||
def f3 [
|
||||
3:number <- copy 0
|
||||
]
|
||||
# by interleaving '+' lines with '-' lines, we allow f1 and f3 to run in any order
|
||||
|
@ -258,7 +258,7 @@ recipe f3 [
|
|||
:(scenario scheduler_starts_at_middle_of_routines)
|
||||
% Routines.push_back(new routine(COPY));
|
||||
% Routines.back()->state = COMPLETED;
|
||||
recipe f1 [
|
||||
def f1 [
|
||||
1:number <- copy 0
|
||||
2:number <- copy 0
|
||||
]
|
||||
|
@ -270,12 +270,12 @@ recipe f1 [
|
|||
:(scenario scheduler_terminates_routines_after_errors)
|
||||
% Hide_errors = true;
|
||||
% Scheduling_interval = 2;
|
||||
recipe f1 [
|
||||
def f1 [
|
||||
start-running f2
|
||||
1:number <- copy 0
|
||||
2:number <- copy 0
|
||||
]
|
||||
recipe f2 [
|
||||
def f2 [
|
||||
# divide by 0 twice
|
||||
3:number <- divide-with-remainder 4, 0
|
||||
4:number <- divide-with-remainder 4, 0
|
||||
|
@ -292,11 +292,11 @@ recipe f2 [
|
|||
//:: Routines are marked completed when their parent completes.
|
||||
|
||||
:(scenario scheduler_kills_orphans)
|
||||
recipe main [
|
||||
def main [
|
||||
start-running f1
|
||||
# f1 never actually runs because its parent completes without waiting for it
|
||||
]
|
||||
recipe f1 [
|
||||
def f1 [
|
||||
1:number <- copy 0
|
||||
]
|
||||
-schedule: f1
|
||||
|
@ -323,13 +323,13 @@ bool has_completed_parent(long long int routine_index) {
|
|||
|
||||
:(scenario routine_state_test)
|
||||
% Scheduling_interval = 2;
|
||||
recipe f1 [
|
||||
def f1 [
|
||||
1:number/child-id <- start-running f2
|
||||
12:number <- copy 0 # race condition since we don't care about location 12
|
||||
# thanks to Scheduling_interval, f2's one instruction runs in between here and completes
|
||||
2:number/state <- routine-state 1:number/child-id
|
||||
]
|
||||
recipe f2 [
|
||||
def f2 [
|
||||
12:number <- copy 0
|
||||
# trying to run a second instruction marks routine as completed
|
||||
]
|
||||
|
@ -445,7 +445,7 @@ case _DUMP_ROUTINES: {
|
|||
|
||||
:(scenario routine_discontinues_past_limit)
|
||||
% Scheduling_interval = 2;
|
||||
recipe f1 [
|
||||
def f1 [
|
||||
1:number/child-id <- start-running f2
|
||||
limit-time 1:number/child-id, 10
|
||||
# padding loop just to make sure f2 has time to completed
|
||||
|
@ -453,7 +453,7 @@ recipe f1 [
|
|||
2:number <- subtract 2:number, 1
|
||||
jump-if 2:number, -2:offset
|
||||
]
|
||||
recipe f2 [
|
||||
def f2 [
|
||||
jump -1:offset # run forever
|
||||
$print [should never get here], 10/newline
|
||||
]
|
||||
|
@ -514,7 +514,7 @@ case LIMIT_TIME: {
|
|||
//:: make sure that each routine gets a different alloc to start
|
||||
|
||||
:(scenario new_concurrent)
|
||||
recipe f1 [
|
||||
def f1 [
|
||||
start-running f2
|
||||
1:address:shared:number/raw <- new number:type
|
||||
# wait for f2 to complete
|
||||
|
@ -522,7 +522,7 @@ recipe f1 [
|
|||
loop-unless 4:number/raw
|
||||
}
|
||||
]
|
||||
recipe f2 [
|
||||
def f2 [
|
||||
2:address:shared:number/raw <- new number:type
|
||||
# hack: assumes scheduler implementation
|
||||
3:boolean/raw <- equal 1:address:shared:number/raw, 2:address:shared:number/raw
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
//: operate.
|
||||
|
||||
:(scenario wait_for_location)
|
||||
recipe f1 [
|
||||
def f1 [
|
||||
1:number <- copy 0
|
||||
start-running f2
|
||||
wait-for-location 1:number
|
||||
# now wait for f2 to run and modify location 1 before using its value
|
||||
2:number <- copy 1:number
|
||||
]
|
||||
recipe f2 [
|
||||
def f2 [
|
||||
1:number <- copy 34
|
||||
]
|
||||
# if we got the synchronization wrong we'd be storing 0 in location 2
|
||||
|
@ -65,14 +65,14 @@ for (long long int i = 0; i < SIZE(Routines); ++i) {
|
|||
//: also allow waiting on a routine to stop running
|
||||
|
||||
:(scenario wait_for_routine)
|
||||
recipe f1 [
|
||||
def f1 [
|
||||
1:number <- copy 0
|
||||
12:number/routine <- start-running f2
|
||||
wait-for-routine 12:number/routine
|
||||
# now wait for f2 to run and modify location 1 before using its value
|
||||
3:number <- copy 1:number
|
||||
]
|
||||
recipe f2 [
|
||||
def f2 [
|
||||
1:number <- copy 34
|
||||
]
|
||||
+schedule: f1
|
||||
|
|
146
070text.mu
|
@ -2,20 +2,20 @@
|
|||
|
||||
# to-text-line gets called implicitly in various places
|
||||
# define it to be identical to 'to-text' by default
|
||||
recipe to-text-line x:_elem -> y:address:shared:array:character [
|
||||
def to-text-line x:_elem -> y:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
y <- to-text x
|
||||
]
|
||||
|
||||
# to-text on text is just the identity function
|
||||
recipe to-text x:address:shared:array:character -> y:address:shared:array:character [
|
||||
def to-text x:address:shared:array:character -> y:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply x
|
||||
return x
|
||||
]
|
||||
|
||||
recipe equal a:address:shared:array:character, b:address:shared:array:character -> result:boolean [
|
||||
def equal a:address:shared:array:character, b:address:shared:array:character -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
a-len:number <- length *a
|
||||
|
@ -25,7 +25,7 @@ recipe equal a:address:shared:array:character, b:address:shared:array:character
|
|||
trace 99, [text-equal], [comparing lengths]
|
||||
length-equal?:boolean <- equal a-len, b-len
|
||||
break-if length-equal?
|
||||
reply 0
|
||||
return 0
|
||||
}
|
||||
# compare each corresponding character
|
||||
trace 99, [text-equal], [comparing characters]
|
||||
|
@ -38,12 +38,12 @@ recipe equal a:address:shared:array:character, b:address:shared:array:character
|
|||
{
|
||||
chars-match?:boolean <- equal a2, b2
|
||||
break-if chars-match?
|
||||
reply 0
|
||||
return 0
|
||||
}
|
||||
i <- add i, 1
|
||||
loop
|
||||
}
|
||||
reply 1
|
||||
return 1
|
||||
]
|
||||
|
||||
scenario text-equal-reflexive [
|
||||
|
@ -117,7 +117,7 @@ container buffer [
|
|||
data:address:shared:array:character
|
||||
]
|
||||
|
||||
recipe new-buffer capacity:number -> result:address:shared:buffer [
|
||||
def new-buffer capacity:number -> result:address:shared:buffer [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- new buffer:type
|
||||
|
@ -125,10 +125,10 @@ recipe new-buffer capacity:number -> result:address:shared:buffer [
|
|||
*len:address:number <- copy 0
|
||||
s:address:address:shared:array:character <- get-address *result, data:offset
|
||||
*s <- new character:type, capacity
|
||||
reply result
|
||||
return result
|
||||
]
|
||||
|
||||
recipe grow-buffer in:address:shared:buffer -> in:address:shared:buffer [
|
||||
def grow-buffer in:address:shared:buffer -> in:address:shared:buffer [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# double buffer size
|
||||
|
@ -150,7 +150,7 @@ recipe grow-buffer in:address:shared:buffer -> in:address:shared:buffer [
|
|||
}
|
||||
]
|
||||
|
||||
recipe buffer-full? in:address:shared:buffer -> result:boolean [
|
||||
def buffer-full? in:address:shared:buffer -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
len:number <- get *in, length:offset
|
||||
|
@ -160,7 +160,7 @@ recipe buffer-full? in:address:shared:buffer -> result:boolean [
|
|||
]
|
||||
|
||||
# most broadly applicable definition of append to a buffer: just call to-text
|
||||
recipe append buf:address:shared:buffer, x:_elem -> buf:address:shared:buffer [
|
||||
def append buf:address:shared:buffer, x:_elem -> buf:address:shared:buffer [
|
||||
local-scope
|
||||
load-ingredients
|
||||
text:address:shared:array:character <- to-text x
|
||||
|
@ -176,7 +176,7 @@ recipe append buf:address:shared:buffer, x:_elem -> buf:address:shared:buffer [
|
|||
}
|
||||
]
|
||||
|
||||
recipe append in:address:shared:buffer, c:character -> in:address:shared:buffer [
|
||||
def append in:address:shared:buffer, c:character -> in:address:shared:buffer [
|
||||
local-scope
|
||||
load-ingredients
|
||||
len:address:number <- get-address *in, length:offset
|
||||
|
@ -185,9 +185,9 @@ recipe append in:address:shared:buffer, c:character -> in:address:shared:buffer
|
|||
backspace?:boolean <- equal c, 8/backspace
|
||||
break-unless backspace?
|
||||
empty?:boolean <- lesser-or-equal *len, 0
|
||||
reply-if empty?
|
||||
return-if empty?
|
||||
*len <- subtract *len, 1
|
||||
reply
|
||||
return
|
||||
}
|
||||
{
|
||||
# grow buffer if necessary
|
||||
|
@ -263,14 +263,14 @@ scenario buffer-append-handles-backspace [
|
|||
]
|
||||
]
|
||||
|
||||
recipe to-text n:number -> result:address:shared:array:character [
|
||||
def to-text n:number -> result:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# is n zero?
|
||||
{
|
||||
break-if n
|
||||
result <- new [0]
|
||||
reply
|
||||
return
|
||||
}
|
||||
# save sign
|
||||
negate-result:boolean <- copy 0
|
||||
|
@ -317,27 +317,27 @@ recipe to-text n:number -> result:address:shared:array:character [
|
|||
}
|
||||
]
|
||||
|
||||
recipe to-text x:boolean -> result:address:shared:array:character [
|
||||
def to-text x:boolean -> result:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
n:number <- copy x:boolean
|
||||
result <- to-text n
|
||||
]
|
||||
|
||||
recipe to-text x:address:_elem -> result:address:shared:array:character [
|
||||
def to-text x:address:_elem -> result:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
n:number <- copy x
|
||||
result <- to-text n
|
||||
]
|
||||
|
||||
recipe buffer-to-array in:address:shared:buffer -> result:address:shared:array:character [
|
||||
def buffer-to-array in:address:shared:buffer -> result:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
# propagate null buffer
|
||||
break-if in
|
||||
reply 0
|
||||
return 0
|
||||
}
|
||||
len:number <- get *in, length:offset
|
||||
s:address:shared:array:character <- get *in, data:offset
|
||||
|
@ -387,7 +387,7 @@ scenario integer-to-decimal-digit-negative [
|
|||
]
|
||||
]
|
||||
|
||||
recipe append a:address:shared:array:character, b:address:shared:array:character -> result:address:shared:array:character [
|
||||
def append a:address:shared:array:character, b:address:shared:array:character -> result:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# result = new character[a.length + b.length]
|
||||
|
@ -449,13 +449,13 @@ scenario replace-character-in-text [
|
|||
]
|
||||
]
|
||||
|
||||
recipe replace s:address:shared:array:character, oldc:character, newc:character, from:number/optional -> s:address:shared:array:character [
|
||||
def replace s:address:shared:array:character, oldc:character, newc:character, from:number/optional -> s:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
len:number <- length *s
|
||||
i:number <- find-next s, oldc, from
|
||||
done?:boolean <- greater-or-equal i, len
|
||||
reply-if done?, s/same-as-ingredient:0
|
||||
return-if done?, s/same-as-ingredient:0
|
||||
dest:address:character <- index-address *s, i
|
||||
*dest <- copy newc
|
||||
i <- add i, 1
|
||||
|
@ -507,7 +507,7 @@ scenario replace-all-characters [
|
|||
]
|
||||
|
||||
# replace underscores in first with remaining args
|
||||
recipe interpolate template:address:shared:array:character -> result:address:shared:array:character [
|
||||
def interpolate template:address:shared:array:character -> result:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients # consume just the template
|
||||
# compute result-len, space to allocate for result
|
||||
|
@ -621,68 +621,68 @@ scenario interpolate-at-end [
|
|||
]
|
||||
|
||||
# result:boolean <- space? c:character
|
||||
recipe space? c:character -> result:boolean [
|
||||
def space? c:character -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# most common case first
|
||||
result <- equal c, 32/space
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 10/newline
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 9/tab
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 13/carriage-return
|
||||
reply-if result
|
||||
return-if result
|
||||
# remaining uncommon cases in sorted order
|
||||
# http://unicode.org code-points in unicode-set Z and Pattern_White_Space
|
||||
result <- equal c, 11/ctrl-k
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 12/ctrl-l
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 133/ctrl-0085
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 160/no-break-space
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 5760/ogham-space-mark
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 8192/en-quad
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 8193/em-quad
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 8194/en-space
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 8195/em-space
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 8196/three-per-em-space
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 8197/four-per-em-space
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 8198/six-per-em-space
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 8199/figure-space
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 8200/punctuation-space
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 8201/thin-space
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 8202/hair-space
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 8206/left-to-right
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 8207/right-to-left
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 8232/line-separator
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 8233/paragraph-separator
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 8239/narrow-no-break-space
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 8287/medium-mathematical-space
|
||||
reply-if result
|
||||
return-if result
|
||||
result <- equal c, 12288/ideographic-space
|
||||
]
|
||||
|
||||
recipe trim s:address:shared:array:character -> result:address:shared:array:character [
|
||||
def trim s:address:shared:array:character -> result:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
len:number <- length *s
|
||||
|
@ -693,7 +693,7 @@ recipe trim s:address:shared:array:character -> result:address:shared:array:char
|
|||
at-end?:boolean <- greater-or-equal start, len
|
||||
break-unless at-end?
|
||||
result <- new character:type, 0
|
||||
reply
|
||||
return
|
||||
}
|
||||
curr:character <- index *s, start
|
||||
whitespace?:boolean <- space? curr
|
||||
|
@ -788,7 +788,7 @@ scenario trim-newline-tab [
|
|||
]
|
||||
]
|
||||
|
||||
recipe find-next text:address:shared:array:character, pattern:character, idx:number -> next-index:number [
|
||||
def find-next text:address:shared:array:character, pattern:character, idx:number -> next-index:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
len:number <- length *text
|
||||
|
@ -801,7 +801,7 @@ recipe find-next text:address:shared:array:character, pattern:character, idx:num
|
|||
idx <- add idx, 1
|
||||
loop
|
||||
}
|
||||
reply idx
|
||||
return idx
|
||||
]
|
||||
|
||||
scenario text-find-next [
|
||||
|
@ -886,7 +886,7 @@ scenario text-find-next-second [
|
|||
|
||||
# search for a pattern of multiple characters
|
||||
# fairly dumb algorithm
|
||||
recipe find-next text:address:shared:array:character, pattern:address:shared:array:character, idx:number -> next-index:number [
|
||||
def find-next text:address:shared:array:character, pattern:address:shared:array:character, idx:number -> next-index:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
first:character <- index *pattern, 0
|
||||
|
@ -903,7 +903,7 @@ recipe find-next text:address:shared:array:character, pattern:address:shared:arr
|
|||
idx <- find-next text, first, idx
|
||||
loop
|
||||
}
|
||||
reply idx
|
||||
return idx
|
||||
]
|
||||
|
||||
scenario find-next-text-1 [
|
||||
|
@ -962,7 +962,7 @@ scenario find-next-suffix-match-2 [
|
|||
]
|
||||
|
||||
# checks if pattern matches at index 'idx'
|
||||
recipe match-at text:address:shared:array:character, pattern:address:shared:array:character, idx:number -> result:boolean [
|
||||
def match-at text:address:shared:array:character, pattern:address:shared:array:character, idx:number -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
pattern-len:number <- length *pattern
|
||||
|
@ -972,7 +972,7 @@ recipe match-at text:address:shared:array:character, pattern:address:shared:arra
|
|||
x <- subtract x, pattern-len
|
||||
enough-room?:boolean <- lesser-or-equal idx, x
|
||||
break-if enough-room?
|
||||
reply 0/not-found
|
||||
return 0/not-found
|
||||
}
|
||||
# check each character of pattern
|
||||
pattern-idx:number <- copy 0
|
||||
|
@ -984,13 +984,13 @@ recipe match-at text:address:shared:array:character, pattern:address:shared:arra
|
|||
{
|
||||
match?:boolean <- equal c, exp
|
||||
break-if match?
|
||||
reply 0/not-found
|
||||
return 0/not-found
|
||||
}
|
||||
idx <- add idx, 1
|
||||
pattern-idx <- add pattern-idx, 1
|
||||
loop
|
||||
}
|
||||
reply 1/found
|
||||
return 1/found
|
||||
]
|
||||
|
||||
scenario match-at-checks-pattern-at-index [
|
||||
|
@ -1090,7 +1090,7 @@ scenario match-at-inside-bounds-2 [
|
|||
]
|
||||
]
|
||||
|
||||
recipe split s:address:shared:array:character, delim:character -> result:address:shared:array:address:shared:array:character [
|
||||
def split s:address:shared:array:character, delim:character -> result:address:shared:array:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# empty text? return empty array
|
||||
|
@ -1099,7 +1099,7 @@ recipe split s:address:shared:array:character, delim:character -> result:address
|
|||
empty?:boolean <- equal len, 0
|
||||
break-unless empty?
|
||||
result <- new {(address shared array character): type}, 0
|
||||
reply
|
||||
return
|
||||
}
|
||||
# count #pieces we need room for
|
||||
count:number <- copy 1 # n delimiters = n+1 pieces
|
||||
|
@ -1217,7 +1217,7 @@ scenario text-split-empty-piece [
|
|||
]
|
||||
]
|
||||
|
||||
recipe split-first text:address:shared:array:character, delim:character -> x:address:shared:array:character, y:address:shared:array:character [
|
||||
def split-first text:address:shared:array:character, delim:character -> x:address:shared:array:character, y:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# empty text? return empty texts
|
||||
|
@ -1227,7 +1227,7 @@ recipe split-first text:address:shared:array:character, delim:character -> x:add
|
|||
break-unless empty?
|
||||
x:address:shared:array:character <- new []
|
||||
y:address:shared:array:character <- new []
|
||||
reply
|
||||
return
|
||||
}
|
||||
idx:number <- find-next text, delim, 0
|
||||
x:address:shared:array:character <- copy-range text, 0, idx
|
||||
|
@ -1248,7 +1248,7 @@ scenario text-split-first [
|
|||
]
|
||||
]
|
||||
|
||||
recipe copy-range buf:address:shared:array:character, start:number, end:number -> result:address:shared:array:character [
|
||||
def copy-range buf:address:shared:array:character, start:number, end:number -> result:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if end is out of bounds, trim it
|
||||
|
@ -1305,24 +1305,24 @@ scenario text-copy-out-of-bounds-2 [
|
|||
]
|
||||
]
|
||||
|
||||
recipe min x:number, y:number -> z:number [
|
||||
def min x:number, y:number -> z:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
return-x?:boolean <- lesser-than x, y
|
||||
break-if return-x?
|
||||
reply y
|
||||
return y
|
||||
}
|
||||
reply x
|
||||
return x
|
||||
]
|
||||
|
||||
recipe max x:number, y:number -> z:number [
|
||||
def max x:number, y:number -> z:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
return-x?:boolean <- greater-than x, y
|
||||
break-if return-x?
|
||||
reply y
|
||||
return y
|
||||
}
|
||||
reply x
|
||||
return x
|
||||
]
|
||||
|
|
|
@ -31,7 +31,7 @@ container channel [
|
|||
data:address:shared:array:character
|
||||
]
|
||||
|
||||
recipe new-channel capacity:number -> result:address:shared:channel [
|
||||
def new-channel capacity:number -> result:address:shared:channel [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- new channel:type
|
||||
|
@ -47,7 +47,7 @@ recipe new-channel capacity:number -> result:address:shared:channel [
|
|||
*dest <- new character:type, capacity
|
||||
]
|
||||
|
||||
recipe write chan:address:shared:channel, val:character -> chan:address:shared:channel [
|
||||
def write chan:address:shared:channel, val:character -> chan:address:shared:channel [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -73,7 +73,7 @@ recipe write chan:address:shared:channel, val:character -> chan:address:shared:c
|
|||
}
|
||||
]
|
||||
|
||||
recipe read chan:address:shared:channel -> result:character, chan:address:shared:channel [
|
||||
def read chan:address:shared:channel -> result:character, chan:address:shared:channel [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -98,7 +98,7 @@ recipe read chan:address:shared:channel -> result:character, chan:address:shared
|
|||
}
|
||||
]
|
||||
|
||||
recipe clear-channel chan:address:shared:channel -> chan:address:shared:channel [
|
||||
def clear-channel chan:address:shared:channel -> chan:address:shared:channel [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -175,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:shared:channel -> result:boolean [
|
||||
def channel-empty? chan:address:shared:channel -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# return chan.first-full == chan.first-free
|
||||
|
@ -186,7 +186,7 @@ recipe channel-empty? chan:address:shared: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:shared:channel -> result:boolean [
|
||||
def channel-full? chan:address:shared:channel -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# tmp = chan.first-free + 1
|
||||
|
@ -204,7 +204,7 @@ recipe channel-full? chan:address:shared:channel -> result:boolean [
|
|||
result <- equal full, tmp
|
||||
]
|
||||
|
||||
recipe channel-capacity chan:address:shared:channel -> result:number [
|
||||
def channel-capacity chan:address:shared:channel -> result:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
q:address:shared:array:character <- get *chan, data:offset
|
||||
|
@ -264,7 +264,7 @@ scenario channel-read-not-full [
|
|||
]
|
||||
|
||||
# helper for channels of characters in particular
|
||||
recipe buffer-lines in:address:shared:channel, out:address:shared:channel -> out:address:shared:channel, in:address:shared:channel [
|
||||
def buffer-lines in:address:shared:channel, out:address:shared:channel -> out:address:shared:channel, in:address:shared:channel [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# repeat forever
|
||||
|
|
|
@ -12,7 +12,7 @@ scenario array-from-args [
|
|||
]
|
||||
|
||||
# create an array out of a list of scalar args
|
||||
recipe new-array -> result:address:shared:array:character [
|
||||
def new-array -> result:address:shared:array:character [
|
||||
local-scope
|
||||
capacity:number <- copy 0
|
||||
{
|
||||
|
@ -36,5 +36,5 @@ recipe new-array -> result:address:shared:array:character [
|
|||
i <- add i, 1
|
||||
loop
|
||||
}
|
||||
reply result
|
||||
return result
|
||||
]
|
||||
|
|
22
073list.mu
|
@ -8,7 +8,7 @@ container list:_elem [
|
|||
next:address:shared:list:_elem
|
||||
]
|
||||
|
||||
recipe push x:_elem, in:address:shared:list:_elem -> in:address:shared:list:_elem [
|
||||
def push x:_elem, in:address:shared:list:_elem -> in:address:shared:list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result:address:shared:list:_elem <- new {(list _elem): type}
|
||||
|
@ -16,16 +16,16 @@ recipe push x:_elem, in:address:shared:list:_elem -> in:address:shared:list:_ele
|
|||
*val <- copy x
|
||||
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'
|
||||
return result # needed explicitly because we need to replace 'in' with 'result'
|
||||
]
|
||||
|
||||
recipe first in:address:shared:list:_elem -> result:_elem [
|
||||
def first in:address:shared:list:_elem -> result:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- get *in, value:offset
|
||||
]
|
||||
|
||||
recipe rest in:address:shared:list:_elem -> result:address:shared:list:_elem/contained-in:in [
|
||||
def rest in:address:shared:list:_elem -> result:address:shared:list:_elem/contained-in:in [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- get *in, next:offset
|
||||
|
@ -51,7 +51,7 @@ scenario list-handling [
|
|||
]
|
||||
]
|
||||
|
||||
recipe to-text in:address:shared:list:_elem -> result:address:shared:array:character [
|
||||
def to-text in:address:shared:list:_elem -> result:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
buf:address:shared:buffer <- new-buffer 80
|
||||
|
@ -60,7 +60,7 @@ recipe to-text in:address:shared:list:_elem -> result:address:shared:array:chara
|
|||
]
|
||||
|
||||
# variant of 'to-text' which stops printing after a few elements (and so is robust to cycles)
|
||||
recipe to-text-line in:address:shared:list:_elem -> result:address:shared:array:character [
|
||||
def to-text-line in:address:shared:list:_elem -> result:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
buf:address:shared:buffer <- new-buffer 80
|
||||
|
@ -68,13 +68,13 @@ recipe to-text-line in:address:shared:list:_elem -> result:address:shared:array:
|
|||
result <- buffer-to-array buf
|
||||
]
|
||||
|
||||
recipe to-buffer in:address:shared:list:_elem, buf:address:shared:buffer -> buf:address:shared:buffer [
|
||||
def to-buffer in:address:shared:list:_elem, buf:address:shared:buffer -> buf:address:shared:buffer [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
break-if in
|
||||
buf <- append buf, 48/0
|
||||
reply
|
||||
return
|
||||
}
|
||||
# append in.value to buf
|
||||
val:_elem <- get *in, value:offset
|
||||
|
@ -82,7 +82,7 @@ recipe to-buffer in:address:shared:list:_elem, buf:address:shared:buffer -> buf:
|
|||
# now prepare next
|
||||
next:address:shared:list:_elem <- rest in
|
||||
nextn:number <- copy next
|
||||
reply-unless next
|
||||
return-unless next
|
||||
space:character <- copy 32/space
|
||||
buf <- append buf, space:character
|
||||
s:address:shared:array:character <- new [-> ]
|
||||
|
@ -94,14 +94,14 @@ recipe to-buffer in:address:shared:list:_elem, buf:address:shared:buffer -> buf:
|
|||
break-if optional-ingredient-found?
|
||||
# unlimited recursion
|
||||
buf <- to-buffer next, buf
|
||||
reply
|
||||
return
|
||||
}
|
||||
{
|
||||
break-unless remaining
|
||||
# limited recursion
|
||||
remaining <- subtract remaining, 1
|
||||
buf <- to-buffer next, buf, remaining
|
||||
reply
|
||||
return
|
||||
}
|
||||
# past recursion depth; insert ellipses and stop
|
||||
s:address:shared:array:character <- new [...]
|
||||
|
|
|
@ -53,7 +53,7 @@ case ROUND: {
|
|||
}
|
||||
|
||||
:(scenario round_to_nearest_integer)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- round 12.2
|
||||
]
|
||||
+mem: storing 12 in location 1
|
||||
|
|
|
@ -7,7 +7,7 @@ container duplex-list:_elem [
|
|||
]
|
||||
|
||||
# should I say in/contained-in:result, allow ingredients to refer to products?
|
||||
recipe push x:_elem, in:address:shared:duplex-list:_elem -> in:address:shared:duplex-list:_elem [
|
||||
def push x:_elem, in:address:shared:duplex-list:_elem -> in:address:shared:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result:address:shared:duplex-list:_elem <- new {(duplex-list _elem): type}
|
||||
|
@ -20,29 +20,29 @@ recipe push x:_elem, in:address:shared:duplex-list:_elem -> in:address:shared:du
|
|||
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'
|
||||
return result # needed explicitly because we need to replace 'in' with 'result'
|
||||
]
|
||||
|
||||
recipe first in:address:shared:duplex-list:_elem -> result:_elem [
|
||||
def first in:address:shared:duplex-list:_elem -> result:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless in, 0
|
||||
return-unless in, 0
|
||||
result <- get *in, value:offset
|
||||
]
|
||||
|
||||
recipe next in:address:shared:duplex-list:_elem -> result:address:shared:duplex-list:_elem/contained-in:in [
|
||||
def next in:address:shared:duplex-list:_elem -> result:address:shared:duplex-list:_elem/contained-in:in [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless in, 0
|
||||
return-unless in, 0
|
||||
result <- get *in, next:offset
|
||||
]
|
||||
|
||||
recipe prev in:address:shared:duplex-list:_elem -> result:address:shared:duplex-list:_elem/contained-in:in [
|
||||
def prev in:address:shared:duplex-list:_elem -> result:address:shared:duplex-list:_elem/contained-in:in [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless in, 0
|
||||
return-unless in, 0
|
||||
result <- get *in, prev:offset
|
||||
reply result
|
||||
return result
|
||||
]
|
||||
|
||||
scenario duplex-list-handling [
|
||||
|
@ -87,7 +87,7 @@ scenario duplex-list-handling [
|
|||
]
|
||||
|
||||
# insert 'x' after 'in'
|
||||
recipe insert x:_elem, in:address:shared:duplex-list:_elem -> in:address:shared:duplex-list:_elem [
|
||||
def insert x:_elem, in:address:shared:duplex-list:_elem -> in:address:shared:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
new-node:address:shared:duplex-list:_elem <- new {(duplex-list _elem): type}
|
||||
|
@ -104,7 +104,7 @@ recipe insert x:_elem, in:address:shared:duplex-list:_elem -> in:address:shared:
|
|||
y <- get-address *new-node, next:offset
|
||||
*y <- copy next-node
|
||||
# if next-node is not null
|
||||
reply-unless next-node
|
||||
return-unless next-node
|
||||
# next-node.prev = new-node
|
||||
y <- get-address *next-node, prev:offset
|
||||
*y <- copy new-node
|
||||
|
@ -222,11 +222,11 @@ 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:shared:duplex-list:_elem/contained-in:in, in:address:shared:duplex-list:_elem -> in:address:shared:duplex-list:_elem [
|
||||
def 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
|
||||
return-unless x
|
||||
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
|
||||
|
@ -245,11 +245,11 @@ recipe remove x:address:shared:duplex-list:_elem/contained-in:in, in:address:sha
|
|||
break-unless prev-node
|
||||
tmp <- get-address *prev-node, next:offset
|
||||
*tmp <- copy next-node
|
||||
reply
|
||||
return
|
||||
}
|
||||
# if prev-node is null, then we removed the node at 'in'
|
||||
# return the new head rather than the old 'in'
|
||||
reply next-node
|
||||
return next-node
|
||||
]
|
||||
|
||||
scenario removing-from-duplex-list [
|
||||
|
@ -347,19 +347,19 @@ 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:shared:duplex-list:_elem, end:address:shared:duplex-list:_elem/contained-in:start -> start:address:shared:duplex-list:_elem [
|
||||
def 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
|
||||
return-unless start
|
||||
# start->next->prev = 0
|
||||
# start->next = end
|
||||
next:address:address:shared:duplex-list:_elem <- get-address *start, next:offset
|
||||
nothing-to-delete?:boolean <- equal *next, end
|
||||
reply-if nothing-to-delete?
|
||||
return-if nothing-to-delete?
|
||||
prev:address:address:shared:duplex-list:_elem <- get-address **next, prev:offset
|
||||
*prev <- copy 0
|
||||
*next <- copy end
|
||||
reply-unless end
|
||||
return-unless end
|
||||
# end->prev->next = 0
|
||||
# end->prev = start
|
||||
prev <- get-address *end, prev:offset
|
||||
|
@ -455,11 +455,11 @@ scenario remove-range-empty [
|
|||
]
|
||||
|
||||
# insert list beginning at 'new' after 'in'
|
||||
recipe insert-range in:address:shared:duplex-list:_elem, start:address:shared:duplex-list:_elem/contained-in:in -> in:address:shared:duplex-list:_elem [
|
||||
def 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
|
||||
return-unless in
|
||||
return-unless start
|
||||
end:address:shared:duplex-list:_elem <- copy start
|
||||
{
|
||||
next:address:shared:duplex-list:_elem <- next end/insert-range
|
||||
|
@ -481,18 +481,18 @@ recipe insert-range in:address:shared:duplex-list:_elem, start:address:shared:du
|
|||
*dest <- copy in
|
||||
]
|
||||
|
||||
recipe append in:address:shared:duplex-list:_elem, new:address:shared:duplex-list:_elem/contained-in:in -> in:address:shared:duplex-list:_elem [
|
||||
def 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:shared:duplex-list:_elem <- last in
|
||||
dest:address:address:shared:duplex-list:_elem <- get-address *last, next:offset
|
||||
*dest <- copy new
|
||||
reply-unless new
|
||||
return-unless new
|
||||
dest <- get-address *new, prev:offset
|
||||
*dest <- copy last
|
||||
]
|
||||
|
||||
recipe last in:address:shared:duplex-list:_elem -> result:address:shared:duplex-list:_elem [
|
||||
def last in:address:shared:duplex-list:_elem -> result:address:shared:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- copy in
|
||||
|
@ -505,7 +505,7 @@ recipe last in:address:shared:duplex-list:_elem -> result:address:shared:duplex-
|
|||
]
|
||||
|
||||
# helper for debugging
|
||||
recipe dump-from x:address:shared:duplex-list:_elem [
|
||||
def dump-from x:address:shared:duplex-list:_elem [
|
||||
local-scope
|
||||
load-ingredients
|
||||
$print x, [: ]
|
||||
|
|
|
@ -4,7 +4,7 @@ container stream [
|
|||
data:address:shared:array:character
|
||||
]
|
||||
|
||||
recipe new-stream s:address:shared:array:character -> result:address:shared:stream [
|
||||
def new-stream s:address:shared:array:character -> result:address:shared:stream [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- new stream:type
|
||||
|
@ -14,14 +14,14 @@ recipe new-stream s:address:shared:array:character -> result:address:shared:stre
|
|||
*d <- copy s
|
||||
]
|
||||
|
||||
recipe rewind-stream in:address:shared:stream -> in:address:shared:stream [
|
||||
def 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:shared:stream -> result:address:shared:array:character, in:address:shared:stream [
|
||||
def 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
|
||||
|
@ -31,7 +31,7 @@ recipe read-line in:address:shared:stream -> result:address:shared:array:charact
|
|||
*idx <- add next-idx, 1 # skip newline
|
||||
]
|
||||
|
||||
recipe end-of-stream? in:address:shared:stream -> result:boolean [
|
||||
def end-of-stream? in:address:shared:stream -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
idx:number <- get *in, index:offset
|
||||
|
|
62
077hash.cc
|
@ -143,13 +143,13 @@ container foo [
|
|||
x:number
|
||||
y:character
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo <- merge 34, 97/a
|
||||
3:number <- hash 1:foo
|
||||
reply-unless 3:number
|
||||
return-unless 3:number
|
||||
4:foo <- merge 34, 98/a
|
||||
6:number <- hash 4:foo
|
||||
reply-unless 6:number
|
||||
return-unless 6:number
|
||||
7:boolean <- equal 3:number, 6:number
|
||||
]
|
||||
# hash on containers includes all elements
|
||||
|
@ -164,13 +164,13 @@ container bar [
|
|||
a:number
|
||||
b:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo <- merge 0/x, 34, 35
|
||||
4:number <- hash 1:foo
|
||||
reply-unless 4:number
|
||||
return-unless 4:number
|
||||
5:foo <- merge 0/x, 34, 36
|
||||
8:number <- hash 5:foo
|
||||
reply-unless 8:number
|
||||
return-unless 8:number
|
||||
9:boolean <- equal 4:number, 8:number
|
||||
]
|
||||
# hash on containers includes all elements
|
||||
|
@ -181,13 +181,13 @@ container foo [
|
|||
x:number
|
||||
y:character/ignore-for-hash
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo <- merge 34, 97/a
|
||||
3:number <- hash 1:foo
|
||||
reply-unless 3:number
|
||||
return-unless 3:number
|
||||
4:foo <- merge 34, 98/a
|
||||
6:number <- hash 4:foo
|
||||
reply-unless 6:number
|
||||
return-unless 6:number
|
||||
7:boolean <- equal 3:number, 6:number
|
||||
]
|
||||
# hashes match even though y is different
|
||||
|
@ -197,7 +197,7 @@ recipe main [
|
|||
//: current implementation works like we think it does.
|
||||
|
||||
:(scenario hash_of_zero_address)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:number <- copy 0
|
||||
2:number <- hash 1:address:number
|
||||
]
|
||||
|
@ -206,7 +206,7 @@ recipe main [
|
|||
//: This is probably too aggressive, but we need some way to avoid depending
|
||||
//: on the precise bit pattern of a floating-point number.
|
||||
:(scenario hash_of_numbers_ignores_fractional_part)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- hash 1.5
|
||||
2:number <- hash 1
|
||||
3:boolean <- equal 1:number, 2:number
|
||||
|
@ -214,22 +214,22 @@ recipe main [
|
|||
+mem: storing 1 in location 3
|
||||
|
||||
:(scenario hash_of_array_same_as_string)
|
||||
recipe main [
|
||||
def main [
|
||||
10:number <- copy 3
|
||||
11:number <- copy 97
|
||||
12:number <- copy 98
|
||||
13:number <- copy 99
|
||||
2:number <- hash 10:array:number/unsafe
|
||||
reply-unless 2:number
|
||||
return-unless 2:number
|
||||
3:address:shared:array:character <- new [abc]
|
||||
4:number <- hash 3:address:shared:array:character
|
||||
reply-unless 4:number
|
||||
return-unless 4:number
|
||||
5:boolean <- equal 2:number, 4:number
|
||||
]
|
||||
+mem: storing 1 in location 5
|
||||
|
||||
:(scenario hash_ignores_address_value)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:number <- new number:type
|
||||
*1:address:shared:number <- copy 34
|
||||
2:number <- hash 1:address:shared:number
|
||||
|
@ -242,15 +242,15 @@ recipe main [
|
|||
+mem: storing 1 in location 5
|
||||
|
||||
:(scenario hash_ignores_address_refcount)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:number <- new number:type
|
||||
*1:address:shared:number <- copy 34
|
||||
2:number <- hash 1:address:shared:number
|
||||
reply-unless 2:number
|
||||
return-unless 2:number
|
||||
# increment refcount
|
||||
3:address:shared:number <- copy 1:address:shared:number
|
||||
4:number <- hash 3:address:shared:number
|
||||
reply-unless 4:number
|
||||
return-unless 4:number
|
||||
5:boolean <- equal 2:number, 4:number
|
||||
]
|
||||
# hash doesn't change when refcount changes
|
||||
|
@ -265,13 +265,13 @@ container bar [
|
|||
x:number
|
||||
y:character
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo <- merge 34, 97/a
|
||||
3:number <- hash 1:foo
|
||||
reply-unless 3:number
|
||||
return-unless 3:number
|
||||
4:bar <- merge 34, 97/a
|
||||
6:number <- hash 4:bar
|
||||
reply-unless 6:number
|
||||
return-unless 6:number
|
||||
7:boolean <- equal 3:number, 6:number
|
||||
]
|
||||
# containers with identical elements return identical hashes
|
||||
|
@ -283,17 +283,17 @@ container foo [
|
|||
y:character
|
||||
z:address:shared:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:number <- new number:type
|
||||
*1:address:shared:number <- copy 34
|
||||
2:foo <- merge 34, 97/a, 1:address:shared:number
|
||||
5:number <- hash 2:foo
|
||||
reply-unless 5:number
|
||||
return-unless 5:number
|
||||
6:address:shared:number <- new number:type
|
||||
*6:address:shared:number <- copy 34
|
||||
7:foo <- merge 34, 97/a, 6:address:shared:number
|
||||
10:number <- hash 7:foo
|
||||
reply-unless 10:number
|
||||
return-unless 10:number
|
||||
11:boolean <- equal 5:number, 10:number
|
||||
]
|
||||
# containers with identical 'leaf' elements return identical hashes
|
||||
|
@ -309,13 +309,13 @@ container bar [
|
|||
x:number
|
||||
y:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo <- merge 34, 97/a, 47, 48
|
||||
6:number <- hash 1:foo
|
||||
reply-unless 6:number
|
||||
return-unless 6:number
|
||||
7:foo <- merge 34, 97/a, 47, 48
|
||||
12:number <- hash 7:foo
|
||||
reply-unless 12:number
|
||||
return-unless 12:number
|
||||
13:boolean <- equal 6:number, 12:number
|
||||
]
|
||||
# containers with identical 'leaf' elements return identical hashes
|
||||
|
@ -330,13 +330,13 @@ container bar [
|
|||
a:number
|
||||
b:number
|
||||
]
|
||||
recipe main [
|
||||
def main [
|
||||
1:foo <- merge 0/x, 34, 35
|
||||
4:number <- hash 1:foo
|
||||
reply-unless 4:number
|
||||
return-unless 4:number
|
||||
5:bar <- merge 34, 35
|
||||
7:number <- hash 5:bar
|
||||
reply-unless 7:number
|
||||
return-unless 7:number
|
||||
8:boolean <- equal 4:number, 7:number
|
||||
]
|
||||
# hash on containers includes all elements
|
||||
|
@ -347,7 +347,7 @@ recipe main [
|
|||
//: version around and check that the new one is consistent with it.
|
||||
|
||||
:(scenario hash_matches_old_version)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:array:character <- new [abc]
|
||||
2:number <- hash 1:address:shared:array:character
|
||||
3:number <- hash_old 1:address:shared:array:character
|
||||
|
|
10
078table.mu
|
@ -36,7 +36,7 @@ container table_row:_key:_value [
|
|||
value:_value
|
||||
]
|
||||
|
||||
recipe new-table capacity:number -> result:address:shared:table:_key:_value [
|
||||
def new-table capacity:number -> result:address:shared:table:_key:_value [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- new {(table _key _value): type}
|
||||
|
@ -46,7 +46,7 @@ recipe new-table capacity:number -> result:address:shared:table:_key:_value [
|
|||
*data <- new {(table_row _key _value): type}, capacity
|
||||
]
|
||||
|
||||
recipe put table:address:shared:table:_key:_value, key:_key, value:_value -> table:address:shared:table:_key:_value [
|
||||
def put table:address:shared:table:_key:_value, key:_key, value:_value -> table:address:shared:table:_key:_value [
|
||||
local-scope
|
||||
load-ingredients
|
||||
hash:number <- hash key
|
||||
|
@ -62,15 +62,15 @@ recipe put table:address:shared:table:_key:_value, key:_key, value:_value -> tab
|
|||
*x <- merge 1/true, key, value
|
||||
]
|
||||
|
||||
recipe abs n:number -> result:number [
|
||||
def abs n:number -> result:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
positive?:boolean <- greater-or-equal n, 0
|
||||
reply-if positive?, n
|
||||
return-if positive?, n
|
||||
result <- multiply n, -1
|
||||
]
|
||||
|
||||
recipe index table:address:shared:table:_key:_value, key:_key -> result:_value [
|
||||
def index table:address:shared:table:_key:_value, key:_key -> result:_value [
|
||||
local-scope
|
||||
load-ingredients
|
||||
hash:number <- hash key
|
||||
|
|
96
081print.mu
|
@ -14,7 +14,7 @@ container screen-cell [
|
|||
color:number
|
||||
]
|
||||
|
||||
recipe new-fake-screen w:number, h:number -> result:address:shared:screen [
|
||||
def new-fake-screen w:number, h:number -> result:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result <- new screen:type
|
||||
|
@ -32,7 +32,7 @@ recipe new-fake-screen w:number, h:number -> result:address:shared:screen [
|
|||
result <- clear-screen result
|
||||
]
|
||||
|
||||
recipe clear-screen screen:address:shared:screen -> screen:address:shared:screen [
|
||||
def clear-screen screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists
|
||||
|
@ -58,13 +58,13 @@ recipe clear-screen screen:address:shared:screen -> screen:address:shared:screen
|
|||
*x <- copy 0
|
||||
x <- get-address *screen, cursor-column:offset
|
||||
*x <- copy 0
|
||||
reply
|
||||
return
|
||||
}
|
||||
# otherwise, real screen
|
||||
clear-display
|
||||
]
|
||||
|
||||
recipe sync-screen screen:address:shared:screen -> screen:address:shared:screen [
|
||||
def sync-screen screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -74,10 +74,10 @@ recipe sync-screen screen:address:shared:screen -> screen:address:shared:screen
|
|||
# do nothing for fake screens
|
||||
]
|
||||
|
||||
recipe fake-screen-is-empty? screen:address:shared:screen -> result:boolean [
|
||||
def fake-screen-is-empty? screen:address:shared:screen -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless screen, 1/true
|
||||
return-unless screen, 1/true
|
||||
buf:address:shared:array:screen-cell <- get *screen, data:offset
|
||||
i:number <- copy 0
|
||||
len:number <- length *buf
|
||||
|
@ -89,12 +89,12 @@ recipe fake-screen-is-empty? screen:address:shared:screen -> result:boolean [
|
|||
i <- add i, 1
|
||||
loop-unless curr-contents
|
||||
# not 0
|
||||
reply 0/false
|
||||
return 0/false
|
||||
}
|
||||
reply 1/true
|
||||
return 1/true
|
||||
]
|
||||
|
||||
recipe print screen:address:shared:screen, c:character -> screen:address:shared:screen [
|
||||
def print screen:address:shared:screen, c:character -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
color:number, color-found?:boolean <- next-ingredient
|
||||
|
@ -119,14 +119,14 @@ recipe print screen:address:shared:screen, c:character -> screen:address:shared:
|
|||
# if cursor is out of bounds, silently exit
|
||||
row:address:number <- get-address *screen, cursor-row:offset
|
||||
legal?:boolean <- greater-or-equal *row, 0
|
||||
reply-unless legal?
|
||||
return-unless legal?
|
||||
legal? <- lesser-than *row, height
|
||||
reply-unless legal?
|
||||
return-unless legal?
|
||||
column:address:number <- get-address *screen, cursor-column:offset
|
||||
legal? <- greater-or-equal *column, 0
|
||||
reply-unless legal?
|
||||
return-unless legal?
|
||||
legal? <- lesser-than *column, width
|
||||
reply-unless legal?
|
||||
return-unless legal?
|
||||
#? $print [print-character (], *row, [, ], *column, [): ], c, 10/newline
|
||||
# special-case: newline
|
||||
{
|
||||
|
@ -141,7 +141,7 @@ recipe print screen:address:shared:screen, c:character -> screen:address:shared:
|
|||
*column <- copy 0
|
||||
*row <- add *row, 1
|
||||
}
|
||||
reply
|
||||
return
|
||||
}
|
||||
# save character in fake screen
|
||||
index:number <- multiply *row, width
|
||||
|
@ -165,7 +165,7 @@ recipe print screen:address:shared:screen, c:character -> screen:address:shared:
|
|||
cursor-color:address:number <- get-address *cursor, color:offset
|
||||
*cursor-color <- copy 7/white
|
||||
}
|
||||
reply
|
||||
return
|
||||
}
|
||||
cursor:address:screen-cell <- index-address *buf, index
|
||||
cursor-contents:address:character <- get-address *cursor, contents:offset
|
||||
|
@ -179,7 +179,7 @@ recipe print screen:address:shared:screen, c:character -> screen:address:shared:
|
|||
break-if at-right?
|
||||
*column <- add *column, 1
|
||||
}
|
||||
reply
|
||||
return
|
||||
}
|
||||
# otherwise, real screen
|
||||
print-character-to-display c, color, bg-color
|
||||
|
@ -356,7 +356,7 @@ scenario print-character-at-bottom-right [
|
|||
]
|
||||
]
|
||||
|
||||
recipe clear-line screen:address:shared:screen -> screen:address:shared:screen [
|
||||
def clear-line screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
space:character <- copy 0/nul
|
||||
|
@ -376,13 +376,13 @@ recipe clear-line screen:address:shared:screen -> screen:address:shared:screen [
|
|||
}
|
||||
# now back to where the cursor was
|
||||
*column <- copy original-column
|
||||
reply
|
||||
return
|
||||
}
|
||||
# otherwise, real screen
|
||||
clear-line-on-display
|
||||
]
|
||||
|
||||
recipe cursor-position screen:address:shared:screen -> row:number, column:number [
|
||||
def cursor-position screen:address:shared:screen -> row:number, column:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, lookup cursor in fake screen
|
||||
|
@ -390,12 +390,12 @@ recipe cursor-position screen:address:shared:screen -> row:number, column:number
|
|||
break-unless screen
|
||||
row:number <- get *screen, cursor-row:offset
|
||||
column:number <- get *screen, cursor-column:offset
|
||||
reply
|
||||
return
|
||||
}
|
||||
row, column <- cursor-position-on-display
|
||||
]
|
||||
|
||||
recipe move-cursor screen:address:shared:screen, new-row:number, new-column:number -> screen:address:shared:screen [
|
||||
def 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
|
||||
|
@ -405,7 +405,7 @@ recipe move-cursor screen:address:shared:screen, new-row:number, new-column:numb
|
|||
*row <- copy new-row
|
||||
column:address:number <- get-address *screen, cursor-column:offset
|
||||
*column <- copy new-column
|
||||
reply
|
||||
return
|
||||
}
|
||||
# otherwise, real screen
|
||||
move-cursor-on-display new-row, new-column
|
||||
|
@ -442,7 +442,7 @@ scenario clear-line-erases-printed-characters [
|
|||
]
|
||||
]
|
||||
|
||||
recipe cursor-down screen:address:shared:screen -> screen:address:shared:screen [
|
||||
def cursor-down screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -457,13 +457,13 @@ recipe cursor-down screen:address:shared:screen -> screen:address:shared:screen
|
|||
break-if at-bottom?
|
||||
*row <- add *row, 1
|
||||
}
|
||||
reply
|
||||
return
|
||||
}
|
||||
# otherwise, real screen
|
||||
move-cursor-down-on-display
|
||||
]
|
||||
|
||||
recipe cursor-up screen:address:shared:screen -> screen:address:shared:screen [
|
||||
def cursor-up screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -476,13 +476,13 @@ recipe cursor-up screen:address:shared:screen -> screen:address:shared:screen [
|
|||
break-if at-top?
|
||||
*row <- subtract *row, 1
|
||||
}
|
||||
reply
|
||||
return
|
||||
}
|
||||
# otherwise, real screen
|
||||
move-cursor-up-on-display
|
||||
]
|
||||
|
||||
recipe cursor-right screen:address:shared:screen -> screen:address:shared:screen [
|
||||
def cursor-right screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -497,13 +497,13 @@ recipe cursor-right screen:address:shared:screen -> screen:address:shared:screen
|
|||
break-if at-bottom?
|
||||
*column <- add *column, 1
|
||||
}
|
||||
reply
|
||||
return
|
||||
}
|
||||
# otherwise, real screen
|
||||
move-cursor-right-on-display
|
||||
]
|
||||
|
||||
recipe cursor-left screen:address:shared:screen -> screen:address:shared:screen [
|
||||
def cursor-left screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
|
@ -516,13 +516,13 @@ recipe cursor-left screen:address:shared:screen -> screen:address:shared:screen
|
|||
break-if at-top?
|
||||
*column <- subtract *column, 1
|
||||
}
|
||||
reply
|
||||
return
|
||||
}
|
||||
# otherwise, real screen
|
||||
move-cursor-left-on-display
|
||||
]
|
||||
|
||||
recipe cursor-to-start-of-line screen:address:shared:screen -> screen:address:shared:screen [
|
||||
def cursor-to-start-of-line screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
row:number <- cursor-position screen
|
||||
|
@ -530,90 +530,90 @@ recipe cursor-to-start-of-line screen:address:shared:screen -> screen:address:sh
|
|||
screen <- move-cursor screen, row, column
|
||||
]
|
||||
|
||||
recipe cursor-to-next-line screen:address:shared:screen -> screen:address:shared:screen [
|
||||
def 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:shared:screen -> width:number [
|
||||
def screen-width screen:address:shared:screen -> width:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
{
|
||||
break-unless screen
|
||||
width <- get *screen, num-columns:offset
|
||||
reply
|
||||
return
|
||||
}
|
||||
# otherwise, real screen
|
||||
width <- display-width
|
||||
]
|
||||
|
||||
recipe screen-height screen:address:shared:screen -> height:number [
|
||||
def screen-height screen:address:shared:screen -> height:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists, move cursor in fake screen
|
||||
{
|
||||
break-unless screen
|
||||
height <- get *screen, num-rows:offset
|
||||
reply
|
||||
return
|
||||
}
|
||||
# otherwise, real screen
|
||||
height <- display-height
|
||||
]
|
||||
|
||||
recipe hide-cursor screen:address:shared:screen -> screen:address:shared:screen [
|
||||
def hide-cursor screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists (not real display), do nothing
|
||||
{
|
||||
break-unless screen
|
||||
reply
|
||||
return
|
||||
}
|
||||
# otherwise, real screen
|
||||
hide-cursor-on-display
|
||||
]
|
||||
|
||||
recipe show-cursor screen:address:shared:screen -> screen:address:shared:screen [
|
||||
def show-cursor screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists (not real display), do nothing
|
||||
{
|
||||
break-unless screen
|
||||
reply
|
||||
return
|
||||
}
|
||||
# otherwise, real screen
|
||||
show-cursor-on-display
|
||||
]
|
||||
|
||||
recipe hide-screen screen:address:shared:screen -> screen:address:shared:screen [
|
||||
def hide-screen screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists (not real display), do nothing
|
||||
# todo: help test this
|
||||
{
|
||||
break-unless screen
|
||||
reply
|
||||
return
|
||||
}
|
||||
# otherwise, real screen
|
||||
hide-display
|
||||
]
|
||||
|
||||
recipe show-screen screen:address:shared:screen -> screen:address:shared:screen [
|
||||
def show-screen screen:address:shared:screen -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if x exists (not real display), do nothing
|
||||
# todo: help test this
|
||||
{
|
||||
break-unless screen
|
||||
reply
|
||||
return
|
||||
}
|
||||
# otherwise, real screen
|
||||
show-display
|
||||
]
|
||||
|
||||
recipe print screen:address:shared:screen, s:address:shared:array:character -> screen:address:shared:screen [
|
||||
def 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
|
||||
|
@ -660,7 +660,7 @@ scenario print-text-stops-at-right-margin [
|
|||
]
|
||||
]
|
||||
|
||||
recipe print-integer screen:address:shared:screen, n:number -> screen:address:shared:screen [
|
||||
def print-integer screen:address:shared:screen, n:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
color:number, color-found?:boolean <- next-ingredient
|
||||
|
@ -681,7 +681,7 @@ recipe print-integer screen:address:shared:screen, n:number -> screen:address:sh
|
|||
]
|
||||
|
||||
# for now, we can only print integers
|
||||
recipe print screen:address:shared:screen, n:number -> screen:address:shared:screen [
|
||||
def print screen:address:shared:screen, n:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
color:number, color-found?:boolean <- next-ingredient
|
||||
|
@ -700,7 +700,7 @@ recipe print screen:address:shared:screen, n:number -> screen:address:shared:scr
|
|||
]
|
||||
|
||||
# addresses
|
||||
recipe print screen:address:shared:screen, n:address:_elem -> screen:address:shared:screen [
|
||||
def print screen:address:shared:screen, n:address:_elem -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
color:number, color-found?:boolean <- next-ingredient
|
||||
|
|
|
@ -115,7 +115,7 @@ if (s == "screen") return true;
|
|||
:(scenarios run)
|
||||
:(scenario convert_names_does_not_fail_when_mixing_special_names_and_numeric_locations)
|
||||
% Scenario_testing_scenario = true;
|
||||
recipe main [
|
||||
def main [
|
||||
screen:number <- copy 1:number
|
||||
]
|
||||
-error: mixing variable names and numeric addresses in main
|
||||
|
|
|
@ -25,7 +25,7 @@ container console [
|
|||
events:address:shared:array:event
|
||||
]
|
||||
|
||||
recipe new-fake-console events:address:shared:array:event -> result:address:shared:console [
|
||||
def new-fake-console events:address:shared:array:event -> result:address:shared:console [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result:address:shared:console <- new console:type
|
||||
|
@ -35,7 +35,7 @@ recipe new-fake-console events:address:shared:array:event -> result:address:shar
|
|||
*idx <- copy 0
|
||||
]
|
||||
|
||||
recipe read-event console:address:shared:console -> result:event, console:address:shared:console, found?:boolean, quit?:boolean [
|
||||
def read-event console:address:shared:console -> result:event, console:address:shared:console, found?:boolean, quit?:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -47,32 +47,32 @@ recipe read-event console:address:shared:console -> result:event, console:addres
|
|||
done?:boolean <- greater-or-equal *current-event-index, max
|
||||
break-unless done?
|
||||
dummy:address:shared:event <- new event:type
|
||||
reply *dummy, console/same-as-ingredient:0, 1/found, 1/quit
|
||||
return *dummy, console/same-as-ingredient:0, 1/found, 1/quit
|
||||
}
|
||||
result <- index *buf, *current-event-index
|
||||
*current-event-index <- add *current-event-index, 1
|
||||
reply result, console/same-as-ingredient:0, 1/found, 0/quit
|
||||
return result, console/same-as-ingredient:0, 1/found, 0/quit
|
||||
}
|
||||
switch # real event source is infrequent; avoid polling it too much
|
||||
result:event, found?:boolean <- check-for-interaction
|
||||
reply result, console/same-as-ingredient:0, found?, 0/quit
|
||||
return result, console/same-as-ingredient:0, found?, 0/quit
|
||||
]
|
||||
|
||||
# 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:shared:console -> result:character, console:address:shared:console, found?:boolean, quit?:boolean [
|
||||
def 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
|
||||
reply-if quit?, 0, console/same-as-ingredient:0, found?, quit?
|
||||
reply-unless found?, 0, console/same-as-ingredient:0, found?, quit?
|
||||
return-if quit?, 0, console/same-as-ingredient:0, found?, quit?
|
||||
return-unless found?, 0, console/same-as-ingredient:0, found?, quit?
|
||||
c:address:character <- maybe-convert x, text:variant
|
||||
reply-unless c, 0, console/same-as-ingredient:0, 0/found, 0/quit
|
||||
reply *c, console/same-as-ingredient:0, 1/found, 0/quit
|
||||
return-unless c, 0, console/same-as-ingredient:0, 0/found, 0/quit
|
||||
return *c, console/same-as-ingredient:0, 1/found, 0/quit
|
||||
]
|
||||
|
||||
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 [
|
||||
def 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:shared:console, chan:address:shared:
|
|||
}
|
||||
]
|
||||
|
||||
recipe wait-for-event console:address:shared:console -> console:address:shared:console [
|
||||
def wait-for-event console:address:shared:console -> console:address:shared:console [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -96,13 +96,13 @@ recipe wait-for-event console:address:shared:console -> console:address:shared:c
|
|||
]
|
||||
|
||||
# use this helper to skip rendering if there's lots of other events queued up
|
||||
recipe has-more-events? console:address:shared:console -> result:boolean [
|
||||
def has-more-events? console:address:shared:console -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
break-unless console
|
||||
# fake consoles should be plenty fast; never skip
|
||||
reply 0/false
|
||||
return 0/false
|
||||
}
|
||||
result <- interactions-left?
|
||||
]
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//: return some result in string form.
|
||||
|
||||
:(scenario run_interactive_code)
|
||||
recipe main [
|
||||
def main [
|
||||
1:number/raw <- copy 0
|
||||
2:address:shared:array:character <- new [1:number/raw <- copy 34]
|
||||
run-interactive 2:address:shared:array:character
|
||||
|
@ -11,7 +11,7 @@ recipe main [
|
|||
+mem: storing 34 in location 3
|
||||
|
||||
:(scenario run_interactive_empty)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:array:character <- copy 0/unsafe
|
||||
2:address:shared:array:character <- run-interactive 1:address:shared:array:character
|
||||
]
|
||||
|
@ -92,7 +92,7 @@ bool run_interactive(long long int address) {
|
|||
"$start-tracking-products\n" +
|
||||
command + "\n" +
|
||||
"$stop-tracking-products\n" +
|
||||
"reply screen\n" +
|
||||
"return screen\n" +
|
||||
"]\n");
|
||||
transform_all();
|
||||
Current_routine = save_current_routine;
|
||||
|
@ -159,7 +159,7 @@ load(string(
|
|||
"errors:address:shared:array:character <- save-errors\n" +
|
||||
"stashes:address:shared:array:character <- save-app-trace\n" +
|
||||
"$cleanup-run-interactive\n" +
|
||||
"reply output, errors, screen, stashes, completed?\n" +
|
||||
"return output, errors, screen, stashes, completed?\n" +
|
||||
"]\n");
|
||||
transform_all();
|
||||
Recently_added_recipes.clear();
|
||||
|
@ -169,7 +169,7 @@ Recently_added_recipes.clear();
|
|||
if (s == "interactive") return "";
|
||||
|
||||
:(scenario run_interactive_comments)
|
||||
recipe main [
|
||||
def main [
|
||||
1:address:shared:array:character <- new [# ab
|
||||
add 2, 2]
|
||||
2:address:shared:array:character <- run-interactive 1:address:shared:array:character
|
||||
|
@ -265,7 +265,7 @@ case _CLEANUP_RUN_INTERACTIVE: {
|
|||
}
|
||||
|
||||
:(scenario "run_interactive_converts_result_to_text")
|
||||
recipe main [
|
||||
def main [
|
||||
# try to interactively add 2 and 2
|
||||
1:address:shared:array:character <- new [add 2, 2]
|
||||
2:address:shared:array:character <- run-interactive 1:address:shared:array:character
|
||||
|
@ -275,7 +275,7 @@ recipe main [
|
|||
+mem: storing 52 in location 11
|
||||
|
||||
:(scenario "run_interactive_returns_text")
|
||||
recipe main [
|
||||
def main [
|
||||
# try to interactively add 2 and 2
|
||||
1:address:shared:array:character <- new [
|
||||
x:address:shared:array:character <- new [a]
|
||||
|
@ -290,7 +290,7 @@ recipe main [
|
|||
+mem: storing 98 in location 12
|
||||
|
||||
:(scenario "run_interactive_returns_errors")
|
||||
recipe main [
|
||||
def main [
|
||||
# run a command that generates an error
|
||||
1:address:shared:array:character <- new [x:number <- copy 34
|
||||
get x:number, foo:offset]
|
||||
|
@ -305,7 +305,7 @@ get x:number, foo:offset]
|
|||
# ...
|
||||
|
||||
:(scenario run_interactive_with_comment)
|
||||
recipe main [
|
||||
def main [
|
||||
# 2 instructions, with a comment after the first
|
||||
1:address:shared:array:number <- new [a:number <- copy 0 # abc
|
||||
b:number <- copy 0
|
||||
|
@ -320,7 +320,7 @@ void test_run_interactive_cleans_up_any_created_specializations() {
|
|||
// define a generic recipe
|
||||
assert(!contains_key(Recipe_ordinal, "foo"));
|
||||
load("recipe foo x:_elem -> n:number [\n"
|
||||
" reply 34\n"
|
||||
" return 34\n"
|
||||
"]\n");
|
||||
assert(SIZE(Recently_added_recipes) == 1); // foo
|
||||
assert(variant_count("foo") == 1);
|
||||
|
@ -494,7 +494,7 @@ case RELOAD: {
|
|||
}
|
||||
|
||||
:(scenario reload_continues_past_error)
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
x:address:shared:array:character <- new [recipe foo [
|
||||
get 1234:number, foo:offset
|
||||
|
@ -515,7 +515,7 @@ void test_reload_cleans_up_any_created_specializations() {
|
|||
" x:address:shared:array:character <- new [recipe foo x:_elem -> n:number [\n"
|
||||
"local-scope\n"
|
||||
"load-ingredients\n"
|
||||
"reply 34\n"
|
||||
"return 34\n"
|
||||
"]\n"
|
||||
"recipe main2 [\n"
|
||||
"local-scope\n"
|
||||
|
|
|
@ -43,7 +43,7 @@ assert(Max_callstack_depth == 9989);
|
|||
//:
|
||||
//: begin instruction modifying transforms
|
||||
//: 56.2 check header ingredients
|
||||
//: ↳ 56.4 fill in reply ingredients
|
||||
//: ↳ 56.4 fill in return ingredients
|
||||
//: 48 check or set types by name
|
||||
//:
|
||||
//: begin type modifying transforms
|
||||
|
@ -68,9 +68,9 @@ assert(Max_callstack_depth == 9989);
|
|||
//: ↳ 56 check calls against header
|
||||
//: ↳ 43 transform 'new' to 'allocate'
|
||||
//: 30 check merge calls
|
||||
//: 36 check types of reply instructions
|
||||
//: 36 check types of return instructions
|
||||
//: 43 check default space
|
||||
//: 56 check reply instructions against header
|
||||
//: 56 check return instructions against header
|
||||
//: end checks
|
||||
//: end transforms
|
||||
|
||||
|
|
58
Readme.md
|
@ -210,7 +210,7 @@ Running Mu will always recompile it if necessary:
|
|||
As a sneak peek, here's how you perform some simple arithmetic:
|
||||
|
||||
```nim
|
||||
recipe example1 [
|
||||
def example1 [
|
||||
a:number <- add 2, 2
|
||||
a <- multiply a, 3
|
||||
]
|
||||
|
@ -218,10 +218,10 @@ As a sneak peek, here's how you perform some simple arithmetic:
|
|||
|
||||
But it's easier to read in color:
|
||||
|
||||
<img alt='code example' src='html/example1.png' width='188px'>
|
||||
<img alt='code example' src='html/example1.png'>
|
||||
|
||||
Mu functions or 'recipes' are lists of instructions, one to a line. Each
|
||||
instruction operates on some *ingredients* and returns some *products*.
|
||||
Mu functions are lists of instructions, one to a line. Each instruction
|
||||
operates on some *ingredients* and returns some *products*.
|
||||
|
||||
```
|
||||
[products] <- instruction [ingredients]
|
||||
|
@ -255,31 +255,31 @@ Try out the program now:
|
|||
```
|
||||
|
||||
Not much to see yet, since it doesn't print anything. To print the result, try
|
||||
adding the instruction `$print a` to the recipe.
|
||||
adding the instruction `$print a` to the function.
|
||||
|
||||
---
|
||||
|
||||
Here's a second example, of a recipe that can take ingredients:
|
||||
Here's a second example, of a function that can take ingredients:
|
||||
|
||||
<img alt='fahrenheit to celsius' src='html/f2c-1.png' width='426px'>
|
||||
<img alt='fahrenheit to celsius' src='html/f2c-1.png'>
|
||||
|
||||
Recipes can specify headers showing their expected ingredients and products,
|
||||
separated by `->` (unlike the `<-` in *calls*).
|
||||
|
||||
Since Mu is a low-level VM language, it provides extra control at the cost of
|
||||
verbosity. Using `local-scope`, you have explicit control over stack frames to
|
||||
isolate your recipes (in a type-safe manner; more on that below). One
|
||||
isolate your functions (in a type-safe manner; more on that below). One
|
||||
consequence: you have to explicitly `load-ingredients` after you set up the
|
||||
stack.
|
||||
|
||||
An alternative syntax is what the above example is converted to internally:
|
||||
|
||||
<img alt='fahrenheit to celsius desugared' src='html/f2c-2.png' width='426px'>
|
||||
<img alt='fahrenheit to celsius desugared' src='html/f2c-2.png'>
|
||||
|
||||
The header gets dropped after checking types at call-sites, and after
|
||||
replacing `load-ingredients` with explicit instructions to load each
|
||||
ingredient separately, and to explicitly return products to the caller. After
|
||||
this translation recipes are once again just lists of instructions.
|
||||
this translation functions are once again just lists of instructions.
|
||||
|
||||
This alternative syntax isn't just an implementation detail. I've actually
|
||||
found it easier to teach functions to non-programmers by starting with this
|
||||
|
@ -290,7 +290,7 @@ names of variables gradually get translated through the pipe.
|
|||
|
||||
A third example, this time illustrating conditionals:
|
||||
|
||||
<img alt='factorial example' src='html/factorial.png' width='330px'>
|
||||
<img alt='factorial example' src='html/factorial.png'>
|
||||
|
||||
In spite of how it looks, this is still just a list of instructions.
|
||||
Internally, the instructions `break` and `loop` get converted to `jump`
|
||||
|
@ -311,7 +311,7 @@ You can also run its unit tests:
|
|||
|
||||
Here's what one of the tests inside `factorial.mu` looks like:
|
||||
|
||||
<img alt='test example' src='html/factorial-test.png' width='250px'>
|
||||
<img alt='test example' src='html/factorial-test.png'>
|
||||
|
||||
Every test conceptually spins up a really lightweight virtual machine, so you
|
||||
can do things like check the value of specific locations in memory. You can
|
||||
|
@ -319,7 +319,7 @@ also print to screen and check that the screen contains what you expect at the
|
|||
end of a test. For example, `chessboard.mu` checks the initial position of a
|
||||
game of chess (delimiting the edges of the screen with periods):
|
||||
|
||||
<img alt='screen test' src='html/chessboard-test.png' width='320px'>
|
||||
<img alt='screen test' src='html/chessboard-test.png'>
|
||||
|
||||
Similarly you can fake the keyboard to pretend someone typed something:
|
||||
|
||||
|
@ -348,11 +348,11 @@ might turn into this:
|
|||
|
||||
You shouldn't rely on the specific address Mu chooses for a variable, but it
|
||||
will be unique (other variables won't clobber it) and consistent (all mentions
|
||||
of the name will map to the same address inside a recipe).
|
||||
of the name will map to the same address inside a function).
|
||||
|
||||
Things get more complicated when your recipes call other recipes. Mu
|
||||
doesn't preserve uniqueness of addresses across recipes, so you need to
|
||||
organize your names into spaces. At the start of each recipe (like
|
||||
Things get more complicated when your functions call other functions. Mu
|
||||
doesn't preserve uniqueness of addresses across functions, so you need to
|
||||
organize your names into spaces. At the start of each function (like
|
||||
`factorial` above), set its *default space*:
|
||||
|
||||
```nim
|
||||
|
@ -371,10 +371,10 @@ or
|
|||
default-space:address:array:location <- new location:type, 30/capacity
|
||||
```
|
||||
|
||||
Without one of these lines, all variables in the recipe will be *global*,
|
||||
Without one of these lines, all variables in the function will be *global*,
|
||||
something you rarely want. (Luckily, this is also the sort of mistake that
|
||||
will be easily caught by tests.) *With* this line, all addresses in your
|
||||
recipe will by default refer to one of the (30, in the final case) slots
|
||||
function will by default refer to one of the (30, in the final case) slots
|
||||
inside this local space. (If you choose the last, most explicit option and
|
||||
need more than 30 slots, Mu will complain asking you to increase capacity.)
|
||||
|
||||
|
@ -444,7 +444,7 @@ An alternative way to define factorial is by inserting *labels* and later
|
|||
inserting code at them.
|
||||
|
||||
```nim
|
||||
recipe factorial [
|
||||
def factorial [
|
||||
local-scope
|
||||
n:number <- next-ingredient
|
||||
{
|
||||
|
@ -457,7 +457,7 @@ inserting code at them.
|
|||
# if n=0 return 1
|
||||
zero?:boolean <- equal n, 0
|
||||
break-unless zero?
|
||||
reply 1
|
||||
return 1
|
||||
]
|
||||
|
||||
after <recursive-case> [
|
||||
|
@ -465,7 +465,7 @@ inserting code at them.
|
|||
x:number <- subtract n, 1
|
||||
subresult:number <- factorial x
|
||||
result:number <- multiply subresult, n
|
||||
reply result
|
||||
return result
|
||||
]
|
||||
```
|
||||
|
||||
|
@ -473,7 +473,7 @@ inserting code at them.
|
|||
|
||||
Any instruction without ingredients or products that starts with a
|
||||
non-alphanumeric character is a label. By convention we use '+' to indicate
|
||||
recipe-local label names you can jump to, and surround in '<>' global label
|
||||
function-local label names you can jump to, and surround in '<>' global label
|
||||
names for inserting code at.
|
||||
|
||||
---
|
||||
|
@ -481,7 +481,7 @@ names for inserting code at.
|
|||
Another example, this time with concurrency.
|
||||
|
||||
```
|
||||
recipe main [
|
||||
def main [
|
||||
start-running thread2
|
||||
{
|
||||
$print 34
|
||||
|
@ -489,7 +489,7 @@ Another example, this time with concurrency.
|
|||
}
|
||||
]
|
||||
|
||||
recipe thread2 [
|
||||
def thread2 [
|
||||
{
|
||||
$print 35
|
||||
loop
|
||||
|
@ -569,9 +569,9 @@ d) Try out the programming environment:
|
|||
|
||||
Screenshot:
|
||||
|
||||
<img alt='programming environment' src='html/edit.png' width='720px'>
|
||||
<img alt='programming environment' src='html/edit.png'>
|
||||
|
||||
You write recipes on the left and try them out in *sandboxes* on the right.
|
||||
You write functions on the left and try them out in *sandboxes* on the right.
|
||||
Hit F4 to rerun all sandboxes with the latest version of the code. More
|
||||
details: http://akkartik.name/post/mu. Beware, it won't save your edits by
|
||||
default. But if you create a sub-directory called `lesson/` under `mu/` it
|
||||
|
@ -580,12 +580,12 @@ back up each version you try out.
|
|||
|
||||
Once you have a sandbox you can click on its result to mark it as expected:
|
||||
|
||||
<img alt='expected result' src='html/expected-result.png' width='180px'>
|
||||
<img alt='expected result' src='html/expected-result.png'>
|
||||
|
||||
Later if the result changes it'll be flagged in red to draw your attention to
|
||||
it. Thus, manually tested sandboxes become reproducible automated tests.
|
||||
|
||||
<img alt='unexpected result' src='html/unexpected-result.png' width='180px'>
|
||||
<img alt='unexpected result' src='html/unexpected-result.png'>
|
||||
|
||||
Another feature: Clicking on the code in a sandbox expands its trace for you
|
||||
to browse. To add to the trace, use `stash`. For example:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# example program: communicating between routines using channels
|
||||
|
||||
recipe producer chan:address:shared:channel -> chan:address:shared:channel [
|
||||
def producer chan:address:shared:channel -> chan:address:shared:channel [
|
||||
# produce characters 1 to 5 on a channel
|
||||
local-scope
|
||||
load-ingredients
|
||||
|
@ -18,7 +18,7 @@ recipe producer chan:address:shared:channel -> chan:address:shared:channel [
|
|||
}
|
||||
]
|
||||
|
||||
recipe consumer chan:address:shared:channel -> chan:address:shared:channel [
|
||||
def consumer chan:address:shared:channel -> chan:address:shared:channel [
|
||||
# consume and print integers from a channel
|
||||
local-scope
|
||||
load-ingredients
|
||||
|
@ -32,7 +32,7 @@ recipe consumer chan:address:shared:channel -> chan:address:shared:channel [
|
|||
}
|
||||
]
|
||||
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
chan:address:shared:channel <- new-channel 3
|
||||
# create two background 'routines' that communicate by a channel
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# display the position after each move.
|
||||
|
||||
# recipes are mu's names for functions
|
||||
recipe main [
|
||||
def main [
|
||||
open-console # take control of screen, keyboard and mouse
|
||||
|
||||
# The chessboard recipe takes keyboard and screen objects as 'ingredients'.
|
||||
|
@ -66,7 +66,7 @@ scenario print-board-and-read-move [
|
|||
|
||||
## Here's how 'chessboard' is implemented.
|
||||
|
||||
recipe chessboard screen:address:shared:screen, console:address:shared:console -> screen:address:shared:screen, console:address:shared:console [
|
||||
def chessboard screen:address:shared:screen, console:address:shared:console -> screen:address:shared:screen, console:address:shared:console [
|
||||
local-scope
|
||||
load-ingredients
|
||||
board:address:shared:array:address:shared:array:character <- initial-position
|
||||
|
@ -109,7 +109,7 @@ recipe chessboard screen:address:shared:screen, console:address:shared:console -
|
|||
|
||||
## a board is an array of files, a file is an array of characters (squares)
|
||||
|
||||
recipe new-board initial-position:address:shared:array:character -> board:address:shared:array:address:shared:array:character [
|
||||
def 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)
|
||||
|
@ -129,7 +129,7 @@ recipe new-board initial-position:address:shared:array:character -> board:addres
|
|||
}
|
||||
]
|
||||
|
||||
recipe new-file position:address:shared:array:character, index:number -> result:address:shared:array:character [
|
||||
def new-file position:address:shared:array:character, index:number -> result:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
index <- multiply index, 8
|
||||
|
@ -146,7 +146,7 @@ recipe new-file position:address:shared:array:character, index:number -> result:
|
|||
}
|
||||
]
|
||||
|
||||
recipe print-board screen:address:shared:screen, board:address:shared:array:address:shared:array:character -> screen:address:shared:screen [
|
||||
def 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
|
||||
|
@ -185,7 +185,7 @@ recipe print-board screen:address:shared:screen, board:address:shared:array:addr
|
|||
screen <- cursor-to-next-line screen
|
||||
]
|
||||
|
||||
recipe initial-position -> board:address:shared:array:address:shared:array:character [
|
||||
def initial-position -> board:address:shared:array:address:shared:array:character [
|
||||
local-scope
|
||||
# layout in memory (in raster order):
|
||||
# R P _ _ _ _ p r
|
||||
|
@ -242,61 +242,61 @@ container move [
|
|||
]
|
||||
|
||||
# prints only error messages to 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 [
|
||||
def 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?
|
||||
return-if quit?, 0/dummy, quit?, error?
|
||||
return-if error?, 0/dummy, quit?, error?
|
||||
# construct the move object
|
||||
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
|
||||
*x, quit?, error? <- read-rank stdin, screen
|
||||
reply-if quit?, 0/dummy, quit?, error?
|
||||
reply-if error?, 0/dummy, quit?, error?
|
||||
return-if quit?, 0/dummy, quit?, error?
|
||||
return-if error?, 0/dummy, quit?, error?
|
||||
error? <- expect-from-channel stdin, 45/dash, screen
|
||||
reply-if error?, 0/dummy, 0/quit, error?
|
||||
return-if error?, 0/dummy, 0/quit, error?
|
||||
x <- get-address *result, to-file:offset
|
||||
*x, quit?, error? <- read-file stdin, screen
|
||||
reply-if quit?:boolean, 0/dummy, quit?:boolean, error?:boolean
|
||||
reply-if error?:boolean, 0/dummy, quit?:boolean, error?:boolean
|
||||
return-if quit?:boolean, 0/dummy, quit?:boolean, error?:boolean
|
||||
return-if error?:boolean, 0/dummy, quit?:boolean, error?:boolean
|
||||
x:address:number <- get-address *result, to-rank:offset
|
||||
*x, quit?, error? <- read-rank stdin, screen
|
||||
reply-if quit?, 0/dummy, quit?, error?
|
||||
reply-if error?, 0/dummy, quit?, error?
|
||||
return-if quit?, 0/dummy, quit?, error?
|
||||
return-if error?, 0/dummy, quit?, error?
|
||||
error? <- expect-from-channel stdin, 10/newline, screen
|
||||
reply-if error?, 0/dummy, 0/quit, error?
|
||||
reply result, quit?, error?
|
||||
return-if error?, 0/dummy, 0/quit, error?
|
||||
return result, quit?, error?
|
||||
]
|
||||
|
||||
# valid values for file: 0-7
|
||||
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 [
|
||||
def 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
|
||||
{
|
||||
q-pressed?:boolean <- equal c, 81/Q
|
||||
break-unless q-pressed?
|
||||
reply 0/dummy, 1/quit, 0/error
|
||||
return 0/dummy, 1/quit, 0/error
|
||||
}
|
||||
{
|
||||
q-pressed? <- equal c, 113/q
|
||||
break-unless q-pressed?
|
||||
reply 0/dummy, 1/quit, 0/error
|
||||
return 0/dummy, 1/quit, 0/error
|
||||
}
|
||||
{
|
||||
empty-fake-keyboard?:boolean <- equal c, 0/eof
|
||||
break-unless empty-fake-keyboard?
|
||||
reply 0/dummy, 1/quit, 0/error
|
||||
return 0/dummy, 1/quit, 0/error
|
||||
}
|
||||
{
|
||||
newline?:boolean <- equal c, 10/newline
|
||||
break-unless newline?
|
||||
error-message:address:shared:array:character <- new [that's not enough]
|
||||
print screen, error-message
|
||||
reply 0/dummy, 0/quit, 1/error
|
||||
return 0/dummy, 0/quit, 1/error
|
||||
}
|
||||
file:number <- subtract c, 97/a
|
||||
# 'a' <= file <= 'h'
|
||||
|
@ -307,7 +307,7 @@ recipe read-file stdin:address:shared:channel, screen:address:shared:screen -> f
|
|||
print screen, error-message
|
||||
print screen, c
|
||||
cursor-to-next-line screen
|
||||
reply 0/dummy, 0/quit, 1/error
|
||||
return 0/dummy, 0/quit, 1/error
|
||||
}
|
||||
{
|
||||
below-max:boolean <- lesser-than file, 8
|
||||
|
@ -315,32 +315,32 @@ recipe read-file stdin:address:shared:channel, screen:address:shared:screen -> f
|
|||
error-message <- new [file too high: ]
|
||||
print screen, error-message
|
||||
print screen, c
|
||||
reply 0/dummy, 0/quit, 1/error
|
||||
return 0/dummy, 0/quit, 1/error
|
||||
}
|
||||
reply file, 0/quit, 0/error
|
||||
return file, 0/quit, 0/error
|
||||
]
|
||||
|
||||
# valid values: 0-7, -1 (quit), -2 (error)
|
||||
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 [
|
||||
def 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
|
||||
{
|
||||
q-pressed?:boolean <- equal c, 8/Q
|
||||
break-unless q-pressed?
|
||||
reply 0/dummy, 1/quit, 0/error
|
||||
return 0/dummy, 1/quit, 0/error
|
||||
}
|
||||
{
|
||||
q-pressed? <- equal c, 113/q
|
||||
break-unless q-pressed?
|
||||
reply 0/dummy, 1/quit, 0/error
|
||||
return 0/dummy, 1/quit, 0/error
|
||||
}
|
||||
{
|
||||
newline?:boolean <- equal c, 10 # newline
|
||||
break-unless newline?
|
||||
error-message:address:shared:array:character <- new [that's not enough]
|
||||
print screen, error-message
|
||||
reply 0/dummy, 0/quit, 1/error
|
||||
return 0/dummy, 0/quit, 1/error
|
||||
}
|
||||
rank:number <- subtract c, 49/'1'
|
||||
# assert'1' <= rank <= '8'
|
||||
|
@ -350,7 +350,7 @@ recipe read-rank stdin:address:shared:channel, screen:address:shared:screen -> r
|
|||
error-message <- new [rank too low: ]
|
||||
print screen, error-message
|
||||
print screen, c
|
||||
reply 0/dummy, 0/quit, 1/error
|
||||
return 0/dummy, 0/quit, 1/error
|
||||
}
|
||||
{
|
||||
below-max:boolean <- lesser-or-equal rank, 7
|
||||
|
@ -358,14 +358,14 @@ recipe read-rank stdin:address:shared:channel, screen:address:shared:screen -> r
|
|||
error-message <- new [rank too high: ]
|
||||
print screen, error-message
|
||||
print screen, c
|
||||
reply 0/dummy, 0/quit, 1/error
|
||||
return 0/dummy, 0/quit, 1/error
|
||||
}
|
||||
reply rank, 0/quit, 0/error
|
||||
return rank, 0/quit, 0/error
|
||||
]
|
||||
|
||||
# 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:shared:channel, expected:character, screen:address:shared:screen -> result:boolean, stdin:address:shared:channel, screen:address:shared:screen [
|
||||
def 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
|
||||
|
@ -542,7 +542,7 @@ F read-move-file: routine failed to pause after coming up (before any keys were
|
|||
]
|
||||
]
|
||||
|
||||
recipe make-move board:address:shared:array:address:shared:array:character, m:address:shared:move -> board:address:shared:array:address:shared:array:character [
|
||||
def 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
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Keeps printing 'a' until you press a key or click on the mouse.
|
||||
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
open-console
|
||||
{
|
||||
|
|
12
counters.mu
|
@ -1,19 +1,19 @@
|
|||
# example program: maintain multiple counters with isolated lexical scopes
|
||||
# (spaces)
|
||||
|
||||
recipe new-counter n:number -> default-space:address:shared:array:location [
|
||||
def new-counter n:number -> default-space:address:shared:array:location [
|
||||
default-space <- new location:type, 30
|
||||
load-ingredients
|
||||
]
|
||||
|
||||
recipe increment-counter outer:address:shared:array:location/names:new-counter, x:number -> n:number/space:1 [
|
||||
def increment-counter outer:address:shared:array:location/names:new-counter, x:number -> n:number/space:1 [
|
||||
local-scope
|
||||
load-ingredients
|
||||
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 [
|
||||
def main [
|
||||
local-scope
|
||||
# counter A
|
||||
a:address:shared:array:location <- new-counter 34
|
||||
|
@ -24,9 +24,7 @@ recipe main [
|
|||
b-value:number <- increment-counter b, 2
|
||||
a-value:number <- increment-counter a, 1
|
||||
# check results
|
||||
$print [Contents of counters
|
||||
]
|
||||
$print [Contents of counters], 10/newline
|
||||
# trailing space in next line is to help with syntax highlighting
|
||||
$print [a: ], a-value, [ b: ], b-value, [
|
||||
]
|
||||
$print [a: ], a-value, [ b: ], b-value, 10/newline
|
||||
]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# example program: managing the display
|
||||
|
||||
recipe main [
|
||||
def main [
|
||||
open-console
|
||||
print-character-to-display 97, 1/red, 2/green
|
||||
1:number/raw, 2:number/raw <- cursor-position-on-display
|
||||
|
|
|
@ -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:shared:array:character [
|
||||
def! main text:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
open-console
|
||||
|
@ -48,7 +48,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:shared:array:character, screen:address:shared:screen, left:number, right:number -> result:address:shared:editor-data, screen:address:shared:screen [
|
||||
def 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
|
||||
|
@ -79,13 +79,13 @@ recipe new-editor s:address:shared:array:character, screen:address:shared:screen
|
|||
<editor-initialization>
|
||||
]
|
||||
|
||||
recipe insert-text editor:address:shared:editor-data, text:address:shared:array:character -> editor:address:shared:editor-data [
|
||||
def 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
|
||||
reply-unless text, editor/same-as-ingredient:0
|
||||
return-unless text, editor/same-as-ingredient:0
|
||||
len:number <- length *text
|
||||
reply-unless len, editor/same-as-ingredient:0
|
||||
return-unless len, editor/same-as-ingredient:0
|
||||
idx:number <- copy 0
|
||||
# now we can start appending the rest, character by character
|
||||
curr:address:shared:duplex-list:character <- get *editor, data:offset
|
||||
|
@ -99,7 +99,7 @@ recipe insert-text editor:address:shared:editor-data, text:address:shared:array:
|
|||
idx <- add idx, 1
|
||||
loop
|
||||
}
|
||||
reply editor/same-as-ingredient:0
|
||||
return editor/same-as-ingredient:0
|
||||
]
|
||||
|
||||
scenario editor-initializes-without-data [
|
||||
|
@ -129,10 +129,10 @@ 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:shared:screen, editor:address:shared:editor-data -> last-row:number, last-column:number, screen:address:shared:screen, editor:address:shared:editor-data [
|
||||
def 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
|
||||
return-unless editor, 1/top, 0/left, screen/same-as-ingredient:0, editor/same-as-ingredient:1
|
||||
left:number <- get *editor, left:offset
|
||||
screen-height:number <- screen-height screen
|
||||
right:number <- get *editor, right:offset
|
||||
|
@ -226,10 +226,10 @@ recipe render screen:address:shared:screen, editor:address:shared:editor-data ->
|
|||
}
|
||||
bottom:address:number <- get-address *editor, bottom:offset
|
||||
*bottom <- copy row
|
||||
reply row, column, screen/same-as-ingredient:0, editor/same-as-ingredient:1
|
||||
return row, column, screen/same-as-ingredient:0, editor/same-as-ingredient:1
|
||||
]
|
||||
|
||||
recipe clear-line-delimited screen:address:shared:screen, column:number, right:number -> screen:address:shared:screen [
|
||||
def clear-line-delimited screen:address:shared:screen, column:number, right:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
space:character <- copy 32/space
|
||||
|
@ -248,23 +248,23 @@ recipe clear-line-delimited screen:address:shared:screen, column:number, right:n
|
|||
}
|
||||
]
|
||||
|
||||
recipe clear-screen-from screen:address:shared:screen, row:number, column:number, left:number, right:number -> screen:address:shared:screen [
|
||||
def 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
|
||||
{
|
||||
break-if screen
|
||||
clear-display-from row, column, left, right
|
||||
reply screen/same-as-ingredient:0
|
||||
return screen/same-as-ingredient:0
|
||||
}
|
||||
# if not, go the slower route
|
||||
screen <- move-cursor screen, row, column
|
||||
clear-line-delimited screen, column, right
|
||||
clear-rest-of-screen screen, row, left, right
|
||||
reply screen/same-as-ingredient:0
|
||||
return screen/same-as-ingredient:0
|
||||
]
|
||||
|
||||
recipe clear-rest-of-screen screen:address:shared:screen, row:number, left:number, right:number -> screen:address:shared:screen [
|
||||
def 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
|
||||
|
@ -422,7 +422,7 @@ after <character-c-received> [
|
|||
]
|
||||
|
||||
# so far the previous color is all the information we need; that may change
|
||||
recipe get-color color:number, c:character -> color:number [
|
||||
def get-color color:number, c:character -> color:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
color-is-white?:boolean <- equal color, 7/white
|
||||
|
@ -464,7 +464,7 @@ recipe get-color color:number, c:character -> color:number [
|
|||
}
|
||||
# otherwise no change
|
||||
+exit
|
||||
reply color
|
||||
return color
|
||||
]
|
||||
|
||||
scenario render-colors-assignment [
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# temporary main: interactive editor
|
||||
# hit ctrl-c to exit
|
||||
recipe! main text:address:shared:array:character [
|
||||
def! main text:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
open-console
|
||||
|
@ -11,7 +11,7 @@ recipe! main text:address:shared:array:character [
|
|||
close-console
|
||||
]
|
||||
|
||||
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 [
|
||||
def 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
|
||||
{
|
||||
|
@ -45,35 +45,35 @@ recipe editor-event-loop screen:address:shared:screen, console:address:shared:co
|
|||
]
|
||||
|
||||
# process click, return if it was on current editor
|
||||
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 [
|
||||
def 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
|
||||
return-unless editor, 0/false
|
||||
click-row:number <- get t, row:offset
|
||||
reply-unless click-row, 0/false # ignore clicks on 'menu'
|
||||
return-unless click-row, 0/false # ignore clicks on 'menu'
|
||||
click-column:number <- get t, column:offset
|
||||
left:number <- get *editor, left:offset
|
||||
too-far-left?:boolean <- lesser-than click-column, left
|
||||
reply-if too-far-left?, 0/false
|
||||
return-if too-far-left?, 0/false
|
||||
right:number <- get *editor, right:offset
|
||||
too-far-right?:boolean <- greater-than click-column, right
|
||||
reply-if too-far-right?, 0/false
|
||||
return-if too-far-right?, 0/false
|
||||
# position cursor
|
||||
<move-cursor-begin>
|
||||
editor <- snap-cursor screen, editor, click-row, click-column
|
||||
undo-coalesce-tag:number <- copy 0/never
|
||||
<move-cursor-end>
|
||||
# gain focus
|
||||
reply 1/true
|
||||
return 1/true
|
||||
]
|
||||
|
||||
# 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:shared:screen, editor:address:shared:editor-data, target-row:number, target-column:number -> editor:address:shared:editor-data [
|
||||
def 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
|
||||
return-unless editor
|
||||
left:number <- get *editor, left:offset
|
||||
right:number <- get *editor, right:offset
|
||||
screen-height:number <- screen-height screen
|
||||
|
@ -155,11 +155,11 @@ recipe snap-cursor screen:address:shared:screen, editor:address:shared:editor-da
|
|||
|
||||
# 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:shared:screen, editor:address:shared:editor-data, e:event -> screen:address:shared:screen, editor:address:shared:editor-data, go-render?:boolean [
|
||||
def 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
|
||||
reply-unless editor
|
||||
return-unless editor
|
||||
screen-width:number <- screen-width screen
|
||||
screen-height:number <- screen-height screen
|
||||
left:number <- get *editor, left:offset
|
||||
|
@ -179,12 +179,12 @@ recipe handle-keyboard-event screen:address:shared:screen, editor:address:shared
|
|||
# ignore any other special characters
|
||||
regular-character?:boolean <- greater-or-equal *c, 32/space
|
||||
go-render? <- copy 0/false
|
||||
reply-unless regular-character?
|
||||
return-unless regular-character?
|
||||
# otherwise type it in
|
||||
<insert-character-begin>
|
||||
editor, screen, go-render?:boolean <- insert-at-cursor editor, *c, screen
|
||||
<insert-character-end>
|
||||
reply
|
||||
return
|
||||
}
|
||||
# special key to modify the text or move the cursor
|
||||
k:address:number <- maybe-convert e:event, keycode:variant
|
||||
|
@ -192,10 +192,10 @@ recipe handle-keyboard-event screen:address:shared:screen, editor:address:shared
|
|||
# handlers for each special key will go here
|
||||
<handle-special-key>
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
]
|
||||
|
||||
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 [
|
||||
def 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:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
|
@ -226,7 +226,7 @@ recipe insert-at-cursor editor:address:shared:editor-data, c:character, screen:a
|
|||
move-cursor screen, save-row, save-column
|
||||
print screen, c
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
{
|
||||
# not at right margin? print the character and rest of line
|
||||
|
@ -240,7 +240,7 @@ recipe insert-at-cursor editor:address:shared:editor-data, c:character, screen:a
|
|||
# hit right margin? give up and let caller render
|
||||
go-render? <- copy 1/true
|
||||
at-right?:boolean <- greater-than curr-column, right
|
||||
reply-if at-right?
|
||||
return-if at-right?
|
||||
break-unless curr
|
||||
# newline? done.
|
||||
currc:character <- get *curr, value:offset
|
||||
|
@ -252,14 +252,14 @@ recipe insert-at-cursor editor:address:shared:editor-data, c:character, screen:a
|
|||
loop
|
||||
}
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
]
|
||||
|
||||
# helper for tests
|
||||
recipe editor-render screen:address:shared:screen, editor:address:shared:editor-data -> screen:address:shared:screen, editor:address:shared:editor-data [
|
||||
def 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
|
||||
|
@ -697,7 +697,7 @@ after <insert-character-special-case> [
|
|||
<scroll-down>
|
||||
}
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -818,11 +818,11 @@ after <handle-special-character> [
|
|||
editor <- insert-new-line-and-indent editor, screen
|
||||
<insert-enter-end>
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
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 [
|
||||
def 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
|
||||
|
@ -846,7 +846,7 @@ recipe insert-new-line-and-indent editor:address:shared:editor-data, screen:addr
|
|||
}
|
||||
# indent if necessary
|
||||
indent?:boolean <- get *editor, indent?:offset
|
||||
reply-unless indent?
|
||||
return-unless indent?
|
||||
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
|
||||
|
@ -862,13 +862,13 @@ recipe insert-new-line-and-indent editor:address:shared:editor-data, screen:addr
|
|||
|
||||
# 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:shared:duplex-list:character, start:address:shared:duplex-list:character -> result:number [
|
||||
def line-indent curr:address:shared:duplex-list:character, start:address:shared:duplex-list:character -> result:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result:number <- copy 0
|
||||
reply-unless curr
|
||||
return-unless curr
|
||||
at-start?:boolean <- equal curr, start
|
||||
reply-if at-start?
|
||||
return-if at-start?
|
||||
{
|
||||
curr <- prev curr
|
||||
break-unless curr
|
||||
|
@ -995,7 +995,7 @@ after <handle-special-key> [
|
|||
indent?:address:boolean <- get-address *editor, indent?:offset
|
||||
*indent? <- copy 0/false
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -1006,13 +1006,13 @@ after <handle-special-key> [
|
|||
indent?:address:boolean <- get-address *editor, indent?:offset
|
||||
*indent? <- copy 1/true
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
## helpers
|
||||
|
||||
recipe draw-horizontal screen:address:shared:screen, row:number, x:number, right:number -> screen:address:shared:screen [
|
||||
def 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
|
||||
|
|
|
@ -32,7 +32,7 @@ after <handle-special-character> [
|
|||
editor, screen, go-render?:boolean <- insert-at-cursor editor, 32/space, screen
|
||||
<insert-character-end>
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -73,14 +73,14 @@ after <handle-special-character> [
|
|||
<backspace-character-begin>
|
||||
editor, screen, go-render?:boolean, backspaced-cell:address:shared:duplex-list:character <- delete-before-cursor editor, screen
|
||||
<backspace-character-end>
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
# return values:
|
||||
# go-render? - whether caller needs to update the screen
|
||||
# backspaced-cell - value deleted (or 0 if nothing was deleted) so we can save it for undo, etc.
|
||||
recipe delete-before-cursor editor:address:shared:editor-data, screen:address:shared:screen -> editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean, backspaced-cell:address:shared:duplex-list:character [
|
||||
def delete-before-cursor editor:address:shared:editor-data, screen:address:shared:screen -> editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean, backspaced-cell:address:shared:duplex-list:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
|
@ -88,7 +88,7 @@ recipe delete-before-cursor editor:address:shared:editor-data, screen:address:sh
|
|||
# if at start of text (before-cursor at § sentinel), return
|
||||
prev:address:shared:duplex-list:character <- prev *before-cursor
|
||||
go-render?, backspaced-cell <- copy 0/no-more-render, 0/nothing-deleted
|
||||
reply-unless prev
|
||||
return-unless prev
|
||||
trace 10, [app], [delete-before-cursor]
|
||||
original-row:number <- get *editor, cursor-row:offset
|
||||
editor, scroll?:boolean <- move-cursor-coordinates-left editor
|
||||
|
@ -96,14 +96,14 @@ recipe delete-before-cursor editor:address:shared:editor-data, screen:address:sh
|
|||
data <- remove *before-cursor, data # will also neatly trim next/prev pointers in backspaced-cell/*before-cursor
|
||||
*before-cursor <- copy prev
|
||||
go-render? <- copy 1/true
|
||||
reply-if scroll?
|
||||
return-if scroll?
|
||||
screen-width:number <- screen-width screen
|
||||
cursor-row:number <- get *editor, cursor-row:offset
|
||||
cursor-column:number <- get *editor, cursor-column:offset
|
||||
# did we just backspace over a newline?
|
||||
same-row?:boolean <- equal cursor-row, original-row
|
||||
go-render? <- copy 1/true
|
||||
reply-unless same-row?
|
||||
return-unless same-row?
|
||||
left:number <- get *editor, left:offset
|
||||
right:number <- get *editor, right:offset
|
||||
curr:address:shared:duplex-list:character <- next *before-cursor
|
||||
|
@ -113,7 +113,7 @@ recipe delete-before-cursor editor:address:shared:editor-data, screen:address:sh
|
|||
# hit right margin? give up and let caller render
|
||||
at-right?:boolean <- greater-or-equal curr-column, right
|
||||
go-render? <- copy 1/true
|
||||
reply-if at-right?
|
||||
return-if at-right?
|
||||
break-unless curr
|
||||
# newline? done.
|
||||
currc:character <- get *curr, value:offset
|
||||
|
@ -130,7 +130,7 @@ recipe delete-before-cursor editor:address:shared:editor-data, screen:address:sh
|
|||
go-render? <- copy 0/false
|
||||
]
|
||||
|
||||
recipe move-cursor-coordinates-left editor:address:shared:editor-data -> editor:address:shared:editor-data, go-render?:boolean [
|
||||
def move-cursor-coordinates-left editor:address:shared:editor-data -> editor:address:shared:editor-data, go-render?:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset
|
||||
|
@ -144,7 +144,7 @@ recipe move-cursor-coordinates-left editor:address:shared:editor-data -> editor:
|
|||
trace 10, [app], [decrementing cursor column]
|
||||
*cursor-column <- subtract *cursor-column, 1
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
# if at left margin, we must move to previous row:
|
||||
top-of-screen?:boolean <- equal *cursor-row, 1 # exclude menu bar
|
||||
|
@ -179,7 +179,7 @@ recipe move-cursor-coordinates-left editor:address:shared:editor-data -> editor:
|
|||
break-if wrap?
|
||||
*cursor-column <- add left, end-of-line
|
||||
}
|
||||
reply
|
||||
return
|
||||
}
|
||||
# case 2: if previous-character was not newline, we're just at a wrapped line
|
||||
trace 10, [app], [wrapping to previous line]
|
||||
|
@ -189,13 +189,13 @@ recipe move-cursor-coordinates-left editor:address:shared:editor-data -> editor:
|
|||
|
||||
# takes a pointer 'curr' into the doubly-linked list and its sentinel, counts
|
||||
# the length of the previous line before the 'curr' pointer.
|
||||
recipe previous-line-length curr:address:shared:duplex-list:character, start:address:shared:duplex-list:character -> result:number [
|
||||
def previous-line-length curr:address:shared:duplex-list:character, start:address:shared:duplex-list:character -> result:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result:number <- copy 0
|
||||
reply-unless curr
|
||||
return-unless curr
|
||||
at-start?:boolean <- equal curr, start
|
||||
reply-if at-start?
|
||||
return-if at-start?
|
||||
{
|
||||
curr <- prev curr
|
||||
break-unless curr
|
||||
|
@ -338,23 +338,23 @@ after <handle-special-key> [
|
|||
<delete-character-begin>
|
||||
editor, screen, go-render?:boolean, deleted-cell:address:shared:duplex-list:character <- delete-at-cursor editor, screen
|
||||
<delete-character-end>
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe delete-at-cursor editor:address:shared:editor-data, screen:address:shared:screen -> editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean, deleted-cell:address:shared:duplex-list:character [
|
||||
def delete-at-cursor editor:address:shared:editor-data, screen:address:shared:screen -> editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean, deleted-cell:address:shared:duplex-list:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
data:address:shared:duplex-list:character <- get *editor, data:offset
|
||||
deleted-cell:address:shared:duplex-list:character <- next *before-cursor
|
||||
go-render? <- copy 0/false
|
||||
reply-unless deleted-cell
|
||||
return-unless deleted-cell
|
||||
currc:character <- get *deleted-cell, value:offset
|
||||
data <- remove deleted-cell, data
|
||||
deleted-newline?:boolean <- equal currc, 10/newline
|
||||
go-render? <- copy 1/true
|
||||
reply-if deleted-newline?
|
||||
return-if deleted-newline?
|
||||
# wasn't a newline? render rest of line
|
||||
curr:address:shared:duplex-list:character <- next *before-cursor # refresh after remove above
|
||||
cursor-row:address:number <- get-address *editor, cursor-row:offset
|
||||
|
@ -366,7 +366,7 @@ recipe delete-at-cursor editor:address:shared:editor-data, screen:address:shared
|
|||
# hit right margin? give up and let caller render
|
||||
at-right?:boolean <- greater-or-equal curr-column, screen-width
|
||||
go-render? <- copy 1/true
|
||||
reply-if at-right?
|
||||
return-if at-right?
|
||||
break-unless curr
|
||||
# newline? done.
|
||||
currc:character <- get *curr, value:offset
|
||||
|
@ -421,11 +421,11 @@ after <handle-special-key> [
|
|||
screen <- move-cursor screen, *cursor-row, *cursor-column
|
||||
undo-coalesce-tag:number <- copy 2/right-arrow
|
||||
<move-cursor-end>
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe move-cursor-coordinates-right editor:address:shared:editor-data, screen-height:number -> editor:address:shared:editor-data, go-render?:boolean [
|
||||
def move-cursor-coordinates-right editor:address:shared:editor-data, screen-height:number -> editor:address:shared:editor-data, go-render?:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
before-cursor:address:shared:duplex-list:character <- get *editor before-cursor:offset
|
||||
|
@ -442,11 +442,11 @@ recipe move-cursor-coordinates-right editor:address:shared:editor-data, screen-h
|
|||
*cursor-column <- copy left
|
||||
below-screen?:boolean <- greater-or-equal *cursor-row, screen-height # must be equal
|
||||
go-render? <- copy 0/false
|
||||
reply-unless below-screen?
|
||||
return-unless below-screen?
|
||||
<scroll-down>
|
||||
*cursor-row <- subtract *cursor-row, 1 # bring back into screen range
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
# if the line wraps, move cursor to start of next row
|
||||
{
|
||||
|
@ -463,11 +463,11 @@ recipe move-cursor-coordinates-right editor:address:shared:editor-data, screen-h
|
|||
*cursor-row <- add *cursor-row, 1
|
||||
*cursor-column <- copy left
|
||||
below-screen?:boolean <- greater-or-equal *cursor-row, screen-height # must be equal
|
||||
reply-unless below-screen?, editor/same-as-ingredient:0, 0/no-more-render
|
||||
return-unless below-screen?, editor/same-as-ingredient:0, 0/no-more-render
|
||||
<scroll-down>
|
||||
*cursor-row <- subtract *cursor-row, 1 # bring back into screen range
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
# otherwise move cursor one character right
|
||||
*cursor-column <- add *cursor-column, 1
|
||||
|
@ -691,13 +691,13 @@ after <handle-special-key> [
|
|||
# if not at start of text (before-cursor at § sentinel)
|
||||
prev:address:shared:duplex-list:character <- prev *before-cursor
|
||||
go-render? <- copy 0/false
|
||||
reply-unless prev
|
||||
return-unless prev
|
||||
<move-cursor-begin>
|
||||
editor, go-render? <- move-cursor-coordinates-left editor
|
||||
*before-cursor <- copy prev
|
||||
undo-coalesce-tag:number <- copy 1/left-arrow
|
||||
<move-cursor-end>
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -954,11 +954,11 @@ after <handle-special-key> [
|
|||
editor, go-render? <- move-to-previous-line editor
|
||||
undo-coalesce-tag:number <- copy 3/up-arrow
|
||||
<move-cursor-end>
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe move-to-previous-line editor:address:shared:editor-data -> editor:address:shared:editor-data, go-render?:boolean [
|
||||
def move-to-previous-line editor:address:shared:editor-data -> editor:address:shared:editor-data, go-render?:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
cursor-row:address:number <- get-address *editor, cursor-row:offset
|
||||
|
@ -982,14 +982,14 @@ recipe move-to-previous-line editor:address:shared:editor-data -> editor:address
|
|||
curr:address:shared:duplex-list:character <- before-previous-line curr, editor
|
||||
no-motion?:boolean <- equal curr, old
|
||||
go-render? <- copy 0/false
|
||||
reply-if no-motion?
|
||||
return-if no-motion?
|
||||
}
|
||||
{
|
||||
old <- copy curr
|
||||
curr <- before-previous-line curr, editor
|
||||
no-motion?:boolean <- equal curr, old
|
||||
go-render? <- copy 0/false
|
||||
reply-if no-motion?
|
||||
return-if no-motion?
|
||||
}
|
||||
*before-cursor <- copy curr
|
||||
*cursor-row <- subtract *cursor-row, 1
|
||||
|
@ -1010,14 +1010,14 @@ recipe move-to-previous-line editor:address:shared:editor-data -> editor:address
|
|||
loop
|
||||
}
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
{
|
||||
# if cursor already at top, scroll up
|
||||
break-unless already-at-top?
|
||||
<scroll-up>
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -1179,11 +1179,11 @@ after <handle-special-key> [
|
|||
editor, go-render? <- move-to-next-line editor, screen-height
|
||||
undo-coalesce-tag:number <- copy 4/down-arrow
|
||||
<move-cursor-end>
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe move-to-next-line editor:address:shared:editor-data, screen-height:number -> editor:address:shared:editor-data, go-render?:boolean [
|
||||
def move-to-next-line editor:address:shared:editor-data, screen-height:number -> editor:address:shared:editor-data, go-render?:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
cursor-row:address:number <- get-address *editor, cursor-row:offset
|
||||
|
@ -1207,7 +1207,7 @@ recipe move-to-next-line editor:address:shared:editor-data, screen-height:number
|
|||
scroll?:boolean <- greater-than *cursor-row, 1
|
||||
break-if scroll?, +try-to-scroll:label
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
*cursor-row <- add *cursor-row, 1
|
||||
*before-cursor <- copy next-line
|
||||
|
@ -1227,7 +1227,7 @@ recipe move-to-next-line editor:address:shared:editor-data, screen-height:number
|
|||
loop
|
||||
}
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
+try-to-scroll
|
||||
<scroll-down>
|
||||
|
@ -1306,7 +1306,7 @@ after <handle-special-character> [
|
|||
undo-coalesce-tag:number <- copy 0/never
|
||||
<move-cursor-end>
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -1319,11 +1319,11 @@ after <handle-special-key> [
|
|||
undo-coalesce-tag:number <- copy 0/never
|
||||
<move-cursor-end>
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe move-to-start-of-line editor:address:shared:editor-data -> editor:address:shared:editor-data [
|
||||
def move-to-start-of-line editor:address:shared:editor-data -> editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# update cursor column
|
||||
|
@ -1477,7 +1477,7 @@ after <handle-special-character> [
|
|||
undo-coalesce-tag:number <- copy 0/never
|
||||
<move-cursor-end>
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -1490,11 +1490,11 @@ after <handle-special-key> [
|
|||
undo-coalesce-tag:number <- copy 0/never
|
||||
<move-cursor-end>
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe move-to-end-of-line editor:address:shared:editor-data -> editor:address:shared:editor-data [
|
||||
def move-to-end-of-line editor:address:shared:editor-data -> editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
|
@ -1620,11 +1620,11 @@ after <handle-special-character> [
|
|||
deleted-cells:address:shared:duplex-list:character <- delete-to-start-of-line editor
|
||||
<delete-to-start-of-line-end>
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe delete-to-start-of-line editor:address:shared:editor-data -> result:address:shared:duplex-list:character, editor:address:shared:editor-data [
|
||||
def delete-to-start-of-line editor:address:shared:editor-data -> result:address:shared:duplex-list:character, editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# compute range to delete
|
||||
|
@ -1754,11 +1754,11 @@ after <handle-special-character> [
|
|||
deleted-cells:address:shared:duplex-list:character <- delete-to-end-of-line editor
|
||||
<delete-to-end-of-line-end>
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe delete-to-end-of-line editor:address:shared:editor-data -> result:address:shared:duplex-list:character, editor:address:shared:editor-data [
|
||||
def delete-to-end-of-line editor:address:shared:editor-data -> result:address:shared:duplex-list:character, editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# compute range to delete
|
||||
|
@ -1937,13 +1937,13 @@ after <scroll-down> [
|
|||
*top-of-screen <- before-start-of-next-line *top-of-screen, max
|
||||
no-movement?:boolean <- equal old-top, *top-of-screen
|
||||
go-render? <- copy 0/false
|
||||
reply-if no-movement?
|
||||
return-if no-movement?
|
||||
]
|
||||
|
||||
# takes a pointer into the doubly-linked list, scans ahead at most 'max'
|
||||
# positions until the next newline
|
||||
# beware: never return null pointer.
|
||||
recipe before-start-of-next-line original:address:shared:duplex-list:character, max:number -> curr:address:shared:duplex-list:character [
|
||||
def before-start-of-next-line original:address:shared:duplex-list:character, max:number -> curr:address:shared:duplex-list:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
count:number <- copy 0
|
||||
|
@ -1957,7 +1957,7 @@ recipe before-start-of-next-line original:address:shared:duplex-list:character,
|
|||
count <- add count, 1
|
||||
}
|
||||
{
|
||||
reply-unless curr, original
|
||||
return-unless curr, original
|
||||
done?:boolean <- greater-or-equal count, max
|
||||
break-if done?
|
||||
c:character <- get *curr, value:offset
|
||||
|
@ -1967,8 +1967,8 @@ recipe before-start-of-next-line original:address:shared:duplex-list:character,
|
|||
count <- add count, 1
|
||||
loop
|
||||
}
|
||||
reply-unless curr, original
|
||||
reply curr
|
||||
return-unless curr, original
|
||||
return curr
|
||||
]
|
||||
|
||||
scenario editor-scrolls-down-past-wrapped-line-using-arrow-keys [
|
||||
|
@ -2304,13 +2304,13 @@ after <scroll-up> [
|
|||
*top-of-screen <- before-previous-line *top-of-screen, editor
|
||||
no-movement?:boolean <- equal old-top, *top-of-screen
|
||||
go-render? <- copy 0/false
|
||||
reply-if no-movement?
|
||||
return-if no-movement?
|
||||
]
|
||||
|
||||
# takes a pointer into the doubly-linked list, scans back to before start of
|
||||
# previous *wrapped* line
|
||||
# beware: never return null pointer
|
||||
recipe before-previous-line in:address:shared:duplex-list:character, editor:address:shared:editor-data -> out:address:shared:duplex-list:character [
|
||||
def before-previous-line in:address:shared:duplex-list:character, editor:address:shared:editor-data -> out:address:shared:duplex-list:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
curr:address:shared:duplex-list:character <- copy in
|
||||
|
@ -2327,8 +2327,8 @@ recipe before-previous-line in:address:shared:duplex-list:character, editor:addr
|
|||
break-if len
|
||||
# empty line; just skip this newline
|
||||
prev:address:shared:duplex-list:character <- prev curr
|
||||
reply-unless prev, curr
|
||||
reply prev
|
||||
return-unless prev, curr
|
||||
return prev
|
||||
}
|
||||
_, max:number <- divide-with-remainder len, max-line-length
|
||||
# remainder 0 => scan one width-worth
|
||||
|
@ -2348,7 +2348,7 @@ recipe before-previous-line in:address:shared:duplex-list:character, editor:addr
|
|||
count <- add count, 1
|
||||
loop
|
||||
}
|
||||
reply curr
|
||||
return curr
|
||||
]
|
||||
|
||||
scenario editor-scrolls-up-past-wrapped-line-using-arrow-keys [
|
||||
|
@ -2698,7 +2698,7 @@ after <handle-special-character> [
|
|||
<move-cursor-end>
|
||||
no-movement?:boolean <- equal *top-of-screen, old-top
|
||||
go-render? <- not no-movement?
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -2714,18 +2714,18 @@ after <handle-special-key> [
|
|||
<move-cursor-end>
|
||||
no-movement?:boolean <- equal *top-of-screen, old-top
|
||||
go-render? <- not no-movement?
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
# page-down skips entire wrapped lines, so it can't scroll past lines
|
||||
# taking up the entire screen
|
||||
recipe page-down editor:address:shared:editor-data -> editor:address:shared:editor-data [
|
||||
def page-down editor:address:shared:editor-data -> editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if editor contents don't overflow screen, do nothing
|
||||
bottom-of-screen:address:shared:duplex-list:character <- get *editor, bottom-of-screen:offset
|
||||
reply-unless bottom-of-screen
|
||||
return-unless bottom-of-screen
|
||||
# if not, position cursor at final character
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
*before-cursor <- prev bottom-of-screen
|
||||
|
@ -2890,7 +2890,7 @@ after <handle-special-character> [
|
|||
<move-cursor-end>
|
||||
no-movement?:boolean <- equal *top-of-screen, old-top
|
||||
go-render? <- not no-movement?
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -2907,11 +2907,11 @@ after <handle-special-key> [
|
|||
no-movement?:boolean <- equal *top-of-screen, old-top
|
||||
# don't bother re-rendering if nothing changed. todo: test this
|
||||
go-render? <- not no-movement?
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe page-up editor:address:shared:editor-data, screen-height:number -> editor:address:shared:editor-data [
|
||||
def page-up editor:address:shared:editor-data, screen-height:number -> editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
max:number <- subtract screen-height, 1/menu-bar, 1/overlapping-line
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# Consists of one editor on the left for recipes and one on the right for the
|
||||
# sandbox.
|
||||
|
||||
recipe! main [
|
||||
def! main [
|
||||
local-scope
|
||||
open-console
|
||||
initial-recipe:address:shared:array:character <- restore [recipes.mu]
|
||||
|
@ -21,7 +21,7 @@ container programming-environment-data [
|
|||
sandbox-in-focus?:boolean # false => cursor in recipes; true => cursor in current-sandbox
|
||||
]
|
||||
|
||||
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 [
|
||||
def 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
|
||||
|
@ -48,7 +48,7 @@ recipe new-programming-environment screen:address:shared:screen, initial-recipe-
|
|||
<programming-environment-initialization>
|
||||
]
|
||||
|
||||
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 [
|
||||
def 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:shared:editor-data <- get *env, recipes:offset
|
||||
|
@ -180,7 +180,7 @@ recipe event-loop screen:address:shared:screen, console:address:shared:console,
|
|||
}
|
||||
]
|
||||
|
||||
recipe resize screen:address:shared:screen, env:address:shared:programming-environment-data -> env:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
def 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
|
||||
|
@ -372,7 +372,7 @@ def]
|
|||
]
|
||||
]
|
||||
|
||||
recipe render-all screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen, env:address:shared:programming-environment-data [
|
||||
def render-all screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
trace 10, [app], [render all]
|
||||
|
@ -405,7 +405,7 @@ recipe render-all screen:address:shared:screen, env:address:shared:programming-e
|
|||
show-screen screen
|
||||
]
|
||||
|
||||
recipe render-recipes screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen, env:address:shared:programming-environment-data [
|
||||
def render-recipes screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
trace 11, [app], [render recipes]
|
||||
|
@ -424,7 +424,7 @@ recipe render-recipes screen:address:shared:screen, env:address:shared:programmi
|
|||
]
|
||||
|
||||
# replaced in a later layer
|
||||
recipe render-sandbox-side screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen, env:address:shared:programming-environment-data [
|
||||
def render-sandbox-side screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
|
@ -439,7 +439,7 @@ recipe render-sandbox-side screen:address:shared:screen, env:address:shared:prog
|
|||
clear-screen-from screen, row, left, left, right
|
||||
]
|
||||
|
||||
recipe update-cursor screen:address:shared:screen, recipes:address:shared:editor-data, current-sandbox:address:shared:editor-data, sandbox-in-focus?:boolean, env:address:shared:programming-environment-data -> screen:address:shared:screen [
|
||||
def update-cursor screen:address:shared:screen, recipes:address:shared:editor-data, current-sandbox:address:shared:editor-data, sandbox-in-focus?:boolean, env:address:shared:programming-environment-data -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
<update-cursor-special-cases>
|
||||
|
@ -458,10 +458,10 @@ recipe update-cursor screen:address:shared:screen, recipes:address:shared:editor
|
|||
|
||||
# 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:shared:screen, s:address:shared:array:character, left:number, right:number, color:number, row:number -> row:number, screen:address:shared:screen [
|
||||
def 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
|
||||
return-unless s
|
||||
column:number <- copy left
|
||||
screen <- move-cursor screen, row, column
|
||||
screen-height:number <- screen-height screen
|
||||
|
@ -519,10 +519,10 @@ recipe render screen:address:shared:screen, s:address:shared:array:character, le
|
|||
]
|
||||
|
||||
# like 'render' for texts, but with colorization for comments like in the editor
|
||||
recipe render-code screen:address:shared:screen, s:address:shared:array:character, left:number, right:number, row:number -> row:number, screen:address:shared:screen [
|
||||
def 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
|
||||
return-unless s
|
||||
color:number <- copy 7/white
|
||||
column:number <- copy left
|
||||
screen <- move-cursor screen, row, column
|
||||
|
@ -608,7 +608,7 @@ after <global-type> [
|
|||
|
||||
## helpers
|
||||
|
||||
recipe draw-vertical screen:address:shared:screen, col:number, y:number, bottom:number -> screen:address:shared:screen [
|
||||
def 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
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# (non-editable) sandboxes below the editor, showing the result and a maybe
|
||||
# few other things.
|
||||
|
||||
recipe! main [
|
||||
def! main [
|
||||
local-scope
|
||||
open-console
|
||||
initial-recipe:address:shared:array:character <- restore [recipes.mu]
|
||||
|
@ -142,11 +142,11 @@ after <global-keypress> [
|
|||
}
|
||||
]
|
||||
|
||||
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 [
|
||||
def 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?
|
||||
return-if errors-found?
|
||||
# check contents of right editor (sandbox)
|
||||
<run-sandboxes-begin>
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
|
@ -189,7 +189,7 @@ recipe run-sandboxes env:address:shared:programming-environment-data, screen:add
|
|||
|
||||
# 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:shared:programming-environment-data, screen:address:shared:screen -> errors-found?:boolean, env:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
def 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:shared:editor-data <- get *env, recipes:offset
|
||||
|
@ -200,7 +200,7 @@ recipe update-recipes env:address:shared:programming-environment-data, screen:ad
|
|||
]
|
||||
|
||||
# replaced in a later layer
|
||||
recipe! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data, idx:number -> sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data [
|
||||
def! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data, idx:number -> sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
data:address:shared:array:character <- get *sandbox, data:offset
|
||||
|
@ -209,14 +209,14 @@ recipe! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:p
|
|||
*response, _, *fake-screen <- run-interactive data
|
||||
]
|
||||
|
||||
recipe update-status screen:address:shared:screen, msg:address:shared:array:character, color:number -> screen:address:shared:screen [
|
||||
def 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:shared:programming-environment-data [
|
||||
def save-sandboxes env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
|
@ -237,7 +237,7 @@ recipe save-sandboxes env:address:shared:programming-environment-data [
|
|||
}
|
||||
]
|
||||
|
||||
recipe! render-sandbox-side screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen, env:address:shared:programming-environment-data [
|
||||
def! render-sandbox-side screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
trace 11, [app], [render sandbox side]
|
||||
|
@ -261,13 +261,13 @@ recipe! render-sandbox-side screen:address:shared:screen, env:address:shared:pro
|
|||
clear-rest-of-screen screen, row, left, right
|
||||
]
|
||||
|
||||
recipe render-sandboxes screen:address:shared:screen, sandbox:address:shared:sandbox-data, left:number, right:number, row:number, render-from:number, idx:number -> row:number, screen:address:shared:screen, sandbox:address:shared:sandbox-data [
|
||||
def render-sandboxes screen:address:shared:screen, sandbox:address:shared:sandbox-data, left:number, right:number, row:number, render-from:number, idx:number -> row:number, screen:address:shared:screen, sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
reply-unless sandbox
|
||||
return-unless sandbox
|
||||
screen-height:number <- screen-height screen
|
||||
at-bottom?:boolean <- greater-or-equal row, screen-height
|
||||
reply-if at-bottom?:boolean
|
||||
return-if at-bottom?:boolean
|
||||
hidden?:boolean <- lesser-than idx, render-from
|
||||
{
|
||||
break-if hidden?
|
||||
|
@ -304,7 +304,7 @@ recipe render-sandboxes screen:address:shared:screen, sandbox:address:shared:san
|
|||
}
|
||||
+render-sandbox-end
|
||||
at-bottom?:boolean <- greater-or-equal row, screen-height
|
||||
reply-if at-bottom?
|
||||
return-if at-bottom?
|
||||
# draw solid line after sandbox
|
||||
draw-horizontal screen, row, left, right, 9473/horizontal-double
|
||||
}
|
||||
|
@ -324,7 +324,7 @@ recipe render-sandboxes screen:address:shared:screen, sandbox:address:shared:san
|
|||
]
|
||||
|
||||
# assumes programming environment has no sandboxes; restores them from previous session
|
||||
recipe restore-sandboxes env:address:shared:programming-environment-data -> env:address:shared:programming-environment-data [
|
||||
def 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
|
||||
|
@ -358,10 +358,10 @@ recipe restore-sandboxes env:address:shared:programming-environment-data -> env:
|
|||
|
||||
# print the fake sandbox screen to 'screen' with appropriate delimiters
|
||||
# leave cursor at start of next line
|
||||
recipe render-screen screen:address:shared:screen, sandbox-screen:address:shared:screen, left:number, right:number, row:number -> row:number, screen:address:shared:screen [
|
||||
def 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
|
||||
return-unless sandbox-screen
|
||||
# print 'screen:'
|
||||
header:address:shared:array:character <- new [screen:]
|
||||
row <- render screen, header, left, right, 245/grey, row
|
||||
|
@ -510,7 +510,7 @@ scenario run-instruction-manages-screen-per-sandbox [
|
|||
]
|
||||
]
|
||||
|
||||
recipe editor-contents editor:address:shared:editor-data -> result:address:shared:array:character [
|
||||
def editor-contents editor:address:shared:editor-data -> result:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
buf:address:shared:buffer <- new-buffer 80
|
||||
|
@ -518,7 +518,7 @@ recipe editor-contents editor:address:shared:editor-data -> result:address:share
|
|||
# skip § sentinel
|
||||
assert curr, [editor without data is illegal; must have at least a sentinel]
|
||||
curr <- next curr
|
||||
reply-unless curr, 0
|
||||
return-unless curr, 0
|
||||
{
|
||||
break-unless curr
|
||||
c:character <- get *curr, value:offset
|
||||
|
@ -655,7 +655,7 @@ after <update-cursor-special-cases> [
|
|||
break-unless scrolling?
|
||||
cursor-column:number <- get *current-sandbox, left:offset
|
||||
screen <- move-cursor screen, 2/row, cursor-column # highlighted sandbox will always start at row 2
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -678,21 +678,21 @@ after <global-keypress> [
|
|||
|
||||
# sandbox belonging to 'env' whose next-sandbox is 'in'
|
||||
# return 0 if there's no such sandbox, either because 'in' doesn't exist in 'env', or because it's the first sandbox
|
||||
recipe previous-sandbox env:address:shared:programming-environment-data, in:address:shared:sandbox-data -> out:address:shared:sandbox-data [
|
||||
def previous-sandbox env:address:shared:programming-environment-data, in:address:shared:sandbox-data -> out:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
curr:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
reply-unless curr, 0/nil
|
||||
return-unless curr, 0/nil
|
||||
next:address:shared:sandbox-data <- get *curr, next-sandbox:offset
|
||||
{
|
||||
reply-unless next, 0/nil
|
||||
return-unless next, 0/nil
|
||||
found?:boolean <- equal next, in
|
||||
break-if found?
|
||||
curr <- copy next
|
||||
next <- get *curr, next-sandbox:offset
|
||||
loop
|
||||
}
|
||||
reply curr
|
||||
return curr
|
||||
]
|
||||
|
||||
scenario scrolling-down-on-recipe-side [
|
||||
|
|
|
@ -92,7 +92,7 @@ after <global-touch> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe empty-editor? editor:address:shared:editor-data -> result:boolean [
|
||||
def empty-editor? editor:address:shared:editor-data -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
head:address:shared:duplex-list:character <- get *editor, data:offset
|
||||
|
@ -100,13 +100,13 @@ recipe empty-editor? editor:address:shared:editor-data -> result:boolean [
|
|||
result <- not first
|
||||
]
|
||||
|
||||
recipe extract-sandbox env:address:shared:programming-environment-data, click-row:number -> result:address:shared:sandbox-data, env:address:shared:programming-environment-data [
|
||||
def 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
|
||||
sandbox:address:address:shared:sandbox-data <- get-address *env, sandbox:offset
|
||||
start:number <- get **sandbox, starting-row-on-screen:offset
|
||||
in-editor?:boolean <- lesser-than click-row, start
|
||||
reply-if in-editor?, 0
|
||||
return-if in-editor?, 0
|
||||
{
|
||||
next-sandbox:address:shared:sandbox-data <- get **sandbox, next-sandbox:offset
|
||||
break-unless next-sandbox
|
||||
|
|
|
@ -77,14 +77,14 @@ after <global-touch> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe delete-sandbox t:touch-event, env:address:shared:programming-environment-data -> was-delete?:boolean, env:address:shared:programming-environment-data [
|
||||
def 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: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
|
||||
return-unless at-right?, 0/false
|
||||
click-row:number <- get t, row:offset
|
||||
prev:address:address:shared:sandbox-data <- get-address *env, sandbox:offset
|
||||
curr:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
|
@ -108,13 +108,13 @@ recipe delete-sandbox t:touch-event, env:address:shared:programming-environment-
|
|||
break-unless reset-scroll?
|
||||
*render-from <- copy -1
|
||||
}
|
||||
reply 1/true # force rerender
|
||||
return 1/true # force rerender
|
||||
}
|
||||
prev <- get-address *curr, next-sandbox:offset
|
||||
curr <- get *curr, next-sandbox:offset
|
||||
loop
|
||||
}
|
||||
reply 0/false
|
||||
return 0/false
|
||||
]
|
||||
|
||||
scenario deleting-sandbox-after-scroll [
|
||||
|
|
|
@ -132,7 +132,7 @@ after <global-touch> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe find-click-in-sandbox-output env:address:shared:programming-environment-data, click-row:number -> sandbox:address:shared:sandbox-data [
|
||||
def 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
|
||||
|
@ -152,13 +152,13 @@ recipe find-click-in-sandbox-output env:address:shared:programming-environment-d
|
|||
}
|
||||
# return sandbox if click is in its output region
|
||||
response-starting-row:number <- get *sandbox, response-starting-row-on-screen:offset
|
||||
reply-unless response-starting-row, 0/no-click-in-sandbox-output
|
||||
return-unless response-starting-row, 0/no-click-in-sandbox-output
|
||||
click-in-response?:boolean <- greater-or-equal click-row, response-starting-row
|
||||
reply-unless click-in-response?, 0/no-click-in-sandbox-output
|
||||
reply sandbox
|
||||
return-unless click-in-response?, 0/no-click-in-sandbox-output
|
||||
return sandbox
|
||||
]
|
||||
|
||||
recipe toggle-expected-response sandbox:address:shared:sandbox-data -> sandbox:address:shared:sandbox-data [
|
||||
def toggle-expected-response sandbox:address:shared:sandbox-data -> sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
expected-response:address:address:shared:array:character <- get-address *sandbox, expected-response:offset
|
||||
|
@ -166,7 +166,7 @@ recipe toggle-expected-response sandbox:address:shared:sandbox-data -> sandbox:a
|
|||
# if expected-response is set, reset
|
||||
break-unless *expected-response
|
||||
*expected-response <- copy 0
|
||||
reply sandbox/same-as-ingredient:0
|
||||
return sandbox/same-as-ingredient:0
|
||||
}
|
||||
# if not, current response is the expected response
|
||||
response:address:shared:array:character <- get *sandbox, response:offset
|
||||
|
|
|
@ -81,7 +81,7 @@ scenario sandbox-shows-app-trace-and-result [
|
|||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
stash [abc]
|
||||
reply 4
|
||||
reply 4
|
||||
]]
|
||||
# run it
|
||||
2:address:shared:array:character <- new [foo]
|
||||
|
@ -127,7 +127,7 @@ container sandbox-data [
|
|||
]
|
||||
|
||||
# replaced in a later layer
|
||||
recipe! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data, idx:number -> sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data [
|
||||
def! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data, idx:number -> sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
data:address:shared:array:character <- get *sandbox, data:offset
|
||||
|
@ -166,7 +166,7 @@ after <global-touch> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe find-click-in-sandbox-code env:address:shared:programming-environment-data, click-row:number -> sandbox:address:shared:sandbox-data [
|
||||
def 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
|
||||
|
@ -192,9 +192,9 @@ recipe find-click-in-sandbox-code env:address:shared:programming-environment-dat
|
|||
click-on-sandbox-code?:boolean <- and click-above-response?, click-below-menu?
|
||||
{
|
||||
break-if click-on-sandbox-code?
|
||||
reply 0/no-click-in-sandbox-output
|
||||
return 0/no-click-in-sandbox-output
|
||||
}
|
||||
reply sandbox
|
||||
return sandbox
|
||||
]
|
||||
|
||||
# when rendering a sandbox, dump its trace before response/warning if display-trace? property is set
|
||||
|
|
|
@ -5,7 +5,7 @@ container programming-environment-data [
|
|||
]
|
||||
|
||||
# copy code from recipe editor, persist, load into mu, save any errors
|
||||
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 [
|
||||
def! 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:shared:editor-data <- get *env, recipes:offset
|
||||
|
@ -19,7 +19,7 @@ recipe! update-recipes env:address:shared:programming-environment-data, screen:a
|
|||
status:address:shared:array:character <- new [errors found ]
|
||||
update-status screen, status, 1/red
|
||||
errors-found? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
errors-found? <- copy 0/false
|
||||
]
|
||||
|
@ -81,7 +81,7 @@ container sandbox-data [
|
|||
errors:address:shared:array:character
|
||||
]
|
||||
|
||||
recipe! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data, idx:number -> sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data [
|
||||
def! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data, idx:number -> sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
data:address:shared:array:character <- get *sandbox, data:offset
|
||||
|
|
|
@ -72,7 +72,7 @@ after <handle-special-character> [
|
|||
redo:address:address:shared:list:address:shared:operation <- get-address *editor, redo:offset
|
||||
*redo <- push op, *redo
|
||||
<handle-undo>
|
||||
reply screen/same-as-ingredient:0, editor/same-as-ingredient:1, 1/go-render
|
||||
return screen/same-as-ingredient:0, editor/same-as-ingredient:1, 1/go-render
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -88,7 +88,7 @@ after <handle-special-character> [
|
|||
undo:address:address:shared:list:address:shared:operation <- get-address *editor, undo:offset
|
||||
*undo <- push op, *undo
|
||||
<handle-redo>
|
||||
reply screen/same-as-ingredient:0, editor/same-as-ingredient:1, 1/go-render
|
||||
return screen/same-as-ingredient:0, editor/same-as-ingredient:1, 1/go-render
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -189,14 +189,14 @@ before <insert-enter-end> [
|
|||
# redo stack, because it's now obsolete.
|
||||
# Beware: since we're counting cursor moves as operations, this means just
|
||||
# moving the cursor can lose work on the undo stack.
|
||||
recipe add-operation editor:address:shared:editor-data, op:address:shared:operation -> editor:address:shared:editor-data [
|
||||
def add-operation editor:address:shared:editor-data, op:address:shared:operation -> editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
undo:address:address:shared:list:address:shared:operation <- get-address *editor, undo:offset
|
||||
*undo <- push op *undo
|
||||
redo:address:address:shared:list:address:shared:operation <- get-address *editor, redo:offset
|
||||
*redo <- copy 0
|
||||
reply editor/same-as-ingredient:0
|
||||
return editor/same-as-ingredient:0
|
||||
]
|
||||
|
||||
after <handle-undo> [
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
recipe example1 [
|
||||
def example1 [
|
||||
local-scope
|
||||
a:number <- add 2, 2
|
||||
a <- multiply a, 3
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
# example program: compute the factorial of 5
|
||||
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
x:number <- factorial 5
|
||||
$print [result: ], x, [
|
||||
]
|
||||
]
|
||||
|
||||
recipe factorial n:number -> result:number [
|
||||
def factorial n:number -> result:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
# if n=0 return 1
|
||||
zero?:boolean <- equal n, 0
|
||||
break-unless zero?
|
||||
reply 1
|
||||
return 1
|
||||
}
|
||||
# return n * factorial(n-1)
|
||||
x:number <- subtract n, 1
|
||||
|
|
4
fork.mu
|
@ -1,6 +1,6 @@
|
|||
# example program: running multiple routines
|
||||
|
||||
recipe main [
|
||||
def main [
|
||||
start-running thread2
|
||||
{
|
||||
$print 34
|
||||
|
@ -8,7 +8,7 @@ recipe main [
|
|||
}
|
||||
]
|
||||
|
||||
recipe thread2 [
|
||||
def thread2 [
|
||||
{
|
||||
$print 35
|
||||
loop
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# example program: creating and using global variables
|
||||
|
||||
recipe main [
|
||||
def main [
|
||||
# allocate 5 locations for globals
|
||||
global-space:address:shared:array:location <- new location:type, 5
|
||||
# read to globals by using /space:global
|
||||
|
@ -8,7 +8,7 @@ recipe main [
|
|||
foo
|
||||
]
|
||||
|
||||
recipe foo [
|
||||
def foo [
|
||||
# ditto for writing to globals
|
||||
$print 1:number/space:global, 10/newline
|
||||
]
|
||||
|
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 21 KiB |
BIN
html/edit.png
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 9.2 KiB |
BIN
html/f2c-1.png
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
BIN
html/f2c-2.png
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 9.1 KiB |
4
mu.vim
|
@ -58,9 +58,9 @@ syntax keyword muKeyword default-space global-space new-default-space local-scop
|
|||
syntax match muDelimiter "[{}]" | highlight link muDelimiter Delimiter
|
||||
syntax match muAssign " <- \|\<raw\>" | highlight link muAssign SpecialChar
|
||||
syntax match muGlobal %[^ ]\+:global/\?[^ ,]*% | highlight link muGlobal SpecialChar
|
||||
syntax keyword muControl reply reply-if reply-unless jump jump-if jump-unless loop loop-if loop-unless break break-if break-unless current-continuation continue-from create-delimited-continuation reply-delimited-continuation | highlight muControl ctermfg=3
|
||||
syntax keyword muControl reply reply-if reply-unless return return-if return-unless jump jump-if jump-unless loop loop-if loop-unless break break-if break-unless current-continuation continue-from create-delimited-continuation reply-delimited-continuation | highlight muControl ctermfg=3
|
||||
" common keywords
|
||||
syntax keyword muRecipe recipe recipe! before after | highlight muRecipe ctermfg=208
|
||||
syntax keyword muRecipe recipe recipe! def def! before after | highlight muRecipe ctermfg=208
|
||||
syntax match muRecipe " -> "
|
||||
syntax keyword muScenario scenario | highlight muScenario ctermfg=34
|
||||
syntax keyword muData container exclusive-container | highlight muData ctermfg=226
|
||||
|
|
|
@ -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:shared:array:character [
|
||||
def! main text:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
open-console
|
||||
|
@ -48,7 +48,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:shared:array:character, screen:address:shared:screen, left:number, right:number -> result:address:shared:editor-data, screen:address:shared:screen [
|
||||
def 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
|
||||
|
@ -79,13 +79,13 @@ recipe new-editor s:address:shared:array:character, screen:address:shared:screen
|
|||
<editor-initialization>
|
||||
]
|
||||
|
||||
recipe insert-text editor:address:shared:editor-data, text:address:shared:array:character -> editor:address:shared:editor-data [
|
||||
def 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
|
||||
reply-unless text, editor/same-as-ingredient:0
|
||||
return-unless text, editor/same-as-ingredient:0
|
||||
len:number <- length *text
|
||||
reply-unless len, editor/same-as-ingredient:0
|
||||
return-unless len, editor/same-as-ingredient:0
|
||||
idx:number <- copy 0
|
||||
# now we can start appending the rest, character by character
|
||||
curr:address:shared:duplex-list:character <- get *editor, data:offset
|
||||
|
@ -99,7 +99,7 @@ recipe insert-text editor:address:shared:editor-data, text:address:shared:array:
|
|||
idx <- add idx, 1
|
||||
loop
|
||||
}
|
||||
reply editor/same-as-ingredient:0
|
||||
return editor/same-as-ingredient:0
|
||||
]
|
||||
|
||||
scenario editor-initializes-without-data [
|
||||
|
@ -129,10 +129,10 @@ 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:shared:screen, editor:address:shared:editor-data -> last-row:number, last-column:number, screen:address:shared:screen, editor:address:shared:editor-data [
|
||||
def 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
|
||||
return-unless editor, 1/top, 0/left, screen/same-as-ingredient:0, editor/same-as-ingredient:1
|
||||
left:number <- get *editor, left:offset
|
||||
screen-height:number <- screen-height screen
|
||||
right:number <- get *editor, right:offset
|
||||
|
@ -226,10 +226,10 @@ recipe render screen:address:shared:screen, editor:address:shared:editor-data ->
|
|||
}
|
||||
bottom:address:number <- get-address *editor, bottom:offset
|
||||
*bottom <- copy row
|
||||
reply row, column, screen/same-as-ingredient:0, editor/same-as-ingredient:1
|
||||
return row, column, screen/same-as-ingredient:0, editor/same-as-ingredient:1
|
||||
]
|
||||
|
||||
recipe clear-line-delimited screen:address:shared:screen, column:number, right:number -> screen:address:shared:screen [
|
||||
def clear-line-delimited screen:address:shared:screen, column:number, right:number -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
space:character <- copy 32/space
|
||||
|
@ -248,23 +248,23 @@ recipe clear-line-delimited screen:address:shared:screen, column:number, right:n
|
|||
}
|
||||
]
|
||||
|
||||
recipe clear-screen-from screen:address:shared:screen, row:number, column:number, left:number, right:number -> screen:address:shared:screen [
|
||||
def 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
|
||||
{
|
||||
break-if screen
|
||||
clear-display-from row, column, left, right
|
||||
reply screen/same-as-ingredient:0
|
||||
return screen/same-as-ingredient:0
|
||||
}
|
||||
# if not, go the slower route
|
||||
screen <- move-cursor screen, row, column
|
||||
clear-line-delimited screen, column, right
|
||||
clear-rest-of-screen screen, row, left, right
|
||||
reply screen/same-as-ingredient:0
|
||||
return screen/same-as-ingredient:0
|
||||
]
|
||||
|
||||
recipe clear-rest-of-screen screen:address:shared:screen, row:number, left:number, right:number -> screen:address:shared:screen [
|
||||
def 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
|
||||
|
@ -422,7 +422,7 @@ after <character-c-received> [
|
|||
]
|
||||
|
||||
# so far the previous color is all the information we need; that may change
|
||||
recipe get-color color:number, c:character -> color:number [
|
||||
def get-color color:number, c:character -> color:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
color-is-white?:boolean <- equal color, 7/white
|
||||
|
@ -464,7 +464,7 @@ recipe get-color color:number, c:character -> color:number [
|
|||
}
|
||||
# otherwise no change
|
||||
+exit
|
||||
reply color
|
||||
return color
|
||||
]
|
||||
|
||||
scenario render-colors-assignment [
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# temporary main: interactive editor
|
||||
# hit ctrl-c to exit
|
||||
recipe! main text:address:shared:array:character [
|
||||
def! main text:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
open-console
|
||||
|
@ -11,7 +11,7 @@ recipe! main text:address:shared:array:character [
|
|||
close-console
|
||||
]
|
||||
|
||||
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 [
|
||||
def 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
|
||||
{
|
||||
|
@ -45,35 +45,35 @@ recipe editor-event-loop screen:address:shared:screen, console:address:shared:co
|
|||
]
|
||||
|
||||
# process click, return if it was on current editor
|
||||
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 [
|
||||
def 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
|
||||
return-unless editor, 0/false
|
||||
click-row:number <- get t, row:offset
|
||||
reply-unless click-row, 0/false # ignore clicks on 'menu'
|
||||
return-unless click-row, 0/false # ignore clicks on 'menu'
|
||||
click-column:number <- get t, column:offset
|
||||
left:number <- get *editor, left:offset
|
||||
too-far-left?:boolean <- lesser-than click-column, left
|
||||
reply-if too-far-left?, 0/false
|
||||
return-if too-far-left?, 0/false
|
||||
right:number <- get *editor, right:offset
|
||||
too-far-right?:boolean <- greater-than click-column, right
|
||||
reply-if too-far-right?, 0/false
|
||||
return-if too-far-right?, 0/false
|
||||
# position cursor
|
||||
<move-cursor-begin>
|
||||
editor <- snap-cursor screen, editor, click-row, click-column
|
||||
undo-coalesce-tag:number <- copy 0/never
|
||||
<move-cursor-end>
|
||||
# gain focus
|
||||
reply 1/true
|
||||
return 1/true
|
||||
]
|
||||
|
||||
# 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:shared:screen, editor:address:shared:editor-data, target-row:number, target-column:number -> editor:address:shared:editor-data [
|
||||
def 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
|
||||
return-unless editor
|
||||
left:number <- get *editor, left:offset
|
||||
right:number <- get *editor, right:offset
|
||||
screen-height:number <- screen-height screen
|
||||
|
@ -155,11 +155,11 @@ recipe snap-cursor screen:address:shared:screen, editor:address:shared:editor-da
|
|||
|
||||
# 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:shared:screen, editor:address:shared:editor-data, e:event -> screen:address:shared:screen, editor:address:shared:editor-data, go-render?:boolean [
|
||||
def 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
|
||||
reply-unless editor
|
||||
return-unless editor
|
||||
screen-width:number <- screen-width screen
|
||||
screen-height:number <- screen-height screen
|
||||
left:number <- get *editor, left:offset
|
||||
|
@ -179,12 +179,12 @@ recipe handle-keyboard-event screen:address:shared:screen, editor:address:shared
|
|||
# ignore any other special characters
|
||||
regular-character?:boolean <- greater-or-equal *c, 32/space
|
||||
go-render? <- copy 0/false
|
||||
reply-unless regular-character?
|
||||
return-unless regular-character?
|
||||
# otherwise type it in
|
||||
<insert-character-begin>
|
||||
editor, screen, go-render?:boolean <- insert-at-cursor editor, *c, screen
|
||||
<insert-character-end>
|
||||
reply
|
||||
return
|
||||
}
|
||||
# special key to modify the text or move the cursor
|
||||
k:address:number <- maybe-convert e:event, keycode:variant
|
||||
|
@ -192,10 +192,10 @@ recipe handle-keyboard-event screen:address:shared:screen, editor:address:shared
|
|||
# handlers for each special key will go here
|
||||
<handle-special-key>
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
]
|
||||
|
||||
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 [
|
||||
def 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:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
|
@ -226,7 +226,7 @@ recipe insert-at-cursor editor:address:shared:editor-data, c:character, screen:a
|
|||
move-cursor screen, save-row, save-column
|
||||
print screen, c
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
{
|
||||
# not at right margin? print the character and rest of line
|
||||
|
@ -240,7 +240,7 @@ recipe insert-at-cursor editor:address:shared:editor-data, c:character, screen:a
|
|||
# hit right margin? give up and let caller render
|
||||
go-render? <- copy 1/true
|
||||
at-right?:boolean <- greater-than curr-column, right
|
||||
reply-if at-right?
|
||||
return-if at-right?
|
||||
break-unless curr
|
||||
# newline? done.
|
||||
currc:character <- get *curr, value:offset
|
||||
|
@ -252,14 +252,14 @@ recipe insert-at-cursor editor:address:shared:editor-data, c:character, screen:a
|
|||
loop
|
||||
}
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
]
|
||||
|
||||
# helper for tests
|
||||
recipe editor-render screen:address:shared:screen, editor:address:shared:editor-data -> screen:address:shared:screen, editor:address:shared:editor-data [
|
||||
def 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
|
||||
|
@ -697,7 +697,7 @@ after <insert-character-special-case> [
|
|||
<scroll-down>
|
||||
}
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -818,11 +818,11 @@ after <handle-special-character> [
|
|||
editor <- insert-new-line-and-indent editor, screen
|
||||
<insert-enter-end>
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
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 [
|
||||
def 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
|
||||
|
@ -846,7 +846,7 @@ recipe insert-new-line-and-indent editor:address:shared:editor-data, screen:addr
|
|||
}
|
||||
# indent if necessary
|
||||
indent?:boolean <- get *editor, indent?:offset
|
||||
reply-unless indent?
|
||||
return-unless indent?
|
||||
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
|
||||
|
@ -862,13 +862,13 @@ recipe insert-new-line-and-indent editor:address:shared:editor-data, screen:addr
|
|||
|
||||
# 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:shared:duplex-list:character, start:address:shared:duplex-list:character -> result:number [
|
||||
def line-indent curr:address:shared:duplex-list:character, start:address:shared:duplex-list:character -> result:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result:number <- copy 0
|
||||
reply-unless curr
|
||||
return-unless curr
|
||||
at-start?:boolean <- equal curr, start
|
||||
reply-if at-start?
|
||||
return-if at-start?
|
||||
{
|
||||
curr <- prev curr
|
||||
break-unless curr
|
||||
|
@ -995,7 +995,7 @@ after <handle-special-key> [
|
|||
indent?:address:boolean <- get-address *editor, indent?:offset
|
||||
*indent? <- copy 0/false
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -1006,13 +1006,13 @@ after <handle-special-key> [
|
|||
indent?:address:boolean <- get-address *editor, indent?:offset
|
||||
*indent? <- copy 1/true
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
## helpers
|
||||
|
||||
recipe draw-horizontal screen:address:shared:screen, row:number, x:number, right:number -> screen:address:shared:screen [
|
||||
def 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
|
||||
|
|
|
@ -32,7 +32,7 @@ after <handle-special-character> [
|
|||
editor, screen, go-render?:boolean <- insert-at-cursor editor, 32/space, screen
|
||||
<insert-character-end>
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -73,14 +73,14 @@ after <handle-special-character> [
|
|||
<backspace-character-begin>
|
||||
editor, screen, go-render?:boolean, backspaced-cell:address:shared:duplex-list:character <- delete-before-cursor editor, screen
|
||||
<backspace-character-end>
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
# return values:
|
||||
# go-render? - whether caller needs to update the screen
|
||||
# backspaced-cell - value deleted (or 0 if nothing was deleted) so we can save it for undo, etc.
|
||||
recipe delete-before-cursor editor:address:shared:editor-data, screen:address:shared:screen -> editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean, backspaced-cell:address:shared:duplex-list:character [
|
||||
def delete-before-cursor editor:address:shared:editor-data, screen:address:shared:screen -> editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean, backspaced-cell:address:shared:duplex-list:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
|
@ -88,7 +88,7 @@ recipe delete-before-cursor editor:address:shared:editor-data, screen:address:sh
|
|||
# if at start of text (before-cursor at § sentinel), return
|
||||
prev:address:shared:duplex-list:character <- prev *before-cursor
|
||||
go-render?, backspaced-cell <- copy 0/no-more-render, 0/nothing-deleted
|
||||
reply-unless prev
|
||||
return-unless prev
|
||||
trace 10, [app], [delete-before-cursor]
|
||||
original-row:number <- get *editor, cursor-row:offset
|
||||
editor, scroll?:boolean <- move-cursor-coordinates-left editor
|
||||
|
@ -96,14 +96,14 @@ recipe delete-before-cursor editor:address:shared:editor-data, screen:address:sh
|
|||
data <- remove *before-cursor, data # will also neatly trim next/prev pointers in backspaced-cell/*before-cursor
|
||||
*before-cursor <- copy prev
|
||||
go-render? <- copy 1/true
|
||||
reply-if scroll?
|
||||
return-if scroll?
|
||||
screen-width:number <- screen-width screen
|
||||
cursor-row:number <- get *editor, cursor-row:offset
|
||||
cursor-column:number <- get *editor, cursor-column:offset
|
||||
# did we just backspace over a newline?
|
||||
same-row?:boolean <- equal cursor-row, original-row
|
||||
go-render? <- copy 1/true
|
||||
reply-unless same-row?
|
||||
return-unless same-row?
|
||||
left:number <- get *editor, left:offset
|
||||
right:number <- get *editor, right:offset
|
||||
curr:address:shared:duplex-list:character <- next *before-cursor
|
||||
|
@ -113,7 +113,7 @@ recipe delete-before-cursor editor:address:shared:editor-data, screen:address:sh
|
|||
# hit right margin? give up and let caller render
|
||||
at-right?:boolean <- greater-or-equal curr-column, right
|
||||
go-render? <- copy 1/true
|
||||
reply-if at-right?
|
||||
return-if at-right?
|
||||
break-unless curr
|
||||
# newline? done.
|
||||
currc:character <- get *curr, value:offset
|
||||
|
@ -130,7 +130,7 @@ recipe delete-before-cursor editor:address:shared:editor-data, screen:address:sh
|
|||
go-render? <- copy 0/false
|
||||
]
|
||||
|
||||
recipe move-cursor-coordinates-left editor:address:shared:editor-data -> editor:address:shared:editor-data, go-render?:boolean [
|
||||
def move-cursor-coordinates-left editor:address:shared:editor-data -> editor:address:shared:editor-data, go-render?:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
before-cursor:address:shared:duplex-list:character <- get *editor, before-cursor:offset
|
||||
|
@ -144,7 +144,7 @@ recipe move-cursor-coordinates-left editor:address:shared:editor-data -> editor:
|
|||
trace 10, [app], [decrementing cursor column]
|
||||
*cursor-column <- subtract *cursor-column, 1
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
# if at left margin, we must move to previous row:
|
||||
top-of-screen?:boolean <- equal *cursor-row, 1 # exclude menu bar
|
||||
|
@ -179,7 +179,7 @@ recipe move-cursor-coordinates-left editor:address:shared:editor-data -> editor:
|
|||
break-if wrap?
|
||||
*cursor-column <- add left, end-of-line
|
||||
}
|
||||
reply
|
||||
return
|
||||
}
|
||||
# case 2: if previous-character was not newline, we're just at a wrapped line
|
||||
trace 10, [app], [wrapping to previous line]
|
||||
|
@ -189,13 +189,13 @@ recipe move-cursor-coordinates-left editor:address:shared:editor-data -> editor:
|
|||
|
||||
# takes a pointer 'curr' into the doubly-linked list and its sentinel, counts
|
||||
# the length of the previous line before the 'curr' pointer.
|
||||
recipe previous-line-length curr:address:shared:duplex-list:character, start:address:shared:duplex-list:character -> result:number [
|
||||
def previous-line-length curr:address:shared:duplex-list:character, start:address:shared:duplex-list:character -> result:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
result:number <- copy 0
|
||||
reply-unless curr
|
||||
return-unless curr
|
||||
at-start?:boolean <- equal curr, start
|
||||
reply-if at-start?
|
||||
return-if at-start?
|
||||
{
|
||||
curr <- prev curr
|
||||
break-unless curr
|
||||
|
@ -338,23 +338,23 @@ after <handle-special-key> [
|
|||
<delete-character-begin>
|
||||
editor, screen, go-render?:boolean, deleted-cell:address:shared:duplex-list:character <- delete-at-cursor editor, screen
|
||||
<delete-character-end>
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe delete-at-cursor editor:address:shared:editor-data, screen:address:shared:screen -> editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean, deleted-cell:address:shared:duplex-list:character [
|
||||
def delete-at-cursor editor:address:shared:editor-data, screen:address:shared:screen -> editor:address:shared:editor-data, screen:address:shared:screen, go-render?:boolean, deleted-cell:address:shared:duplex-list:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
data:address:shared:duplex-list:character <- get *editor, data:offset
|
||||
deleted-cell:address:shared:duplex-list:character <- next *before-cursor
|
||||
go-render? <- copy 0/false
|
||||
reply-unless deleted-cell
|
||||
return-unless deleted-cell
|
||||
currc:character <- get *deleted-cell, value:offset
|
||||
data <- remove deleted-cell, data
|
||||
deleted-newline?:boolean <- equal currc, 10/newline
|
||||
go-render? <- copy 1/true
|
||||
reply-if deleted-newline?
|
||||
return-if deleted-newline?
|
||||
# wasn't a newline? render rest of line
|
||||
curr:address:shared:duplex-list:character <- next *before-cursor # refresh after remove above
|
||||
cursor-row:address:number <- get-address *editor, cursor-row:offset
|
||||
|
@ -366,7 +366,7 @@ recipe delete-at-cursor editor:address:shared:editor-data, screen:address:shared
|
|||
# hit right margin? give up and let caller render
|
||||
at-right?:boolean <- greater-or-equal curr-column, screen-width
|
||||
go-render? <- copy 1/true
|
||||
reply-if at-right?
|
||||
return-if at-right?
|
||||
break-unless curr
|
||||
# newline? done.
|
||||
currc:character <- get *curr, value:offset
|
||||
|
@ -421,11 +421,11 @@ after <handle-special-key> [
|
|||
screen <- move-cursor screen, *cursor-row, *cursor-column
|
||||
undo-coalesce-tag:number <- copy 2/right-arrow
|
||||
<move-cursor-end>
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe move-cursor-coordinates-right editor:address:shared:editor-data, screen-height:number -> editor:address:shared:editor-data, go-render?:boolean [
|
||||
def move-cursor-coordinates-right editor:address:shared:editor-data, screen-height:number -> editor:address:shared:editor-data, go-render?:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
before-cursor:address:shared:duplex-list:character <- get *editor before-cursor:offset
|
||||
|
@ -442,11 +442,11 @@ recipe move-cursor-coordinates-right editor:address:shared:editor-data, screen-h
|
|||
*cursor-column <- copy left
|
||||
below-screen?:boolean <- greater-or-equal *cursor-row, screen-height # must be equal
|
||||
go-render? <- copy 0/false
|
||||
reply-unless below-screen?
|
||||
return-unless below-screen?
|
||||
<scroll-down>
|
||||
*cursor-row <- subtract *cursor-row, 1 # bring back into screen range
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
# if the line wraps, move cursor to start of next row
|
||||
{
|
||||
|
@ -463,11 +463,11 @@ recipe move-cursor-coordinates-right editor:address:shared:editor-data, screen-h
|
|||
*cursor-row <- add *cursor-row, 1
|
||||
*cursor-column <- copy left
|
||||
below-screen?:boolean <- greater-or-equal *cursor-row, screen-height # must be equal
|
||||
reply-unless below-screen?, editor/same-as-ingredient:0, 0/no-more-render
|
||||
return-unless below-screen?, editor/same-as-ingredient:0, 0/no-more-render
|
||||
<scroll-down>
|
||||
*cursor-row <- subtract *cursor-row, 1 # bring back into screen range
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
# otherwise move cursor one character right
|
||||
*cursor-column <- add *cursor-column, 1
|
||||
|
@ -691,13 +691,13 @@ after <handle-special-key> [
|
|||
# if not at start of text (before-cursor at § sentinel)
|
||||
prev:address:shared:duplex-list:character <- prev *before-cursor
|
||||
go-render? <- copy 0/false
|
||||
reply-unless prev
|
||||
return-unless prev
|
||||
<move-cursor-begin>
|
||||
editor, go-render? <- move-cursor-coordinates-left editor
|
||||
*before-cursor <- copy prev
|
||||
undo-coalesce-tag:number <- copy 1/left-arrow
|
||||
<move-cursor-end>
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -954,11 +954,11 @@ after <handle-special-key> [
|
|||
editor, go-render? <- move-to-previous-line editor
|
||||
undo-coalesce-tag:number <- copy 3/up-arrow
|
||||
<move-cursor-end>
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe move-to-previous-line editor:address:shared:editor-data -> editor:address:shared:editor-data, go-render?:boolean [
|
||||
def move-to-previous-line editor:address:shared:editor-data -> editor:address:shared:editor-data, go-render?:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
cursor-row:address:number <- get-address *editor, cursor-row:offset
|
||||
|
@ -982,14 +982,14 @@ recipe move-to-previous-line editor:address:shared:editor-data -> editor:address
|
|||
curr:address:shared:duplex-list:character <- before-previous-line curr, editor
|
||||
no-motion?:boolean <- equal curr, old
|
||||
go-render? <- copy 0/false
|
||||
reply-if no-motion?
|
||||
return-if no-motion?
|
||||
}
|
||||
{
|
||||
old <- copy curr
|
||||
curr <- before-previous-line curr, editor
|
||||
no-motion?:boolean <- equal curr, old
|
||||
go-render? <- copy 0/false
|
||||
reply-if no-motion?
|
||||
return-if no-motion?
|
||||
}
|
||||
*before-cursor <- copy curr
|
||||
*cursor-row <- subtract *cursor-row, 1
|
||||
|
@ -1010,14 +1010,14 @@ recipe move-to-previous-line editor:address:shared:editor-data -> editor:address
|
|||
loop
|
||||
}
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
{
|
||||
# if cursor already at top, scroll up
|
||||
break-unless already-at-top?
|
||||
<scroll-up>
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -1179,11 +1179,11 @@ after <handle-special-key> [
|
|||
editor, go-render? <- move-to-next-line editor, screen-height
|
||||
undo-coalesce-tag:number <- copy 4/down-arrow
|
||||
<move-cursor-end>
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe move-to-next-line editor:address:shared:editor-data, screen-height:number -> editor:address:shared:editor-data, go-render?:boolean [
|
||||
def move-to-next-line editor:address:shared:editor-data, screen-height:number -> editor:address:shared:editor-data, go-render?:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
cursor-row:address:number <- get-address *editor, cursor-row:offset
|
||||
|
@ -1207,7 +1207,7 @@ recipe move-to-next-line editor:address:shared:editor-data, screen-height:number
|
|||
scroll?:boolean <- greater-than *cursor-row, 1
|
||||
break-if scroll?, +try-to-scroll:label
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
*cursor-row <- add *cursor-row, 1
|
||||
*before-cursor <- copy next-line
|
||||
|
@ -1227,7 +1227,7 @@ recipe move-to-next-line editor:address:shared:editor-data, screen-height:number
|
|||
loop
|
||||
}
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
+try-to-scroll
|
||||
<scroll-down>
|
||||
|
@ -1306,7 +1306,7 @@ after <handle-special-character> [
|
|||
undo-coalesce-tag:number <- copy 0/never
|
||||
<move-cursor-end>
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -1319,11 +1319,11 @@ after <handle-special-key> [
|
|||
undo-coalesce-tag:number <- copy 0/never
|
||||
<move-cursor-end>
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe move-to-start-of-line editor:address:shared:editor-data -> editor:address:shared:editor-data [
|
||||
def move-to-start-of-line editor:address:shared:editor-data -> editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# update cursor column
|
||||
|
@ -1477,7 +1477,7 @@ after <handle-special-character> [
|
|||
undo-coalesce-tag:number <- copy 0/never
|
||||
<move-cursor-end>
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -1490,11 +1490,11 @@ after <handle-special-key> [
|
|||
undo-coalesce-tag:number <- copy 0/never
|
||||
<move-cursor-end>
|
||||
go-render? <- copy 0/false
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe move-to-end-of-line editor:address:shared:editor-data -> editor:address:shared:editor-data [
|
||||
def move-to-end-of-line editor:address:shared:editor-data -> editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
|
@ -1620,11 +1620,11 @@ after <handle-special-character> [
|
|||
deleted-cells:address:shared:duplex-list:character <- delete-to-start-of-line editor
|
||||
<delete-to-start-of-line-end>
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe delete-to-start-of-line editor:address:shared:editor-data -> result:address:shared:duplex-list:character, editor:address:shared:editor-data [
|
||||
def delete-to-start-of-line editor:address:shared:editor-data -> result:address:shared:duplex-list:character, editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# compute range to delete
|
||||
|
@ -1754,11 +1754,11 @@ after <handle-special-character> [
|
|||
deleted-cells:address:shared:duplex-list:character <- delete-to-end-of-line editor
|
||||
<delete-to-end-of-line-end>
|
||||
go-render? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe delete-to-end-of-line editor:address:shared:editor-data -> result:address:shared:duplex-list:character, editor:address:shared:editor-data [
|
||||
def delete-to-end-of-line editor:address:shared:editor-data -> result:address:shared:duplex-list:character, editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# compute range to delete
|
||||
|
@ -1937,13 +1937,13 @@ after <scroll-down> [
|
|||
*top-of-screen <- before-start-of-next-line *top-of-screen, max
|
||||
no-movement?:boolean <- equal old-top, *top-of-screen
|
||||
go-render? <- copy 0/false
|
||||
reply-if no-movement?
|
||||
return-if no-movement?
|
||||
]
|
||||
|
||||
# takes a pointer into the doubly-linked list, scans ahead at most 'max'
|
||||
# positions until the next newline
|
||||
# beware: never return null pointer.
|
||||
recipe before-start-of-next-line original:address:shared:duplex-list:character, max:number -> curr:address:shared:duplex-list:character [
|
||||
def before-start-of-next-line original:address:shared:duplex-list:character, max:number -> curr:address:shared:duplex-list:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
count:number <- copy 0
|
||||
|
@ -1957,7 +1957,7 @@ recipe before-start-of-next-line original:address:shared:duplex-list:character,
|
|||
count <- add count, 1
|
||||
}
|
||||
{
|
||||
reply-unless curr, original
|
||||
return-unless curr, original
|
||||
done?:boolean <- greater-or-equal count, max
|
||||
break-if done?
|
||||
c:character <- get *curr, value:offset
|
||||
|
@ -1967,8 +1967,8 @@ recipe before-start-of-next-line original:address:shared:duplex-list:character,
|
|||
count <- add count, 1
|
||||
loop
|
||||
}
|
||||
reply-unless curr, original
|
||||
reply curr
|
||||
return-unless curr, original
|
||||
return curr
|
||||
]
|
||||
|
||||
scenario editor-scrolls-down-past-wrapped-line-using-arrow-keys [
|
||||
|
@ -2304,13 +2304,13 @@ after <scroll-up> [
|
|||
*top-of-screen <- before-previous-line *top-of-screen, editor
|
||||
no-movement?:boolean <- equal old-top, *top-of-screen
|
||||
go-render? <- copy 0/false
|
||||
reply-if no-movement?
|
||||
return-if no-movement?
|
||||
]
|
||||
|
||||
# takes a pointer into the doubly-linked list, scans back to before start of
|
||||
# previous *wrapped* line
|
||||
# beware: never return null pointer
|
||||
recipe before-previous-line in:address:shared:duplex-list:character, editor:address:shared:editor-data -> out:address:shared:duplex-list:character [
|
||||
def before-previous-line in:address:shared:duplex-list:character, editor:address:shared:editor-data -> out:address:shared:duplex-list:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
curr:address:shared:duplex-list:character <- copy in
|
||||
|
@ -2327,8 +2327,8 @@ recipe before-previous-line in:address:shared:duplex-list:character, editor:addr
|
|||
break-if len
|
||||
# empty line; just skip this newline
|
||||
prev:address:shared:duplex-list:character <- prev curr
|
||||
reply-unless prev, curr
|
||||
reply prev
|
||||
return-unless prev, curr
|
||||
return prev
|
||||
}
|
||||
_, max:number <- divide-with-remainder len, max-line-length
|
||||
# remainder 0 => scan one width-worth
|
||||
|
@ -2348,7 +2348,7 @@ recipe before-previous-line in:address:shared:duplex-list:character, editor:addr
|
|||
count <- add count, 1
|
||||
loop
|
||||
}
|
||||
reply curr
|
||||
return curr
|
||||
]
|
||||
|
||||
scenario editor-scrolls-up-past-wrapped-line-using-arrow-keys [
|
||||
|
@ -2698,7 +2698,7 @@ after <handle-special-character> [
|
|||
<move-cursor-end>
|
||||
no-movement?:boolean <- equal *top-of-screen, old-top
|
||||
go-render? <- not no-movement?
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -2714,18 +2714,18 @@ after <handle-special-key> [
|
|||
<move-cursor-end>
|
||||
no-movement?:boolean <- equal *top-of-screen, old-top
|
||||
go-render? <- not no-movement?
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
# page-down skips entire wrapped lines, so it can't scroll past lines
|
||||
# taking up the entire screen
|
||||
recipe page-down editor:address:shared:editor-data -> editor:address:shared:editor-data [
|
||||
def page-down editor:address:shared:editor-data -> editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
# if editor contents don't overflow screen, do nothing
|
||||
bottom-of-screen:address:shared:duplex-list:character <- get *editor, bottom-of-screen:offset
|
||||
reply-unless bottom-of-screen
|
||||
return-unless bottom-of-screen
|
||||
# if not, position cursor at final character
|
||||
before-cursor:address:address:shared:duplex-list:character <- get-address *editor, before-cursor:offset
|
||||
*before-cursor <- prev bottom-of-screen
|
||||
|
@ -2890,7 +2890,7 @@ after <handle-special-character> [
|
|||
<move-cursor-end>
|
||||
no-movement?:boolean <- equal *top-of-screen, old-top
|
||||
go-render? <- not no-movement?
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -2907,11 +2907,11 @@ after <handle-special-key> [
|
|||
no-movement?:boolean <- equal *top-of-screen, old-top
|
||||
# don't bother re-rendering if nothing changed. todo: test this
|
||||
go-render? <- not no-movement?
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
recipe page-up editor:address:shared:editor-data, screen-height:number -> editor:address:shared:editor-data [
|
||||
def page-up editor:address:shared:editor-data, screen-height:number -> editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
max:number <- subtract screen-height, 1/menu-bar, 1/overlapping-line
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
## putting the environment together out of editors
|
||||
|
||||
recipe! main [
|
||||
def! main [
|
||||
local-scope
|
||||
open-console
|
||||
initial-sandbox:address:shared:array:character <- new []
|
||||
|
@ -19,7 +19,7 @@ container programming-environment-data [
|
|||
current-sandbox:address:shared:editor-data
|
||||
]
|
||||
|
||||
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 [
|
||||
def 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
|
||||
|
@ -39,7 +39,7 @@ recipe new-programming-environment screen:address:shared:screen, initial-sandbox
|
|||
<programming-environment-initialization>
|
||||
]
|
||||
|
||||
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 [
|
||||
def 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:shared:editor-data <- get *env, current-sandbox:offset
|
||||
|
@ -136,7 +136,7 @@ recipe event-loop screen:address:shared:screen, console:address:shared:console,
|
|||
}
|
||||
]
|
||||
|
||||
recipe resize screen:address:shared:screen, env:address:shared:programming-environment-data -> env:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
def 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
|
||||
|
@ -152,7 +152,7 @@ recipe resize screen:address:shared:screen, env:address:shared:programming-envir
|
|||
*cursor-column <- copy 0
|
||||
]
|
||||
|
||||
recipe render-all screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen [
|
||||
def render-all screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
trace 10, [app], [render all]
|
||||
|
@ -178,7 +178,7 @@ recipe render-all screen:address:shared:screen, env:address:shared:programming-e
|
|||
]
|
||||
|
||||
# replaced in a later layer
|
||||
recipe render-sandbox-side screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen [
|
||||
def render-sandbox-side screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
|
@ -193,7 +193,7 @@ recipe render-sandbox-side screen:address:shared:screen, env:address:shared:prog
|
|||
clear-screen-from screen, row, left, left, right
|
||||
]
|
||||
|
||||
recipe update-cursor screen:address:shared:screen, current-sandbox:address:shared:editor-data, env:address:shared:programming-environment-data -> screen:address:shared:screen [
|
||||
def update-cursor screen:address:shared:screen, current-sandbox:address:shared:editor-data, env:address:shared:programming-environment-data -> screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
<update-cursor-special-cases>
|
||||
|
@ -204,10 +204,10 @@ recipe update-cursor screen:address:shared:screen, current-sandbox:address:share
|
|||
|
||||
# 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:shared:screen, s:address:shared:array:character, left:number, right:number, color:number, row:number -> row:number, screen:address:shared:screen [
|
||||
def 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
|
||||
return-unless s
|
||||
column:number <- copy left
|
||||
screen <- move-cursor screen, row, column
|
||||
screen-height:number <- screen-height screen
|
||||
|
@ -265,10 +265,10 @@ recipe render screen:address:shared:screen, s:address:shared:array:character, le
|
|||
]
|
||||
|
||||
# like 'render' for texts, but with colorization for comments like in the editor
|
||||
recipe render-code screen:address:shared:screen, s:address:shared:array:character, left:number, right:number, row:number -> row:number, screen:address:shared:screen [
|
||||
def 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
|
||||
return-unless s
|
||||
color:number <- copy 7/white
|
||||
column:number <- copy left
|
||||
screen <- move-cursor screen, row, column
|
||||
|
@ -340,6 +340,6 @@ after <global-type> [
|
|||
]
|
||||
|
||||
# dummy
|
||||
recipe restore-sandboxes env:address:shared:programming-environment-data -> env:address:shared:programming-environment-data [
|
||||
def restore-sandboxes env:address:shared:programming-environment-data -> env:address:shared:programming-environment-data [
|
||||
# do nothing; redefined later
|
||||
]
|
||||
|
|
|
@ -129,7 +129,7 @@ after <global-keypress> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe run-sandboxes env:address:shared:programming-environment-data, screen:address:shared:screen, test-recipes:address:shared:array:character -> errors-found?:boolean, env:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
def run-sandboxes env:address:shared:programming-environment-data, screen:address:shared:screen, test-recipes:address:shared:array:character -> 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, test-recipes
|
||||
|
@ -175,7 +175,7 @@ recipe run-sandboxes env:address:shared:programming-environment-data, screen:add
|
|||
|
||||
# load code from recipes.mu, or from test-recipes in tests
|
||||
# replaced in a later layer (whereupon errors-found? will actually be set)
|
||||
recipe update-recipes env:address:shared:programming-environment-data, screen:address:shared:screen, test-recipes:address:shared:array:character -> errors-found?:boolean, env:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
def update-recipes env:address:shared:programming-environment-data, screen:address:shared:screen, test-recipes:address:shared:array:character -> errors-found?:boolean, env:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -191,7 +191,7 @@ recipe update-recipes env:address:shared:programming-environment-data, screen:ad
|
|||
]
|
||||
|
||||
# replaced in a later layer
|
||||
recipe! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data, idx:number -> sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data [
|
||||
def! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data, idx:number -> sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
data:address:shared:array:character <- get *sandbox, data:offset
|
||||
|
@ -200,14 +200,14 @@ recipe! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:p
|
|||
*response, _, *fake-screen <- run-interactive data
|
||||
]
|
||||
|
||||
recipe update-status screen:address:shared:screen, msg:address:shared:array:character, color:number -> screen:address:shared:screen [
|
||||
def 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:shared:programming-environment-data [
|
||||
def save-sandboxes env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
current-sandbox:address:shared:editor-data <- get *env, current-sandbox:offset
|
||||
|
@ -228,7 +228,7 @@ recipe save-sandboxes env:address:shared:programming-environment-data [
|
|||
}
|
||||
]
|
||||
|
||||
recipe! render-sandbox-side screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen [
|
||||
def! render-sandbox-side screen:address:shared:screen, env:address:shared:programming-environment-data -> screen:address:shared:screen, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
trace 11, [app], [render sandbox side]
|
||||
|
@ -252,14 +252,14 @@ recipe! render-sandbox-side screen:address:shared:screen, env:address:shared:pro
|
|||
clear-rest-of-screen screen, row, left, right
|
||||
]
|
||||
|
||||
recipe render-sandboxes screen:address:shared:screen, sandbox:address:shared:sandbox-data, left:number, right:number, row:number, render-from:number, idx:number -> row:number, screen:address:shared:screen, sandbox:address:shared:sandbox-data [
|
||||
def render-sandboxes screen:address:shared:screen, sandbox:address:shared:sandbox-data, left:number, right:number, row:number, render-from:number, idx:number -> row:number, screen:address:shared:screen, sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
env:address:shared:programming-environment-data, _/optional <- next-ingredient
|
||||
reply-unless sandbox
|
||||
return-unless sandbox
|
||||
screen-height:number <- screen-height screen
|
||||
at-bottom?:boolean <- greater-or-equal row, screen-height
|
||||
reply-if at-bottom?:boolean
|
||||
return-if at-bottom?:boolean
|
||||
hidden?:boolean <- lesser-than idx, render-from
|
||||
{
|
||||
break-if hidden?
|
||||
|
@ -296,7 +296,7 @@ recipe render-sandboxes screen:address:shared:screen, sandbox:address:shared:san
|
|||
}
|
||||
+render-sandbox-end
|
||||
at-bottom?:boolean <- greater-or-equal row, screen-height
|
||||
reply-if at-bottom?
|
||||
return-if at-bottom?
|
||||
# draw solid line after sandbox
|
||||
draw-horizontal screen, row, left, right, 9473/horizontal-double
|
||||
}
|
||||
|
@ -316,7 +316,7 @@ recipe render-sandboxes screen:address:shared:screen, sandbox:address:shared:san
|
|||
]
|
||||
|
||||
# assumes programming environment has no sandboxes; restores them from previous session
|
||||
recipe! restore-sandboxes env:address:shared:programming-environment-data -> env:address:shared:programming-environment-data [
|
||||
def! 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
|
||||
|
@ -350,10 +350,10 @@ recipe! restore-sandboxes env:address:shared:programming-environment-data -> env
|
|||
|
||||
# print the fake sandbox screen to 'screen' with appropriate delimiters
|
||||
# leave cursor at start of next line
|
||||
recipe render-screen screen:address:shared:screen, sandbox-screen:address:shared:screen, left:number, right:number, row:number -> row:number, screen:address:shared:screen [
|
||||
def 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
|
||||
return-unless sandbox-screen
|
||||
# print 'screen:'
|
||||
header:address:shared:array:character <- new [screen:]
|
||||
row <- render screen, header, left, right, 245/grey, row
|
||||
|
@ -421,10 +421,10 @@ scenario run-updates-results [
|
|||
assume-screen 50/width, 12/height
|
||||
# define a recipe (no indent for the 'add' line below so column numbers are more obvious)
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
def foo [
|
||||
local-scope
|
||||
z:number <- add 2, 2
|
||||
reply z
|
||||
return z
|
||||
]]
|
||||
# sandbox editor contains an instruction without storing outputs
|
||||
2:address:shared:array:character <- new [foo]
|
||||
|
@ -446,10 +446,10 @@ reply z
|
|||
]
|
||||
# make a change (incrementing one of the args to 'add'), then rerun
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
def foo [
|
||||
local-scope
|
||||
z:number <- add 2, 3
|
||||
reply z
|
||||
return z
|
||||
]]
|
||||
assume-console [
|
||||
press F4
|
||||
|
@ -501,7 +501,7 @@ scenario run-instruction-manages-screen-per-sandbox [
|
|||
]
|
||||
]
|
||||
|
||||
recipe editor-contents editor:address:shared:editor-data -> result:address:shared:array:character [
|
||||
def editor-contents editor:address:shared:editor-data -> result:address:shared:array:character [
|
||||
local-scope
|
||||
load-ingredients
|
||||
buf:address:shared:buffer <- new-buffer 80
|
||||
|
@ -509,7 +509,7 @@ recipe editor-contents editor:address:shared:editor-data -> result:address:share
|
|||
# skip § sentinel
|
||||
assert curr, [editor without data is illegal; must have at least a sentinel]
|
||||
curr <- next curr
|
||||
reply-unless curr, 0
|
||||
return-unless curr, 0
|
||||
{
|
||||
break-unless curr
|
||||
c:character <- get *curr, value:offset
|
||||
|
@ -646,7 +646,7 @@ after <update-cursor-special-cases> [
|
|||
break-unless scrolling?
|
||||
cursor-column:number <- get *current-sandbox, left:offset
|
||||
screen <- move-cursor screen, 2/row, cursor-column # highlighted sandbox will always start at row 2
|
||||
reply
|
||||
return
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -668,21 +668,21 @@ after <global-keypress> [
|
|||
|
||||
# sandbox belonging to 'env' whose next-sandbox is 'in'
|
||||
# return 0 if there's no such sandbox, either because 'in' doesn't exist in 'env', or because it's the first sandbox
|
||||
recipe previous-sandbox env:address:shared:programming-environment-data, in:address:shared:sandbox-data -> out:address:shared:sandbox-data [
|
||||
def previous-sandbox env:address:shared:programming-environment-data, in:address:shared:sandbox-data -> out:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
curr:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
reply-unless curr, 0/nil
|
||||
return-unless curr, 0/nil
|
||||
next:address:shared:sandbox-data <- get *curr, next-sandbox:offset
|
||||
{
|
||||
reply-unless next, 0/nil
|
||||
return-unless next, 0/nil
|
||||
found?:boolean <- equal next, in
|
||||
break-if found?
|
||||
curr <- copy next
|
||||
next <- get *curr, next-sandbox:offset
|
||||
loop
|
||||
}
|
||||
reply curr
|
||||
return curr
|
||||
]
|
||||
|
||||
scenario scrolling-through-multiple-sandboxes [
|
||||
|
|
|
@ -93,7 +93,7 @@ after <global-touch> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe empty-editor? editor:address:shared:editor-data -> result:boolean [
|
||||
def empty-editor? editor:address:shared:editor-data -> result:boolean [
|
||||
local-scope
|
||||
load-ingredients
|
||||
head:address:shared:duplex-list:character <- get *editor, data:offset
|
||||
|
@ -101,13 +101,13 @@ recipe empty-editor? editor:address:shared:editor-data -> result:boolean [
|
|||
result <- not first
|
||||
]
|
||||
|
||||
recipe extract-sandbox env:address:shared:programming-environment-data, click-row:number -> result:address:shared:sandbox-data, env:address:shared:programming-environment-data [
|
||||
def 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
|
||||
sandbox:address:address:shared:sandbox-data <- get-address *env, sandbox:offset
|
||||
start:number <- get **sandbox, starting-row-on-screen:offset
|
||||
in-editor?:boolean <- lesser-than click-row, start
|
||||
reply-if in-editor?, 0
|
||||
return-if in-editor?, 0
|
||||
{
|
||||
next-sandbox:address:shared:sandbox-data <- get **sandbox, next-sandbox:offset
|
||||
break-unless next-sandbox
|
||||
|
|
|
@ -76,14 +76,14 @@ after <global-touch> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe delete-sandbox t:touch-event, env:address:shared:programming-environment-data -> was-delete?:boolean, env:address:shared:programming-environment-data [
|
||||
def 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: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
|
||||
return-unless at-right?, 0/false
|
||||
click-row:number <- get t, row:offset
|
||||
prev:address:address:shared:sandbox-data <- get-address *env, sandbox:offset
|
||||
curr:address:shared:sandbox-data <- get *env, sandbox:offset
|
||||
|
@ -107,13 +107,13 @@ recipe delete-sandbox t:touch-event, env:address:shared:programming-environment-
|
|||
break-unless reset-scroll?
|
||||
*render-from <- copy -1
|
||||
}
|
||||
reply 1/true # force rerender
|
||||
return 1/true # force rerender
|
||||
}
|
||||
prev <- get-address *curr, next-sandbox:offset
|
||||
curr <- get *curr, next-sandbox:offset
|
||||
loop
|
||||
}
|
||||
reply 0/false
|
||||
return 0/false
|
||||
]
|
||||
|
||||
scenario deleting-sandbox-after-scroll [
|
||||
|
|
|
@ -5,8 +5,8 @@ scenario sandbox-click-on-result-toggles-color-to-green [
|
|||
assume-screen 50/width, 20/height
|
||||
# basic recipe
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
reply 4
|
||||
def foo [
|
||||
return 4
|
||||
]]
|
||||
# run it
|
||||
2:address:shared:array:character <- new [foo]
|
||||
|
@ -59,8 +59,8 @@ recipe foo [
|
|||
]
|
||||
# now change the result
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
reply 3
|
||||
def foo [
|
||||
return 3
|
||||
]]
|
||||
# then rerun
|
||||
assume-console [
|
||||
|
@ -131,7 +131,7 @@ after <global-touch> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe find-click-in-sandbox-output env:address:shared:programming-environment-data, click-row:number -> sandbox:address:shared:sandbox-data [
|
||||
def 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
|
||||
|
@ -151,13 +151,13 @@ recipe find-click-in-sandbox-output env:address:shared:programming-environment-d
|
|||
}
|
||||
# return sandbox if click is in its output region
|
||||
response-starting-row:number <- get *sandbox, response-starting-row-on-screen:offset
|
||||
reply-unless response-starting-row, 0/no-click-in-sandbox-output
|
||||
return-unless response-starting-row, 0/no-click-in-sandbox-output
|
||||
click-in-response?:boolean <- greater-or-equal click-row, response-starting-row
|
||||
reply-unless click-in-response?, 0/no-click-in-sandbox-output
|
||||
reply sandbox
|
||||
return-unless click-in-response?, 0/no-click-in-sandbox-output
|
||||
return sandbox
|
||||
]
|
||||
|
||||
recipe toggle-expected-response sandbox:address:shared:sandbox-data -> sandbox:address:shared:sandbox-data [
|
||||
def toggle-expected-response sandbox:address:shared:sandbox-data -> sandbox:address:shared:sandbox-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
expected-response:address:address:shared:array:character <- get-address *sandbox, expected-response:offset
|
||||
|
@ -165,7 +165,7 @@ recipe toggle-expected-response sandbox:address:shared:sandbox-data -> sandbox:a
|
|||
# if expected-response is set, reset
|
||||
break-unless *expected-response
|
||||
*expected-response <- copy 0
|
||||
reply sandbox/same-as-ingredient:0
|
||||
return sandbox/same-as-ingredient:0
|
||||
}
|
||||
# if not, current response is the expected response
|
||||
response:address:shared:array:character <- get *sandbox, response:offset
|
||||
|
|
|
@ -119,7 +119,7 @@ container sandbox-data [
|
|||
]
|
||||
|
||||
# replaced in a later layer
|
||||
recipe! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data, idx:number -> sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data [
|
||||
def! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data, idx:number -> sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
data:address:shared:array:character <- get *sandbox, data:offset
|
||||
|
@ -158,7 +158,7 @@ after <global-touch> [
|
|||
}
|
||||
]
|
||||
|
||||
recipe find-click-in-sandbox-code env:address:shared:programming-environment-data, click-row:number -> sandbox:address:shared:sandbox-data [
|
||||
def 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
|
||||
|
@ -184,9 +184,9 @@ recipe find-click-in-sandbox-code env:address:shared:programming-environment-dat
|
|||
click-on-sandbox-code?:boolean <- and click-above-response?, click-below-menu?
|
||||
{
|
||||
break-if click-on-sandbox-code?
|
||||
reply 0/no-click-in-sandbox-output
|
||||
return 0/no-click-in-sandbox-output
|
||||
}
|
||||
reply sandbox
|
||||
return sandbox
|
||||
]
|
||||
|
||||
# when rendering a sandbox, dump its trace before response/warning if display-trace? property is set
|
||||
|
|
|
@ -6,7 +6,7 @@ container programming-environment-data [
|
|||
|
||||
# copy code from recipe editor, persist, load into mu, save any errors
|
||||
# test-recipes is a hook for testing
|
||||
recipe! update-recipes env:address:shared:programming-environment-data, screen:address:shared:screen, test-recipes:address:shared:array:character -> errors-found?:boolean, env:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
def! update-recipes env:address:shared:programming-environment-data, screen:address:shared:screen, test-recipes:address:shared:array:character -> errors-found?:boolean, env:address:shared:programming-environment-data, screen:address:shared:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
recipe-errors:address:address:shared:array:character <- get-address *env, recipe-errors:offset
|
||||
|
@ -25,7 +25,7 @@ recipe! update-recipes env:address:shared:programming-environment-data, screen:a
|
|||
status:address:shared:array:character <- new [errors found ]
|
||||
update-status screen, status, 1/red
|
||||
errors-found? <- copy 1/true
|
||||
reply
|
||||
return
|
||||
}
|
||||
errors-found? <- copy 0/false
|
||||
]
|
||||
|
@ -79,7 +79,7 @@ container sandbox-data [
|
|||
errors:address:shared:array:character
|
||||
]
|
||||
|
||||
recipe! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data, idx:number -> sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data [
|
||||
def! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data, idx:number -> sandbox:address:shared:sandbox-data, env:address:shared:programming-environment-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
data:address:shared:array:character <- get *sandbox, data:offset
|
||||
|
@ -91,7 +91,7 @@ recipe! update-sandbox sandbox:address:shared:sandbox-data, env:address:shared:p
|
|||
{
|
||||
break-unless recipe-errors
|
||||
*errors <- copy recipe-errors
|
||||
reply
|
||||
return
|
||||
}
|
||||
*response, *errors, *fake-screen, *trace, completed?:boolean <- run-interactive data
|
||||
{
|
||||
|
@ -131,7 +131,7 @@ scenario run-shows-errors-in-get [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 50/width, 20/height
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
def foo [
|
||||
get 123:number, foo:offset
|
||||
]]
|
||||
2:address:shared:array:character <- new [foo]
|
||||
|
@ -379,7 +379,7 @@ scenario run-shows-missing-type-errors [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 50/width, 20/height
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
def foo [
|
||||
x <- copy 0
|
||||
]]
|
||||
2:address:shared:array:character <- new [foo]
|
||||
|
@ -410,7 +410,7 @@ scenario run-shows-unbalanced-bracket-errors [
|
|||
assume-screen 50/width, 20/height
|
||||
# recipe is incomplete (unbalanced '[')
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo «
|
||||
def foo «
|
||||
x <- copy 0
|
||||
]
|
||||
replace 1:address:shared:array:character, 171/«, 91 # '['
|
||||
|
@ -439,7 +439,7 @@ scenario run-shows-get-on-non-container-errors [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 50/width, 20/height
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
def foo [
|
||||
local-scope
|
||||
x:address:shared:point <- new point:type
|
||||
get x:address:shared:point, 1:offset
|
||||
|
@ -467,7 +467,7 @@ scenario run-shows-non-literal-get-argument-errors [
|
|||
trace-until 100/app # trace too long
|
||||
assume-screen 50/width, 20/height
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
def foo [
|
||||
local-scope
|
||||
x:number <- copy 0
|
||||
y:address:shared:point <- new point:type
|
||||
|
@ -497,7 +497,7 @@ scenario run-shows-errors-everytime [
|
|||
assume-screen 50/width, 20/height
|
||||
# try to run a file with an error
|
||||
1:address:shared:array:character <- new [
|
||||
recipe foo [
|
||||
def foo [
|
||||
local-scope
|
||||
x:number <- copy y:number
|
||||
]]
|
||||
|
@ -635,7 +635,7 @@ a:number <- next-ingredient
|
|||
b:number <- next-ingredient
|
||||
stash [dividing by], b
|
||||
_, c:number <- divide-with-remainder a, b
|
||||
reply b
|
||||
return b
|
||||
]]
|
||||
2:address:shared:array:character <- new [foo 4, 0]
|
||||
3:address:shared:programming-environment-data <- new-programming-environment screen:address:shared:screen, 2:address:shared:array:character
|
||||
|
|
|
@ -72,7 +72,7 @@ after <handle-special-character> [
|
|||
redo:address:address:shared:list:address:shared:operation <- get-address *editor, redo:offset
|
||||
*redo <- push op, *redo
|
||||
<handle-undo>
|
||||
reply screen/same-as-ingredient:0, editor/same-as-ingredient:1, 1/go-render
|
||||
return screen/same-as-ingredient:0, editor/same-as-ingredient:1, 1/go-render
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -88,7 +88,7 @@ after <handle-special-character> [
|
|||
undo:address:address:shared:list:address:shared:operation <- get-address *editor, undo:offset
|
||||
*undo <- push op, *undo
|
||||
<handle-redo>
|
||||
reply screen/same-as-ingredient:0, editor/same-as-ingredient:1, 1/go-render
|
||||
return screen/same-as-ingredient:0, editor/same-as-ingredient:1, 1/go-render
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -189,14 +189,14 @@ before <insert-enter-end> [
|
|||
# redo stack, because it's now obsolete.
|
||||
# Beware: since we're counting cursor moves as operations, this means just
|
||||
# moving the cursor can lose work on the undo stack.
|
||||
recipe add-operation editor:address:shared:editor-data, op:address:shared:operation -> editor:address:shared:editor-data [
|
||||
def add-operation editor:address:shared:editor-data, op:address:shared:operation -> editor:address:shared:editor-data [
|
||||
local-scope
|
||||
load-ingredients
|
||||
undo:address:address:shared:list:address:shared:operation <- get-address *editor, undo:offset
|
||||
*undo <- push op *undo
|
||||
redo:address:address:shared:list:address:shared:operation <- get-address *editor, redo:offset
|
||||
*redo <- copy 0
|
||||
reply editor/same-as-ingredient:0
|
||||
return editor/same-as-ingredient:0
|
||||
]
|
||||
|
||||
after <handle-undo> [
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# The zero screen below means 'use the real screen'. Tests can also use fake
|
||||
# screens.
|
||||
|
||||
recipe main [
|
||||
def main [
|
||||
open-console
|
||||
10:character <- copy 97/a
|
||||
print 0/screen, 10:character/a, 2/red
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
recipe test a:number -> b:number [
|
||||
def test a:number -> b:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
b <- add a, 1
|
||||
]
|
||||
|
||||
recipe test a:number, b:number -> c:number [
|
||||
def test a:number, b:number -> c:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
c <- add a, b
|
||||
]
|
||||
|
||||
recipe main [
|
||||
def main [
|
||||
local-scope
|
||||
a:number <- test 3 # selects single-ingredient version
|
||||
$print a, 10/newline
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
# This isn't a very tasteful example, just a simple demonstration of
|
||||
# possibilities.
|
||||
|
||||
recipe factorial n:number -> result:number [
|
||||
def factorial n:number -> result:number [
|
||||
local-scope
|
||||
load-ingredients
|
||||
{
|
||||
|
@ -19,7 +19,7 @@ after <base-case> [
|
|||
# if n=0 return 1
|
||||
zero?:boolean <- equal n, 0
|
||||
break-unless zero?
|
||||
reply 1
|
||||
return 1
|
||||
]
|
||||
|
||||
after <recursive-case> [
|
||||
|
@ -29,7 +29,7 @@ after <recursive-case> [
|
|||
result <- multiply subresult, n
|
||||
]
|
||||
|
||||
recipe main [
|
||||
def main [
|
||||
1:number <- factorial 5
|
||||
$print [result: ], 1:number, [
|
||||
]
|
||||
|
|