Skip to content

Commit

Permalink
Support function modifier inheritance and overriding
Browse files Browse the repository at this point in the history
  • Loading branch information
ggiraldez committed Sep 23, 2024
1 parent 81fa4f9 commit 96e2c4e
Show file tree
Hide file tree
Showing 11 changed files with 309 additions and 58 deletions.
64 changes: 35 additions & 29 deletions crates/solidity/inputs/language/bindings/rules.msgb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i
;; Keeps a link to the enclosing contract definition to provide a parent for
;; method calls (to correctly resolve virtual methods)
inherit .enclosing_def
inherit .parent_scope

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Source unit (aka .sol file)
Expand All @@ -30,6 +31,11 @@ inherit .enclosing_def
edge export -> @source_unit.defs

let @source_unit.enclosing_def = #null

;; This defines a parent_scope at the source unit level (this attribute is
;; inherited) for contracts to resolve bases (both in inheritance lists and
;; override specifiers)
let @source_unit.parent_scope = @source_unit.lexical_scope
}

;; Top-level definitions...
Expand Down Expand Up @@ -67,16 +73,6 @@ inherit .enclosing_def
edge @source_unit.lexical_scope -> @import.defs
}

;; Contracts need access to the parent scope to resolve bases. This is purely
;; for convenience, as contracts can only appear in SourceUnits so we could
;; potentially connect this directly when connecting to the base contract
;; identifiers (but that would make the query longer)
@source_unit [SourceUnit [SourceUnitMembers
[SourceUnitMember @contract [ContractDefinition]]
]] {
let @contract.parent_scope = @source_unit.lexical_scope
}


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Imports
Expand Down Expand Up @@ -201,7 +197,12 @@ inherit .enclosing_def

edge @contract.lexical_scope -> @contract.members
edge @contract.lexical_scope -> @contract.type_members
edge @contract.lexical_scope -> @contract.modifiers

;; Modifiers are available as a contract type members through a special '@modifier' symbol
node modifier
attr (modifier) pop_symbol = "@modifier"
edge @contract.type_members -> modifier
edge modifier -> @contract.modifiers

let @contract.enclosing_def = @contract.def
}
Expand Down Expand Up @@ -354,7 +355,6 @@ inherit .enclosing_def
[ContractMember @member (
[FunctionDefinition]
| [StateVariableDefinition]
| [ModifierDefinition]
)]
]] {
edge @contract.lexical_scope -> @member.def
Expand Down Expand Up @@ -385,17 +385,18 @@ inherit .enclosing_def
item: [ContractMember @modifier variant: [ModifierDefinition]]
]] {
edge @contract.modifiers -> @modifier.def

;; This may prioritize this definition (when there are multiple options)
;; according to the C3 linerisation ordering
attr (@modifier.def) tag = "c3"
attr (@modifier.def) parents = [@contract.def]
}

@contract [ContractDefinition [ContractMembers [ContractMember
[FunctionDefinition [FunctionAttributes [FunctionAttribute
[OverrideSpecifier [OverridePathsDeclaration [OverridePaths
@base_ident [IdentifierPath]
]]]
]]]
@override [OverrideSpecifier [OverridePathsDeclaration [OverridePaths
@base_ident [IdentifierPath]
]]] {
;; Resolve overriden bases when listed in the function modifiers
edge @base_ident.left -> @contract.parent_scope
;; Resolve overriden bases when listed in the function or modifiers modifiers
edge @base_ident.left -> @override.parent_scope
}


Expand Down Expand Up @@ -633,9 +634,10 @@ inherit .enclosing_def
node @id_path.right
}

[IdentifierPath @name [Identifier]] {
@id_path [IdentifierPath @name [Identifier]] {
node @name.ref
attr (@name.ref) node_reference = @name
attr (@name.ref) parents = [@id_path.enclosing_def]
}

@id_path [IdentifierPath @name [Identifier] .] {
Expand Down Expand Up @@ -752,7 +754,11 @@ inherit .enclosing_def
@modifier [ModifierInvocation @name [IdentifierPath]] {
node @modifier.lexical_scope

edge @name.left -> @modifier.lexical_scope
node modifier
attr (modifier) push_symbol = "@modifier"

edge @name.left -> modifier
edge modifier -> @modifier.lexical_scope
}

@modifier [ModifierInvocation @args [ArgumentsDeclaration]] {
Expand Down Expand Up @@ -855,18 +861,18 @@ inherit .enclosing_def
;;; Function modifiers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

@modifier [ModifierDefinition] {
node @modifier.def
node @modifier.lexical_scope
}

@modifier [ModifierDefinition
@name name: [Identifier]
body: [FunctionBody @body [Block]]
] {
node @modifier.def
node @modifier.lexical_scope

node def
attr (def) node_definition = @name
attr (def) definiens_node = @modifier
attr (@modifier.def) node_definition = @name
attr (@modifier.def) definiens_node = @modifier

edge @modifier.def -> def
edge @body.lexical_scope -> @modifier.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.

Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# This file is generated automatically by infrastructure scripts. Please don't edit by hand.

Parse errors:
Error: Expected OpenBrace or Semicolon.
╭─[input.sol:2:18]
2 │ modifier foo virtual { _; }
│ ───────┬───────
│ ╰───────── Error occurred here.
───╯
Error: Expected OpenBrace or Semicolon.
╭─[input.sol:6:18]
6 │ modifier foo virtual override { _; }
│ ────────────┬───────────
│ ╰───────────── Error occurred here.
───╯
Error: Expected OpenBrace or Semicolon.
╭─[input.sol:10:18]
10 │ modifier foo virtual override { _; }
│ ────────────┬───────────
│ ╰───────────── Error occurred here.
────╯
References and definitions:
╭─[input.sol:1:1]
1 │ contract Base {
│ ──┬─
│ ╰─── def: 1
5 │ contract A is Base {
│ ┬ ──┬─
│ ╰────────── def: 2
│ │
│ ╰─── ref: 1
9 │ contract B is Base {
│ ┬ ──┬─
│ ╰────────── def: 3
│ │
│ ╰─── ref: 1
13 │ contract Test is B, A {
│ ──┬─ ┬ ┬
│ ╰─────────── def: 4
│ │ │
│ ╰───── ref: 3
│ │
│ ╰── ref: 2
14 │ function test() public foo {}
│ ──┬─ ─┬─
│ ╰──────────────── def: 5
│ │
│ ╰─── unresolved
────╯
Loading

0 comments on commit 96e2c4e

Please sign in to comment.