#pragma once #include "opcodes.hpp" #include namespace bast { struct op_print { word code; op_print( word c ) : code( c ) {} }; template< typename it_t > struct op_print_block { it_t _begin, _end; auto begin() const { return _begin; } auto end() const { return _end; } op_print_block( it_t b, it_t e ) : _begin( b ), _end( e ) {} op_print_block( const std::vector< word > &code ) : op_print_block( code.begin() + 1, code.end() ) {} }; op_print_block( const std::vector< word > & ) -> op_print_block< std::vector< word >::const_iterator >; inline brq::string_builder &operator<<( brq::string_builder &b, label o ) { return b << std::hex << "L" << brq::pad( 3, '0' ) << ( o.v & 0xfffff ) << brq::mark; } inline brq::string_builder &operator<<( brq::string_builder &b, op_print o ) { if ( ( o.code & 0xfe000000 ) != 0xaa000000 ) return b << std::hex << "0x" << o.code; if ( ( o.code & 0xff000000 ) == 0xab000000 ) { word t_bits = ( o.code & 0x00fff000 ) >> 12, o_bits = ( o.code & 0x00000fff ); switch ( t_bits ) { case type_id< byte >: b << "byte_"; break; case type_id< word >: b << "word_"; break; case type_id< dict >: b << "dict_"; break; case type_id< type >: b << "type_"; break; default: b << std::hex << t_bits << "_"; break; } switch ( o_bits ) { case bv_const<>: b << "const"; break; case gen_dup<>: b << "dup"; break; case gen_drop<>: b << "drop"; break; case bv_add<>: b << "add"; break; case bv_sub<>: b << "sub"; break; case bv_eq<>: b << "eq"; break; case bv_neq<>: b << "neq"; break; case bv_slt<>: b << "slt"; break; case bv_trunc_w<>: b << "trunc_w"; break; case bv_guard_zero<>: b << "guard_zero"; break; case bv_guard_nonzero<>: b << "guard_nonzero"; break; default: b << std::hex << brq::pad( 3, '0' ) << o_bits << brq::mark; break; } } else switch ( o.code & 0xfff00000 ) { case block_label(): b << label{ o.code }; break; case block_next(): b << label{ o.code }; break; /* this is a bit iffy */ case swap_at(): { word i = ( o.code & 0xf0000 ) >> 16, j = ( o.code & 0xffff ); b << "swap_" << std::dec << i << "_" << j; break; } default: b << std::hex << o.code; } return b; } template< typename it_t > inline brq::string_builder &operator<<( brq::string_builder &b, op_print_block< it_t > ops ) { int i = 0; for ( word op : ops ) b << ( i++ ? " " : "" ) << op_print( op ); return b; } }