mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-22 09:01:35 +03:00
doing some recommended changes
This commit is contained in:
parent
041bd57c5b
commit
3a056220ff
@ -32,14 +32,20 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
use crate::OutputOptions;
|
use crate::OutputOptions;
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
/// The primary entry point of the Leo compiler.
|
/// The primary entry point of the Leo compiler.
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Compiler<'a> {
|
pub struct Compiler<'a> {
|
||||||
|
/// The handler is used for error and warning emissions.
|
||||||
handler: &'a Handler,
|
handler: &'a Handler,
|
||||||
|
/// The path to the main leo file.
|
||||||
main_file_path: PathBuf,
|
main_file_path: PathBuf,
|
||||||
|
/// The path to where the compiler outputs all generated files.
|
||||||
output_directory: PathBuf,
|
output_directory: PathBuf,
|
||||||
|
/// The AST for the program.
|
||||||
pub ast: Ast,
|
pub ast: Ast,
|
||||||
|
/// The input ast for the program if it exists.
|
||||||
pub input_ast: Option<InputAst>,
|
pub input_ast: Option<InputAst>,
|
||||||
|
/// Compiler options on some optional output files.
|
||||||
output_options: OutputOptions,
|
output_options: OutputOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,10 @@
|
|||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct OutputOptions {
|
pub struct OutputOptions {
|
||||||
|
/// Whether spans are enabled in the output ASTs.
|
||||||
pub spans_enabled: bool,
|
pub spans_enabled: bool,
|
||||||
|
/// If enabled writes the AST after parsing.
|
||||||
pub ast_initial: bool,
|
pub ast_initial: bool,
|
||||||
|
/// If enabled writes the input AST after parsing.
|
||||||
pub input_ast_initial: bool,
|
pub input_ast_initial: bool,
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! This file contains tools for benchmarking the Leo compiler and its stages.
|
||||||
|
|
||||||
use leo_compiler::Compiler;
|
use leo_compiler::Compiler;
|
||||||
use leo_errors::emitter::{Emitter, Handler};
|
use leo_errors::emitter::{Emitter, Handler};
|
||||||
use leo_span::{
|
use leo_span::{
|
||||||
@ -28,13 +30,19 @@ use std::{
|
|||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// An enum to represent the stage of the Compiler we are benchmarking.
|
||||||
enum BenchMode {
|
enum BenchMode {
|
||||||
|
/// Benchmarks parsing.
|
||||||
Parse,
|
Parse,
|
||||||
|
/// Benchmarks symbol table generation.
|
||||||
Symbol,
|
Symbol,
|
||||||
|
/// Benchmarks type checking.
|
||||||
Type,
|
Type,
|
||||||
|
/// Benchmarks all the above stages.
|
||||||
Full,
|
Full,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A dummy buffer emitter since we only test on valid programs.
|
||||||
struct BufEmitter;
|
struct BufEmitter;
|
||||||
|
|
||||||
impl Emitter for BufEmitter {
|
impl Emitter for BufEmitter {
|
||||||
@ -53,12 +61,14 @@ impl BufEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The name of the test, and the test content.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Sample {
|
struct Sample {
|
||||||
name: String,
|
name: String,
|
||||||
input: String,
|
input: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A helper function to help create a Leo Compiler struct.
|
||||||
fn new_compiler(handler: &Handler) -> Compiler<'_> {
|
fn new_compiler(handler: &Handler) -> Compiler<'_> {
|
||||||
Compiler::new(
|
Compiler::new(
|
||||||
handler,
|
handler,
|
||||||
@ -69,6 +79,9 @@ fn new_compiler(handler: &Handler) -> Compiler<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Sample {
|
impl Sample {
|
||||||
|
/// Loads all the benchmark samples.
|
||||||
|
/// Leverages the test-framework to grab all tests
|
||||||
|
/// that are passing compiler tests or marked as benchmark tests.
|
||||||
fn load_samples() -> Vec<Self> {
|
fn load_samples() -> Vec<Self> {
|
||||||
get_benches()
|
get_benches()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -91,6 +104,8 @@ impl Sample {
|
|||||||
|
|
||||||
fn bench_parse(&self, c: &mut Criterion) {
|
fn bench_parse(&self, c: &mut Criterion) {
|
||||||
c.bench_function(&format!("parse {}", self.name), |b| {
|
c.bench_function(&format!("parse {}", self.name), |b| {
|
||||||
|
// Iter custom is used so we can use custom timings around the compiler stages.
|
||||||
|
// This way we can only time the necessary stage.
|
||||||
b.iter_custom(|iters| {
|
b.iter_custom(|iters| {
|
||||||
let mut time = Duration::default();
|
let mut time = Duration::default();
|
||||||
for _ in 0..iters {
|
for _ in 0..iters {
|
||||||
@ -111,6 +126,8 @@ impl Sample {
|
|||||||
|
|
||||||
fn bench_symbol_table(&self, c: &mut Criterion) {
|
fn bench_symbol_table(&self, c: &mut Criterion) {
|
||||||
c.bench_function(&format!("symbol table pass {}", self.name), |b| {
|
c.bench_function(&format!("symbol table pass {}", self.name), |b| {
|
||||||
|
// Iter custom is used so we can use custom timings around the compiler stages.
|
||||||
|
// This way we can only time the necessary stage.
|
||||||
b.iter_custom(|iters| {
|
b.iter_custom(|iters| {
|
||||||
let mut time = Duration::default();
|
let mut time = Duration::default();
|
||||||
for _ in 0..iters {
|
for _ in 0..iters {
|
||||||
@ -134,6 +151,8 @@ impl Sample {
|
|||||||
|
|
||||||
fn bench_type_checker(&self, c: &mut Criterion) {
|
fn bench_type_checker(&self, c: &mut Criterion) {
|
||||||
c.bench_function(&format!("type checker pass {}", self.name), |b| {
|
c.bench_function(&format!("type checker pass {}", self.name), |b| {
|
||||||
|
// Iter custom is used so we can use custom timings around the compiler stages.
|
||||||
|
// This way we can only time the necessary stage.
|
||||||
b.iter_custom(|iters| {
|
b.iter_custom(|iters| {
|
||||||
let mut time = Duration::default();
|
let mut time = Duration::default();
|
||||||
for _ in 0..iters {
|
for _ in 0..iters {
|
||||||
@ -158,6 +177,8 @@ impl Sample {
|
|||||||
|
|
||||||
fn bench_full(&self, c: &mut Criterion) {
|
fn bench_full(&self, c: &mut Criterion) {
|
||||||
c.bench_function(&format!("full {}", self.name), |b| {
|
c.bench_function(&format!("full {}", self.name), |b| {
|
||||||
|
// Iter custom is used so we can use custom timings around the compiler stages.
|
||||||
|
// This way we can only time the necessary stages.
|
||||||
b.iter_custom(|iters| {
|
b.iter_custom(|iters| {
|
||||||
let mut time = Duration::default();
|
let mut time = Duration::default();
|
||||||
for _ in 0..iters {
|
for _ in 0..iters {
|
||||||
|
@ -21,20 +21,16 @@ use std::{
|
|||||||
|
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
pub fn find_tests<T: AsRef<Path> + Copy>(path: T) -> Vec<(PathBuf, String)> {
|
pub fn find_tests(path: &'_ Path) -> impl Iterator<Item = (PathBuf, String)> + '_ {
|
||||||
WalkDir::new(path)
|
WalkDir::new(path).into_iter().flatten().filter_map(move |f| {
|
||||||
.into_iter()
|
|
||||||
.flatten()
|
|
||||||
.filter_map(|f| {
|
|
||||||
let path = f.path();
|
let path = f.path();
|
||||||
if matches!(path.extension(), Some(s) if s == "leo") {
|
path.extension().filter(|s| *s == "leo").map(|_| {
|
||||||
let content = fs::read_to_string(path).expect("failed to read test");
|
(
|
||||||
Some((path.to_path_buf(), content))
|
path.to_path_buf(),
|
||||||
} else {
|
fs::read_to_string(path).expect("failed to read test"),
|
||||||
None
|
)
|
||||||
}
|
})
|
||||||
})
|
})
|
||||||
.collect::<Vec<(PathBuf, String)>>()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn split_tests_one_line(source: &str) -> Vec<&str> {
|
pub fn split_tests_one_line(source: &str) -> Vec<&str> {
|
||||||
|
@ -50,6 +50,10 @@ pub trait Runner {
|
|||||||
fn resolve_namespace(&self, name: &str) -> Option<Box<dyn Namespace>>;
|
fn resolve_namespace(&self, name: &str) -> Option<Box<dyn Namespace>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_env_var_set(var: &str) -> bool {
|
||||||
|
std::env::var(var).unwrap_or_else(|_| "".to_string()).trim().is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
fn set_hook() -> Arc<Mutex<Option<String>>> {
|
fn set_hook() -> Arc<Mutex<Option<String>>> {
|
||||||
let panic_buf = Arc::new(Mutex::new(None));
|
let panic_buf = Arc::new(Mutex::new(None));
|
||||||
let thread_id = thread::current().id();
|
let thread_id = thread::current().id();
|
||||||
@ -57,10 +61,7 @@ fn set_hook() -> Arc<Mutex<Option<String>>> {
|
|||||||
let panic_buf = panic_buf.clone();
|
let panic_buf = panic_buf.clone();
|
||||||
Box::new(move |e| {
|
Box::new(move |e| {
|
||||||
if thread::current().id() == thread_id {
|
if thread::current().id() == thread_id {
|
||||||
if !std::env::var("RUST_BACKTRACE")
|
if !is_env_var_set("RUST_BACKTRACE") {
|
||||||
.unwrap_or_else(|_| "".to_string())
|
|
||||||
.is_empty()
|
|
||||||
{
|
|
||||||
*panic_buf.lock().unwrap() = Some(format!("{:?}", backtrace::Backtrace::new()));
|
*panic_buf.lock().unwrap() = Some(format!("{:?}", backtrace::Backtrace::new()));
|
||||||
} else {
|
} else {
|
||||||
*panic_buf.lock().unwrap() = Some(e.to_string());
|
*panic_buf.lock().unwrap() = Some(e.to_string());
|
||||||
@ -111,7 +112,7 @@ impl TestCases {
|
|||||||
fn load_tests(&mut self, additional_check: impl Fn(&TestConfig) -> bool) -> Vec<TestConfig> {
|
fn load_tests(&mut self, additional_check: impl Fn(&TestConfig) -> bool) -> Vec<TestConfig> {
|
||||||
let mut configs = Vec::new();
|
let mut configs = Vec::new();
|
||||||
|
|
||||||
self.tests = find_tests(&self.path_prefix)
|
self.tests = find_tests(&self.path_prefix.clone())
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|(path, content)| {
|
.filter(|(path, content)| {
|
||||||
let config = match extract_test_config(content) {
|
let config = match extract_test_config(content) {
|
||||||
@ -130,6 +131,7 @@ impl TestCases {
|
|||||||
res
|
res
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
dbg!(self.tests.len());
|
||||||
|
|
||||||
configs
|
configs
|
||||||
}
|
}
|
||||||
@ -177,11 +179,7 @@ impl TestCases {
|
|||||||
expectation_path.push(&expectation_name);
|
expectation_path.push(&expectation_name);
|
||||||
|
|
||||||
if expectation_path.exists() {
|
if expectation_path.exists() {
|
||||||
if !std::env::var("CLEAR_LEO_TEST_EXPECTATIONS")
|
if !is_env_var_set("CLEAR_LEO_TEST_EXPECTATIONS") {
|
||||||
.unwrap_or_default()
|
|
||||||
.trim()
|
|
||||||
.is_empty()
|
|
||||||
{
|
|
||||||
(expectation_path, None)
|
(expectation_path, None)
|
||||||
} else {
|
} else {
|
||||||
let raw = std::fs::read_to_string(&expectation_path).expect("failed to read expectations file");
|
let raw = std::fs::read_to_string(&expectation_path).expect("failed to read expectations file");
|
||||||
@ -284,8 +282,10 @@ pub fn get_benches() -> Vec<(String, String)> {
|
|||||||
let (mut cases, configs) = TestCases::new("compiler", |config| {
|
let (mut cases, configs) = TestCases::new("compiler", |config| {
|
||||||
(&config.namespace == "Bench" && config.expectation == TestExpectationMode::Pass)
|
(&config.namespace == "Bench" && config.expectation == TestExpectationMode::Pass)
|
||||||
|| (&config.namespace == "Compile"
|
|| (&config.namespace == "Compile"
|
||||||
&& config.expectation != TestExpectationMode::Fail
|
&& !matches!(
|
||||||
&& config.expectation != TestExpectationMode::Skip)
|
config.expectation,
|
||||||
|
TestExpectationMode::Fail | TestExpectationMode::Skip
|
||||||
|
))
|
||||||
});
|
});
|
||||||
|
|
||||||
cases.process_tests(configs, |_, (_, content, test_name, _)| {
|
cases.process_tests(configs, |_, (_, content, test_name, _)| {
|
||||||
|
Loading…
Reference in New Issue
Block a user