Open tvorogme opened 1 year ago
Usage of up to UInt256
as nat
type in TLB will allow us to do:
_ {b:(## 256)} a:(#< b) = B b;
_ a:(## 256) _:(B a) = A;
Currently, you can do only:
_ {b:#} a:(#< b) = B b;
_ a:(## 256) _:(B a) = A;
And this leads to limitation of b
to simple int32
. This will compile, but will fail in serialization during int32
limitation.
Usage of large >32 bit tags for hex constructor generate not buggy CPP codegen.
Example:
bool_false#000000032 = MyTag;
bool_true#000000064 = MyTag;
This TLB generates:
int MyTag::get_tag(const vm::CellSlice& cs) const {
switch (cs.bselect(6, 3)) {
case 0:
return cs.bit_at(29) ? bool_true : bool_false;
default:
return -1;
}
}
Which is not correct.
Chain of conditional fields convert type to subslice, which is not very useful
_ a:(## 32) b:(## 8) c:(## 1) d:(## 1) e:((a . b)?(c?(d?(## 64)))) = A;
_ a:(## 32) b:(## 8) c:(## 1) d:(## 1) e:(d?(## 64)) = B;
In B
type e
field is int:
struct B::Record {
typedef B type_class;
int a; // a : ## 32
int b; // b : ## 8
bool c; // c : ## 1
bool d; // d : ## 1
int e; // e : d?(## 64)
Record() = default;
Record(int _a, int _b, bool _c, bool _d, int _e) : a(_a), b(_b), c(_c), d(_d), e(_e) {}
};
But in A
type e
field is subslice:
struct A::Record {
typedef A type_class;
int a; // a : ## 32
int b; // b : ## 8
bool c; // c : ## 1
bool d; // d : ## 1
Ref<CellSlice> e; // e : a.b?(c?(d?(## 64)))
Record() = default;
Record(int _a, int _b, bool _c, bool _d, Ref<CellSlice> _e) : a(_a), b(_b), c(_c), d(_d), e(std::move(_e)) {}
};
Sometimes we want to optimize load of TLB structures by add optional refs or bits, but having same tag. As example we can look in DNS change record:
change_dns_record#4eb1f0f9 query_id:uint64 key:uint256 value:^DNSRecord = InternalMsgBody;
Real implementation contains optional value
ref load, but in TLB scheme it's not reflected.
According @mr-tron realization can be done with ?
value separator.
change_dns_record#4eb1f0f9 query_id:uint64 key:uint256 value:^DNSRecord? = InternalMsgBody;
All fields in right side of ?
value separator must contain ?
separator, and must be optional to load.
So if you want to have several optional values, you might write such a scheme:
_ a:uint32 b:uint64? c:^MyObj? = Example;
My original proposal was to add one ?
in declaration. Like
change_dns_record#4eb1f0f9 query_id:uint64 key:uint256 ? value:^DNSRecord = InternalMsgBody;
and all fieds on the right side are optional. But it maybe not good for language. I am not specialist in programing languages theory.
Cool improvements that will help development might be:
int
/uint
constraints (the more complex task can be usage of Int256 in codegen and allow them as NAT)test# a:^uint32 = Test;
andtest# _:^[ a:uint32 b:uint64 ] = Test;
but nottest# a:^[ a:uint32 b:uint64 ] = Test;
else
realization inE ? E [ : E ]
tlb
filesFixedCellChain X
as built-in type (chain ofX
cells concatenated to one bitstring) andCellChain X
(chain up toX
cells) This means that sometimes we want to codegen sum of several Cells (text, on-chain images, ...)Add more strict rules for parametrized variables:
Will generate:
But it'll be cool not to have
Out of cell
so good result can be:(Where
1015
is remaining bits in cell)CellBits
type, means the rest of cell bits (without refs)Allow type tag check 11-13:
Allow complex constants
_ {a:#} b:# c:# { ~a = (c * b) } = NegateSimplePlus;
Some fixes can be made:
##
for example) with more than 64 bits in codegen cpp can crash program. U can geneate & compile, but use of generatedpack
/unpack
method will crash programFix
Any
in codegen cpp (will generate cpp, but not compile)check_constraint_incomplete
forE ? E [ : E ]
(will generate cpp, but not compile)