Skip to content

Commit 9a9733a

Browse files
feat(soroban): Soroban storage types
Signed-off-by: salaheldinsoliman <[email protected]>
1 parent 420fbb8 commit 9a9733a

File tree

29 files changed

+288
-43
lines changed

29 files changed

+288
-43
lines changed

fmt/src/formatter.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::{
2020
};
2121
use alloy_primitives::Address;
2222
use itertools::{Either, Itertools};
23-
use solang_parser::pt::{PragmaDirective, VersionComparator};
23+
use solang_parser::pt::{PragmaDirective, StorageType, VersionComparator};
2424
use std::{fmt::Write, str::FromStr};
2525
use thiserror::Error;
2626

@@ -3333,6 +3333,13 @@ impl<'a, W: Write> Visitor for Formatter<'a, W> {
33333333
self.visit_list("", idents, Some(loc.start()), Some(loc.end()), false)?;
33343334
None
33353335
}
3336+
VariableAttribute::StorageType(s) => {
3337+
match s {
3338+
StorageType::Instance(_) => Some("instance".to_string()),
3339+
StorageType::Temporary(_) => Some("temporary".to_string()),
3340+
StorageType::Persistent(_) => Some("persistent".to_string()),
3341+
}
3342+
}
33363343
};
33373344
if let Some(token) = token {
33383345
let loc = attribute.loc();

fmt/src/solang_ext/ast_eq.rs

+13
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,18 @@ impl AstEq for VariableDefinition {
7575
}
7676
}
7777

78+
impl AstEq for StorageType {
79+
fn ast_eq(&self, other: &Self) -> bool {
80+
match (self, other) {
81+
(StorageType::Instance(_), StorageType::Instance(_)) => true,
82+
(StorageType::Persistent(_), StorageType::Persistent(_)) => true,
83+
(StorageType::Temporary(_), StorageType::Temporary(_)) => true,
84+
_ => false,
85+
86+
}
87+
}
88+
}
89+
7890
impl AstEq for FunctionDefinition {
7991
fn ast_eq(&self, other: &Self) -> bool {
8092
// attributes
@@ -726,5 +738,6 @@ derive_ast_eq! { enum VariableAttribute {
726738
Constant(loc),
727739
Immutable(loc),
728740
Override(loc, idents),
741+
StorageType(s)
729742
_
730743
}}

solang-parser/src/helpers/fmt.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//!
55
//! [ref]: https://docs.soliditylang.org/en/latest/style-guide.html
66
7-
use crate::pt;
7+
use crate::pt::{self, StorageType};
88
use std::{
99
borrow::Cow,
1010
fmt::{Display, Formatter, Result, Write},
@@ -1169,6 +1169,13 @@ impl Display for pt::VariableAttribute {
11691169
}
11701170
Ok(())
11711171
}
1172+
Self::StorageType(storage) => {
1173+
match storage {
1174+
StorageType::Instance(_) => f.write_str("instance"),
1175+
StorageType::Temporary(_) => f.write_str("temporary"),
1176+
StorageType::Persistent(_) => f.write_str("persistent"),
1177+
}
1178+
}
11721179
}
11731180
}
11741181
}

solang-parser/src/helpers/loc.rs

+9
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ impl OptionalCodeLocation for pt::Visibility {
2828
}
2929
}
3030

