2015-04-17 18:22:59 +00:00
//: Calls can also generate products, using 'reply'.
2015-04-24 17:19:03 +00:00
: ( scenario reply )
2015-03-15 16:49:23 +00:00
recipe main [
2015-05-13 17:03:26 +00:00
1 : number , 2 : number < - f 34 : literal
2015-03-15 16:49:23 +00:00
]
recipe f [
2015-05-13 17:03:26 +00:00
12 : number < - next - ingredient
13 : number < - add 1 : literal , 12 : number
reply 12 : number , 13 : number
2015-03-15 16:49:23 +00:00
]
2015-05-07 22:06:53 +00:00
+ mem : storing 34 in location 1
+ mem : storing 35 in location 2
2015-03-15 16:49:23 +00:00
2015-04-17 17:31:17 +00:00
: ( before " End Primitive Recipe Declarations " )
REPLY ,
2015-03-15 16:49:23 +00:00
: ( before " End Primitive Recipe Numbers " )
Recipe_number [ " reply " ] = REPLY ;
: ( before " End Primitive Recipe Implementations " )
case REPLY : {
2015-04-28 19:42:54 +00:00
const instruction & reply_inst = current_instruction ( ) ; // save pointer into recipe before pop
2015-05-22 01:57:25 +00:00
- - Callstack_depth ;
2015-05-27 22:57:38 +00:00
//? if (tb_is_active()) { //? 1
//? tb_clear(); //? 1
//? cerr << Recipe[Current_routine->calls.front().running_recipe].name << ' ' << current_step_index() << '\n'; //? 1
//? } //? 1
2015-05-13 23:33:40 +00:00
Current_routine - > calls . pop_front ( ) ;
2015-05-08 01:35:33 +00:00
// just in case 'main' returns a value, drop it for now
if ( Current_routine - > calls . empty ( ) ) goto stop_running_current_routine ;
2015-04-25 03:49:53 +00:00
const instruction & caller_instruction = current_instruction ( ) ;
2015-05-07 22:06:53 +00:00
// make reply results available to caller
copy ( ingredients . begin ( ) , ingredients . end ( ) , inserter ( products , products . begin ( ) ) ) ;
// check that any reply ingredients with /same-as-ingredient connect up
// the corresponding ingredient and product in the caller.
2015-05-17 09:22:41 +00:00
for ( long long int i = 0 ; i < SIZE ( caller_instruction . products ) ; + + i ) {
2015-05-27 22:57:38 +00:00
//? cerr << Recipe[Current_routine->calls.front().running_recipe].name << '\n'; //? 1
2015-05-22 01:57:25 +00:00
trace ( Primitive_recipe_depth , " run " ) < < " result " < < i < < " is " < < to_string ( ingredients . at ( i ) ) ;
2015-05-07 22:06:53 +00:00
if ( has_property ( reply_inst . ingredients . at ( i ) , " same-as-ingredient " ) ) {
vector < string > tmp = property ( reply_inst . ingredients . at ( i ) , " same-as-ingredient " ) ;
2015-05-17 09:22:41 +00:00
assert ( SIZE ( tmp ) = = 1 ) ;
2015-05-17 04:24:21 +00:00
long long int ingredient_index = to_integer ( tmp . at ( 0 ) ) ;
2015-05-07 22:49:40 +00:00
if ( caller_instruction . products . at ( i ) . value ! = caller_instruction . ingredients . at ( ingredient_index ) . value )
raise < < " 'same-as-ingredient' result " < < caller_instruction . products . at ( i ) . value < < " must be location " < < caller_instruction . ingredients . at ( ingredient_index ) . value < < ' \n ' ;
2015-04-28 19:42:54 +00:00
}
2015-03-15 16:49:23 +00:00
}
2015-05-07 22:06:53 +00:00
// refresh instruction_counter to caller's step_index
instruction_counter = current_step_index ( ) ;
break ;
2015-03-15 16:49:23 +00:00
}
2015-03-31 17:56:01 +00:00
2015-04-17 18:22:59 +00:00
//: Products can include containers and exclusive containers, addresses and arrays.
2015-04-24 17:19:03 +00:00
: ( scenario reply_container )
2015-03-31 17:56:01 +00:00
recipe main [
3 : point < - f 2 : literal
]
recipe f [
2015-05-13 17:03:26 +00:00
12 : number < - next - ingredient
13 : number < - copy 35 : literal
2015-05-26 22:48:35 +00:00
reply 12 : point / raw # unsafe
2015-03-31 17:56:01 +00:00
]
+ run : result 0 is [ 2 , 35 ]
+ mem : storing 2 in location 3
+ mem : storing 35 in location 4
2015-04-28 19:42:54 +00:00
//: In mu we'd like to assume that any instruction doesn't modify its
//: ingredients unless they're also products. The /same-as-ingredient inside
//: the recipe's 'reply' will help catch accidental misuse of such
//: 'ingredient-results' (sometimes called in-out parameters in other languages).
2015-05-10 18:38:18 +00:00
2015-04-28 19:42:54 +00:00
: ( scenario reply_same_as_ingredient )
% Hide_warnings = true ;
recipe main [
2015-05-13 17:03:26 +00:00
1 : number < - copy 0 : literal
2 : number < - test1 1 : number # call with different ingredient and product
2015-04-28 19:42:54 +00:00
]
recipe test1 [
2015-05-13 17:03:26 +00:00
10 : address : number < - next - ingredient
reply 10 : address : number / same - as - ingredient : 0
2015-04-28 19:42:54 +00:00
]
+ warn : ' same - as - ingredient ' result 2 must be location 1
2015-03-31 17:56:01 +00:00
: ( code )
2015-05-13 01:08:47 +00:00
string to_string ( const vector < double > & in ) {
2015-03-31 17:56:01 +00:00
if ( in . empty ( ) ) return " [] " ;
ostringstream out ;
2015-05-17 09:22:41 +00:00
if ( SIZE ( in ) = = 1 ) {
2015-05-07 22:06:53 +00:00
out < < in . at ( 0 ) ;
2015-03-31 17:56:01 +00:00
return out . str ( ) ;
}
out < < " [ " ;
2015-05-17 09:22:41 +00:00
for ( long long int i = 0 ; i < SIZE ( in ) ; + + i ) {
2015-03-31 17:56:01 +00:00
if ( i > 0 ) out < < " , " ;
2015-05-07 22:06:53 +00:00
out < < in . at ( i ) ;
2015-03-31 17:56:01 +00:00
}
out < < " ] " ;
return out . str ( ) ;
}
2015-05-10 18:38:18 +00:00
//: Conditional reply.
: ( scenario reply_if )
recipe main [
2015-05-13 17:03:26 +00:00
1 : number < - test1
2015-05-10 18:38:18 +00:00
]
recipe test1 [
reply - if 0 : literal , 34 : literal
reply 35 : literal
]
+ mem : storing 35 in location 1
: ( scenario reply_if2 )
recipe main [
2015-05-13 17:03:26 +00:00
1 : number < - test1
2015-05-10 18:38:18 +00:00
]
recipe test1 [
reply - if 1 : literal , 34 : literal
reply 35 : literal
]
+ mem : storing 34 in location 1
: ( before " End Rewrite Instruction(curr) " )
// rewrite `reply-if a, b, c, ...` to
// ```
// jump-unless a, 1:offset
// reply b, c, ...
// ```
if ( curr . name = = " reply-if " ) {
assert ( curr . products . empty ( ) ) ;
curr . operation = Recipe_number [ " jump-unless " ] ;
vector < reagent > results ;
copy ( + + curr . ingredients . begin ( ) , curr . ingredients . end ( ) , inserter ( results , results . end ( ) ) ) ;
curr . ingredients . resize ( 1 ) ;
curr . ingredients . push_back ( reagent ( " 1:offset " ) ) ;
result . steps . push_back ( curr ) ;
curr . clear ( ) ;
curr . operation = Recipe_number [ " reply " ] ;
curr . ingredients . swap ( results ) ;
}