| @@ -30,11 +30,14 @@ namespace disvm · 29 unmodified lines |
| 30 | namespace sigkind | 30 | namespace sigkind |
| 31 | { | 31 | { |
| 32 | // Signature stream | 32 | // Signature stream |
| 33 | class sig_stream_t | 33 | class sig_stream_t final |
| 34 | { | 34 | { |
| 35 | public: // static | 35 | public: // static |
| 36 | static uint32_t compute_signature_hash(const char *); | 36 | static uint32_t compute_signature_hash(const char *); |
| 37 | | 37 | |
| | 38 | // Type delimiter |
| | 39 | static const char delim = ','; |
| | 40 | |
| 38 | public: | 41 | public: |
| 39 | std::string get_signature() const; | 42 | std::string get_signature() const; |
| 40 | | 43 | |
| @@ -42,10 +45,11 @@ namespace disvm · 1 unmodified line |
| 42 | | 45 | |
| 43 | sig_stream_t &operator<<(const char); | 46 | sig_stream_t &operator<<(const char); |
| 44 | sig_stream_t &operator<<(const char *); | 47 | sig_stream_t &operator<<(const char *); |
| | 48 | sig_stream_t &operator<<(const uint32_t); |
| 45 | sig_stream_t &operator<<(const sig_stream_t &); | 49 | sig_stream_t &operator<<(const sig_stream_t &); |
| 46 | | 50 | |
| 47 | private: | 51 | private: |
| 48 | std::stringstream _ss; | 52 | mutable std::stringstream _ss; |
| 49 | }; | 53 | }; |
| 50 | | 54 | |
| 51 | // Type context modifiers | 55 | // Type context modifiers |
| @@ -55,12 +59,12 @@ namespace disvm · 3 unmodified lines |
| 55 | cycle = 'y', | 59 | cycle = 'y', |
| 56 | }; | 60 | }; |
| 57 | | 61 | |
| 58 | sig_stream_t & operator<<(sig_stream_t &, const disvm::assembly::sigkind::modifier_id_t &); | 62 | sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::modifier_id_t &); |
| 59 | | 63 | |
| 60 | // Instrinsic VM types | 64 | // Instrinsic VM types |
| 61 | enum class type_id_t : uint8_t | 65 | enum class type_id_t : uint8_t |
| 62 | { | 66 | { |
| 63 | unknown = 0, | 67 | unknown = 0, // This will be interpreted as a 'null' value which will help debug where the type building failed. |
| 64 | none = 'n', | 68 | none = 'n', |
| 65 | byte = 'b', | 69 | byte = 'b', |
| 66 | integer = 'i', | 70 | integer = 'i', |
| @@ -74,14 +78,14 @@ namespace disvm · 7 unmodified lines |
| 74 | list = 'L', | 78 | list = 'L', |
| 75 | channel = 'C', | 79 | channel = 'C', |
| 76 | adt = 'a', | 80 | adt = 'a', |
| 77 | //adtpick = 'p', | 81 | adt_pick_tag = 'p', |
| 78 | tuple = 't', | 82 | tuple = 't', |
| 79 | module = 'm', | 83 | module = 'm', |
| 80 | function = 'f', | 84 | function = 'f', |
| 81 | function_varargs = 0xff, // "f*" | 85 | function_varargs = 0xff, // "f*" |
| 82 | }; | 86 | }; |
| 83 | | 87 | |
| 84 | sig_stream_t & operator<<(sig_stream_t &, const disvm::assembly::sigkind::type_id_t &); | 88 | sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::type_id_t &); |
| 85 | | 89 | |
| 86 | template<type_id_t T> | 90 | template<type_id_t T> |
| 87 | struct Tbasic_type | 91 | struct Tbasic_type |
| @@ -102,7 +106,7 @@ namespace disvm · 14 unmodified lines |
| 102 | using Tstring = Tbasic_type<type_id_t::string>; | 106 | using Tstring = Tbasic_type<type_id_t::string>; |
| 103 | using Tpoly = Tbasic_type<type_id_t::poly>; | 107 | using Tpoly = Tbasic_type<type_id_t::poly>; |
| 104 | | 108 | |
| 105 | class Tfixed : public Tbasic_type<type_id_t::fixed> | 109 | class Tfixed final : public Tbasic_type<type_id_t::fixed> |
| 106 | { | 110 | { |
| 107 | public: | 111 | public: |
| 108 | Tfixed(double scale); | 112 | Tfixed(double scale); |
| @@ -113,7 +117,7 @@ namespace disvm · 4 unmodified lines |
| 113 | const double _scale; | 117 | const double _scale; |
| 114 | }; | 118 | }; |
| 115 | | 119 | |
| 116 | sig_stream_t & operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tfixed &); | 120 | sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tfixed &); |
| 117 | | 121 | |
| 118 | // Type that contains/modifies another type | 122 | // Type that contains/modifies another type |
| 119 | template <type_id_t ID> | 123 | template <type_id_t ID> |
| @@ -141,14 +145,18 @@ namespace disvm · 21 unmodified lines |
| 141 | using Tlist = Tbasic_aggregate_type<type_id_t::list>; | 145 | using Tlist = Tbasic_aggregate_type<type_id_t::list>; |
| 142 | using Tchannel = Tbasic_aggregate_type<type_id_t::channel>; | 146 | using Tchannel = Tbasic_aggregate_type<type_id_t::channel>; |
| 143 | | 147 | |
| 144 | sig_stream_t & operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tarray &); | 148 | sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tarray &); |
| 145 | sig_stream_t & operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tref &); | 149 | sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tref &); |
| 146 | sig_stream_t & operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tlist &); | 150 | sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tlist &); |
| 147 | sig_stream_t & operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tchannel &); | 151 | sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tchannel &); |
| 148 | | 152 | |
| 149 | // Reference to another previously defined type in the current signature | 153 | // Reference to another previously defined type in the current signature |
| 150 | struct Ttype_ref | 154 | class Ttype_ref final |
| 151 | { | 155 | { |
| | 156 | public: // static |
| | 157 | static const char id = '@'; |
| | 158 | |
| | 159 | public: |
| 152 | Ttype_ref(uint32_t num); | 160 | Ttype_ref(uint32_t num); |
| 153 | | 161 | |
| 154 | friend sig_stream_t &operator<<(sig_stream_t &os, const Ttype_ref &); | 162 | friend sig_stream_t &operator<<(sig_stream_t &os, const Ttype_ref &); |
| @@ -157,23 +165,25 @@ namespace disvm · 2 unmodified lines |
| 157 | const uint32_t _num; | 165 | const uint32_t _num; |
| 158 | }; | 166 | }; |
| 159 | | 167 | |
| 160 | sig_stream_t & operator<<(sig_stream_t &, const disvm::assembly::sigkind::Ttype_ref &); | 168 | sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Ttype_ref &); |
| 161 | | 169 | |
| 162 | // Named member type | 170 | // Named member type |
| 163 | struct Tm | 171 | class Tm final |
| 164 | { | 172 | { |
| 165 | Tm(const char *name, const type_id_t &type_id); | 173 | public: |
| 166 | Tm(const char *name, const char *type_id); | 174 | template <typename T> |
| | 175 | Tm(const char *name, const T &type) |
| | 176 | { |
| | 177 | _s << name << ':' << type; |
| | 178 | } |
| 167 | | 179 | |
| 168 | friend sig_stream_t &operator<<(sig_stream_t &os, const Tm &); | 180 | friend sig_stream_t &operator<<(sig_stream_t &os, const Tm &); |
| 169 | | 181 | |
| 170 | private: | 182 | private: |
| 171 | const char *_type_id_str; | 183 | sig_stream_t _s; |
| 172 | const type_id_t _type_id; | | |
| 173 | const char *_name; | | |
| 174 | }; | 184 | }; |
| 175 | | 185 | |
| 176 | sig_stream_t & operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tm &); | 186 | sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tm &); |
| 177 | | 187 | |
| 178 | inline void nested_type(const sig_stream_t &) | 188 | inline void nested_type(const sig_stream_t &) |
| 179 | { | 189 | { |
| @@ -190,7 +200,7 @@ namespace disvm · 10 unmodified lines |
| 190 | template<typename T1, typename T2, typename ...S> | 200 | template<typename T1, typename T2, typename ...S> |
| 191 | void nested_type(sig_stream_t &ss, const T1 &t1, const T2 &t2, const S&...s) | 201 | void nested_type(sig_stream_t &ss, const T1 &t1, const T2 &t2, const S&...s) |
| 192 | { | 202 | { |
| 193 | ss << t1 << ','; | 203 | ss << t1 << sig_stream_t::type_delim; |
| 194 | nested_type(ss, t2, s...); | 204 | nested_type(ss, t2, s...); |
| 195 | } | 205 | } |
| 196 | | 206 | |
| @@ -198,7 +208,7 @@ namespace disvm · 1 unmodified line |
| 198 | template <type_id_t ID> | 208 | template <type_id_t ID> |
| 199 | class Tnested_aggregate_type : public Tbasic_type<ID> | 209 | class Tnested_aggregate_type : public Tbasic_type<ID> |
| 200 | { | 210 | { |
| 201 | public: | 211 | public: // static |
| 202 | static const char begin; | 212 | static const char begin; |
| 203 | static const char end; | 213 | static const char end; |
| 204 | | 214 | |
| @@ -215,26 +225,96 @@ namespace disvm · 10 unmodified lines |
| 215 | return Tnested_aggregate_type{ ss }; | 225 | return Tnested_aggregate_type{ ss }; |
| 216 | } | 226 | } |
| 217 | | 227 | |
| | 228 | public: |
| | 229 | Tnested_aggregate_type(sig_stream_t &s) |
| | 230 | : _s{ std::move(s) } |
| | 231 | { } |
| | 232 | |
| 218 | friend sig_stream_t &operator<<(sig_stream_t &, const Tnested_aggregate_type &); | 233 | friend sig_stream_t &operator<<(sig_stream_t &, const Tnested_aggregate_type &); |
| 219 | | 234 | |
| 220 | private: | 235 | private: |
| 221 | sig_stream_t _s; | 236 | sig_stream_t _s; |
| 222 | Tnested_aggregate_type(sig_stream_t &s) : _s{ std::move(s) } { } | | |
| 223 | }; | 237 | }; |
| 224 | | 238 | |
| 225 | using Ttuple = Tnested_aggregate_type<type_id_t::tuple>; | 239 | using Ttuple = Tnested_aggregate_type<type_id_t::tuple>; |
| 226 | using Tadt = Tnested_aggregate_type<type_id_t::adt>; | | |
| 227 | using Tmodule = Tnested_aggregate_type<type_id_t::module>; | 240 | using Tmodule = Tnested_aggregate_type<type_id_t::module>; |
| 228 | | 241 | |
| 229 | sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Ttuple &); | 242 | sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Ttuple &); |
| 230 | sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tadt &); | | |
| 231 | sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tmodule &); | 243 | sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tmodule &); |
| 232 | | 244 | |
| | 245 | // Abstract data type (ADT) pick tag |
| | 246 | // Note: This type should only be a part of an ADT instance. |
| | 247 | class Tadt_pick_tag final : public Tbasic_type<type_id_t::adt_pick_tag> |
| | 248 | { |
| | 249 | public: // static |
| | 250 | static const char *tag_delim; |
| | 251 | static const char begin = '('; |
| | 252 | static const char end = ')'; |
| | 253 | |
| | 254 | static Tadt_pick_tag create(const char *pick_tag, uint32_t adt_ref, std::initializer_list<const Tm> tms); |
| | 255 | |
| | 256 | friend sig_stream_t &operator<<(sig_stream_t &, const Tadt_pick_tag &); |
| | 257 | |
| | 258 | private: |
| | 259 | sig_stream_t _s; |
| | 260 | Tadt_pick_tag(sig_stream_t &s) : _s{ std::move(s) } { } |
| | 261 | }; |
| | 262 | |
| | 263 | sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tadt_pick_tag &); |
| | 264 | |
| | 265 | // Abstract data type (ADT) |
| | 266 | class Tadt final : public Tnested_aggregate_type<type_id_t::adt> |
| | 267 | { |
| | 268 | public: // static |
| | 269 | // Unhide base class version of function |
| | 270 | using Tnested_aggregate_type::create; |
| | 271 | |
| | 272 | // Create an ADT with a single pick tag |
| | 273 | static Tadt create(const Tadt_pick_tag &p) |
| | 274 | { |
| | 275 | sig_stream_t ss; |
| | 276 | ss << Tbasic_type::id |
| | 277 | << Tadt::begin |
| | 278 | << sig_stream_t::delim |
| | 279 | << p |
| | 280 | << Tadt::end; |
| | 281 | |
| | 282 | return Tadt{ ss }; |
| | 283 | } |
| | 284 | |
| | 285 | template<typename T, typename ...NT> |
| | 286 | static Tadt create(const Tadt_pick_tag &p, const T &t, const NT&... nestedTypes) |
| | 287 | { |
| | 288 | // [SPEC] When generating type signatures, the Limbo compiler |
| | 289 | // doesn't identify the case where a pick tag is the first type |
| | 290 | // so it always prefixes the nested signature with a leading ','. |
| | 291 | // We special case this scenario to maintain compatibility. The |
| | 292 | // single pick tag for an ADT must also be handled (above). |
| | 293 | sig_stream_t ss; |
| | 294 | ss << Tbasic_type::id |
| | 295 | << Tadt::begin |
| | 296 | << sig_stream_t::delim |
| | 297 | << p |
| | 298 | << sig_stream_t::delim; |
| | 299 | |
| | 300 | nested_type(ss, t, nestedTypes...); |
| | 301 | |
| | 302 | ss << Tadt::end; |
| | 303 | |
| | 304 | return Tadt{ ss }; |
| | 305 | } |
| | 306 | |
| | 307 | private: |
| | 308 | Tadt(sig_stream_t &s) : Tnested_aggregate_type{ std::move(s) } { } |
| | 309 | }; |
| | 310 | |
| | 311 | sig_stream_t &operator<<(sig_stream_t &, const disvm::assembly::sigkind::Tnested_aggregate_type<type_id_t::adt> &); |
| | 312 | |
| 233 | // Function type | 313 | // Function type |
| 234 | template<type_id_t T> | 314 | template<type_id_t T> |
| 235 | class Tfunction_base_type : public Tbasic_type<T> | 315 | class Tfunction_base_type final : public Tbasic_type<T> |
| 236 | { | 316 | { |
| 237 | public: | 317 | public: // static |
| 238 | static const char begin = '('; | 318 | static const char begin = '('; |
| 239 | static const char end = ')'; | 319 | static const char end = ')'; |
| 240 | | 320 | |
| @@ -250,6 +330,7 @@ namespace disvm · 9 unmodified lines |
| 250 | return a; | 330 | return a; |
| 251 | } | 331 | } |
| 252 | | 332 | |
| | 333 | public: |
| 253 | template<typename RT> | 334 | template<typename RT> |
| 254 | Tfunction_base_type &returns(RT r) | 335 | Tfunction_base_type &returns(RT r) |
| 255 | { | 336 | { |