Skip to content

Instantly share code, notes, and snippets.

@mrwonko
Last active August 29, 2015 14:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrwonko/4e5ac2c7fb1330efc6ea to your computer and use it in GitHub Desktop.
Save mrwonko/4e5ac2c7fb1330efc6ea to your computer and use it in GitHub Desktop.
BOOST_AUTO_TEST_CASE( call_and_return_factorial )
{
auto code = create_code_segment(
// stack: [-4: n] (supplied by executor)
opcode::relative_load_stack, std::uint32_t( 4 ), std::int32_t( -4 ),
// stack: [-8: n (return value memory, to be overwritten)] [-4: n]
// result = factorial( n )
opcode::call, label_reference( "factorial" ),
// stack: [factorial( n )]
opcode::exit,
label( "factorial" ),
// stack: [-12: return_value] [-8: n] [-4: return_address]
opcode::relative_load_stack, std::uint32_t( 4 ), std::int32_t( -8 ),
// stack: [-16: return_value] [-12: n] [-8: return_address] [-4: n]
opcode::push_32, std::int32_t( 1 ),
// stack: [-20: return_value] [-16: n] [-12: return_address] [-8: n] [-4: 1]
opcode::less_than_or_equals_i32,
// stack: [-16: return_value] [-12: n] [-8: return_address] [-4: n <= 1]
opcode::relative_jump_if_false, label_reference_offset( "n > 1" ),
// stack: [-12: return_value] [-8: n] [-4: return_address]
// n <= 1: return 1
opcode::push_32, std::int32_t( 1 ),
// stack: [-16: return_value] [-12: n] [-8: return_address] [-4: 1]
opcode::relative_jump, label_reference_offset( "return_top_of_stack" ),
// n > 1: return n * factorial( n - 1)
label( "n > 1" ),
// stack: [-12: return_value] [-8: n] [-4: return_address]
opcode::reserve, std::uint32_t( 4 ),
opcode::relative_load_stack, std::uint32_t( 4 ), std::int32_t( -12 ),
// stack: [-20: return_value] [-16: n] [-12: return_address] [-8: 0] [-4: n]
opcode::push_32, std::int32_t( 1 ),
opcode::subtract_i32,
// stack: [-20: return_value] [-16: n] [-12: return_address] [-8: 0] [-4: n-1]
opcode::call, label_reference( "factorial" ),
// stack: [-16: return_value] [-12: n] [-8: return_address] [-4: factorial(n-1)]
opcode::relative_load_stack, std::uint32_t( 4 ), std::int32_t( -12 ),
// stack: [-20: return_value] [-16: n] [-12: return_address] [-8: factorial(n-1)] [-4: n]
opcode::multiply_i32,
// stack: [-16: return_value] [-12: n] [-8: return_address] [-4: factorial(n-1)*n]
label( "return_top_of_stack" ),
opcode::relative_store_stack, std::uint32_t( 4 ), std::int32_t( -16 ), // store result in return_value
opcode::pop, std::uint32_t( 4 ), // pop result from top of stack
// stack: [-12: return_value = 1] [-8: n] [-4: return_address]
opcode::return_, std::uint32_t( 4 ) // return
);
perseus::stack result = processor( std::move( code ) ).execute( 0, std::move( perseus::stack().push< std::int32_t >( 5 ) ) );
BOOST_CHECK_EQUAL( result.pop< std::uint32_t >(), 120 );
BOOST_CHECK_EQUAL( result.size(), 0 );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment