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
2016-01-20 07:18:03 +00:00
default - space : address : shared : array : location < - copy 10 / unsafe
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
2016-01-20 07:18:03 +00:00
default - space : address : shared : array : location < - copy 1000 / unsafe
2015-11-22 19:51:36 +00:00
1 : address : number < - copy 3 / unsafe
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
2015-10-26 04:42:18 +00:00
: ( before " End canonize(x) Special-cases " )
absolutize ( x ) ;
2015-03-22 00:53:20 +00:00
: ( code )
2015-10-26 04:42:18 +00:00
void absolutize ( reagent & x ) {
if ( is_raw ( x ) | | is_dummy ( x ) ) return ;
if ( x . name = = " default-space " ) return ;
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
}
2015-10-26 04:42:18 +00:00
x . set_value ( address ( x . value , space_base ( x ) ) ) ;
2015-10-27 03:00:38 +00:00
x . properties . push_back ( pair < string , string_tree * > ( " raw " , NULL ) ) ;
2015-10-26 04:42:18 +00:00
assert ( is_raw ( x ) ) ;
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
2016-01-20 07:18:03 +00:00
default - space : address : shared : array : location < - copy 1000 / unsafe
2015-11-22 19:51:36 +00:00
1 : address : point < - copy 12 / unsafe
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: " )
2015-10-27 03:00:38 +00:00
tmp . properties . push_back ( pair < string , string_tree * > ( " raw " , NULL ) ) ;
2015-04-18 04:51:13 +00:00
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
2016-01-20 07:18:03 +00:00
default - space : address : shared : array : location < - copy 1000 / unsafe
2015-11-22 19:51:36 +00:00
1 : address : array : number < - copy 12 / unsafe
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: " )
2015-10-27 03:00:38 +00:00
tmp . properties . push_back ( pair < string , string_tree * > ( " raw " , NULL ) ) ;
2015-04-18 04:51:13 +00:00
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 ;
2015-10-29 01:19:41 +00:00
: ( before " End Rewrite Instruction(curr, recipe result) " )
2015-07-14 02:59:27 +00:00
// rewrite `new-default-space` to
2016-01-20 07:18:03 +00:00
// `default-space:address:shared:array:location <- new location:type, number-of-locals:literal`
2015-07-14 02:59:27 +00:00
// 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 ;
2015-11-06 19:06:58 +00:00
result . push_back ( Name [ get ( Recipe_ordinal , current_recipe_name ( ) ) ] [ " " ] ) ;
2015-07-14 02:59:27 +00:00
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
2016-01-20 07:18:03 +00:00
reply default - space : address : shared : array : location
2015-07-14 05:43:16 +00:00
]
# 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
2015-10-29 01:19:41 +00:00
: ( before " End Rewrite Instruction(curr, recipe result) " )
2015-07-14 05:43:16 +00:00
if ( curr . name = = " local-scope " ) {
rewrite_default_space_instruction ( curr ) ;
}
: ( code )
void try_reclaim_locals ( ) {
// only reclaim routines starting with 'local-scope'
2015-11-06 19:06:58 +00:00
const recipe_ordinal r = get ( Recipe_ordinal , current_recipe_name ( ) ) ;
if ( get ( Recipe , r ) . steps . empty ( ) ) return ;
const instruction & inst = get ( Recipe , r ) . steps . at ( 0 ) ;
2015-10-30 00:15:09 +00:00
if ( inst . old_name ! = " local-scope " ) return ;
2015-10-28 13:27:01 +00:00
abandon ( current_call ( ) . default_space ,
2015-07-14 05:43:16 +00:00
/*array length*/ 1 + /*number-of-locals*/ Name [ r ] [ " " ] ) ;
}
void rewrite_default_space_instruction ( instruction & curr ) {
if ( ! curr . ingredients . empty ( ) )
2015-10-30 00:15:09 +00:00
raise_error < < curr . to_string ( ) < < " can't take any ingredients \n " < < end ( ) ;
curr . name = " new " ;
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 ( ) ;
2016-01-20 07:18:03 +00:00
curr . products . push_back ( reagent ( " default-space:address:shared:array:location " ) ) ;
2015-07-14 05:43:16 +00:00
}
2015-04-18 06:24:52 +00:00
//:: helpers
2015-04-03 18:42:50 +00:00
: ( code )
2015-10-28 21:16:26 +00:00
long long int space_base ( const reagent & x ) {
// temporary stub; will be replaced in a later layer
2015-10-28 13:27:01 +00:00
return current_call ( ) . 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-11-06 19:06:58 +00:00
if ( offset > = static_cast < long long int > ( get_or_insert ( Memory , base ) ) ) {
2015-03-29 17:21:15 +00:00
// todo: test
2015-11-06 19:06:58 +00:00
raise_error < < " location " < < offset < < " is out of bounds " < < no_scientific ( get_or_insert ( 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 )
2015-10-26 04:42:18 +00:00
| | ! x . type
2015-11-06 19:06:58 +00:00
| | x . type - > value ! = get ( Type_ordinal , " address " )
2015-10-26 04:42:18 +00:00
| | ! x . type - > right
2016-01-20 07:18:03 +00:00
| | x . type - > right - > value ! = get ( Type_ordinal , " shared " )
2015-10-26 04:42:18 +00:00
| | ! x . type - > right - > right
2016-01-20 07:18:03 +00:00
| | x . type - > right - > right - > value ! = get ( Type_ordinal , " array " )
| | ! x . type - > right - > right - > right
| | x . type - > right - > right - > right - > value ! = get ( Type_ordinal , " location " )
| | x . type - > right - > right - > right - > right ) {
raise_error < < maybe ( current_recipe_name ( ) ) < < " 'default-space' should be of type address:shared:array:location, but tried to write " < < to_string ( data ) < < ' \n ' < < end ( ) ;
2015-10-07 07:22:49 +00:00
}
2015-10-28 13:27:01 +00:00
current_call ( ) . 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 [
2016-01-20 07:18:03 +00:00
default - space : address : shared : array : location < - copy 10 / unsafe
1 : address : shared : array : location / raw < - copy default - space : address : shared : 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-10-28 13:27:01 +00:00
result . push_back ( current_call ( ) . default_space ) ;
2015-04-15 00:46:43 +00:00
return result ;
}