2015-04-25 06:30:14 +00:00
//: Arrays contain a variable number of elements of the same type. Their value
//: starts with the length of the array.
2015-04-18 03:36:25 +00:00
//:
//: You can create arrays of containers, but containers can only contain
//: elements of a fixed size, so you can't create containers containing arrays.
//: Create containers containing addresses to arrays instead.
2015-04-17 18:22:59 +00:00
2015-08-14 23:58:59 +00:00
//: You can create arrays using 'create-array'.
: ( scenario create_array )
2016-03-08 09:30:14 +00:00
def main [
2015-08-14 23:58:59 +00:00
# create an array occupying locations 1 (for the size) and 2-4 (for the elements)
1 : array : number : 3 < - create - array
]
+ run : creating array of size 4
: ( before " End Primitive Recipe Declarations " )
CREATE_ARRAY ,
: ( before " End Primitive Recipe Numbers " )
2015-11-06 19:06:58 +00:00
put ( Recipe_ordinal , " create-array " , CREATE_ARRAY ) ;
2015-10-01 23:25:21 +00:00
: ( before " End Primitive Recipe Checks " )
2015-08-14 23:58:59 +00:00
case CREATE_ARRAY : {
2015-10-01 23:25:21 +00:00
if ( inst . products . empty ( ) ) {
2016-03-21 09:25:52 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " 'create-array' needs one product and no ingredients but got ' " < < to_original_string ( inst ) < < ' \n ' < < end ( ) ;
2015-08-14 23:58:59 +00:00
break ;
}
2015-10-01 23:25:21 +00:00
reagent product = inst . products . at ( 0 ) ;
canonize_type ( product ) ;
2015-08-14 23:58:59 +00:00
if ( ! is_mu_array ( product ) ) {
2016-02-26 21:04:55 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " 'create-array' cannot create non-array " < < product . original_string < < ' \n ' < < end ( ) ;
2015-08-14 23:58:59 +00:00
break ;
}
2015-10-26 04:42:18 +00:00
if ( ! product . type - > right ) {
2016-03-21 09:25:52 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " create array of what? " < < to_original_string ( inst ) < < ' \n ' < < end ( ) ;
2015-08-14 23:58:59 +00:00
break ;
}
// 'create-array' will need to check properties rather than types
2016-02-22 04:30:02 +00:00
if ( ! product . type - > right - > right ) {
2016-03-21 09:25:52 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " create array of what size? " < < to_original_string ( inst ) < < ' \n ' < < end ( ) ;
2015-08-14 23:58:59 +00:00
break ;
}
2016-02-22 04:30:02 +00:00
if ( ! is_integer ( product . type - > right - > right - > name ) ) {
2016-02-26 21:04:55 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " 'create-array' product should specify size of array after its element type, but got " < < product . type - > right - > right - > name < < ' \n ' < < end ( ) ;
2015-08-14 23:58:59 +00:00
break ;
}
2015-10-01 23:25:21 +00:00
break ;
}
: ( before " End Primitive Recipe Implementations " )
case CREATE_ARRAY : {
2015-10-26 04:42:18 +00:00
reagent product = current_instruction ( ) . products . at ( 0 ) ;
canonize ( product ) ;
2016-03-14 03:26:47 +00:00
int base_address = product . value ;
2016-04-13 16:03:06 +00:00
int array_length = to_integer ( product . type - > right - > right - > name ) ;
2015-08-14 23:58:59 +00:00
// initialize array size, so that size_of will work
2016-04-13 16:03:06 +00:00
put ( Memory , base_address , array_length ) ; // in array elements
2016-03-14 03:26:47 +00:00
int size = size_of ( product ) ; // in locations
2015-10-29 18:56:10 +00:00
trace ( 9998 , " run " ) < < " creating array of size " < < size < < ' \n ' < < end ( ) ;
2015-08-14 23:58:59 +00:00
// initialize array
2016-03-14 03:26:47 +00:00
for ( int i = 1 ; i < = size_of ( product ) ; + + i ) {
2015-11-06 19:06:58 +00:00
put ( Memory , base_address + i , 0 ) ;
2015-08-14 23:58:59 +00:00
}
2016-04-13 16:03:06 +00:00
// no need to update product
goto finish_instruction ;
2015-08-14 23:58:59 +00:00
}
2015-02-22 06:08:58 +00:00
: ( scenario copy_array )
2015-05-13 17:03:26 +00:00
# Arrays can be copied around with a single instruction just like numbers,
2015-03-27 04:47:29 +00:00
# no matter how large they are.
2016-04-13 16:03:06 +00:00
# You don't need to pass the size around, since each array variable stores its
# size in memory at run-time. We'll call a variable with an explicit size a
# 'static' array, and one without a 'dynamic' array since it can contain
# arrays of many different sizes.
2016-03-08 09:30:14 +00:00
def main [
2015-08-14 23:58:59 +00:00
1 : array : number : 3 < - create - array
2015-07-28 21:33:22 +00:00
2 : number < - copy 14
3 : number < - copy 15
4 : number < - copy 16
2015-08-14 23:58:59 +00:00
5 : array : number < - copy 1 : array : number : 3
2015-02-22 06:08:58 +00:00
]
2015-03-24 06:59:59 +00:00
+ mem : storing 3 in location 5
+ mem : storing 14 in location 6
+ mem : storing 15 in location 7
+ mem : storing 16 in location 8
2015-02-22 06:08:58 +00:00
2015-04-18 04:49:40 +00:00
: ( scenario copy_array_indirect )
2016-03-08 09:30:14 +00:00
def main [
2015-08-14 23:58:59 +00:00
1 : array : number : 3 < - create - array
2015-07-28 21:33:22 +00:00
2 : number < - copy 14
3 : number < - copy 15
4 : number < - copy 16
2015-11-22 19:51:36 +00:00
5 : address : array : number < - copy 1 / unsafe
2015-07-29 08:35:06 +00:00
6 : array : number < - copy * 5 : address : array : number
2015-04-18 04:49:40 +00:00
]
+ mem : storing 3 in location 6
+ mem : storing 14 in location 7
+ mem : storing 15 in location 8
+ mem : storing 16 in location 9
2015-08-11 06:15:00 +00:00
: ( scenario stash_array )
2016-03-08 09:30:14 +00:00
def main [
2015-08-14 23:58:59 +00:00
1 : array : number : 3 < - create - array
2015-08-11 06:15:00 +00:00
2 : number < - copy 14
3 : number < - copy 15
4 : number < - copy 16
2015-08-24 20:40:21 +00:00
stash [ foo : ] , 1 : array : number : 3
2015-08-11 06:15:00 +00:00
]
+ app : foo : 3 14 15 16
2015-07-24 06:27:36 +00:00
: ( before " End size_of(reagent) Cases " )
2015-11-06 19:06:58 +00:00
if ( r . type & & r . type - > value = = get ( Type_ordinal , " array " ) ) {
2015-10-26 04:42:18 +00:00
if ( ! r . type - > right ) {
2016-02-26 21:04:55 +00:00
raise < < maybe ( current_recipe_name ( ) ) < < " ' " < < r . original_string < < " ' is an array of what? \n " < < end ( ) ;
2015-08-07 19:18:09 +00:00
return 1 ;
2015-03-27 03:24:38 +00:00
}
2016-04-13 16:03:06 +00:00
return 1 + array_length ( r ) * size_of ( array_element ( r . type ) ) ;
2015-08-07 19:18:09 +00:00
}
2015-02-22 09:32:24 +00:00
2016-04-13 16:03:06 +00:00
//: disable the size mismatch check for arrays since the destination array
//: need not be initialized
: ( before " End size_mismatch(x) Cases " )
if ( x . type & & x . type - > value = = get ( Type_ordinal , " array " ) ) return false ;
2016-02-15 20:25:13 +00:00
//: arrays are disallowed inside containers unless their length is fixed in
//: advance
: ( scenario container_contains_array )
container foo [
x : array : number : 3
]
$ error : 0
2016-02-25 19:29:42 +00:00
: ( scenario container_disallows_dynamic_array_element )
2016-02-15 20:25:13 +00:00
% Hide_errors = true ;
container foo [
x : array : number
]
+ error : container ' foo ' cannot determine size of element x
: ( before " End Load Container Element Definition " )
2016-02-17 18:09:48 +00:00
{
2016-02-22 04:30:02 +00:00
const type_tree * type = info . elements . back ( ) . type ;
if ( type - > name = = " array " ) {
if ( ! type - > right ) {
2016-02-26 21:04:55 +00:00
raise < < " container ' " < < name < < " ' doesn't specify type of array elements for " < < info . elements . back ( ) . name < < ' \n ' < < end ( ) ;
2016-02-17 18:09:48 +00:00
continue ;
}
2016-02-22 04:30:02 +00:00
if ( ! type - > right - > right ) { // array has no length
2016-02-26 21:04:55 +00:00
raise < < " container ' " < < name < < " ' cannot determine size of element " < < info . elements . back ( ) . name < < ' \n ' < < end ( ) ;
2016-02-17 18:09:48 +00:00
continue ;
}
2016-02-15 20:25:13 +00:00
}
}
2015-04-18 06:24:52 +00:00
//:: To access elements of an array, use 'index'
2015-04-24 17:19:03 +00:00
: ( scenario index )
2016-03-08 09:30:14 +00:00
def main [
2015-08-14 23:58:59 +00:00
1 : array : number : 3 < - create - array
2015-07-28 21:33:22 +00:00
2 : number < - copy 14
3 : number < - copy 15
4 : number < - copy 16
2015-08-14 23:58:59 +00:00
5 : number < - index 1 : array : number : 3 , 0
2015-03-27 04:47:29 +00:00
]
+ mem : storing 14 in location 5
2015-04-24 17:19:03 +00:00
: ( scenario index_direct_offset )
2016-03-08 09:30:14 +00:00
def main [
2015-08-14 23:58:59 +00:00
1 : array : number : 3 < - create - array
2015-07-28 21:33:22 +00:00
2 : number < - copy 14
3 : number < - copy 15
4 : number < - copy 16
5 : number < - copy 0
2015-08-14 23:58:59 +00:00
6 : number < - index 1 : array : number , 5 : number
2015-04-03 19:49:11 +00:00
]
+ mem : storing 14 in location 6
2015-04-17 17:31:17 +00:00
: ( before " End Primitive Recipe Declarations " )
INDEX ,
2015-02-22 09:32:24 +00:00
: ( before " End Primitive Recipe Numbers " )
2015-11-06 19:06:58 +00:00
put ( Recipe_ordinal , " index " , INDEX ) ;
2015-10-01 23:25:21 +00:00
: ( before " End Primitive Recipe Checks " )
2015-02-22 09:32:24 +00:00
case INDEX : {
2015-10-01 23:25:21 +00:00
if ( SIZE ( inst . ingredients ) ! = 2 ) {
2016-03-21 09:25:52 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " 'index' expects exactly 2 ingredients in ' " < < to_original_string ( inst ) < < " ' \n " < < end ( ) ;
2015-07-25 21:19:28 +00:00
break ;
}
2015-10-01 23:25:21 +00:00
reagent base = inst . ingredients . at ( 0 ) ;
canonize_type ( base ) ;
2015-08-13 23:32:36 +00:00
if ( ! is_mu_array ( base ) ) {
2016-02-26 21:04:55 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " 'index' on a non-array " < < base . original_string < < ' \n ' < < end ( ) ;
2015-08-01 00:06:38 +00:00
break ;
}
2015-10-06 00:02:32 +00:00
if ( inst . products . empty ( ) ) break ;
reagent product = inst . products . at ( 0 ) ;
canonize_type ( product ) ;
reagent element ;
2015-10-26 04:42:18 +00:00
element . type = new type_tree ( * array_element ( base . type ) ) ;
2015-11-27 18:32:34 +00:00
if ( ! types_coercible ( product , element ) ) {
2016-02-26 21:04:55 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " 'index' on " < < base . original_string < < " can't be saved in " < < product . original_string < < " ; type should be " < < names_to_string_without_quotes ( element . type ) < < ' \n ' < < end ( ) ;
2015-10-06 00:02:32 +00:00
break ;
}
2015-10-01 23:25:21 +00:00
break ;
}
: ( before " End Primitive Recipe Implementations " )
case INDEX : {
2015-10-26 04:42:18 +00:00
reagent base = current_instruction ( ) . ingredients . at ( 0 ) ;
canonize ( base ) ;
2016-03-14 03:26:47 +00:00
int base_address = base . value ;
2016-01-21 04:47:54 +00:00
trace ( 9998 , " run " ) < < " base address is " < < base_address < < end ( ) ;
2015-08-01 00:06:38 +00:00
if ( base_address = = 0 ) {
2016-03-21 09:25:52 +00:00
raise < < maybe ( current_recipe_name ( ) ) < < " tried to access location 0 in ' " < < to_original_string ( current_instruction ( ) ) < < " ' \n " < < end ( ) ;
2015-07-24 08:14:49 +00:00
break ;
}
2015-10-26 04:42:18 +00:00
reagent offset = current_instruction ( ) . ingredients . at ( 1 ) ;
canonize ( offset ) ;
2015-05-13 01:08:47 +00:00
vector < double > offset_val ( read_memory ( offset ) ) ;
2015-10-26 04:42:18 +00:00
type_tree * element_type = array_element ( base . type ) ;
2015-11-06 19:06:58 +00:00
if ( offset_val . at ( 0 ) < 0 | | offset_val . at ( 0 ) > = get_or_insert ( Memory , base_address ) ) {
2016-02-26 21:04:55 +00:00
raise < < maybe ( current_recipe_name ( ) ) < < " invalid index " < < no_scientific ( offset_val . at ( 0 ) ) < < ' \n ' < < end ( ) ;
2015-07-17 21:30:17 +00:00
break ;
}
2016-03-14 03:26:47 +00:00
int src = base_address + 1 + offset_val . at ( 0 ) * size_of ( element_type ) ;
2015-10-29 19:09:23 +00:00
trace ( 9998 , " run " ) < < " address to copy is " < < src < < end ( ) ;
2015-11-06 19:06:58 +00:00
trace ( 9998 , " run " ) < < " its type is " < < get ( Type , element_type - > value ) . name < < end ( ) ;
2016-04-20 16:58:07 +00:00
reagent element ;
element . set_value ( src ) ;
element . type = new type_tree ( * element_type ) ;
// Read element
products . push_back ( read_memory ( element ) ) ;
2015-02-22 09:32:24 +00:00
break ;
}
2015-03-27 04:47:29 +00:00
: ( code )
2015-10-26 04:42:18 +00:00
type_tree * array_element ( const type_tree * type ) {
2016-02-27 05:30:43 +00:00
if ( type - > right - > left ) {
assert ( ! type - > right - > left - > left ) ;
return type - > right - > left ;
}
2015-10-26 04:42:18 +00:00
return type - > right ;
2015-03-27 04:47:29 +00:00
}
2016-04-13 16:03:06 +00:00
int array_length ( const reagent & x ) {
if ( x . type - > right - > right ) {
return to_integer ( x . type - > right - > right - > name ) ;
}
// this should never happen at transform time
// x should already be canonized.
return get_or_insert ( Memory , x . value ) ;
}
2015-07-17 21:30:17 +00:00
: ( scenario index_indirect )
2016-03-08 09:30:14 +00:00
def main [
2015-08-14 23:58:59 +00:00
1 : array : number : 3 < - create - array
2015-07-28 21:33:22 +00:00
2 : number < - copy 14
3 : number < - copy 15
4 : number < - copy 16
2015-11-22 19:51:36 +00:00
5 : address : array : number < - copy 1 / unsafe
2015-07-29 08:35:06 +00:00
6 : number < - index * 5 : address : array : number , 1
2015-02-22 09:32:24 +00:00
]
2015-07-17 21:30:17 +00:00
+ mem : storing 15 in location 6
: ( scenario index_out_of_bounds )
2015-10-07 05:15:45 +00:00
% Hide_errors = true ;
2016-03-08 09:30:14 +00:00
def main [
2015-08-14 23:58:59 +00:00
1 : array : number : 3 < - create - array
2015-07-28 21:33:22 +00:00
2 : number < - copy 14
3 : number < - copy 15
4 : number < - copy 16
5 : number < - copy 14
6 : number < - copy 15
7 : number < - copy 16
2016-01-12 06:57:35 +00:00
8 : address : array : point < - copy 1 / unsafe
2015-07-29 08:35:06 +00:00
index * 8 : address : array : point , 4 # less than size of array in locations , but larger than its length in elements
2015-07-17 21:30:17 +00:00
]
2015-10-07 05:15:45 +00:00
+ error : main : invalid index 4
2015-07-17 21:30:17 +00:00
2015-08-09 19:26:31 +00:00
: ( scenario index_out_of_bounds_2 )
2015-10-07 05:15:45 +00:00
% Hide_errors = true ;
2016-03-08 09:30:14 +00:00
def main [
2015-08-14 23:58:59 +00:00
1 : array : point : 3 < - create - array
2015-07-28 21:33:22 +00:00
2 : number < - copy 14
3 : number < - copy 15
4 : number < - copy 16
5 : number < - copy 14
6 : number < - copy 15
7 : number < - copy 16
2015-11-22 19:51:36 +00:00
8 : address : array : point < - copy 1 / unsafe
2015-07-29 08:35:06 +00:00
index * 8 : address : array : point , - 1
2015-07-17 21:30:17 +00:00
]
2015-10-07 05:15:45 +00:00
+ error : main : invalid index - 1
2015-02-22 09:32:24 +00:00
2015-10-06 00:02:32 +00:00
: ( scenario index_product_type_mismatch )
2015-10-07 05:15:45 +00:00
% Hide_errors = true ;
2016-03-08 09:30:14 +00:00
def main [
2015-10-06 00:02:32 +00:00
1 : array : point : 3 < - create - array
2 : number < - copy 14
3 : number < - copy 15
4 : number < - copy 16
5 : number < - copy 14
6 : number < - copy 15
7 : number < - copy 16
2015-11-22 19:51:36 +00:00
8 : address : array : point < - copy 1 / unsafe
2015-10-06 00:02:32 +00:00
9 : number < - index * 8 : address : array : point , 0
]
2015-10-07 05:15:45 +00:00
+ error : main : ' index ' on * 8 : address : array : point can ' t be saved in 9 : number ; type should be point
2015-10-06 00:02:32 +00:00
2015-11-16 02:36:34 +00:00
//: we might want to call 'index' without saving the results, say in a sandbox
: ( scenario index_without_product )
2016-03-08 09:30:14 +00:00
def main [
2015-11-16 02:36:34 +00:00
1 : array : number : 3 < - create - array
2 : number < - copy 14
3 : number < - copy 15
4 : number < - copy 16
index 1 : array : number : 3 , 0
]
# just don't die
2015-04-18 06:24:52 +00:00
//:: To write to elements of containers, you need their address.
2015-04-17 17:31:17 +00:00
2015-07-17 21:30:17 +00:00
: ( scenario index_address )
2016-03-08 09:30:14 +00:00
def main [
2015-08-14 23:58:59 +00:00
1 : array : number : 3 < - create - array
2015-07-28 21:33:22 +00:00
2 : number < - copy 14
3 : number < - copy 15
4 : number < - copy 16
2015-10-06 00:02:32 +00:00
5 : address : number < - index - address 1 : array : number , 0
2015-04-17 17:31:17 +00:00
]
2015-07-17 21:30:17 +00:00
+ mem : storing 2 in location 5
2015-04-17 17:31:17 +00:00
: ( before " End Primitive Recipe Declarations " )
INDEX_ADDRESS ,
2015-02-22 09:32:24 +00:00
: ( before " End Primitive Recipe Numbers " )
2015-11-06 19:06:58 +00:00
put ( Recipe_ordinal , " index-address " , INDEX_ADDRESS ) ;
2015-10-01 23:25:21 +00:00
: ( before " End Primitive Recipe Checks " )
2015-02-22 09:32:24 +00:00
case INDEX_ADDRESS : {
2015-10-01 23:25:21 +00:00
if ( SIZE ( inst . ingredients ) ! = 2 ) {
2016-03-21 09:25:52 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " 'index-address' expects exactly 2 ingredients in ' " < < to_original_string ( inst ) < < " ' \n " < < end ( ) ;
2015-07-25 21:19:28 +00:00
break ;
}
2015-10-01 23:25:21 +00:00
reagent base = inst . ingredients . at ( 0 ) ;
canonize_type ( base ) ;
2015-08-13 23:32:36 +00:00
if ( ! is_mu_array ( base ) ) {
2016-02-26 21:04:55 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " 'index-address' on a non-array " < < base . original_string < < ' \n ' < < end ( ) ;
2015-07-24 08:14:49 +00:00
break ;
}
2015-10-06 00:02:32 +00:00
if ( inst . products . empty ( ) ) break ;
reagent product = inst . products . at ( 0 ) ;
canonize_type ( product ) ;
reagent element ;
2016-02-20 16:54:42 +00:00
element . type = new type_tree ( " address " , get ( Type_ordinal , " address " ) ,
new type_tree ( * array_element ( base . type ) ) ) ;
2015-11-27 18:32:34 +00:00
if ( ! types_coercible ( product , element ) ) {
2016-02-26 21:04:55 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " 'index' on " < < base . original_string < < " can't be saved in " < < product . original_string < < " ; type should be " < < names_to_string_without_quotes ( element . type ) < < ' \n ' < < end ( ) ;
2015-10-06 00:02:32 +00:00
break ;
}
2015-10-01 23:25:21 +00:00
break ;
}
: ( before " End Primitive Recipe Implementations " )
case INDEX_ADDRESS : {
2015-10-26 04:42:18 +00:00
reagent base = current_instruction ( ) . ingredients . at ( 0 ) ;
canonize ( base ) ;
2016-03-14 03:26:47 +00:00
int base_address = base . value ;
2015-08-01 00:06:38 +00:00
if ( base_address = = 0 ) {
2016-03-21 09:25:52 +00:00
raise < < maybe ( current_recipe_name ( ) ) < < " tried to access location 0 in ' " < < to_original_string ( current_instruction ( ) ) < < " ' \n " < < end ( ) ;
2015-08-01 00:06:38 +00:00
break ;
}
2015-10-26 04:42:18 +00:00
reagent offset = current_instruction ( ) . ingredients . at ( 1 ) ;
canonize ( offset ) ;
2015-05-13 01:08:47 +00:00
vector < double > offset_val ( read_memory ( offset ) ) ;
2015-10-26 04:42:18 +00:00
type_tree * element_type = array_element ( base . type ) ;
2015-11-06 19:06:58 +00:00
if ( offset_val . at ( 0 ) < 0 | | offset_val . at ( 0 ) > = get_or_insert ( Memory , base_address ) ) {
2016-02-26 21:04:55 +00:00
raise < < maybe ( current_recipe_name ( ) ) < < " invalid index " < < no_scientific ( offset_val . at ( 0 ) ) < < ' \n ' < < end ( ) ;
2015-07-17 21:30:17 +00:00
break ;
}
2016-03-14 03:26:47 +00:00
int result = base_address + 1 + offset_val . at ( 0 ) * size_of ( element_type ) ;
2015-08-03 05:18:19 +00:00
products . resize ( 1 ) ;
2015-05-13 00:00:56 +00:00
products . at ( 0 ) . push_back ( result ) ;
2015-02-22 09:32:24 +00:00
break ;
}
2015-05-26 22:16:36 +00:00
2015-07-17 21:30:17 +00:00
: ( scenario index_address_out_of_bounds )
2015-10-07 05:15:45 +00:00
% Hide_errors = true ;
2016-03-08 09:30:14 +00:00
def main [
2015-08-14 23:58:59 +00:00
1 : array : point : 3 < - create - array
2015-07-28 21:33:22 +00:00
2 : number < - copy 14
3 : number < - copy 15
4 : number < - copy 16
5 : number < - copy 14
6 : number < - copy 15
7 : number < - copy 16
2016-01-12 06:57:35 +00:00
8 : address : array : point < - copy 1 / unsafe
2015-07-29 08:35:06 +00:00
index - address * 8 : address : array : point , 4 # less than size of array in locations , but larger than its length in elements
2015-07-17 21:30:17 +00:00
]
2015-10-07 05:15:45 +00:00
+ error : main : invalid index 4
2015-07-17 21:30:17 +00:00
2015-08-09 19:26:31 +00:00
: ( scenario index_address_out_of_bounds_2 )
2015-10-07 05:15:45 +00:00
% Hide_errors = true ;
2016-03-08 09:30:14 +00:00
def main [
2015-08-14 23:58:59 +00:00
1 : array : point : 3 < - create - array
2015-07-28 21:33:22 +00:00
2 : number < - copy 14
3 : number < - copy 15
4 : number < - copy 16
5 : number < - copy 14
6 : number < - copy 15
7 : number < - copy 16
2015-11-22 19:51:36 +00:00
8 : address : array : point < - copy 1 / unsafe
2015-07-29 08:35:06 +00:00
index - address * 8 : address : array : point , - 1
2015-07-17 21:30:17 +00:00
]
2015-10-07 05:15:45 +00:00
+ error : main : invalid index - 1
2015-07-17 21:30:17 +00:00
2015-10-06 00:02:32 +00:00
: ( scenario index_address_product_type_mismatch )
2015-10-07 05:15:45 +00:00
% Hide_errors = true ;
2016-03-08 09:30:14 +00:00
def main [
2015-10-06 00:02:32 +00:00
1 : array : point : 3 < - create - array
2 : number < - copy 14
3 : number < - copy 15
4 : number < - copy 16
5 : number < - copy 14
6 : number < - copy 15
7 : number < - copy 16
2015-11-22 19:51:36 +00:00
8 : address : array : point < - copy 1 / unsafe
2015-10-06 00:02:32 +00:00
9 : address : number < - index - address * 8 : address : array : point , 0
]
2016-02-22 04:30:02 +00:00
+ error : main : ' index ' on * 8 : address : array : point can ' t be saved in 9 : address : number ; type should be ( address point )
2015-10-06 00:02:32 +00:00
2015-05-26 22:16:36 +00:00
//:: compute the length of an array
: ( scenario array_length )
2016-03-08 09:30:14 +00:00
def main [
2015-08-14 23:58:59 +00:00
1 : array : number : 3 < - create - array
2015-07-28 21:33:22 +00:00
2 : number < - copy 14
3 : number < - copy 15
4 : number < - copy 16
2015-08-14 23:58:59 +00:00
5 : number < - length 1 : array : number : 3
2015-05-26 22:16:36 +00:00
]
+ mem : storing 3 in location 5
: ( before " End Primitive Recipe Declarations " )
LENGTH ,
: ( before " End Primitive Recipe Numbers " )
2015-11-06 19:06:58 +00:00
put ( Recipe_ordinal , " length " , LENGTH ) ;
2015-10-01 23:25:21 +00:00
: ( before " End Primitive Recipe Checks " )
2015-05-26 22:16:36 +00:00
case LENGTH : {
2015-10-01 23:25:21 +00:00
if ( SIZE ( inst . ingredients ) ! = 1 ) {
2016-03-21 09:25:52 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " 'length' expects exactly 2 ingredients in ' " < < to_original_string ( inst ) < < " ' \n " < < end ( ) ;
2015-07-25 21:19:28 +00:00
break ;
}
2015-10-01 23:25:21 +00:00
reagent x = inst . ingredients . at ( 0 ) ;
canonize_type ( x ) ;
2015-08-13 23:32:36 +00:00
if ( ! is_mu_array ( x ) ) {
2016-02-26 21:04:55 +00:00
raise < < " tried to calculate length of non-array " < < x . original_string < < ' \n ' < < end ( ) ;
2015-05-26 22:16:36 +00:00
break ;
}
2015-10-01 23:25:21 +00:00
break ;
}
: ( before " End Primitive Recipe Implementations " )
case LENGTH : {
2015-10-26 04:42:18 +00:00
reagent x = current_instruction ( ) . ingredients . at ( 0 ) ;
canonize ( x ) ;
2015-08-01 00:06:38 +00:00
if ( x . value = = 0 ) {
2016-03-21 09:25:52 +00:00
raise < < maybe ( current_recipe_name ( ) ) < < " tried to access location 0 in ' " < < to_original_string ( current_instruction ( ) ) < < " ' \n " < < end ( ) ;
2015-08-01 00:06:38 +00:00
break ;
}
2015-08-03 05:18:19 +00:00
products . resize ( 1 ) ;
2015-11-06 19:06:58 +00:00
products . at ( 0 ) . push_back ( get_or_insert ( Memory , x . value ) ) ;
2015-05-26 22:16:36 +00:00
break ;
}
2015-08-15 04:13:49 +00:00
//: optimization: none of the instructions in this layer use 'ingredients' so
//: stop copying potentially huge arrays into it.
: ( before " End should_copy_ingredients Special-cases " )
recipe_ordinal r = current_instruction ( ) . operation ;
if ( r = = CREATE_ARRAY | | r = = INDEX | | r = = INDEX_ADDRESS | | r = = LENGTH )
return false ;
2015-11-18 21:50:37 +00:00
//: a particularly common array type is the string, or address:array:character
: ( code )
bool is_mu_string ( const reagent & x ) {
return x . type
& & x . type - > value = = get ( Type_ordinal , " address " )
& & x . type - > right
2016-01-20 07:18:03 +00:00
& & x . type - > right - > value = = get ( Type_ordinal , " shared " )
2015-11-18 21:50:37 +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 , " character " )
& & x . type - > right - > right - > right - > right = = NULL ;
2015-11-18 21:50:37 +00:00
}