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-07 22:06:53 +00:00
1 : integer , 2 : integer < - f 34 : literal
2015-03-15 16:49:23 +00:00
]
recipe f [
2015-03-17 05:45:24 +00:00
12 : integer < - next - ingredient
2015-03-15 16:49:23 +00:00
13 : integer < - add 1 : literal , 12 : integer
reply 12 : integer , 13 : integer
]
+ run : instruction main / 0
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-04-25 02:58:38 +00:00
Current_routine - > calls . pop ( ) ;
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-04 18:02:56 +00:00
for ( index_t i = 0 ; i < caller_instruction . products . size ( ) ; + + i ) {
2015-05-07 22:06:53 +00:00
trace ( " run " ) < < " result " < < i < < " is " < < to_string ( ingredients . at ( i ) ) ;
if ( has_property ( reply_inst . ingredients . at ( i ) , " same-as-ingredient " ) ) {
vector < string > tmp = property ( reply_inst . ingredients . at ( i ) , " same-as-ingredient " ) ;
2015-04-28 19:42:54 +00:00
assert ( tmp . size ( ) = = 1 ) ;
2015-05-07 22:06:53 +00:00
long long int ingredient_index = to_int ( 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 [
12 : integer < - next - ingredient
13 : integer < - copy 35 : literal
reply 12 : point
]
+ run : instruction main / 0
+ 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).
: ( scenario reply_same_as_ingredient )
% Hide_warnings = true ;
recipe main [
2015-05-07 22:06:53 +00:00
1 : integer < - copy 0 : literal
2 : integer < - test1 1 : integer # call with different ingredient and product
2015-04-28 19:42:54 +00:00
]
recipe test1 [
10 : address : integer < - next - ingredient
reply 10 : address : integer / same - as - ingredient : 0
]
+ warn : ' same - as - ingredient ' result 2 must be location 1
2015-03-31 17:56:01 +00:00
: ( code )
2015-05-06 00:20:11 +00:00
string to_string ( const vector < long long int > & in ) {
2015-03-31 17:56:01 +00:00
if ( in . empty ( ) ) return " [] " ;
ostringstream out ;
if ( in . size ( ) = = 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-04 18:02:56 +00:00
for ( index_t i = 0 ; i < in . size ( ) ; + + 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 ( ) ;
}