@@ -193,6 +193,17 @@ TypePtr TypeDataIntN::create(bool is_unsigned, bool is_variadic, int n_bits) {
193193 return hash.register_unique (new TypeDataIntN (hash.type_id (), is_unsigned, is_variadic, n_bits));
194194}
195195
196+ TypePtr TypeDataBytesN::create (bool is_bits, int n_width) {
197+ TypeDataTypeIdCalculation hash (7810988137199333041ULL );
198+ hash.feed_hash (is_bits);
199+ hash.feed_hash (n_width);
200+
201+ if (TypePtr existing = hash.get_existing ()) {
202+ return existing;
203+ }
204+ return hash.register_unique (new TypeDataBytesN (hash.type_id (), is_bits, n_width));
205+ }
206+
196207TypePtr TypeDataUnresolved::create (std::string&& text, SrcLocation loc) {
197208 TypeDataTypeIdCalculation hash (3680147223540048162ULL );
198209 hash.feed_string (text);
@@ -262,6 +273,11 @@ std::string TypeDataIntN::as_human_readable() const {
262273 return s_int + std::to_string (n_bits);
263274}
264275
276+ std::string TypeDataBytesN::as_human_readable () const {
277+ std::string s_bytes = is_bits ? " bits" : " bytes" ;
278+ return s_bytes + std::to_string (n_width);
279+ }
280+
265281
266282// --------------------------------------------
267283// traverse()
@@ -376,7 +392,7 @@ bool TypeDataSlice::can_rhs_be_assigned(TypePtr rhs) const {
376392 if (rhs == this ) {
377393 return true ;
378394 }
379- return rhs == TypeDataNever::create ();
395+ return rhs == TypeDataNever::create (); // note, that bytesN is NOT automatically cast to slice without `as` operator
380396}
381397
382398bool TypeDataBuilder::can_rhs_be_assigned (TypePtr rhs) const {
@@ -469,6 +485,15 @@ bool TypeDataIntN::can_rhs_be_assigned(TypePtr rhs) const {
469485 return rhs == TypeDataNever::create (); // `int8` is NOT assignable to `int32` without `as`
470486}
471487
488+ bool TypeDataBytesN::can_rhs_be_assigned (TypePtr rhs) const {
489+ // `slice` is NOT assignable to bytesN without `as`
490+ // `bytes32` is NOT assignable to `bytes256` and even to `bits256` without `as`
491+ if (rhs == this ) {
492+ return true ;
493+ }
494+ return rhs == TypeDataNever::create ();
495+ }
496+
472497bool TypeDataCoins::can_rhs_be_assigned (TypePtr rhs) const {
473498 if (rhs == this ) {
474499 return true ;
@@ -541,6 +566,9 @@ bool TypeDataCell::can_be_casted_with_as_operator(TypePtr cast_to) const {
541566}
542567
543568bool TypeDataSlice::can_be_casted_with_as_operator (TypePtr cast_to) const {
569+ if (cast_to->try_as <TypeDataBytesN>()) { // `slice` to `bytes32` / `slice` to `bits8`
570+ return true ;
571+ }
544572 if (const auto * to_nullable = cast_to->try_as <TypeDataNullable>()) {
545573 return can_be_casted_with_as_operator (to_nullable->inner );
546574 }
@@ -630,6 +658,16 @@ bool TypeDataIntN::can_be_casted_with_as_operator(TypePtr cast_to) const {
630658 return cast_to == TypeDataInt::create () || cast_to == TypeDataCoins::create ();
631659}
632660
661+ bool TypeDataBytesN::can_be_casted_with_as_operator (TypePtr cast_to) const {
662+ if (cast_to->try_as <TypeDataBytesN>()) { // `bytes256` as `bytes512`, `bits1` as `bytes8`
663+ return true ;
664+ }
665+ if (const auto * to_nullable = cast_to->try_as <TypeDataNullable>()) { // `bytes8` as `slice?`
666+ return can_be_casted_with_as_operator (to_nullable->inner );
667+ }
668+ return cast_to == TypeDataSlice::create ();
669+ }
670+
633671bool TypeDataCoins::can_be_casted_with_as_operator (TypePtr cast_to) const {
634672 if (cast_to->try_as <TypeDataIntN>()) { // `coins` as `int8`
635673 return true ;
@@ -750,6 +788,16 @@ static TypePtr parse_intN(std::string_view strN, bool is_unsigned) {
750788 return TypeDataIntN::create (is_unsigned, false , n);
751789}
752790
791+ static TypePtr parse_bytesN (std::string_view strN, bool is_bits) {
792+ int n;
793+ auto result = std::from_chars (strN.data () + 5 - static_cast <int >(is_bits), strN.data () + strN.size (), n);
794+ bool parsed = result.ec == std::errc () && result.ptr == strN.data () + strN.size ();
795+ if (!parsed || n <= 0 || n > 1024 ) {
796+ return nullptr ; // `bytes9999`, maybe it's user-defined alias, let it be unresolved
797+ }
798+ return TypeDataBytesN::create (is_bits, n);
799+ }
800+
753801static TypePtr parse_simple_type (Lexer& lex) {
754802 switch (lex.tok ()) {
755803 case tok_self:
@@ -795,6 +843,16 @@ static TypePtr parse_simple_type(Lexer& lex) {
795843 return uintN;
796844 }
797845 }
846+ if (str.size () > 4 && str.starts_with (" bits" )) {
847+ if (TypePtr bitsN = parse_bytesN (str, true )) {
848+ return bitsN;
849+ }
850+ }
851+ if (str.size () > 5 && str.starts_with (" bytes" )) {
852+ if (TypePtr bytesN = parse_bytesN (str, false )) {
853+ return bytesN;
854+ }
855+ }
798856 return TypeDataUnresolved::create (std::string (str), loc);
799857 }
800858 case tok_null:
0 commit comments