2015-04-18 14:50:51 +00:00
//: Jump primitives
2015-04-17 18:22:59 +00:00
2015-05-17 07:52:23 +00:00
: ( scenario jump_can_skip_instructions )
2016-03-08 09:30:14 +00:00
def main [
2015-05-17 07:52:23 +00:00
jump 1 : offset
2016-09-17 07:43:13 +00:00
1 : num < - copy 1
2015-05-17 07:52:23 +00:00
]
2016-03-21 09:25:52 +00:00
+ run : jump { 1 : " offset " }
- run : { 1 : " number " } < - copy { 1 : " literal " }
2015-05-17 07:52:23 +00:00
- mem : storing 1 in location 1
2015-04-17 17:31:17 +00:00
: ( before " End Primitive Recipe Declarations " )
JUMP ,
2015-02-20 01:28:25 +00:00
: ( before " End Primitive Recipe Numbers " )
2015-11-06 19:06:58 +00:00
put ( Recipe_ordinal , " jump " , JUMP ) ;
2015-09-30 09:18:05 +00:00
: ( before " End Primitive Recipe Checks " )
2015-02-20 01:28:25 +00:00
case JUMP : {
2015-09-30 09:18:05 +00:00
if ( SIZE ( inst . ingredients ) ! = 1 ) {
2017-05-26 23:43:18 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " ' " < < to_original_string ( inst ) < < " ' should get exactly one ingredient \n " < < end ( ) ;
2015-07-25 21:19:28 +00:00
break ;
}
2016-04-28 20:20:12 +00:00
if ( ! is_literal ( inst . ingredients . at ( 0 ) ) ) {
2017-05-26 23:43:18 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " first ingredient of ' " < < to_original_string ( inst ) < < " ' should be a label or offset, but ' " < < inst . ingredients . at ( 0 ) . name < < " ' has type ' " < < names_to_string_without_quotes ( inst . ingredients . at ( 0 ) . type ) < < " ' \n " < < end ( ) ;
2015-07-25 21:19:28 +00:00
break ;
}
2018-05-25 19:25:13 +00:00
if ( ! inst . products . empty ( ) ) {
raise < < maybe ( get ( Recipe , r ) . name ) < < " 'jump' instructions write no products \n " < < end ( ) ;
break ;
}
2015-09-30 09:18:05 +00:00
break ;
}
: ( before " End Primitive Recipe Implementations " )
case JUMP : {
2015-05-10 15:34:12 +00:00
assert ( current_instruction ( ) . ingredients . at ( 0 ) . initialized ) ;
2015-06-04 01:00:11 +00:00
current_step_index ( ) + = ingredients . at ( 0 ) . at ( 0 ) + 1 ;
2019-02-25 08:17:46 +00:00
trace ( Callstack_depth + 1 , " run " ) < < " jumping to instruction " < < current_step_index ( ) < < end ( ) ;
2017-05-28 21:28:07 +00:00
// skip rest of this instruction
write_products = false ;
fall_through_to_next_instruction = false ;
break ;
2015-02-20 01:28:25 +00:00
}
2015-05-17 07:52:23 +00:00
//: special type to designate jump targets
: ( before " End Mu Types Initialization " )
2015-11-06 19:06:58 +00:00
put ( Type_ordinal , " offset " , 0 ) ;
2015-02-20 01:28:25 +00:00
2015-04-24 17:19:03 +00:00
: ( scenario jump_backward )
2016-03-08 09:30:14 +00:00
def main [
2015-03-17 05:47:28 +00:00
jump 1 : offset # 0 - +
2015-05-21 19:36:59 +00:00
jump 3 : offset # | + - + 1
2015-03-17 05:47:28 +00:00
# \ / / \ |
jump - 2 : offset # 2 + - - > + |
] # \ / 3
2016-03-21 09:25:52 +00:00
+ run : jump { 1 : " offset " }
+ run : jump { - 2 : " offset " }
+ run : jump { 3 : " offset " }
2015-02-20 02:25:25 +00:00
2018-05-25 19:25:13 +00:00
: ( scenario jump_takes_no_products )
% Hide_errors = true ;
def main [
1 : num < - jump 1
]
+ error : main : ' jump ' instructions write no products
2015-04-17 17:31:17 +00:00
: ( before " End Primitive Recipe Declarations " )
JUMP_IF ,
2015-02-20 02:25:25 +00:00
: ( before " End Primitive Recipe Numbers " )
2015-11-06 19:06:58 +00:00
put ( Recipe_ordinal , " jump-if " , JUMP_IF ) ;
2015-09-30 09:18:05 +00:00
: ( before " End Primitive Recipe Checks " )
2015-02-20 02:25:25 +00:00
case JUMP_IF : {
2015-09-30 09:18:05 +00:00
if ( SIZE ( inst . ingredients ) ! = 2 ) {
2017-05-26 23:43:18 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " ' " < < to_original_string ( inst ) < < " ' should get exactly two ingredients \n " < < end ( ) ;
2015-07-25 21:19:28 +00:00
break ;
}
2018-06-24 16:16:17 +00:00
if ( ! is_mu_address ( inst . ingredients . at ( 0 ) ) & & ! is_mu_scalar ( inst . ingredients . at ( 0 ) ) ) {
2017-05-26 23:43:18 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " ' " < < to_original_string ( inst ) < < " ' requires a boolean for its first ingredient, but ' " < < inst . ingredients . at ( 0 ) . name < < " ' has type ' " < < names_to_string_without_quotes ( inst . ingredients . at ( 0 ) . type ) < < " ' \n " < < end ( ) ;
2015-07-25 21:19:28 +00:00
break ;
}
2016-04-28 20:20:12 +00:00
if ( ! is_literal ( inst . ingredients . at ( 1 ) ) ) {
2017-05-26 23:43:18 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " ' " < < to_original_string ( inst ) < < " ' requires a label or offset for its second ingredient, but ' " < < inst . ingredients . at ( 1 ) . name < < " ' has type ' " < < names_to_string_without_quotes ( inst . ingredients . at ( 1 ) . type ) < < " ' \n " < < end ( ) ;
2015-07-25 21:19:28 +00:00
break ;
}
2018-05-25 19:25:13 +00:00
if ( ! inst . products . empty ( ) ) {
raise < < maybe ( get ( Recipe , r ) . name ) < < " 'jump-if' instructions write no products \n " < < end ( ) ;
break ;
}
2016-04-28 20:20:12 +00:00
// End JUMP_IF Checks
2015-09-30 09:18:05 +00:00
break ;
}
: ( before " End Primitive Recipe Implementations " )
case JUMP_IF : {
2015-05-10 15:34:12 +00:00
assert ( current_instruction ( ) . ingredients . at ( 1 ) . initialized ) ;
2018-06-24 16:16:17 +00:00
if ( ! scalar_ingredient ( ingredients , 0 ) ) {
2019-02-25 08:17:46 +00:00
trace ( Callstack_depth + 1 , " run " ) < < " jump-if fell through " < < end ( ) ;
2015-02-20 02:25:25 +00:00
break ;
}
2015-06-04 01:00:11 +00:00
current_step_index ( ) + = ingredients . at ( 1 ) . at ( 0 ) + 1 ;
2019-02-25 08:17:46 +00:00
trace ( Callstack_depth + 1 , " run " ) < < " jumping to instruction " < < current_step_index ( ) < < end ( ) ;
2017-05-28 21:28:07 +00:00
// skip rest of this instruction
write_products = false ;
fall_through_to_next_instruction = false ;
break ;
2015-02-20 02:25:25 +00:00
}
2015-04-24 17:19:03 +00:00
: ( scenario jump_if )
2016-03-08 09:30:14 +00:00
def main [
2015-07-28 21:33:22 +00:00
jump - if 999 , 1 : offset
2016-09-17 07:43:13 +00:00
123 : num < - copy 1
2015-02-20 02:25:25 +00:00
]
2016-03-21 09:25:52 +00:00
+ run : jump - if { 999 : " literal " } , { 1 : " offset " }
2015-02-20 02:25:25 +00:00
+ run : jumping to instruction 2
2018-06-24 16:16:17 +00:00
- run : { 123 : " number " } < - copy { 1 : " literal " }
2015-05-21 19:36:59 +00:00
- mem : storing 1 in location 123
2015-02-20 02:25:25 +00:00
2015-04-24 17:19:03 +00:00
: ( scenario jump_if_fallthrough )
2016-03-08 09:30:14 +00:00
def main [
2015-07-28 21:33:22 +00:00
jump - if 0 , 1 : offset
2016-09-17 07:43:13 +00:00
123 : num < - copy 1
2015-02-20 02:25:25 +00:00
]
2016-03-21 09:25:52 +00:00
+ run : jump - if { 0 : " literal " } , { 1 : " offset " }
2015-02-20 02:25:25 +00:00
+ run : jump - if fell through
2016-03-21 09:25:52 +00:00
+ run : { 123 : " number " } < - copy { 1 : " literal " }
2015-03-24 06:59:59 +00:00
+ mem : storing 1 in location 123
2015-02-20 02:25:25 +00:00
2018-06-24 16:16:17 +00:00
: ( scenario jump_if_on_address )
def main [
10 : num / alloc - id , 11 : num < - copy 0 , 999
jump - if 10 : & : number , 1 : offset
123 : num < - copy 1
]
+ run : jump - if { 10 : ( " address " " number " ) } , { 1 : " offset " }
+ run : jumping to instruction 3
- run : { 123 : " number " } < - copy { 1 : " literal " }
- mem : storing 1 in location 123
2015-04-17 17:31:17 +00:00
: ( before " End Primitive Recipe Declarations " )
JUMP_UNLESS ,
2015-02-20 02:25:25 +00:00
: ( before " End Primitive Recipe Numbers " )
2015-11-06 19:06:58 +00:00
put ( Recipe_ordinal , " jump-unless " , JUMP_UNLESS ) ;
2015-09-30 09:18:05 +00:00
: ( before " End Primitive Recipe Checks " )
2015-02-20 02:25:25 +00:00
case JUMP_UNLESS : {
2015-09-30 09:18:05 +00:00
if ( SIZE ( inst . ingredients ) ! = 2 ) {
2017-05-26 23:43:18 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " ' " < < to_original_string ( inst ) < < " ' should get exactly two ingredients \n " < < end ( ) ;
2015-07-25 21:19:28 +00:00
break ;
}
2018-06-24 16:16:17 +00:00
if ( ! is_mu_address ( inst . ingredients . at ( 0 ) ) & & ! is_mu_scalar ( inst . ingredients . at ( 0 ) ) ) {
2017-05-26 23:43:18 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " ' " < < to_original_string ( inst ) < < " ' requires a boolean for its first ingredient, but ' " < < inst . ingredients . at ( 0 ) . name < < " ' has type ' " < < names_to_string_without_quotes ( inst . ingredients . at ( 0 ) . type ) < < " ' \n " < < end ( ) ;
2015-07-25 21:19:28 +00:00
break ;
}
2016-04-28 20:20:12 +00:00
if ( ! is_literal ( inst . ingredients . at ( 1 ) ) ) {
2017-05-26 23:43:18 +00:00
raise < < maybe ( get ( Recipe , r ) . name ) < < " ' " < < to_original_string ( inst ) < < " ' requires a label or offset for its second ingredient, but ' " < < inst . ingredients . at ( 1 ) . name < < " ' has type ' " < < names_to_string_without_quotes ( inst . ingredients . at ( 1 ) . type ) < < " ' \n " < < end ( ) ;
2015-07-25 21:19:28 +00:00
break ;
}
2018-05-25 19:25:13 +00:00
if ( ! inst . products . empty ( ) ) {
raise < < maybe ( get ( Recipe , r ) . name ) < < " 'jump' instructions write no products \n " < < end ( ) ;
break ;
}
2016-04-28 20:20:12 +00:00
// End JUMP_UNLESS Checks
2015-09-30 09:18:05 +00:00
break ;
}
: ( before " End Primitive Recipe Implementations " )
case JUMP_UNLESS : {
2015-05-10 15:34:12 +00:00
assert ( current_instruction ( ) . ingredients . at ( 1 ) . initialized ) ;
2018-06-24 16:16:17 +00:00
if ( scalar_ingredient ( ingredients , 0 ) ) {
2019-02-25 08:17:46 +00:00
trace ( Callstack_depth + 1 , " run " ) < < " jump-unless fell through " < < end ( ) ;
2015-02-20 02:25:25 +00:00
break ;
}
2015-06-04 01:00:11 +00:00
current_step_index ( ) + = ingredients . at ( 1 ) . at ( 0 ) + 1 ;
2019-02-25 08:17:46 +00:00
trace ( Callstack_depth + 1 , " run " ) < < " jumping to instruction " < < current_step_index ( ) < < end ( ) ;
2017-05-28 21:28:07 +00:00
// skip rest of this instruction
write_products = false ;
fall_through_to_next_instruction = false ;
break ;
2015-02-20 02:25:25 +00:00
}
2015-04-24 17:19:03 +00:00
: ( scenario jump_unless )
2016-03-08 09:30:14 +00:00
def main [
2015-07-28 21:33:22 +00:00
jump - unless 0 , 1 : offset
2016-09-17 07:43:13 +00:00
123 : num < - copy 1
2015-02-20 02:25:25 +00:00
]
2016-03-21 09:25:52 +00:00
+ run : jump - unless { 0 : " literal " } , { 1 : " offset " }
2015-02-20 02:25:25 +00:00
+ run : jumping to instruction 2
2016-03-21 09:25:52 +00:00
- run : { 123 : " number " } < - copy { 1 : " literal " }
2015-05-21 19:36:59 +00:00
- mem : storing 1 in location 123
2015-02-20 02:25:25 +00:00
2015-04-24 17:19:03 +00:00
: ( scenario jump_unless_fallthrough )
2016-03-08 09:30:14 +00:00
def main [
2015-07-28 21:33:22 +00:00
jump - unless 999 , 1 : offset
2016-09-17 07:43:13 +00:00
123 : num < - copy 1
2015-02-20 02:25:25 +00:00
]
2016-03-21 09:25:52 +00:00
+ run : jump - unless { 999 : " literal " } , { 1 : " offset " }
2015-02-20 02:25:25 +00:00
+ run : jump - unless fell through
2016-03-21 09:25:52 +00:00
+ run : { 123 : " number " } < - copy { 1 : " literal " }
2015-03-24 06:59:59 +00:00
+ mem : storing 1 in location 123