/* * (c) 2022 Petr Ročkai * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #pragma once #include #include #include #include #include namespace bast { inline namespace types { using byte = uint8_t; using half = uint16_t; using word = uint32_t; using dyad = uint64_t; struct type { uint16_t stid; uint16_t vtid; auto operator<=>( const type & ) const = default; friend brq::string_builder &operator<<( brq::string_builder &b, const type &t ) { return b << t.stid << "/" << t.vtid; } }; struct coro { uint32_t v; }; struct dict { uint32_t v; }; struct label { uint32_t v; }; struct objid { uint32_t v; }; } struct stop_t { bool operator==( stop_t ) const { return true; } }; struct next_t { bool operator==( next_t ) const { return true; } }; struct error_t { bool operator==( error_t ) const { return true; } }; struct jump { types::label to; bool operator==( jump ) const { UNREACHABLE( "jumps cannot be compared" ); } }; using step = std::variant< stop_t, next_t, error_t, jump >; constexpr step next = next_t(); constexpr step stop = stop_t(); constexpr step error = error_t(); enum class builtin_type : word { none, byte, half, word, dyad, type, coro, dict, label, objid, _count_ }; template< builtin_type > struct to_type_impl {}; template<> struct to_type_impl< builtin_type::none > { using type = void; }; template<> struct to_type_impl< builtin_type::byte > { using type = types::byte; }; template<> struct to_type_impl< builtin_type::half > { using type = types::half; }; template<> struct to_type_impl< builtin_type::word > { using type = types::word; }; template<> struct to_type_impl< builtin_type::dyad > { using type = types::dyad; }; template<> struct to_type_impl< builtin_type::type > { using type = types::type; }; template<> struct to_type_impl< builtin_type::coro > { using type = types::coro; }; template<> struct to_type_impl< builtin_type::dict > { using type = types::dict; }; template<> struct to_type_impl< builtin_type::label > { using type = types::label; }; template<> struct to_type_impl< builtin_type::objid > { using type = types::objid; }; template< builtin_type tid > using to_type = typename to_type_impl< tid >::type; template< builtin_type > struct bitvec_type : std::false_type {}; template<> struct bitvec_type< builtin_type::byte > : std::true_type { using type = byte; }; template<> struct bitvec_type< builtin_type::half > : std::true_type { using type = half; }; template<> struct bitvec_type< builtin_type::word > : std::true_type { using type = word; }; template<> struct bitvec_type< builtin_type::dyad > : std::true_type { using type = dyad; }; template< builtin_type > struct signed_type : std::false_type {}; template<> struct signed_type< builtin_type::byte > : std::true_type { using type = int8_t; }; template<> struct signed_type< builtin_type::half > : std::true_type { using type = int16_t; }; template<> struct signed_type< builtin_type::word > : std::true_type { using type = int32_t; }; template<> struct signed_type< builtin_type::dyad > : std::true_type { using type = int64_t; }; template< typename T > constexpr void static_fail() { static_assert( ( T(), false ) ); } template< typename T > constexpr word type_id = static_fail< T >(); template<> constexpr word type_id< void > = 0; template<> constexpr word type_id< byte > = word( builtin_type::byte ); template<> constexpr word type_id< half > = word( builtin_type::half ); template<> constexpr word type_id< word > = word( builtin_type::word ); template<> constexpr word type_id< dyad > = word( builtin_type::dyad ); template<> constexpr word type_id< coro > = word( builtin_type::coro ); template<> constexpr word type_id< type > = word( builtin_type::type ); template<> constexpr word type_id< dict > = word( builtin_type::dict ); template<> constexpr word type_id< label > = word( builtin_type::label ); template<> constexpr word type_id< objid > = word( builtin_type::objid ); inline brq::string_builder &operator<<( brq::string_builder &b, builtin_type t ) { switch ( t ) { case builtin_type::byte: return b << "byte"; case builtin_type::half: return b << "half"; case builtin_type::word: return b << "word"; case builtin_type::dyad: return b << "dyad"; case builtin_type::type: return b << "type"; case builtin_type::coro: return b << "coro"; case builtin_type::dict: return b << "dict"; default: return b << "type( " << word( t ) << " )"; } } template< typename tag_t, builtin_type type > struct op { template< typename state_t > static step push_word( state_t &, word ) { NOT_IMPLEMENTED(); } template< typename state_t > static step push_half( state_t &, half ) { NOT_IMPLEMENTED(); } template< typename state_t > static step push_label( state_t &, label ) { NOT_IMPLEMENTED(); } template< typename state_t > static step apply( state_t &state, word opcode ) { UNREACHABLE( "not implemented", typeid( state_t ).name(), type ); } }; struct exec_tag {}; }