-
Notifications
You must be signed in to change notification settings - Fork 180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tuple support. #352
Tuple support. #352
Conversation
6a6bb93
to
3fe10c6
Compare
Codecov Report
@@ Coverage Diff @@
## master #352 +/- ##
==========================================
+ Coverage 82.80% 83.14% +0.33%
==========================================
Files 62 64 +2
Lines 3862 3980 +118
==========================================
+ Hits 3198 3309 +111
- Misses 664 671 +7
Continue to review full report at Codecov.
|
0466977
to
e8a3b47
Compare
76ec902
to
eeb4e42
Compare
@@ -82,30 +82,24 @@ pub struct AbiComponent { | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I grouped trait implementations together in this file, so there is some noise.
|
||
/// The ABI type of a Fe type. | ||
fn abi_type(&self) -> AbiType; | ||
} | ||
|
||
/// Names that can be used to build identifiers. | ||
pub trait SafeNames { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new trait
53ba696
to
baad6ab
Compare
baad6ab
to
511b416
Compare
511b416
to
04cedf0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Heroic effort! ⚔️ 👷
Left a few comments inline but just tiny suggestions. The most important thing I think is opening issues for a few things left and right.
@@ -297,6 +318,8 @@ impl Context { | |||
contracts: HashMap::new(), | |||
calls: HashMap::new(), | |||
events: HashMap::new(), | |||
type_descs: HashMap::new(), | |||
module: None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you consider using ModuleAttributes
instead of Option<ModuleAttributes>
and using ModuleAttributes::new()
which would in turn initialize with an empty HashMap
and BTreeSet
. This would feel slightly more symmetric with the rest of the Context
and eliminate checking for Some(_)
down the road. But it may make other things trickier so I'm just curious if you considered it and deliberately went for this design.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what I went for initially, but then realized fe::Module
isn't wrapped in a node and therefore doesn't have a nodeId.
@@ -670,6 +711,19 @@ fn expr_call_value_attribute( | |||
Location::Memory, | |||
)) | |||
} | |||
Type::Tuple(tuple) => { | |||
if value_attributes.final_location() != Location::Memory { | |||
todo!("encode tuple from storage") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be good to create an issue for this.
let typ = context.get_type_desc(&desc).expect("missing attributes"); | ||
|
||
match typ { | ||
Type::Tuple(tuple) if !tuple.is_empty() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should allow to define zero sized structs probably just as struct Something
. That's struct
followed by the name and then not followed by a :
. Rust has support for empty structs, too so we are in good company.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not saying that has to be in this PR so. But worth creating an issue for.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what I was thinking too 👍
num2=self.reserve1, | ||
num3=self.block_timestamp_last | ||
) | ||
pub def get_reserves() -> (u256, u256, u256): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super cool to see it in action and leading to this code cleanup 👍
@@ -0,0 +1,43 @@ | |||
contract Foo: | |||
my_sto_tuple: (u256, i32) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's this todo!("encode tuple from storage")
in the analyzer...what exactly is it doesn't yet work with tuples in storage yet. Is it that we can not yet move an entire tuple from storage to memory?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now someone would need to do self.my_sto_tuple.to_mem().abi_encode()
instead of self.my_sto_tuple.abi_encode()
. It's a low priority todo
imo, we might not event want to support encoding values from storage.
@@ -0,0 +1,68 @@ | |||
struct tuple_u256_bool: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding the naming collisions. We could suffix all of them with an uuid and call it a day (e.g. tuple_u256_bool_ce6819ea_e0a1_4af2_92f5_7d3be21437d1
). Alternatively I guess we could try to generate the most human readable name possible (so, tuple_u256_bool
) unless we detect that the user has also used the same name in which case we just append something like _1
. In any case, we should create an issue for that as it should have a high priority.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Btw, super cool that we have these lowering tests now!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer to have a solution that does not involve checking to see if a name is already take. Something to discuss in the issue once it's written..
|
||
pub def bing(): | ||
foo: tuple_address_address_u16_i32_bool = tuple_address_address_u16_i32_bool( | ||
item0=address(0), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Random fact, C# also exposes tuple items as item0
, item1
etc (just with a capitalized I
) so we are in good company.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Correct decision for sure 😆
04cedf0
to
6623028
Compare
To support tuples, we need the following lowerings:
1.) New struct definitions need to be added for each tuple that is used in the module.
For example, if
(u256, bool)
is used somewhere in a module, we must add the following struct definition to the module:2.) Tuple type descriptions need to be mapped to struct type descriptions.
my_tuple: (u256, bool)
->my_tuple: TUPLE_U256_BOOL
3.) Tuple constructions need to be mapped to struct constructions
(42, true)
->TUPLE_U256_BOOL(item0=42, item1=true)
bonus: Tuple deconstruction can be mapped to multiple assignments.
->
Included in this PR:
SafeNames
trait to to generate identifiers for the tuple structs. These names may conflict with user defined types, which is something that needs to be addressed.One thing to note is that empty tuples are not lowered, since we don't have zero-sized structs. It's not a big deal, but it would be nice to have all tuple branches marked as
unimplemented
in the Yul codegen pass.To-Do