Skip to content

Commit

Permalink
feat: implement transient data location parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes committed Aug 2, 2024
1 parent 3fad734 commit 96895ae
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 21 deletions.
9 changes: 6 additions & 3 deletions crates/ast/src/ast/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,10 +425,12 @@ pub struct Override {
/// A storage location.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum DataLocation {
/// `memory`
Memory,
/// `storage`
Storage,
/// `transient`
Transient,
/// `memory`
Memory,
/// `calldata`
Calldata,
}
Expand All @@ -443,8 +445,9 @@ impl DataLocation {
/// Returns the string representation of the storage location.
pub const fn to_str(self) -> &'static str {
match self {
Self::Memory => "memory",
Self::Storage => "storage",
Self::Transient => "transient",
Self::Memory => "memory",
Self::Calldata => "calldata",
}
}
Expand Down
2 changes: 2 additions & 0 deletions crates/interface/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,7 @@ symbols! {
Itself: "itself",
StaticAssert: "static_assert",
Builtin: "__builtin",
ForAll: "forall",
}

// Pre-interned symbols that can be referred to with `sym::*`.
Expand Down Expand Up @@ -810,6 +811,7 @@ symbols! {
global,
object,
solidity,
transient,
underscore: "_",
x,
}
Expand Down
46 changes: 28 additions & 18 deletions crates/parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -713,8 +713,10 @@ impl<'a> Parser<'a> {
let mut indexed = false;
loop {
if let Some(s) = self.parse_data_location() {
if !flags.contains(VarFlags::DATALOC) {
let msg = "storage specifiers are not allowed here";
if !(matches!(s, DataLocation::Transient) && flags.contains(VarFlags::TRANSIENT))
&& !flags.contains(VarFlags::DATALOC)
{
let msg = "data locations are not allowed here";
self.dcx().err(msg).span(self.prev_token.span).emit();
} else if data_location.is_some() {
let msg = "data location already specified";
Expand Down Expand Up @@ -893,14 +895,19 @@ impl<'a> Parser<'a> {
Some(StrLit { span, value: symbol })
}

/// Parses a storage location: `storage | memory | calldata`.
pub(super) fn parse_data_location(&mut self) -> Option<DataLocation> {
/// Parses a storage location: `storage | memory | calldata | transient`.
fn parse_data_location(&mut self) -> Option<DataLocation> {
if self.eat_keyword(kw::Storage) {
Some(DataLocation::Storage)
} else if self.eat_keyword(kw::Memory) {
Some(DataLocation::Memory)
} else if self.eat_keyword(kw::Calldata) {
Some(DataLocation::Calldata)
} else if self.check_keyword(sym::transient)
&& !matches!(self.look_ahead(1).kind, TokenKind::Eq | TokenKind::Semi)
{
let _ = self.bump(); // `transient`
Some(DataLocation::Transient)
} else {
None
}
Expand Down Expand Up @@ -940,28 +947,30 @@ bitflags::bitflags! {
#[derive(Clone, Copy, PartialEq, Eq)]
pub(super) struct VarFlags: u16 {
// `ty` is always required. `name` is always optional, unless `NAME` is specified.
const DATALOC = 1 << 0;
const INDEXED = 1 << 1;

const PRIVATE = 1 << 2;
const INTERNAL = 1 << 3;
const PUBLIC = 1 << 4;
const EXTERNAL = 1 << 5; // Never accepted, just for error messages.
const TRANSIENT = 1 << 0;
const DATALOC = Self::TRANSIENT.bits() | 1 << 1;
const INDEXED = 1 << 2;

const PRIVATE = 1 << 3;
const INTERNAL = 1 << 4;
const PUBLIC = 1 << 5;
const EXTERNAL = 1 << 6; // Never accepted, just for error messages.
const VISIBILITY = Self::PRIVATE.bits() |
Self::INTERNAL.bits() |
Self::PUBLIC.bits() |
Self::EXTERNAL.bits();

const CONSTANT = 1 << 6;
const IMMUTABLE = 1 << 7;
const CONSTANT = 1 << 7;
const IMMUTABLE = 1 << 8;

const OVERRIDE = 1 << 8;
const OVERRIDE = 1 << 9;

const NAME = 1 << 9;
const NAME_WARN = 1 << 10;
const NAME = 1 << 10;
const NAME_WARN = 1 << 11;

const INITIALIZER = 1 << 11;
const SEMI = 1 << 12;
const INITIALIZER = 1 << 12;
const SEMI = 1 << 13;

const STRUCT = Self::NAME.bits();
const ERROR = 0;
Expand All @@ -970,7 +979,8 @@ bitflags::bitflags! {
const FUNCTION_TY = Self::DATALOC.bits() | Self::NAME_WARN.bits();

// https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.stateVariableDeclaration
const STATE_VAR = Self::PRIVATE.bits() |
const STATE_VAR = Self::TRANSIENT.bits() |
Self::PRIVATE.bits() |
Self::INTERNAL.bits() |
Self::PUBLIC.bits() |
Self::CONSTANT.bits() |
Expand Down
15 changes: 15 additions & 0 deletions tests/ui/parser/transient.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
contract C {
uint256 transient;

function f() external {
transient = 1;
}
}

contract D {
uint256 transient transient;

function f() external {
transient = 1;
}
}

0 comments on commit 96895ae

Please sign in to comment.