Skip to content

Commit

Permalink
Binding rules for supporting mapping types
Browse files Browse the repository at this point in the history
Key and value types are resolved, as well as indexing in a mapping
variable will output the correct type to allow chaining, eg. member access
expressions
  • Loading branch information
ggiraldez committed Aug 19, 2024
1 parent b1660b8 commit 8cdebda
Show file tree
Hide file tree
Showing 14 changed files with 434 additions and 2 deletions.
54 changes: 54 additions & 0 deletions crates/solidity/inputs/language/bindings/rules.msgb
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,49 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i
edge @type_name.output -> @id_path.right
}

@type_name [TypeName @mapping [MappingType]] {
edge @mapping.lexical_scope -> @type_name.type_ref
edge @type_name.output -> @mapping.output
}


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Mappings
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

@mapping [MappingType] {
node @mapping.lexical_scope
node @mapping.output
}

@mapping [MappingType [MappingKey [MappingKeyType @key_ident [IdentifierPath]]]] {
edge @key_ident.left -> @mapping.lexical_scope
}

@mapping [MappingType [MappingValue @value_type [TypeName]]] {
edge @value_type.type_ref -> @mapping.lexical_scope

node typeof_input
attr (typeof_input) pop_symbol = "@typeof"

node index
attr (index) pop_symbol = "[]"

node typeof_output
attr (typeof_output) push_symbol = "@typeof"

;; The mapping's type exposes the `[]` operator that returns the value type
edge @mapping.output -> typeof_input
edge typeof_input -> index
edge index -> typeof_output
edge typeof_output -> @value_type.output
}


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Identifier Paths (aka. references to custom types)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; The identifier path constructs a path of nodes connected from right to left
@id_path [IdentifierPath] {
node @id_path.left
Expand Down Expand Up @@ -1039,6 +1082,17 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i
edge @expr.output -> ref
}

;; Index access expressions
@expr [Expression [IndexAccessExpression
@operand operand: [Expression]
]] {
node index
attr (index) push_symbol = "[]"

edge @expr.output -> index
edge index -> @operand.output
}

;; Type expressions
@type_expr [Expression [TypeExpression @type [TypeName]]] {
edge @type.type_ref -> @type_expr.lexical_scope
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
contract NestedMapping {
mapping(address => mapping(uint256 => bool)) public nested;
// ^def:1

function get(address _addr1, uint256 _i) public view returns (bool) {
// ^def:2
// ^def:3
return nested[_addr1][_i];
// ^ref:2
// ^ref:3
// ^ref:1
}

function set(address _addr1, uint256 _i, bool _boo) public {
// ^def:4
// ^def:5
// ^def:6
nested[_addr1][_i] = _boo;
// ^ref:4
// ^ref:5
// ^ref:6
//<ref:1
}

function remove(address _addr1, uint256 _i) public {
// ^def:7
// ^def:8
delete nested[_addr1][_i];
// ^ref:7
// ^ref:8
// ^ref:1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
contract NestedCustom {
enum Kind { Alpha, Beta }
// ^def:1
struct Values {
// ^def:2
uint balance;
// ^def:3
}
mapping(address => mapping(Kind => Values)) vaults;
// ^def:4
// ^ref:2
// ^ref:1

function store(address _addr, Kind _kind, uint _amount) public {
// ^def:5
// ^def:6
// ^def:7
vaults[_addr][_kind].balance += _amount;
// ^ref:5
// ^ref:3
// ^ref:6
// ^ref:7
//<ref:4
}

function balance(address _addr, Kind _kind) public returns (uint) {
// ^def:8
// ^def:9
return vaults[_addr][_kind].balance;
// ^ref:3
// ^ref:8
// ^ref:9
// ^ref:4
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
contract Mapping {
mapping(address => uint256) public myMap;
// ^def:1

function get(address _addr) public view returns (uint256) {
// ^def:2
return myMap[_addr];
// ^ref:2
// ^ref:1
}

function set(address _addr, uint256 _i) public {
// ^def:3
// ^def:4
myMap[_addr] = _i;
// ^ref:3
// ^ref:4
//<ref:1
}

function remove(address _addr) public {
// ^def:5
delete myMap[_addr];
// ^ref:5
// ^ref:1
}
}
Loading

0 comments on commit 8cdebda

Please sign in to comment.