31+
impl OptionalCodeLocation for pt::StorageType {
32+
fn loc_opt(&self) -> Option<Loc> {
33+
match self {
34+
Self::Persistent(l) | Self::Temporary(l) | Self::Instance(l) => *l,
35+
}
36+
}
37+
}
38+
3139
impl OptionalCodeLocation for pt::SourceUnit {
3240
#[inline]
3341
fn loc_opt(&self) -> Option<Loc> {
@@ -431,6 +439,7 @@ impl_for_enums! {
431439

432440
pt::VariableAttribute: match self {
433441
Self::Visibility(ref l, ..) => l.loc_opt().unwrap_or_default(),
442+
Self::StorageType(ref l, ..) => l.loc_opt().unwrap_or_default(),
434443
Self::Constant(l, ..)
435444
| Self::Immutable(l, ..)
436445
| Self::Override(l, ..) => l,

solang-parser/src/lexer.rs

+11
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,11 @@ pub enum Token<'input> {
179179
Default,
180180
YulArrow,
181181

182+
// Storage types for Soroban
183+
Persistent,
184+
Temporary,
185+
Instance,
186+
182187
Annotation(&'input str),
183188
}
184189

@@ -316,6 +321,9 @@ impl<'input> fmt::Display for Token<'input> {
316321
Token::Default => write!(f, "default"),
317322
Token::YulArrow => write!(f, "->"),
318323
Token::Annotation(name) => write!(f, "@{name}"),
324+
Token::Persistent => write!(f, "persistent"),
325+
Token::Temporary => write!(f, "temporary"),
326+
Token::Instance => write!(f, "instance"),
319327
}
320328
}
321329
}
@@ -553,6 +561,9 @@ static KEYWORDS: phf::Map<&'static str, Token> = phf_map! {
553561
"unchecked" => Token::Unchecked,
554562
"assembly" => Token::Assembly,
555563
"let" => Token::Let,
564+
"persistent" => Token::Persistent,
565+
"temporary" => Token::Temporary,
566+
"instance" => Token::Instance,
556567
};
557568

558569
impl<'input> Lexer<'input> {

solang-parser/src/pt.rs

+18
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,24 @@ pub enum VariableAttribute {
955955

956956
/// `ovveride(<1>,*)`
957957
Override(Loc, Vec<IdentifierPath>),
958+
959+
/// Storage type.
960+
StorageType(StorageType),
961+
}
962+
963+
/// Soroban storage types.
964+
#[derive(Debug, PartialEq, Eq, Clone)]
965+
#[cfg_attr(feature = "pt-serde", derive(Serialize, Deserialize))]
966+
#[repr(u8)] // for cmp; order of variants is important
967+
pub enum StorageType {
968+
/// `persistent`
969+
Persistent(Option<Loc>),
970+
971+
/// `Instance`
972+
Instance(Option<Loc>),
973+
974+
/// `Temporary`
975+
Temporary(Option<Loc>),
958976
}
959977

960978
/// A variable definition.

solang-parser/src/solidity.lalrpop

+10
Original file line numberDiff line numberDiff line change
@@ -359,8 +359,15 @@ Visibility: Visibility = {
359359
<l:@L> "private" <r:@R> => Visibility::Private(Some(Loc::File(file_no, l, r))),
360360
}
361361

362+
StorageType: StorageType = {
363+
<l:@L> "persistent" <r:@R> => StorageType::Persistent(Some(Loc::File(file_no, l, r))),
364+
<l:@R> "temporary" <r:@R> => StorageType::Temporary(Some(Loc::File(file_no, l, r))),
365+
<l:@R> "instance" <r:@R> => StorageType::Instance(Some(Loc::File(file_no, l, r))),
366+
}
367+
362368
VariableAttribute: VariableAttribute = {
363369
Visibility => VariableAttribute::Visibility(<>),
370+
StorageType => VariableAttribute::StorageType(<>),
364371
<l:@L> "constant" <r:@R> => VariableAttribute::Constant(Loc::File(file_no, l, r)),
365372
<l:@L> "immutable" <r:@R> => VariableAttribute::Immutable(Loc::File(file_no, l, r)),
366373
<l:@L> "override" <r:@R> => VariableAttribute::Override(Loc::File(file_no, l, r), Vec::new()),
@@ -1312,5 +1319,8 @@ extern {
13121319
"switch" => Token::Switch,
13131320
"case" => Token::Case,
13141321
"default" => Token::Default,
1322+
"persistent" => Token::Persistent,
1323+
"temporary" => Token::Temporary,
1324+
"instance" => Token::Instance,
13151325
}
13161326
}

solang-parser/src/tests.rs

+16
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,22 @@ contract 9c {
6161
}
6262
}
6363

64+
#[test]
65+
fn parse_storage_type() {
66+
let src = r#"contract counter {
67+
uint64 instance count = 1;
68+
69+
function decrement() public returns (uint64){
70+
//count -= 1;
71+
return count;
72+
}
73+
}"#;
74+
75+
let res = crate::parse(src, 0);
76+
77+
println!("{:?}", res);
78+
}
79+
6480
#[test]
6581
fn parse_test() {
6682
let src = r#"/// @title Foo

src/codegen/cfg.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub enum Instr {
7070
res: usize,
7171
ty: Type,
7272
storage: Expression,
73+
storage_type: Option<pt::StorageType>,
7374
},
7475
/// Clear storage at slot for ty (might span multiple slots)
7576
ClearStorage { ty: Type, storage: Expression },
@@ -78,6 +79,7 @@ pub enum Instr {
7879
ty: Type,
7980
value: Expression,
8081
storage: Expression,
82+
storage_type: Option<pt::StorageType>,
8183
},
8284
/// In storage slot, set the value at the offset
8385
SetStorageBytes {
@@ -1027,7 +1029,7 @@ impl ControlFlowGraph {
10271029
true_block,
10281030
false_block,
10291031
),
1030-
Instr::LoadStorage { ty, res, storage } => format!(
1032+
Instr::LoadStorage { ty, res, storage, .. } => format!(
10311033
"%{} = load storage slot({}) ty:{}",
10321034
self.vars[res].id.name,
10331035
self.expr_to_string(contract, ns, storage),
@@ -1038,7 +1040,7 @@ impl ControlFlowGraph {
10381040
self.expr_to_string(contract, ns, storage),
10391041
ty.to_string(ns),
10401042
),
1041-
Instr::SetStorage { ty, value, storage } => format!(
1043+
Instr::SetStorage { ty, value, storage, .. } => format!(
10421044
"store storage slot({}) ty:{} = {}",
10431045
self.expr_to_string(contract, ns, storage),
10441046
ty.to_string(ns),

src/codegen/constant_folding.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,12 @@ pub fn constant_folding(cfg: &mut ControlFlowGraph, dry_run: bool, ns: &mut Name
129129
};
130130
}
131131
}
132-
Instr::SetStorage { ty, storage, value } => {
132+
Instr::SetStorage {
133+
ty,
134+
storage,
135+
value,
136+
storage_type,
137+
} => {
133138
let (storage, _) = expression(storage, Some(&vars), cfg, ns);
134139
let (value, _) = expression(value, Some(&vars), cfg, ns);
135140

@@ -138,17 +143,19 @@ pub fn constant_folding(cfg: &mut ControlFlowGraph, dry_run: bool, ns: &mut Name
138143
ty: ty.clone(),
139144
storage,
140145
value,
146+
storage_type: storage_type.clone(),
141147
};
142148
}
143149
}
144-
Instr::LoadStorage { ty, storage, res } => {
150+
Instr::LoadStorage { ty, storage, res, storage_type } => {
145151
let (storage, _) = expression(storage, Some(&vars), cfg, ns);
146152

147153
if !dry_run {
148154
cfg.blocks[block_no].instr[instr_no] = Instr::LoadStorage {
149155
ty: ty.clone(),
150156
storage,
151157
res: *res,
158+
storage_type: storage_type.clone(),
152159
};
153160
}
154161
}

src/codegen/dead_storage.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ pub fn dead_storage(cfg: &mut ControlFlowGraph, _ns: &mut Namespace) {
488488
let vars = &block_vars[&block_no][instr_no];
489489

490490
match &cfg.blocks[block_no].instr[instr_no] {
491-
Instr::LoadStorage { res, ty, storage } => {
491+
Instr::LoadStorage { res, ty, storage, .. } => {
492492
// is there a definition which has the same storage expression
493493
let mut found = None;
494494

src/codegen/dispatch/solana.rs

+1
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,7 @@ fn check_magic(magic_value: u32, cfg: &mut ControlFlowGraph, vartab: &mut Vartab
491491
ty: Type::Uint(32),
492492
value: 0.into(),
493493
},
494+
storage_type: None,
494495
},
495496
);
496497

src/codegen/encoding/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ fn calculate_size_args(
156156
vartab: &mut Vartable,
157157
cfg: &mut ControlFlowGraph,
158158
) -> Expression {
159+
println!("calculate_size_args");
159160
let mut size = encoder.get_expr_size(0, &args[0], ns, vartab, cfg);
160161
for (i, item) in args.iter().enumerate().skip(1) {
161162
let additional = encoder.get_expr_size(i, item, ns, vartab, cfg);
@@ -1422,7 +1423,8 @@ pub(crate) trait AbiEncoding {
14221423
self.get_expr_size(arg_no, &loaded, ns, vartab, cfg)
14231424
}
14241425
Type::StorageRef(_, r) => {
1425-
let var = load_storage(&Codegen, r, expr.clone(), cfg, vartab);
1426+
println!("EH DAH BA@A A&A");
1427+
let var = load_storage(&Codegen, r, expr.clone(), cfg, vartab, None);
14261428
let size = self.get_expr_size(arg_no, &var, ns, vartab, cfg);
14271429
self.storage_cache_insert(arg_no, var.clone());
14281430
size

0 commit comments

Comments
 (0)