2015-05-19 17:38:23 +00:00
//: Spaces help isolate recipes from each other. You can create them at will,
2015-03-22 00:53:20 +00:00
//: and all addresses in arguments are implicitly based on the 'default-space'
//: (unless they have the /raw property)
2015-04-24 17:19:03 +00:00
: ( scenario set_default_space )
2015-03-29 17:21:15 +00:00
# if default-space is 10, and if an array of 5 locals lies from location 11 to 15 (inclusive),
# then location 0 is really location 11, location 1 is really location 12, and so on.
2015-03-22 00:53:20 +00:00
recipe main [
2015-07-28 21:33:22 +00:00
10 : number < - copy 5 # pretend array ; in practice we ' ll use new
2015-09-30 07:07:33 +00:00
default - space : address : array : location < - copy 10 / raw
2015-07-28 21:33:22 +00:00
1 : number < - copy 23
2015-03-22 00:53:20 +00:00
]
2015-03-29 03:50:23 +00:00
+ mem : storing 23 in location 12
2015-03-22 00:53:20 +00:00
2015-07-28 22:03:46 +00:00
: ( scenario lookup_sidesteps_default_space )
2015-04-03 18:42:50 +00:00
recipe main [
# pretend pointer from outside
2015-07-28 21:33:22 +00:00
3 : number < - copy 34
2015-04-03 18:42:50 +00:00
# pretend array
2015-07-28 21:33:22 +00:00
1000 : number < - copy 5
2015-05-19 17:38:23 +00:00
# actual start of this recipe
2015-09-30 07:07:33 +00:00
default - space : address : array : location < - copy 1000 / raw
1 : address : number < - copy 3 / raw
2015-07-29 08:35:06 +00:00
8 : number / raw < - copy * 1 : address : number
2015-04-03 18:42:50 +00:00
]
+ mem : storing 34 in location 8
2015-05-23 19:30:58 +00:00
//:: first disable name conversion for 'default-space'
: ( scenario convert_names_passes_default_space )
2015-10-07 07:22:49 +00:00
% Hide_errors = true ;
2015-05-23 19:30:58 +00:00
recipe main [
2015-07-28 21:33:22 +00:00
default - space : number , x : number < - copy 0 , 1
2015-05-23 19:30:58 +00:00
]
+ name : assign x 1
- name : assign default - space 1
: ( before " End Disqualified Reagents " )
if ( x . name = = " default-space " )
x . initialized = true ;
: ( before " End is_special_name Cases " )
if ( s = = " default-space " ) return true ;
//:: now implement space support
2015-04-13 03:56:45 +00:00
: ( before " End call Fields " )
2015-05-17 09:22:41 +00:00
long long int default_space ;
2015-05-24 00:58:10 +00:00
: ( before " End call Constructor " )
default_space = 0 ;
2015-03-22 00:53:20 +00:00
: ( replace " reagent r = x " following " reagent canonize(reagent x) " )
reagent r = absolutize ( x ) ;
: ( code )
reagent absolutize ( reagent x ) {
if ( is_raw ( x ) | | is_dummy ( x ) ) return x ;
2015-08-07 19:56:09 +00:00
if ( x . name = = " default-space " ) return x ;
2015-07-25 07:02:20 +00:00
if ( ! x . initialized ) {
2015-10-07 05:15:45 +00:00
raise_error < < current_instruction ( ) . to_string ( ) < < " : reagent not initialized: " < < x . original_string < < ' \n ' < < end ( ) ;
2015-07-25 07:02:20 +00:00
return x ;
}
2015-03-22 00:53:20 +00:00
reagent r = x ;
2015-05-13 00:00:56 +00:00
r . set_value ( address ( r . value , space_base ( r ) ) ) ;
2015-03-22 00:53:20 +00:00
r . properties . push_back ( pair < string , vector < string > > ( " raw " , vector < string > ( ) ) ) ;
assert ( is_raw ( r ) ) ;
return r ;
}
2015-07-28 22:03:46 +00:00
: ( before " return result " following " reagent lookup_memory(reagent x) " )
2015-04-03 18:42:50 +00:00
result . properties . push_back ( pair < string , vector < string > > ( " raw " , vector < string > ( ) ) ) ;
2015-03-22 00:53:20 +00:00
2015-04-18 06:24:52 +00:00
//:: fix 'get'
2015-07-28 22:03:46 +00:00
: ( scenario lookup_sidesteps_default_space_in_get )
2015-04-18 04:51:13 +00:00
recipe main [
# pretend pointer to container from outside
2015-07-28 21:33:22 +00:00
12 : number < - copy 34
13 : number < - copy 35
2015-04-18 04:51:13 +00:00
# pretend array
2015-07-28 21:33:22 +00:00
1000 : number < - copy 5
2015-05-19 17:38:23 +00:00
# actual start of this recipe
2015-09-30 07:07:33 +00:00
default - space : address : array : location < - copy 1000 / raw
1 : address : point < - copy 12 / raw
2015-07-29 08:35:06 +00:00
9 : number / raw < - get * 1 : address : point , 1 : offset
2015-04-18 04:51:13 +00:00
]
+ mem : storing 35 in location 9
: ( after " reagent tmp " following " case GET: " )
tmp . properties . push_back ( pair < string , vector < string > > ( " raw " , vector < string > ( ) ) ) ;
2015-04-18 06:24:52 +00:00
//:: fix 'index'
2015-07-28 22:03:46 +00:00
: ( scenario lookup_sidesteps_default_space_in_index )
2015-04-18 04:51:13 +00:00
recipe main [
# pretend pointer to array from outside
2015-07-28 21:33:22 +00:00
12 : number < - copy 2
13 : number < - copy 34
14 : number < - copy 35
2015-04-18 04:51:13 +00:00
# pretend array
2015-07-28 21:33:22 +00:00
1000 : number < - copy 5
2015-05-19 17:38:23 +00:00
# actual start of this recipe
2015-09-30 07:07:33 +00:00
default - space : address : array : location < - copy 1000 / raw
1 : address : array : number < - copy 12 / raw
2015-07-29 08:35:06 +00:00
9 : number / raw < - index * 1 : address : array : number , 1
2015-04-18 04:51:13 +00:00
]
+ mem : storing 35 in location 9
: ( after " reagent tmp " following " case INDEX: " )
tmp . properties . push_back ( pair < string , vector < string > > ( " raw " , vector < string > ( ) ) ) ;
2015-07-14 02:59:27 +00:00
//:: convenience operation to automatically deduce the amount of space to
//:: allocate in a default space with names
: ( scenario new_default_space )
recipe main [
new - default - space
2015-07-28 21:33:22 +00:00
x : number < - copy 0
y : number < - copy 3
2015-07-14 02:59:27 +00:00
]
# allocate space for x and y, as well as the chaining slot at 0
+ mem : array size is 3
: ( before " End Disqualified Reagents " )
if ( x . name = = " number-of-locals " )
x . initialized = true ;
: ( before " End is_special_name Cases " )
if ( s = = " number-of-locals " ) return true ;
: ( before " End Rewrite Instruction(curr) " )
// rewrite `new-default-space` to
// `default-space:address:array:location <- new location:type, number-of-locals:literal`
// where N is Name[recipe][""]
if ( curr . name = = " new-default-space " ) {
2015-07-14 05:43:16 +00:00
rewrite_default_space_instruction ( curr ) ;
2015-07-14 02:59:27 +00:00
}
: ( after " vector<double> read_memory(reagent x) " )
if ( x . name = = " number-of-locals " ) {
vector < double > result ;
result . push_back ( Name [ Recipe_ordinal [ current_recipe_name ( ) ] ] [ " " ] ) ;
if ( result . back ( ) = = 0 )
2015-10-07 07:23:40 +00:00
raise_error < < " no space allocated for default-space in recipe " < < current_recipe_name ( ) < < " ; are you using names? \n " < < end ( ) ;
2015-07-14 02:59:27 +00:00
return result ;
}
: ( after " void write_memory(reagent x, vector<double> data) " )
if ( x . name = = " number-of-locals " ) {
2015-10-07 05:15:45 +00:00
raise_error < < maybe ( current_recipe_name ( ) ) < < " can't write to special name 'number-of-locals' \n " < < end ( ) ;
2015-07-14 02:59:27 +00:00
return ;
}
2015-07-14 05:43:16 +00:00
//:: a little hook to automatically reclaim the default-space when returning
//:: from a recipe
: ( scenario local_scope )
recipe main [
1 : address < - foo
2 : address < - foo
3 : boolean < - equal 1 : address , 2 : address
]
recipe foo [
local - scope
2015-07-28 21:33:22 +00:00
x : number < - copy 34
2015-07-14 05:43:16 +00:00
reply default - space : address : array : location
]
# both calls to foo should have received the same default-space
+ mem : storing 1 in location 3
: ( after " Falling Through End Of Recipe " )
try_reclaim_locals ( ) ;
: ( after " Starting Reply " )
try_reclaim_locals ( ) ;
//: now 'local-scope' is identical to 'new-default-space' except that we'll
//: reclaim the default-space when the routine exits
: ( before " End Rewrite Instruction(curr) " )
if ( curr . name = = " local-scope " ) {
rewrite_default_space_instruction ( curr ) ;
}
: ( code )
void try_reclaim_locals ( ) {
// only reclaim routines starting with 'local-scope'
const recipe_ordinal r = Recipe_ordinal [ current_recipe_name ( ) ] ;
2015-07-25 21:19:28 +00:00
if ( Recipe [ r ] . steps . empty ( ) ) return ;
2015-07-14 05:43:16 +00:00
const instruction & inst = Recipe [ r ] . steps . at ( 0 ) ;
2015-07-25 21:19:28 +00:00
if ( inst . name ! = " local-scope " ) return ;
2015-07-14 05:43:16 +00:00
abandon ( Current_routine - > calls . front ( ) . default_space ,
/*array length*/ 1 + /*number-of-locals*/ Name [ r ] [ " " ] ) ;
}
void rewrite_default_space_instruction ( instruction & curr ) {
curr . operation = Recipe_ordinal [ " new " ] ;
if ( ! curr . ingredients . empty ( ) )
2015-10-07 05:15:45 +00:00
raise_error < < " new-default-space can't take any ingredients \n " < < end ( ) ;
2015-07-14 05:43:16 +00:00
curr . ingredients . push_back ( reagent ( " location:type " ) ) ;
curr . ingredients . push_back ( reagent ( " number-of-locals:literal " ) ) ;
if ( ! curr . products . empty ( ) )
2015-10-07 05:15:45 +00:00
raise_error < < " new-default-space can't take any results \n " < < end ( ) ;
2015-07-14 05:43:16 +00:00
curr . products . push_back ( reagent ( " default-space:address:array:location " ) ) ;
}
2015-04-18 06:24:52 +00:00
//:: helpers
2015-04-03 18:42:50 +00:00
: ( code )
2015-05-17 09:22:41 +00:00
long long int space_base ( const reagent & x ) {
2015-05-13 23:33:40 +00:00
return Current_routine - > calls . front ( ) . default_space ;
2015-03-29 03:57:21 +00:00
}
2015-05-17 09:22:41 +00:00
long long int address ( long long int offset , long long int base ) {
2015-03-29 03:50:23 +00:00
if ( base = = 0 ) return offset ; // raw
2015-05-17 09:22:41 +00:00
if ( offset > = static_cast < long long int > ( Memory [ base ] ) ) {
2015-03-29 17:21:15 +00:00
// todo: test
2015-10-07 05:15:45 +00:00
raise_error < < " location " < < offset < < " is out of bounds " < < no_scientific ( Memory [ base ] ) < < " at " < < base < < ' \n ' < < end ( ) ;
2015-03-29 17:21:15 +00:00
}
2015-05-13 00:00:56 +00:00
return base + 1 + offset ;
2015-03-29 03:50:23 +00:00
}
2015-05-13 01:08:47 +00:00
: ( after " void write_memory(reagent x, vector<double> data) " )
2015-03-22 00:53:20 +00:00
if ( x . name = = " default-space " ) {
2015-10-07 07:22:49 +00:00
if ( ! scalar ( data )
| | SIZE ( x . types ) ! = 3
| | x . types . at ( 0 ) ! = Type_ordinal [ " address " ]
| | x . types . at ( 1 ) ! = Type_ordinal [ " array " ]
| | x . types . at ( 2 ) ! = Type_ordinal [ " location " ] ) {
2015-10-07 05:15:45 +00:00
raise_error < < maybe ( current_recipe_name ( ) ) < < " 'default-space' should be of type address:array:location, but tried to write " < < to_string ( data ) < < ' \n ' < < end ( ) ;
2015-10-07 07:22:49 +00:00
}
2015-05-13 23:33:40 +00:00
Current_routine - > calls . front ( ) . default_space = data . at ( 0 ) ;
2015-03-22 00:53:20 +00:00
return ;
}
2015-04-15 00:46:43 +00:00
2015-04-24 17:19:03 +00:00
: ( scenario get_default_space )
2015-04-15 00:46:43 +00:00
recipe main [
2015-09-30 07:07:33 +00:00
default - space : address : array : location < - copy 10 / raw
1 : address : array : location / raw < - copy default - space : address : array : location
2015-04-15 00:46:43 +00:00
]
+ mem : storing 10 in location 1
2015-05-13 01:08:47 +00:00
: ( after " vector<double> read_memory(reagent x) " )
2015-04-15 00:46:43 +00:00
if ( x . name = = " default-space " ) {
2015-05-13 01:08:47 +00:00
vector < double > result ;
2015-05-13 23:33:40 +00:00
result . push_back ( Current_routine - > calls . front ( ) . default_space ) ;
2015-04-15 00:46:43 +00:00
return result ;
}