Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refac: separate compiler and parser #123

Merged
merged 38 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
957334f
refac: create a workspace
Aug 24, 2024
6911827
fixup! refac: create a workspace
sayon Aug 25, 2024
0424223
adjust the path to LLVM in the new workspace
sayon Aug 25, 2024
75e4eb4
rearrange cargo configs
sayon Aug 25, 2024
5e6bb1f
fixup! rearrange cargo configs
sayon Aug 26, 2024
43330c0
Merge branch 'main' into iz-extract-parser
sayon Aug 26, 2024
ecb7f07
move description in Cargo.toml to workspace root
sayon Aug 26, 2024
09b3024
version the workspace
sayon Aug 26, 2024
04e5795
refac: move in the parser code
Aug 24, 2024
cefb4ba
refac: extract parser
sayon Aug 24, 2024
132ef0e
Merge remote-tracking branch 'origin/main' into iz-workspace-with-parser
sayon Aug 26, 2024
d70420e
Merge branch 'main' into iz-cpr-1493-extract-yul-parser-into-a-separa…
hedgar2017 Aug 26, 2024
093c15b
better decoupling and additional tests
sayon Aug 28, 2024
8e70ba9
Merge remote-tracking branch 'origin/main' into iz-workspace-with-parser
sayon Aug 28, 2024
d1e0b69
fix: separate dialect-agnostic and dialect-specific tests
sayon Aug 28, 2024
7bbc6e0
refac: clippy, fmt, codestyle
sayon Aug 28, 2024
ba0b1a3
refac: rename dialect to era
sayon Aug 28, 2024
c8afc71
refac: renaming and comments
sayon Aug 28, 2024
980bc78
fix: update dependencies in tests
sayon Aug 28, 2024
d847914
extract parser
sayon Aug 28, 2024
43b1e4f
make YUL store a wrapper object
sayon Aug 28, 2024
1a9ad15
fmt
sayon Aug 28, 2024
d6a9180
fix: wrong names
sayon Aug 28, 2024
672c7db
refac: format
sayon Aug 28, 2024
fdd5de8
refac: fmt and clippy
sayon Aug 29, 2024
8e997dd
Merge branch 'main' into iz-workspace-with-parser
sayon Aug 29, 2024
efab350
Merge branch 'main' into iz-cpr-1493-extract-yul-parser-into-a-separa…
hedgar2017 Aug 30, 2024
1bf3d49
Merge remote-tracking branch 'origin/main' into iz-cpr-1493-extract-y…
sayon Aug 30, 2024
cd8eb6d
refac: omit "as _"
sayon Aug 30, 2024
12d2de5
refac: remove Wrapped prefix where possible
sayon Aug 30, 2024
0ec42ed
fix: autoreplacement artifact
sayon Aug 30, 2024
b6fd06f
fix: wrong documentation comment
sayon Aug 30, 2024
171139f
fix: documentation full stops
sayon Aug 30, 2024
9ec591c
refac: move constant to the beginning of trait
sayon Aug 30, 2024
4bbc699
refac: format tests
sayon Aug 30, 2024
50cfe4b
refac: fmt
sayon Aug 31, 2024
5813edf
fix: tests
sayon Aug 31, 2024
e94cd66
chore: update deps
hedgar2017 Sep 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[workspace]
members = [
"era-compiler-solidity",
"era-yul",
]
resolver = "2"

Expand Down
1 change: 1 addition & 0 deletions era-compiler-solidity/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ sha3 = "0.10"

era-compiler-common = { git = "https://github.com/matter-labs/era-compiler-common", branch = "main" }
era-compiler-llvm-context = { git = "https://github.com/matter-labs/era-compiler-llvm-context", branch = "main" }
era-yul = { path = "../era-yul" }

[dev-dependencies]
assert_cmd = "2.0.16"
Expand Down
8 changes: 5 additions & 3 deletions era-compiler-solidity/src/project/contract/ir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ use std::collections::HashSet;

use crate::evmla::assembly::Assembly;
use crate::solc::standard_json::output::contract::evm::extra_metadata::ExtraMetadata;
use crate::yul::parser::statement::object::Object;
use crate::yul::parser::dialect::era::EraDialect;
use crate::yul::parser::wrapper::Wrap;
use era_yul::yul::parser::statement::object::Object;

