1use serde::{Deserialize, Serialize};
2
3use crate::{bytecode::*, bytes_util::*, error::CodegenError, evm::Opcode};
4use std::path::PathBuf;
5
6pub type Literal = [u8; 32];
8
9pub type FilePath = PathBuf;
13
14#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
21pub struct Contract {
22 pub macros: Vec<MacroDefinition>,
24 pub invocations: Vec<MacroInvocation>,
26 pub imports: Vec<FilePath>,
28 pub constants: Vec<ConstantDefinition>,
30 pub functions: Vec<Function>,
32 pub events: Vec<Event>,
34 pub tables: Vec<Table>,
36}
37
38impl Contract {
39 pub fn find_macro_by_name(&self, name: &str) -> Option<MacroDefinition> {
41 if let Some(m) = self
42 .macros
43 .iter()
44 .filter(|m| m.name == name)
45 .cloned()
46 .collect::<Vec<MacroDefinition>>()
47 .get(0)
48 {
49 Some(m.clone())
50 } else {
51 tracing::warn!("Failed to find macro \"{}\" in contract", name);
52 None
53 }
54 }
55
56 pub fn derive_storage_pointers(&mut self) {
58 let mut storage_pointers: Vec<[u8; 32]> = Vec::new();
59 let mut last_assigned_free_pointer = 0;
60 for constant in &self.constants {
63 if let ConstVal::Literal(literal) = &constant.value {
64 storage_pointers.push(*literal);
65 }
66 }
67 for constant in self.constants.iter_mut() {
68 if let ConstVal::FreeStoragePointer(_) = &constant.value {
69 let mut fsp_bytes = str_to_bytes32(&format!("{}", last_assigned_free_pointer));
70 while storage_pointers.contains(&fsp_bytes) {
71 last_assigned_free_pointer += 1;
72 fsp_bytes = str_to_bytes32(&format!("{}", last_assigned_free_pointer));
73 }
74 storage_pointers.push(fsp_bytes);
75 last_assigned_free_pointer += 1;
76 constant.value = ConstVal::Literal(fsp_bytes);
77 }
78 }
79 }
80}
81
82#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
84pub struct Argument {
85 pub arg_type: Option<String>,
87 pub name: Option<String>,
89 pub indexed: bool,
91}
92
93#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
95pub struct Function {
96 pub name: String,
98 pub signature: [u8; 4],
100 pub inputs: Vec<Argument>,
102 pub fn_type: FunctionType,
104 pub outputs: Vec<Argument>,
106}
107
108#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
110pub enum FunctionType {
111 View,
113 Payable,
115 NonPayable,
117 Pure,
119}
120
121#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
123pub struct Event {
124 pub name: String,
126 pub parameters: Vec<Argument>,
128}
129
130#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
132pub struct Table {
133 pub name: String,
135 }
137
138#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
140pub struct MacroDefinition {
141 pub name: String,
143 pub parameters: Vec<Argument>,
145 pub statements: Vec<Statement>,
147 pub takes: usize,
149 pub returns: usize,
151}
152
153impl ToIRBytecode<CodegenError> for MacroDefinition {
154 fn to_irbytecode(&self) -> Result<IRBytecode, CodegenError> {
155 let mut inner_irbytes: Vec<IRByte> = vec![];
156
157 self.statements.iter().for_each(|statement| {
159 match statement {
160 Statement::Literal(l) => {
161 let combined = l
162 .iter()
163 .map(|b| IRByte::Byte(Byte(format!("{:04x}", b))))
164 .collect::<Vec<IRByte>>();
165 println!("Combined IRBytes: {:?}", combined);
166 combined.iter().for_each(|irb| inner_irbytes.push(irb.clone()));
167 }
168 Statement::Opcode(o) => {
169 let opcode_str = o.string();
170 tracing::info!("Got opcode hex string: {}", opcode_str);
171 inner_irbytes.push(IRByte::Byte(Byte(opcode_str)))
172 }
173 Statement::MacroInvocation(mi) => {
174 inner_irbytes.push(IRByte::Statement(Statement::MacroInvocation(mi.clone())));
175 }
176 Statement::Constant(name) => {
177 inner_irbytes.push(IRByte::Constant(name.to_string()));
179 }
180 Statement::ArgCall(arg_name) => {
181 inner_irbytes.push(IRByte::ArgCall(arg_name.to_string()));
183 }
184 }
185 });
186 Ok(IRBytecode(inner_irbytes))
187 }
188}
189
190impl MacroDefinition {
191 pub fn new(
193 name: String,
194 parameters: Vec<Argument>,
195 statements: Vec<Statement>,
196 takes: usize,
197 returns: usize,
198 ) -> Self {
199 MacroDefinition { name, parameters, statements, takes, returns }
200 }
201}
202
203#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
205pub struct MacroInvocation {
206 pub macro_name: String,
208 pub args: Vec<MacroArg>,
210}
211
212#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
214pub enum MacroArg {
215 Literal(Literal),
217 Ident(String),
219}
220
221#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
223pub struct FreeStoragePointer;
224
225#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
227pub enum ConstVal {
228 Literal(Literal),
230 FreeStoragePointer(FreeStoragePointer),
232}
233
234#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
236pub struct ConstantDefinition {
237 pub name: String,
239 pub value: ConstVal,
241}
242
243#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
245pub enum Statement {
246 Literal(Literal),
248 Opcode(Opcode),
250 MacroInvocation(MacroInvocation),
252 Constant(String),
254 ArgCall(String),
256}