use self::eravm_assembly::EraVMAssembly;
use self::evmla::EVMLA;
Expand All @@ -37,8 +39,8 @@ impl IR {
///
/// A shortcut constructor.
///
pub fn new_yul(object: Object) -> Self {
Self::Yul(Yul::new(object))
pub fn new_yul(object: Object<EraDialect>) -> Self {
Self::Yul(Yul::new(object.wrap()))
}

///
Expand Down
13 changes: 7 additions & 6 deletions era-compiler-solidity/src/project/contract/ir/yul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,38 @@

use std::collections::HashSet;

use crate::yul::parser::statement::object::Object;
use crate::yul::parser::dialect::era::EraDialect;
use era_yul::yul::parser::statement::object::Object;

///
/// The contract Yul source code.
///
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Yul {
/// The Yul AST object.
pub object: Object,
pub object: crate::yul::parser::statement::object::Object,
}

impl Yul {
///
/// A shortcut constructor.
///
pub fn new(object: Object) -> Self {
pub fn new(object: crate::yul::parser::statement::object::Object) -> Self {
Self { object }
}

///
/// Extracts the runtime code from the Yul object.
///
pub fn take_runtime_code(&mut self) -> Option<Object> {
self.object.inner_object.take().map(|object| *object)
pub fn take_runtime_code(&mut self) -> Option<Object<EraDialect>> {
self.object.0.inner_object.take().map(|object| *object)
}

///
/// Get the list of missing deployable libraries.
///
pub fn get_missing_libraries(&self) -> HashSet<String> {
self.object.get_missing_libraries()
self.object.0.get_missing_libraries()
}
}

Expand Down
12 changes: 9 additions & 3 deletions era-compiler-solidity/src/project/contract/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::build_eravm::contract::Contract as EraVMContractBuild;
use crate::build_evm::contract::Contract as EVMContractBuild;
use crate::process::input_eravm::dependency_data::DependencyData as EraVMProcessInputDependencyData;
use crate::process::input_evm::dependency_data::DependencyData as EVMProcessInputDependencyData;
use crate::yul::parser::wrapper::Wrap;

use self::factory_dependency::FactoryDependency;
use self::ir::IR;
Expand Down Expand Up @@ -54,7 +55,7 @@ impl Contract {
///
pub fn identifier(&self) -> &str {
match self.ir {
IR::Yul(ref yul) => yul.object.identifier.as_str(),
IR::Yul(ref yul) => yul.object.0.identifier.as_str(),
IR::EVMLA(ref evm) => evm.assembly.full_path(),
IR::LLVMIR(ref llvm_ir) => llvm_ir.path.as_str(),
IR::EraVMAssembly(ref eravm_assembly) => eravm_assembly.path.as_str(),
Expand Down Expand Up @@ -244,7 +245,10 @@ impl Contract {
era_compiler_llvm_context::EVMBuild,
>; 2] = [
(era_compiler_llvm_context::CodeType::Deploy, deploy_code),
(era_compiler_llvm_context::CodeType::Runtime, runtime_code),
(
era_compiler_llvm_context::CodeType::Runtime,
runtime_code.wrap(),
),
]
.into_iter()
.map(|(code_type, mut code)| {
Expand Down Expand Up @@ -393,6 +397,7 @@ impl FactoryDependency for Contract {
match self.ir {
IR::Yul(ref yul) => yul
.object
.0
.factory_dependencies
.iter()
.map(|path| path.as_str())
Expand All @@ -410,7 +415,7 @@ impl FactoryDependency for Contract {

fn drain_factory_dependencies(&mut self) -> HashSet<String> {
match self.ir {
IR::Yul(ref mut yul) => yul.object.factory_dependencies.drain().collect(),
IR::Yul(ref mut yul) => yul.object.0.factory_dependencies.drain().collect(),
IR::EVMLA(ref mut evm) => evm.assembly.factory_dependencies.drain().collect(),
IR::LLVMIR(_) => HashSet::new(),
IR::EraVMAssembly(_) => HashSet::new(),
Expand All @@ -428,6 +433,7 @@ impl FactoryDependency for Contract {
match self.ir {
IR::Yul(ref yul) => yul
.object
.0
.factory_dependencies
.iter()
.map(|identifier| {
Expand Down
4 changes: 2 additions & 2 deletions era-compiler-solidity/src/project/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ use crate::solc::standard_json::output::error::Error as SolcStandardJsonOutputEr
use crate::solc::standard_json::output::Output as SolcStandardJsonOutput;
use crate::solc::version::Version as SolcVersion;
use crate::solc::Compiler as SolcCompiler;
use crate::yul::lexer::Lexer;
use crate::yul::parser::statement::object::Object;
use era_yul::yul::lexer::Lexer;
use era_yul::yul::parser::statement::object::Object;

use self::contract::ir::IR as ContractIR;
use self::contract::Contract;
Expand Down
2 changes: 0 additions & 2 deletions era-compiler-solidity/src/yul/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,4 @@
//! The Yul IR compiling tools.
//!

pub mod error;
pub mod lexer;
pub mod parser;
140 changes: 140 additions & 0 deletions era-compiler-solidity/src/yul/parser/dialect/era/attributes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
//!
//! Parser of LLVM attributes encoded in the function identifier.
//!

use std::collections::BTreeSet;

use era_yul::yul::error::Error as YulError;
use era_yul::yul::parser::error::Error as ParserError;
use era_yul::yul::parser::identifier::Identifier;

/// The LLVM attribute section prefix.
pub const LLVM_ATTRIBUTE_PREFIX: &str = "$llvm_";

/// The LLVM attribute section suffix.
pub const LLVM_ATTRIBUTE_SUFFIX: &str = "_llvm$";

///
/// Gets the list of LLVM attributes provided in the function name.
///
pub(crate) fn get_llvm_attributes(
identifier: &Identifier,
) -> Result<BTreeSet<era_compiler_llvm_context::Attribute>, YulError> {
let mut valid_attributes = BTreeSet::new();

let llvm_begin = identifier.inner.find(LLVM_ATTRIBUTE_PREFIX);
let llvm_end = identifier.inner.find(LLVM_ATTRIBUTE_SUFFIX);
let attribute_string = if let (Some(llvm_begin), Some(llvm_end)) = (llvm_begin, llvm_end) {
if llvm_begin < llvm_end {
&identifier.inner[llvm_begin + LLVM_ATTRIBUTE_PREFIX.len()..llvm_end]
} else {
return Ok(valid_attributes);
}
} else {
return Ok(valid_attributes);
};

let mut invalid_attributes = BTreeSet::new();
for value in attribute_string.split('_') {
match era_compiler_llvm_context::Attribute::try_from(value) {
Ok(attribute) => valid_attributes.insert(attribute),
Err(value) => invalid_attributes.insert(value),
};
}

if !invalid_attributes.is_empty() {
return Err(ParserError::InvalidAttributes {
location: identifier.location,
values: invalid_attributes,
}
.into());
}

Ok(valid_attributes)
}

#[cfg(test)]
mod tests {
use std::collections::BTreeSet;

use era_yul::yul::error::Error as YulError;
use era_yul::yul::lexer::token::location::Location;
use era_yul::yul::parser::error::Error as ParserError;
use era_yul::yul::parser::identifier::Identifier;

use super::get_llvm_attributes;

fn identifier_of(name: &str) -> Identifier {
Identifier {
location: Location { line: 0, column: 0 },
inner: name.to_string(),
r#type: None,
}
}

fn attribute_helper(s: &&str) -> era_compiler_llvm_context::Attribute {
era_compiler_llvm_context::Attribute::try_from(*s).expect(
"Internal error in test: trying to create an instance of `era_compiler_llvm_context::Attribute` from an invalid string representation.",
)
}
fn immediate_attributes(
representations: &[&str],
) -> BTreeSet<era_compiler_llvm_context::Attribute> {
representations.iter().map(attribute_helper).collect()
}

#[test]
fn parse_single_attribute() {
let input = r#"
$llvm_Hot_llvm$
"#;
let expected = immediate_attributes(&["Hot"]);
let result = get_llvm_attributes(&identifier_of(input)).unwrap_or_else(|_| {
panic!(
"LLVM attribute parser should be able to parse a valid input: \"{}\"",
input
)
});
assert_eq!(result, expected)
}

#[test]
fn parse_multiple_attributes() {
let input = r#"
$llvm_Hot_Cold_MinSize_llvm$
"#;
let expected = immediate_attributes(&["Cold", "Hot", "MinSize"]);
let result = get_llvm_attributes(&identifier_of(input)).unwrap_or_else(|_| {
panic!(
"LLVM attribute parser should be able to parse a valid input: \"{}\"",
input
)
});
assert_eq!(result, expected)
}
#[test]
fn parse_malformed_attributes() {
let input = r#"
$llvm____*&@_llvm$
"#;
get_llvm_attributes(&identifier_of(input)).expect_err(&format!(
"LLVM attributes parser should not parse attributes from the malformed input \"{}\"",
input
));
}

#[test]
fn parse_invalid_attributes() {
let input = r#"
$llvm_Hot_Cold_MinSize_BogusAttr_llvm$
"#;

let values = BTreeSet::from(["BogusAttr".into()]);
let location = Location { line: 0, column: 0 };
let expected = YulError::Parser(ParserError::InvalidAttributes { location, values });
let result = get_llvm_attributes(&identifier_of(input))
.expect_err("LLVM attributes parser should not mask unknown attributes");

assert_eq!(result, expected);
}
}
Loading
Loading