Fmts and clippies

This commit is contained in:
Pranav Gaddamadugu 2023-03-26 23:18:03 -07:00
parent 47e81a5d15
commit 8adc6c76b8
102 changed files with 839 additions and 1685 deletions

View File

@ -26,17 +26,8 @@ use walkdir::WalkDir;
const EXPECTED_LICENSE_TEXT: &str = include_str!(".resources/license_header");
// The following directories will be excluded from the license scan.
const DIRS_TO_SKIP: [&str; 9] = [
".cargo",
".circleci",
".git",
".github",
".resources",
"docs",
"examples",
"target",
"tests",
];
const DIRS_TO_SKIP: [&str; 9] =
[".cargo", ".circleci", ".git", ".github", ".resources", "docs", "examples", "target", "tests"];
fn compare_license_text(path: &Path, expected_lines: &[&str]) {
let file = File::open(path).unwrap();

View File

@ -29,10 +29,7 @@ pub fn serialize<S: Serializer>(
let joined: IndexMap<String, DefinitionStatement> = global_consts
.into_iter()
.map(|(idents, program)| {
(
idents.iter().map(|i| i.name.to_string()).collect::<Vec<_>>().join(","),
program.clone(),
)
(idents.iter().map(|i| i.name.to_string()).collect::<Vec<_>>().join(","), program.clone())
})
.collect();
@ -47,10 +44,7 @@ pub fn deserialize<'de, D: Deserializer<'de>>(
.map(|(name, program)| {
(
name.split(',')
.map(|ident_name| Identifier {
name: Symbol::intern(ident_name),
span: Default::default(),
})
.map(|ident_name| Identifier { name: Symbol::intern(ident_name), span: Default::default() })
.collect::<Vec<Identifier>>(),
program,
)

View File

@ -20,9 +20,13 @@ use leo_span::{Span, Symbol};
use crate::{simple_node_impl, Node};
use serde::{
de::{
Visitor, {self},
Visitor,
{self},
},
Deserialize, Deserializer, Serialize, Serializer,
Deserialize,
Deserializer,
Serialize,
Serializer,
};
use std::{
collections::BTreeMap,
@ -48,10 +52,7 @@ simple_node_impl!(Identifier);
impl Identifier {
/// Constructs a new identifier with `name` and a default span.
pub fn new(name: Symbol) -> Self {
Self {
name,
span: Span::default(),
}
Self { name, span: Span::default() }
}
/// Check if the Identifier name matches the other name.

View File

@ -30,10 +30,7 @@ pub fn serialize<S: Serializer>(
imported_modules
.into_iter()
.map(|(package, program)| {
let package = package
.iter()
.map(|x| x.as_str(s, |s| s.to_owned()))
.collect::<Vec<_>>();
let package = package.iter().map(|x| x.as_str(s, |s| s.to_owned())).collect::<Vec<_>>();
(package.join("."), program.clone())
})
.collect()

View File

@ -15,8 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
use std::{fmt, str::FromStr};
/// A number string guaranteed to be positive.
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)]

View File

@ -86,42 +86,38 @@ pub enum BinaryOperation {
impl fmt::Display for BinaryOperation {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}",
match self {
Self::Add => "+",
Self::AddWrapped => "add_wrapped",
Self::And => "&&",
Self::BitwiseAnd => "&",
Self::Div => "/",
Self::DivWrapped => "div_wrapped",
Self::Eq => "==",
Self::Gte => ">=",
Self::Gt => ">",
Self::Lte => "<=",
Self::Lt => "<",
Self::Mod => "mod",
Self::Mul => "*",
Self::MulWrapped => "mul_wrapped",
Self::Nand => "NAND",
Self::Neq => "!=",
Self::Nor => "NOR",
Self::Or => "||",
Self::BitwiseOr => "|",
Self::Pow => "**",
Self::PowWrapped => "pow_wrapped",
Self::Rem => "%",
Self::RemWrapped => "rem_wrapped",
Self::Shl => "<<",
Self::ShlWrapped => "shl_wrapped",
Self::Shr => ">>",
Self::ShrWrapped => "shr_wrapped",
Self::Sub => "-",
Self::SubWrapped => "sub_wrapped",
Self::Xor => "^",
}
)
write!(f, "{}", match self {
Self::Add => "+",
Self::AddWrapped => "add_wrapped",
Self::And => "&&",
Self::BitwiseAnd => "&",
Self::Div => "/",
Self::DivWrapped => "div_wrapped",
Self::Eq => "==",
Self::Gte => ">=",
Self::Gt => ">",
Self::Lte => "<=",
Self::Lt => "<",
Self::Mod => "mod",
Self::Mul => "*",
Self::MulWrapped => "mul_wrapped",
Self::Nand => "NAND",
Self::Neq => "!=",
Self::Nor => "NOR",
Self::Or => "||",
Self::BitwiseOr => "|",
Self::Pow => "**",
Self::PowWrapped => "pow_wrapped",
Self::Rem => "%",
Self::RemWrapped => "rem_wrapped",
Self::Shl => "<<",
Self::ShlWrapped => "shl_wrapped",
Self::Shr => ">>",
Self::ShrWrapped => "shr_wrapped",
Self::Sub => "-",
Self::SubWrapped => "sub_wrapped",
Self::Xor => "^",
})
}
}

View File

@ -82,15 +82,7 @@ impl StructExpression {
impl fmt::Display for StructExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{{{}}}",
self.members
.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(", ")
)
write!(f, "{{{}}}", self.members.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(", "))
}
}

View File

@ -30,15 +30,7 @@ pub struct TupleExpression {
impl fmt::Display for TupleExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"({})",
self.elements
.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(",")
)
write!(f, "({})", self.elements.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(","))
}
}

View File

@ -41,11 +41,7 @@ impl External {
impl fmt::Display for External {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}: {}.leo/{}.record",
self.identifier, self.program_name, self.record
)
write!(f, "{}: {}.leo/{}.record", self.identifier, self.program_name, self.record)
}
}

View File

@ -47,14 +47,7 @@ impl Finalize {
_ => Type::Tuple(Tuple(output.iter().map(|output| output.type_()).collect())),
};
Self {
identifier,
input,
output,
output_type,
block,
span,
}
Self { identifier, input, output, output_type, block, span }
}
}
@ -64,16 +57,9 @@ impl fmt::Display for Finalize {
let returns = match self.output.len() {
0 => "()".to_string(),
1 => self.output[0].to_string(),
_ => format!(
"({})",
self.output.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(",")
),
_ => format!("({})", self.output.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(",")),
};
write!(
f,
" finalize {}({parameters}) -> {returns} {}",
self.identifier, self.block
)
write!(f, " finalize {}({parameters}) -> {returns} {}", self.identifier, self.block)
}
}

View File

@ -97,18 +97,9 @@ impl Function {
_ => Type::Tuple(Tuple(output.iter().map(|output| get_output_type(output)).collect())),
};
Function {
annotations,
variant,
identifier,
input,
output,
output_type,
block,
finalize,
span,
}
Function { annotations, variant, identifier, input, output, output_type, block, finalize, span }
}
/// Returns function name.
pub fn name(&self) -> Symbol {
self.identifier.name

View File

@ -31,6 +31,7 @@ pub enum InputValue {
impl TryFrom<(Type, Expression)> for InputValue {
type Error = LeoError;
fn try_from(value: (Type, Expression)) -> Result<Self> {
Ok(match value {
(type_, Expression::Literal(lit)) => match (type_, lit) {

View File

@ -24,6 +24,7 @@ pub struct ProgramInput {
impl TryFrom<InputAst> for ProgramInput {
type Error = LeoError;
fn try_from(input: InputAst) -> Result<Self> {
let mut main = IndexMap::new();
@ -34,10 +35,7 @@ impl TryFrom<InputAst> for ProgramInput {
};
for definition in section.definitions {
target.insert(
definition.name.name,
InputValue::try_from((definition.type_, definition.value))?,
);
target.insert(definition.name.name, InputValue::try_from((definition.type_, definition.value))?);
}
}

View File

@ -157,10 +157,7 @@ impl AsRef<Program> for Ast {
pub(crate) fn remove_key_from_json(value: serde_json::Value, key: &str) -> serde_json::Value {
match value {
serde_json::Value::Object(map) => serde_json::Value::Object(
map.into_iter()
.filter(|(k, _)| k != key)
.map(|(k, v)| (k, remove_key_from_json(v, key)))
.collect(),
map.into_iter().filter(|(k, _)| k != key).map(|(k, v)| (k, remove_key_from_json(v, key))).collect(),
),
serde_json::Value::Array(values) => {
serde_json::Value::Array(values.into_iter().map(|v| remove_key_from_json(v, key)).collect())

View File

@ -36,11 +36,7 @@ pub struct Mapping {
impl fmt::Display for Mapping {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"mapping {}: {} => {}",
self.identifier, self.key_type, self.value_type
)
write!(f, "mapping {}: {} => {}", self.identifier, self.key_type, self.value_type)
}
}

View File

@ -47,11 +47,7 @@ pub trait ExpressionReconstructor {
AccessExpression::AssociatedFunction(AssociatedFunction {
ty: function.ty,
name: function.name,
args: function
.args
.into_iter()
.map(|arg| self.reconstruct_expression(arg).0)
.collect(),
args: function.args.into_iter().map(|arg| self.reconstruct_expression(arg).0).collect(),
span: function.span,
})
}
@ -87,11 +83,7 @@ pub trait ExpressionReconstructor {
(
Expression::Call(CallExpression {
function: Box::new(self.reconstruct_expression(*input.function).0),
arguments: input
.arguments
.into_iter()
.map(|arg| self.reconstruct_expression(arg).0)
.collect(),
arguments: input.arguments.into_iter().map(|arg| self.reconstruct_expression(arg).0).collect(),
external: input.external,
span: input.span,
}),
@ -130,11 +122,7 @@ pub trait ExpressionReconstructor {
fn reconstruct_tuple(&mut self, input: TupleExpression) -> (Expression, Self::AdditionalOutput) {
(
Expression::Tuple(TupleExpression {
elements: input
.elements
.into_iter()
.map(|element| self.reconstruct_expression(element).0)
.collect(),
elements: input.elements.into_iter().map(|element| self.reconstruct_expression(element).0).collect(),
span: input.span,
}),
Default::default(),
@ -212,11 +200,7 @@ pub trait StatementReconstructor: ExpressionReconstructor {
fn reconstruct_block(&mut self, input: Block) -> (Block, Self::AdditionalOutput) {
(
Block {
statements: input
.statements
.into_iter()
.map(|s| self.reconstruct_statement(s).0)
.collect(),
statements: input.statements.into_iter().map(|s| self.reconstruct_statement(s).0).collect(),
span: input.span,
},
Default::default(),
@ -326,10 +310,7 @@ pub trait StatementReconstructor: ExpressionReconstructor {
Statement::Return(ReturnStatement {
expression: self.reconstruct_expression(input.expression).0,
finalize_arguments: input.finalize_arguments.map(|arguments| {
arguments
.into_iter()
.map(|argument| self.reconstruct_expression(argument).0)
.collect()
arguments.into_iter().map(|argument| self.reconstruct_expression(argument).0).collect()
}),
span: input.span,
}),
@ -358,21 +339,9 @@ pub trait ProgramReconstructor: StatementReconstructor {
fn reconstruct_program_scope(&mut self, input: ProgramScope) -> ProgramScope {
ProgramScope {
program_id: input.program_id,
structs: input
.structs
.into_iter()
.map(|(i, c)| (i, self.reconstruct_struct(c)))
.collect(),
mappings: input
.mappings
.into_iter()
.map(|(id, mapping)| (id, self.reconstruct_mapping(mapping)))
.collect(),
functions: input
.functions
.into_iter()
.map(|(i, f)| (i, self.reconstruct_function(f)))
.collect(),
structs: input.structs.into_iter().map(|(i, c)| (i, self.reconstruct_struct(c))).collect(),
mappings: input.mappings.into_iter().map(|(id, mapping)| (id, self.reconstruct_mapping(mapping))).collect(),
functions: input.functions.into_iter().map(|(i, f)| (i, self.reconstruct_function(f))).collect(),
span: input.span,
}
}

View File

@ -214,10 +214,7 @@ pub trait ProgramVisitor<'a>: StatementVisitor<'a> {
fn visit_program(&mut self, input: &'a Program) {
input.imports.values().for_each(|import| self.visit_import(&import.0));
input
.program_scopes
.values()
.for_each(|scope| self.visit_program_scope(scope));
input.program_scopes.values().for_each(|scope| self.visit_program_scope(scope));
}
fn visit_program_scope(&mut self, input: &'a ProgramScope) {
@ -225,10 +222,7 @@ pub trait ProgramVisitor<'a>: StatementVisitor<'a> {
input.mappings.values().for_each(|mapping| self.visit_mapping(mapping));
input
.functions
.values()
.for_each(|function| self.visit_function(function));
input.functions.values().for_each(|function| self.visit_function(function));
}
fn visit_import(&mut self, input: &'a Program) {

View File

@ -53,9 +53,6 @@ impl fmt::Display for Program {
impl Default for Program {
/// Constructs an empty program node.
fn default() -> Self {
Self {
imports: IndexMap::new(),
program_scopes: IndexMap::new(),
}
Self { imports: IndexMap::new(), program_scopes: IndexMap::new() }
}
}

View File

@ -17,8 +17,7 @@
use crate::Identifier;
use core::fmt;
use serde::de::Visitor;
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use serde::{de, de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
use std::collections::BTreeMap;
/// An identifier for a program that is eventually deployed to the network.

View File

@ -35,9 +35,7 @@ impl fmt::Display for Block {
if self.statements.is_empty() {
writeln!(f, "\t")?;
} else {
self.statements
.iter()
.try_for_each(|statement| writeln!(f, "\t{statement}"))?;
self.statements.iter().try_for_each(|statement| writeln!(f, "\t{statement}"))?;
}
write!(f, "}}")
}

View File

@ -19,8 +19,7 @@ use crate::{Block, Expression, Identifier, Node, Type, Value};
use leo_span::Span;
use serde::{Deserialize, Serialize};
use std::cell::RefCell;
use std::fmt;
use std::{cell::RefCell, fmt};
/// A bounded `for` loop statement `for variable in start .. =? stop block`.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
@ -51,11 +50,7 @@ pub struct IterationStatement {
impl fmt::Display for IterationStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let eq = if self.inclusive { "=" } else { "" };
write!(
f,
"for {} in {}..{eq}{} {}",
self.variable, self.start, self.stop, self.block
)
write!(f, "for {} in {}..{eq}{} {}", self.variable, self.start, self.stop, self.block)
}
}

View File

@ -84,10 +84,7 @@ pub enum Statement {
impl Statement {
/// Returns a dummy statement made from an empty block `{}`.
pub fn dummy(span: Span) -> Self {
Self::Block(Block {
statements: Vec::new(),
span,
})
Self::Block(Block { statements: Vec::new(), span })
}
}

View File

@ -35,10 +35,6 @@ impl Deref for Tuple {
impl fmt::Display for Tuple {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"({})",
self.0.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(",")
)
write!(f, "({})", self.0.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(","))
}
}

View File

@ -70,10 +70,9 @@ impl Type {
(Type::Mapping(left), Type::Mapping(right)) => {
left.key.eq_flat(&right.key) && left.value.eq_flat(&right.value)
}
(Type::Tuple(left), Type::Tuple(right)) if left.len() == right.len() => left
.iter()
.zip_eq(right.iter())
.all(|(left_type, right_type)| left_type.eq_flat(right_type)),
(Type::Tuple(left), Type::Tuple(right)) if left.len() == right.len() => {
left.iter().zip_eq(right.iter()).all(|(left_type, right_type)| left_type.eq_flat(right_type))
}
(Type::Identifier(left), Type::Identifier(right)) => left.matches(right),
_ => false,
}

View File

@ -201,26 +201,6 @@ pub enum Value {
}
impl Value {
// TODO: This is temporary since the currently unused code is used in constant folding.
#[allow(dead_code)]
pub(crate) fn is_supported_const_fold_type(&self) -> bool {
use Value::*;
matches!(
self,
Boolean(_, _)
| I8(_, _)
| I16(_, _)
| I32(_, _)
| I64(_, _)
| I128(_, _)
| U8(_, _)
| U16(_, _)
| U32(_, _)
| U64(_, _)
| U128(_, _)
)
}
implement_const_unary!(
@overflowing
name: abs,
@ -720,6 +700,26 @@ impl Value {
[U128, [U128], U128, u128, u128]
]
);
// TODO: This is temporary since the currently unused code is used in constant folding.
#[allow(dead_code)]
pub(crate) fn is_supported_const_fold_type(&self) -> bool {
use Value::*;
matches!(
self,
Boolean(_, _)
| I8(_, _)
| I16(_, _)
| I32(_, _)
| I64(_, _)
| I128(_, _)
| U8(_, _)
| U16(_, _)
| U32(_, _)
| U64(_, _)
| U128(_, _)
)
}
}
impl Display for Value {

View File

@ -19,16 +19,13 @@
//! The [`Compiler`] type compiles Leo programs into R1CS circuits.
use leo_ast::Program;
pub use leo_ast::{Ast, InputAst};
use leo_errors::emitter::Handler;
use leo_errors::{CompilerError, Result};
use leo_errors::{emitter::Handler, CompilerError, Result};
pub use leo_passes::SymbolTable;
use leo_passes::*;
use leo_span::source_map::FileName;
use leo_span::symbol::with_session_globals;
use leo_span::{source_map::FileName, symbol::with_session_globals};
use sha2::{Digest, Sha256};
use std::fs;
use std::path::PathBuf;
use std::{fs, path::PathBuf};
use crate::CompilerOptions;
@ -273,10 +270,7 @@ impl<'a> Compiler<'a> {
fn write_ast_to_json(&self, file_suffix: &str) -> Result<()> {
// Remove `Span`s if they are not enabled.
if self.compiler_options.spans_enabled {
self.ast.to_json_file(
self.output_directory.clone(),
&format!("{}.{file_suffix}", self.program_name),
)?;
self.ast.to_json_file(self.output_directory.clone(), &format!("{}.{file_suffix}", self.program_name))?;
} else {
self.ast.to_json_file_without_keys(
self.output_directory.clone(),

View File

@ -29,8 +29,7 @@ use snarkvm::prelude::*;
use crate::utilities::{get_cwd_option, hash_asts, hash_content, setup_build_directory};
use serde::{Deserialize, Serialize};
use serde_yaml::Value;
use std::rc::Rc;
use std::{fs, path::Path};
use std::{fs, path::Path, rc::Rc};
struct CompileNamespace;

View File

@ -15,8 +15,16 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
mod utilities;
use utilities::{buffer_if_err, compile_and_process, parse_program, BufferEmitter};
use utilities::{get_cwd_option, setup_build_directory, Aleo, Network};
use utilities::{
buffer_if_err,
compile_and_process,
get_cwd_option,
parse_program,
setup_build_directory,
Aleo,
BufferEmitter,
Network,
};
use crate::utilities::{hash_asts, hash_content};
@ -27,15 +35,13 @@ use leo_test_framework::{
Test,
};
use snarkvm::console;
use snarkvm::prelude::*;
use snarkvm::{console, prelude::*};
use leo_test_framework::test::TestExpectationMode;
use regex::Regex;
use serde::{Deserialize, Serialize};
use serde_yaml::Value;
use std::collections::BTreeMap;
use std::{fs, path::Path, rc::Rc};
use std::{collections::BTreeMap, fs, path::Path, rc::Rc};
// TODO: Evaluate namespace.
struct ExecuteNamespace;
@ -69,10 +75,7 @@ struct ExecuteOutput {
fn run_test(test: Test, handler: &Handler, err_buf: &BufferEmitter) -> Result<Value, ()> {
// Check that config expectation is always pass.
if test.config.expectation != TestExpectationMode::Pass {
buffer_if_err(
err_buf,
Err("Test expectation must be `Pass` for `Execute` tests.".to_string()),
)?;
buffer_if_err(err_buf, Err("Test expectation must be `Pass` for `Execute` tests.".to_string()))?;
}
// Check for CWD option:
@ -86,13 +89,8 @@ fn run_test(test: Test, handler: &Handler, err_buf: &BufferEmitter) -> Result<Va
let bytecode = handler.extend_if_error(compile_and_process(&mut parsed))?;
// Extract the cases from the test config.
let all_cases = test
.config
.extra
.get("cases")
.expect("An `Execute` config must have a `cases` field.")
.as_mapping()
.unwrap();
let all_cases =
test.config.extra.get("cases").expect("An `Execute` config must have a `cases` field.").as_mapping().unwrap();
// Initialize a map for the expected results.
let mut results = BTreeMap::new();

View File

@ -17,7 +17,8 @@
use leo_compiler::{Compiler, CompilerOptions};
use leo_errors::{
emitter::{Buffer, Emitter, Handler},
LeoError, LeoWarning,
LeoError,
LeoWarning,
};
use leo_passes::{CodeGenerator, Pass};
use leo_span::source_map::FileName;
@ -25,12 +26,11 @@ use leo_test_framework::Test;
use snarkvm::prelude::*;
use snarkvm::file::Manifest;
use snarkvm::package::Package;
use std::fs::File;
use snarkvm::{file::Manifest, package::Package};
use std::{
cell::RefCell,
fs,
fs::File,
path::{Path, PathBuf},
rc::Rc,
};
@ -152,10 +152,7 @@ impl Display for LeoOrString {
/// A buffer used to emit errors into.
#[derive(Clone)]
pub struct BufferEmitter(
pub Rc<RefCell<Buffer<LeoOrString>>>,
pub Rc<RefCell<Buffer<LeoWarning>>>,
);
pub struct BufferEmitter(pub Rc<RefCell<Buffer<LeoOrString>>>, pub Rc<RefCell<Buffer<LeoWarning>>>);
impl Emitter for BufferEmitter {
fn emit_err(&mut self, err: LeoError) {
@ -181,9 +178,7 @@ pub fn buffer_if_err<T>(buf: &BufferEmitter, res: Result<T, String>) -> Result<T
}
pub fn temp_dir() -> PathBuf {
tempfile::tempdir()
.expect("Failed to open temporary directory")
.into_path()
tempfile::tempdir().expect("Failed to open temporary directory").into_path()
}
pub fn compile_and_process<'a>(parsed: &'a mut Compiler<'a>) -> Result<String, LeoError> {

View File

@ -26,10 +26,7 @@ use std::{
};
#[derive(Debug, StructOpt)]
#[structopt(
name = "input parser",
about = "Parse an Input file and save its JSON representation"
)]
#[structopt(name = "input parser", about = "Parse an Input file and save its JSON representation")]
struct Opt {
/// Path to the input file.
#[structopt(parse(from_os_str))]
@ -47,10 +44,7 @@ struct Opt {
fn main() -> Result<(), String> {
let opt = Opt::parse();
let input_tree = create_session_if_not_set_then(|s| {
let input_string = s
.source_map
.load_file(&opt.input_path)
.expect("failed to open an input file");
let input_string = s.source_map.load_file(&opt.input_path).expect("failed to open an input file");
Handler::with(|handler| {
let input = leo_parser::parse_program_inputs(handler, &input_string.src, input_string.start_pos)?;
@ -64,11 +58,7 @@ fn main() -> Result<(), String> {
}
let out_path = if let Some(out_dir) = opt.out_dir_path {
format!(
"{}/{}.json",
out_dir.as_path().display(),
opt.input_path.file_stem().unwrap().to_str().unwrap()
)
format!("{}/{}.json", out_dir.as_path().display(), opt.input_path.file_stem().unwrap().to_str().unwrap())
} else {
format!("./{}.json", opt.input_path.file_stem().unwrap().to_str().unwrap())
};

View File

@ -62,11 +62,7 @@ fn main() -> Result<(), String> {
}
let out_path = if let Some(out_dir) = opt.out_dir_path {
format!(
"{}/{}.json",
out_dir.as_path().display(),
opt.input_path.file_stem().unwrap().to_str().unwrap()
)
format!("{}/{}.json", out_dir.as_path().display(), opt.input_path.file_stem().unwrap().to_str().unwrap())
} else {
format!("./{}.json", opt.input_path.file_stem().unwrap().to_str().unwrap())
};

View File

@ -32,8 +32,7 @@ pub mod parser;
pub use parser::*;
use leo_ast::{input::InputData, Ast, ProgramInput};
use leo_errors::emitter::Handler;
use leo_errors::Result;
use leo_errors::{emitter::Handler, Result};
#[cfg(test)]
mod test;

View File

@ -17,12 +17,10 @@
use crate::{tokenizer::*, Token};
use leo_ast::*;
use leo_errors::emitter::Handler;
use leo_errors::{ParserError, ParserWarning, Result};
use leo_errors::{emitter::Handler, ParserError, ParserWarning, Result};
use leo_span::{Span, Symbol};
use std::fmt::Display;
use std::mem;
use std::{fmt::Display, mem};
/// Stores a program in tokenized format plus additional context.
/// May be converted into a [`Program`] AST by parsing all tokens.
@ -44,10 +42,7 @@ pub(crate) struct ParserContext<'a> {
}
/// Dummy span used to appease borrow checker.
const DUMMY_EOF: SpannedToken = SpannedToken {
token: Token::Eof,
span: Span::dummy(),
};
const DUMMY_EOF: SpannedToken = SpannedToken { token: Token::Eof, span: Span::dummy() };
impl<'a> ParserContext<'a> {
/// Returns a new [`ParserContext`] type given a vector of tokens.
@ -81,10 +76,7 @@ impl<'a> ParserContext<'a> {
}
// Extract next token, or `Eof` if there was none.
let next_token = self.tokens.pop().unwrap_or(SpannedToken {
token: Token::Eof,
span: self.token.span,
});
let next_token = self.tokens.pop().unwrap_or(SpannedToken { token: Token::Eof, span: self.token.span });
// Set the new token.
self.prev_token = mem::replace(&mut self.token, next_token);
@ -183,11 +175,7 @@ impl<'a> ParserContext<'a> {
/// Eats the expected `token`, or errors.
pub(super) fn expect(&mut self, token: &Token) -> Result<Span> {
if self.eat(token) {
Ok(self.prev_token.span)
} else {
self.unexpected(token)
}
if self.eat(token) { Ok(self.prev_token.span) } else { self.unexpected(token) }
}
/// Eats one of the expected `tokens`, or errors.

View File

@ -215,10 +215,7 @@ impl ParserContext<'_> {
///
/// Otherwise, tries to parse the next token using [`parse_exponential_expression`].
fn parse_multiplicative_expression(&mut self) -> Result<Expression> {
self.parse_bin_expr(
&[Token::Mul, Token::Div, Token::Rem],
Self::parse_exponential_expression,
)
self.parse_bin_expr(&[Token::Mul, Token::Div, Token::Rem], Self::parse_exponential_expression)
}
/// Returns an [`Expression`] AST node if the next tokens represent a
@ -266,11 +263,7 @@ impl ParserContext<'_> {
Expression::Literal(Literal::Integer(integer_type, format!("-{string}"), op_span + span))
}
// Otherwise, produce a unary expression.
_ => Expression::Unary(UnaryExpression {
span: op_span + inner.span(),
op,
receiver: Box::new(inner),
}),
_ => Expression::Unary(UnaryExpression { span: op_span + inner.span(), op, receiver: Box::new(inner) }),
};
}
Ok(inner)
@ -285,11 +278,7 @@ impl ParserContext<'_> {
if let (true, Some(op)) = (args.is_empty(), UnaryOperation::from_symbol(method.name)) {
// Found an unary operator and the argument list is empty.
Ok(Expression::Unary(UnaryExpression {
span,
op,
receiver: Box::new(receiver),
}))
Ok(Expression::Unary(UnaryExpression { span, op, receiver: Box::new(receiver) }))
} else if let (1, Some(op)) = (args.len(), BinaryOperation::from_symbol(method.name)) {
// Found a binary operator and the argument list contains a single argument.
Ok(Expression::Binary(BinaryExpression {
@ -359,11 +348,8 @@ impl ParserContext<'_> {
if self.check_int() {
// Eat a tuple member access.
let (index, span) = self.eat_integer()?;
expr = Expression::Access(AccessExpression::Tuple(TupleAccess {
tuple: Box::new(expr),
index,
span,
}))
expr =
Expression::Access(AccessExpression::Tuple(TupleAccess { tuple: Box::new(expr), index, span }))
} else if self.eat(&Token::Leo) {
// Eat an external function call.
self.eat(&Token::Div); // todo: Make `/` a more general token.
@ -484,11 +470,7 @@ impl ParserContext<'_> {
let end_span = check_ahead(dist, &Token::Group)?;
dist += 1; // Standing at `)` so advance one for 'group'.
let gt = GroupTuple {
span: start_span + &end_span,
x: first_gc,
y: second_gc,
};
let gt = GroupTuple { span: start_span + &end_span, x: first_gc, y: second_gc };
// Eat everything so that this isn't just peeking.
for _ in 0..dist {
@ -525,15 +507,10 @@ impl ParserContext<'_> {
/// struct initialization expression.
/// let foo = Foo { x: 1u8 };
pub fn parse_struct_init_expression(&mut self, identifier: Identifier) -> Result<Expression> {
let (members, _, end) = self.parse_list(Delimiter::Brace, Some(Token::Comma), |p| {
p.parse_struct_member().map(Some)
})?;
let (members, _, end) =
self.parse_list(Delimiter::Brace, Some(Token::Comma), |p| p.parse_struct_member().map(Some))?;
Ok(Expression::Struct(StructExpression {
span: identifier.span + end,
name: identifier,
members,
}))
Ok(Expression::Struct(StructExpression { span: identifier.span + end, name: identifier, members }))
}
/// Returns an [`Expression`] AST node if the next token is a primary expression:
@ -600,14 +577,10 @@ impl ParserContext<'_> {
Expression::Identifier(ident)
}
}
Token::SelfLower => Expression::Identifier(Identifier {
name: sym::SelfLower,
span,
}),
t if crate::type_::TYPE_TOKENS.contains(&t) => Expression::Identifier(Identifier {
name: t.keyword_to_symbol().unwrap(),
span,
}),
Token::SelfLower => Expression::Identifier(Identifier { name: sym::SelfLower, span }),
t if crate::type_::TYPE_TOKENS.contains(&t) => {
Expression::Identifier(Identifier { name: t.keyword_to_symbol().unwrap(), span })
}
token => {
return Err(ParserError::unexpected_str(token, "expression", span).into());
}

View File

@ -17,8 +17,7 @@
use super::*;
use crate::parse_ast;
use leo_errors::{CompilerError, ParserError, Result};
use leo_span::source_map::FileName;
use leo_span::symbol::with_session_globals;
use leo_span::{source_map::FileName, symbol::with_session_globals};
use std::fs;
@ -57,10 +56,7 @@ impl ParserContext<'_> {
return Err(ParserError::missing_program_scope(self.token.span).into());
}
Ok(Program {
imports,
program_scopes,
})
Ok(Program { imports, program_scopes })
}
fn unexpected_item(token: &SpannedToken, expected: &[Token]) -> ParserError {
@ -162,19 +158,16 @@ impl ParserContext<'_> {
}
Token::RightCurly => break,
_ => {
return Err(Self::unexpected_item(
&self.token,
&[
Token::Struct,
Token::Record,
Token::Mapping,
Token::At,
Token::Function,
Token::Transition,
Token::Inline,
],
)
.into())
return Err(Self::unexpected_item(&self.token, &[
Token::Struct,
Token::Record,
Token::Mapping,
Token::At,
Token::Function,
Token::Transition,
Token::Inline,
])
.into());
}
}
}
@ -182,13 +175,7 @@ impl ParserContext<'_> {
// Parse `}`.
let end = self.expect(&Token::RightCurly)?;
Ok(ProgramScope {
program_id,
functions,
structs,
mappings,
span: start + end,
})
Ok(ProgramScope { program_id, functions, structs, mappings, span: start + end })
}
/// Returns a [`Vec<Member>`] AST node if the next tokens represent a struct member.
@ -236,12 +223,7 @@ impl ParserContext<'_> {
let (identifier, type_, span) = self.parse_typed_ident()?;
Ok(Member {
mode,
identifier,
type_,
span,
})
Ok(Member { mode, identifier, type_, span })
}
/// Parses a struct or record definition, e.g., `struct Foo { ... }` or `record Foo { ... }`.
@ -253,15 +235,7 @@ impl ParserContext<'_> {
self.expect(&Token::LeftCurly)?;
let (members, end) = self.parse_struct_members()?;
Ok((
struct_name.name,
Struct {
identifier: struct_name,
members,
is_record,
span: start + end,
},
))
Ok((struct_name.name, Struct { identifier: struct_name, members, is_record, span: start + end }))
}
/// Parses a mapping declaration, e.g. `mapping balances: address => u128`.
@ -273,15 +247,7 @@ impl ParserContext<'_> {
self.expect(&Token::BigArrow)?;
let (value_type, _) = self.parse_type()?;
let end = self.expect(&Token::Semicolon)?;
Ok((
identifier.name,
Mapping {
identifier,
key_type,
value_type,
span: start + end,
},
))
Ok((identifier.name, Mapping { identifier, key_type, value_type, span: start + end }))
}
// TODO: Return a span associated with the mode.
@ -332,21 +298,11 @@ impl ParserContext<'_> {
self.eat(&Token::Record);
span = span + self.prev_token.span;
Ok(functions::Input::External(External {
identifier: name,
program_name: external,
record,
span,
}))
Ok(functions::Input::External(External { identifier: name, program_name: external, record, span }))
} else {
let type_ = self.parse_type()?.0;
Ok(functions::Input::Internal(FunctionInput {
identifier: name,
mode,
type_,
span: name.span,
}))
Ok(functions::Input::Internal(FunctionInput { identifier: name, mode, type_, span: name.span }))
}
}
@ -389,10 +345,7 @@ impl ParserContext<'_> {
}
fn peek_is_external(&self) -> bool {
matches!(
(&self.token.token, self.look_ahead(1, |t| &t.token)),
(Token::Identifier(_), Token::Dot)
)
matches!((&self.token.token, self.look_ahead(1, |t| &t.token)), (Token::Identifier(_), Token::Dot))
}
/// Returns an [`Annotation`] AST node if the next tokens represent an annotation.
@ -400,10 +353,7 @@ impl ParserContext<'_> {
// Parse the `@` symbol and identifier.
let start = self.expect(&Token::At)?;
let identifier = match self.token.token {
Token::Program => Identifier {
name: sym::program,
span: self.expect(&Token::Program)?,
},
Token::Program => Identifier { name: sym::program, span: self.expect(&Token::Program)? },
_ => self.expect_identifier()?,
};
let span = start + identifier.span;
@ -490,10 +440,7 @@ impl ParserContext<'_> {
};
let span = start + block.span;
Ok((
name.name,
Function::new(annotations, variant, name, inputs, output, block, finalize, span),
))
Ok((name.name, Function::new(annotations, variant, name, inputs, output, block, finalize, span)))
}
}

View File

@ -55,11 +55,7 @@ impl ParserContext<'_> {
definitions.push(self.parse_input_definition()?);
}
Ok(Section {
name: section.name,
span: section.span,
definitions,
})
Ok(Section { name: section.name, span: section.span, definitions })
}
/// Parses a single parameter definition:
@ -75,12 +71,6 @@ impl ParserContext<'_> {
let value = self.parse_unary_expression()?;
self.expect(&Token::Semicolon)?;
Ok(Definition {
mode,
name,
type_,
value,
span,
})
Ok(Definition { mode, name, type_, value, span })
}
}

View File

@ -22,8 +22,7 @@
use crate::{tokenizer::*, Token};
use leo_ast::*;
use leo_errors::emitter::Handler;
use leo_errors::Result;
use leo_errors::{emitter::Handler, Result};
use leo_span::Span;
use indexmap::IndexMap;

View File

@ -133,10 +133,7 @@ impl ParserContext<'_> {
} else {
// Parse the expression as a statement.
let end = self.expect(&Token::Semicolon)?;
Ok(Statement::Expression(ExpressionStatement {
span: place.span() + end,
expression: place,
}))
Ok(Statement::Expression(ExpressionStatement { span: place.span() + end, expression: place }))
}
}
@ -174,11 +171,7 @@ impl ParserContext<'_> {
};
let end = self.expect(&Token::Semicolon)?;
let span = start + end;
Ok(ReturnStatement {
span,
expression,
finalize_arguments: finalize_args,
})
Ok(ReturnStatement { span, expression, finalize_arguments: finalize_args })
}
/// Returns a [`DecrementStatement`] AST node if the next tokens represent a decrement statement.
@ -194,12 +187,7 @@ impl ParserContext<'_> {
let end = self.expect(&Token::RightParen)?;
self.expect(&Token::Semicolon)?;
let span = start + end;
Ok(DecrementStatement {
mapping,
index,
amount,
span,
})
Ok(DecrementStatement { mapping, index, amount, span })
}
/// Returns an [`IncrementStatement`] AST node if the next tokens represent an increment statement.
@ -215,12 +203,7 @@ impl ParserContext<'_> {
let end = self.expect(&Token::RightParen)?;
self.expect(&Token::Semicolon)?;
let span = start + end;
Ok(IncrementStatement {
mapping,
index,
amount,
span,
})
Ok(IncrementStatement { mapping, index, amount, span })
}
/// Returns a [`ConditionalStatement`] AST node if the next tokens represent a conditional statement.
@ -316,18 +299,13 @@ impl ParserContext<'_> {
));
(
Default::default(),
ConsoleFunction::Assert(Expression::Err(ErrExpression {
span: Default::default(),
})),
ConsoleFunction::Assert(Expression::Err(ErrExpression { span: Default::default() })),
)
}
};
self.expect(&Token::Semicolon)?;
Ok(ConsoleStatement {
span: keyword + span,
function,
})
Ok(ConsoleStatement { span: keyword + span, function })
}
/// Returns a [`DefinitionStatement`] AST node if the next tokens represent a definition statement.
@ -349,12 +327,6 @@ impl ParserContext<'_> {
let value = self.parse_expression()?;
self.expect(&Token::Semicolon)?;
Ok(DefinitionStatement {
span: decl_span + value.span(),
declaration_type: decl_type,
place,
type_,
value,
})
Ok(DefinitionStatement { span: decl_span + value.span(), declaration_type: decl_type, place, type_, value })
}
}

View File

@ -40,13 +40,7 @@ impl Namespace for TokenNamespace {
fn run_test(&self, test: Test) -> Result<Value, String> {
create_session_if_not_set_then(|s| {
tokenize(test, s).map(|tokens| {
Value::String(
tokens
.into_iter()
.map(|x| x.to_string())
.collect::<Vec<String>>()
.join(","),
)
Value::String(tokens.into_iter().map(|x| x.to_string()).collect::<Vec<String>>().join(","))
})
})
}
@ -71,9 +65,7 @@ fn with_handler<T>(
) -> Result<T, String> {
let (handler, buf) = Handler::new_with_buf();
let mut tokens = ParserContext::new(&handler, tokens);
let parsed = handler
.extend_if_error(logic(&mut tokens))
.map_err(|_| buf.extract_errs().to_string())?;
let parsed = handler.extend_if_error(logic(&mut tokens)).map_err(|_| buf.extract_errs().to_string())?;
not_fully_consumed(&mut tokens)?;
Ok(parsed)
}
@ -84,9 +76,7 @@ fn tokenize(test: Test, s: &SessionGlobals) -> Result<Vec<SpannedToken>, String>
}
fn all_are_comments(tokens: &[SpannedToken]) -> bool {
tokens
.iter()
.all(|x| matches!(x.token, Token::CommentLine(_) | Token::CommentBlock(_)))
tokens.iter().all(|x| matches!(x.token, Token::CommentLine(_) | Token::CommentBlock(_)))
}
fn yaml_or_fail<T: Serialize>(value: T) -> Value {

View File

@ -196,11 +196,7 @@ impl Token {
// Otherwise, return the `first_token` that matches the one character.
let match_two = |input: &mut Peekable<_>, first_token, second_char, second_token| {
input.next();
Ok(if input.next_if_eq(&second_char).is_some() {
(2, second_token)
} else {
(1, first_token)
})
Ok(if input.next_if_eq(&second_char).is_some() { (2, second_token) } else { (1, first_token) })
};
// Returns one token matching one or two characters.
@ -281,7 +277,7 @@ impl Token {
Token::And,
'=',
Token::AndAssign,
)
);
}
'(' => return match_one(&mut input, Token::LeftParen),
')' => return match_one(&mut input, Token::RightParen),
@ -296,7 +292,7 @@ impl Token {
Token::Pow,
'=',
Token::PowAssign,
)
);
}
'+' => return match_two(&mut input, Token::Add, '=', Token::AddAssign),
',' => return match_one(&mut input, Token::Comma),
@ -350,30 +346,8 @@ impl Token {
'%' => return match_two(&mut input, Token::Rem, '=', Token::RemAssign),
':' => return match_two(&mut input, Token::Colon, ':', Token::DoubleColon),
';' => return match_one(&mut input, Token::Semicolon),
'<' => {
return match_four(
&mut input,
Token::Lt,
'=',
Token::LtEq,
'<',
Token::Shl,
'=',
Token::ShlAssign,
)
}
'>' => {
return match_four(
&mut input,
Token::Gt,
'=',
Token::GtEq,
'>',
Token::Shr,
'=',
Token::ShrAssign,
)
}
'<' => return match_four(&mut input, Token::Lt, '=', Token::LtEq, '<', Token::Shl, '=', Token::ShlAssign),
'>' => return match_four(&mut input, Token::Gt, '=', Token::GtEq, '>', Token::Shr, '=', Token::ShrAssign),
'=' => return match_three(&mut input, Token::Assign, '=', Token::Eq, '>', Token::BigArrow),
'[' => return match_one(&mut input, Token::LeftSquare),
']' => return match_one(&mut input, Token::RightSquare),
@ -389,7 +363,7 @@ impl Token {
Token::Or,
'=',
Token::OrAssign,
)
);
}
'^' => return match_two(&mut input, Token::BitXor, '=', Token::BitXorAssign),
'@' => return Ok((1, Token::At)),
@ -451,12 +425,8 @@ impl Token {
));
}
Err(ParserError::could_not_lex(
input
.take_while(|c| *c != ';' && !c.is_whitespace())
.collect::<String>(),
)
.into())
Err(ParserError::could_not_lex(input.take_while(|c| *c != ';' && !c.is_whitespace()).collect::<String>())
.into())
}
}
@ -469,10 +439,7 @@ pub struct SpannedToken {
impl SpannedToken {
/// Returns a dummy token at a dummy span.
pub const fn dummy() -> Self {
Self {
token: Token::Question,
span: Span::dummy(),
}
Self { token: Token::Question, span: Span::dummy() }
}
}

View File

@ -14,8 +14,7 @@
// 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/>.
use crate::SymbolTable;
use crate::{CallGraph, StructGraph};
use crate::{CallGraph, StructGraph, SymbolTable};
use leo_ast::Function;
use leo_span::Symbol;

View File

@ -25,8 +25,7 @@ mod visit_statements;
mod visit_type;
use crate::SymbolTable;
use crate::{CallGraph, Pass, StructGraph};
use crate::{CallGraph, Pass, StructGraph, SymbolTable};
use leo_ast::Ast;
use leo_errors::Result;

View File

@ -16,9 +16,23 @@
use crate::CodeGenerator;
use leo_ast::{
AccessExpression, AssociatedFunction, BinaryExpression, BinaryOperation, CallExpression, ErrExpression, Expression,
Identifier, Literal, MemberAccess, StructExpression, TernaryExpression, TupleExpression, Type, UnaryExpression,
UnaryOperation, UnitExpression,
AccessExpression,
AssociatedFunction,
BinaryExpression,
BinaryOperation,
CallExpression,
ErrExpression,
Expression,
Identifier,
Literal,
MemberAccess,
StructExpression,
TernaryExpression,
TupleExpression,
Type,
UnaryExpression,
UnaryOperation,
UnitExpression,
};
use leo_span::sym;
use std::borrow::Borrow;
@ -287,13 +301,7 @@ impl<'a> CodeGenerator<'a> {
Expression::Identifier(identifier) => identifier.name,
_ => unreachable!("Parsing guarantees that all `input.function` is always an identifier."),
};
let return_type = &self
.symbol_table
.borrow()
.functions
.get(&function_name)
.unwrap()
.output_type;
let return_type = &self.symbol_table.borrow().functions.get(&function_name).unwrap().output_type;
match return_type {
Type::Unit => {
call_instruction.push(';');

View File

@ -76,13 +76,7 @@ impl<'a> CodeGenerator<'a> {
program_string.push('\n');
// Visit each mapping in the Leo AST and produce an Aleo mapping declaration.
program_string.push_str(
&program_scope
.mappings
.values()
.map(|mapping| self.visit_mapping(mapping))
.join("\n"),
);
program_string.push_str(&program_scope.mappings.values().map(|mapping| self.visit_mapping(mapping)).join("\n"));
// Visit each function in the program scope and produce an Aleo function.
// Note that in the function inlining pass, we reorder the functions such that they are in post-order.
@ -118,17 +112,12 @@ impl<'a> CodeGenerator<'a> {
}
fn visit_struct_or_record(&mut self, struct_: &'a Struct) -> String {
if struct_.is_record {
self.visit_record(struct_)
} else {
self.visit_struct(struct_)
}
if struct_.is_record { self.visit_record(struct_) } else { self.visit_struct(struct_) }
}
fn visit_struct(&mut self, struct_: &'a Struct) -> String {
// Add private symbol to composite types.
self.composite_mapping
.insert(&struct_.identifier.name, (false, String::from("private"))); // todo: private by default here.
self.composite_mapping.insert(&struct_.identifier.name, (false, String::from("private"))); // todo: private by default here.
let mut output_string = format!("struct {}:\n", struct_.identifier); // todo: check if this is safe from name conflicts.
@ -143,8 +132,7 @@ impl<'a> CodeGenerator<'a> {
fn visit_record(&mut self, record: &'a Struct) -> String {
// Add record symbol to composite types.
let mut output_string = String::from("record");
self.composite_mapping
.insert(&record.identifier.name, (true, output_string.clone()));
self.composite_mapping.insert(&record.identifier.name, (true, output_string.clone()));
writeln!(output_string, " {}:", record.identifier).expect("failed to write to string"); // todo: check if this is safe from name conflicts.
// Construct and append the record variables.
@ -190,8 +178,7 @@ impl<'a> CodeGenerator<'a> {
let type_string = match input {
functions::Input::Internal(input) => {
self.variable_mapping
.insert(&input.identifier.name, register_string.clone());
self.variable_mapping.insert(&input.identifier.name, register_string.clone());
let visibility = match (self.is_transition_function, input.mode) {
(true, Mode::None) => Mode::Private,
_ => input.mode,
@ -199,8 +186,7 @@ impl<'a> CodeGenerator<'a> {
self.visit_type_with_visibility(&input.type_, visibility)
}
functions::Input::External(input) => {
self.variable_mapping
.insert(&input.identifier.name, register_string.clone());
self.variable_mapping.insert(&input.identifier.name, register_string.clone());
format!("{}.aleo/{}.record", input.program_name, input.record)
}
};
@ -234,8 +220,7 @@ impl<'a> CodeGenerator<'a> {
// TODO: Dedup code.
let type_string = match input {
functions::Input::Internal(input) => {
self.variable_mapping
.insert(&input.identifier.name, register_string.clone());
self.variable_mapping.insert(&input.identifier.name, register_string.clone());
let visibility = match (self.is_transition_function, input.mode) {
(true, Mode::None) => Mode::Public,
@ -244,8 +229,7 @@ impl<'a> CodeGenerator<'a> {
self.visit_type_with_visibility(&input.type_, visibility)
}
functions::Input::External(input) => {
self.variable_mapping
.insert(&input.program_name.name, register_string.clone());
self.variable_mapping.insert(&input.program_name.name, register_string.clone());
format!("{}.aleo/{}.record", input.program_name, input.record)
}
};

View File

@ -17,9 +17,22 @@
use crate::CodeGenerator;
use leo_ast::{
AssertStatement, AssertVariant, AssignStatement, Block, ConditionalStatement, ConsoleStatement, DecrementStatement,
DefinitionStatement, Expression, ExpressionStatement, IncrementStatement, IterationStatement, Mode, Output,
ReturnStatement, Statement,
AssertStatement,
AssertVariant,
AssignStatement,
Block,
ConditionalStatement,
ConsoleStatement,
DecrementStatement,
DefinitionStatement,
Expression,
ExpressionStatement,
IncrementStatement,
IterationStatement,
Mode,
Output,
ReturnStatement,
Statement,
};
use itertools::Itertools;

View File

@ -48,10 +48,7 @@ impl Assigner {
// Create a new variable for the expression.
let name = self.unique_symbol("$var", "$");
let place = Identifier {
name,
span: Default::default(),
};
let place = Identifier { name, span: Default::default() };
(place, self.simple_assign_statement(place, expr))
}

View File

@ -17,8 +17,7 @@
use leo_span::Symbol;
use indexmap::{IndexMap, IndexSet};
use std::fmt::Debug;
use std::hash::Hash;
use std::{fmt::Debug, hash::Hash};
/// A struct dependency graph.
pub type StructGraph = DiGraph<Symbol>;
@ -54,10 +53,7 @@ pub struct DiGraph<N: Node> {
impl<N: Node> DiGraph<N> {
/// Initializes a new `DiGraph` from a vector of source nodes.
pub fn new(nodes: IndexSet<N>) -> Self {
Self {
nodes,
edges: IndexMap::new(),
}
Self { nodes, edges: IndexMap::new() }
}
/// Adds an edge to the graph.

View File

@ -30,10 +30,7 @@ pub struct RenameTable {
impl RenameTable {
/// Create a new `RenameTable` with the given parent.
pub(crate) fn new(parent: Option<Box<RenameTable>>) -> Self {
Self {
parent,
mapping: IndexMap::new(),
}
Self { parent, mapping: IndexMap::new() }
}
/// Returns the symbols that were renamed in the current scope.

View File

@ -146,11 +146,7 @@ impl SymbolTable {
/// Returns true if the variable exists in any parent scope
pub fn variable_in_parent_scope(&self, symbol: Symbol) -> bool {
if let Some(parent) = self.parent.as_ref() {
if parent.variables.contains_key(&symbol) {
true
} else {
parent.variable_in_parent_scope(symbol)
}
if parent.variables.contains_key(&symbol) { true } else { parent.variable_in_parent_scope(symbol) }
} else {
false
}

View File

@ -29,9 +29,6 @@ pub struct DeadCodeEliminator {
impl DeadCodeEliminator {
/// Initializes a new `DeadCodeEliminator`.
pub fn new() -> Self {
Self {
used_variables: Default::default(),
is_necessary: false,
}
Self { used_variables: Default::default(), is_necessary: false }
}
}

View File

@ -17,9 +17,22 @@
use crate::DeadCodeEliminator;
use leo_ast::{
AssertStatement, AssertVariant, AssignStatement, Block, ConditionalStatement, ConsoleStatement, DecrementStatement,
DefinitionStatement, Expression, ExpressionReconstructor, ExpressionStatement, IncrementStatement,
IterationStatement, ReturnStatement, Statement, StatementReconstructor,
AssertStatement,
AssertVariant,
AssignStatement,
Block,
ConditionalStatement,
ConsoleStatement,
DecrementStatement,
DefinitionStatement,
Expression,
ExpressionReconstructor,
ExpressionStatement,
IncrementStatement,
IterationStatement,
ReturnStatement,
Statement,
StatementReconstructor,
};
impl StatementReconstructor for DeadCodeEliminator {
@ -31,14 +44,12 @@ impl StatementReconstructor for DeadCodeEliminator {
let statement = Statement::Assert(AssertStatement {
variant: match input.variant {
AssertVariant::Assert(expr) => AssertVariant::Assert(self.reconstruct_expression(expr).0),
AssertVariant::AssertEq(left, right) => AssertVariant::AssertEq(
self.reconstruct_expression(left).0,
self.reconstruct_expression(right).0,
),
AssertVariant::AssertNeq(left, right) => AssertVariant::AssertNeq(
self.reconstruct_expression(left).0,
self.reconstruct_expression(right).0,
),
AssertVariant::AssertEq(left, right) => {
AssertVariant::AssertEq(self.reconstruct_expression(left).0, self.reconstruct_expression(right).0)
}
AssertVariant::AssertNeq(left, right) => {
AssertVariant::AssertNeq(self.reconstruct_expression(left).0, self.reconstruct_expression(right).0)
}
},
span: input.span,
});
@ -95,23 +106,13 @@ impl StatementReconstructor for DeadCodeEliminator {
/// Reconstructs the statements inside a basic block, eliminating any dead code.
fn reconstruct_block(&mut self, block: Block) -> (Block, Self::AdditionalOutput) {
// Reconstruct each of the statements in reverse.
let mut statements: Vec<Statement> = block
.statements
.into_iter()
.rev()
.map(|statement| self.reconstruct_statement(statement).0)
.collect();
let mut statements: Vec<Statement> =
block.statements.into_iter().rev().map(|statement| self.reconstruct_statement(statement).0).collect();
// Reverse the direction of `statements`.
statements.reverse();
(
Block {
statements,
span: block.span,
},
Default::default(),
)
(Block { statements, span: block.span }, Default::default())
}
/// Flattening removes conditional statements from the program.
@ -200,10 +201,7 @@ impl StatementReconstructor for DeadCodeEliminator {
let statement = Statement::Return(ReturnStatement {
expression: self.reconstruct_expression(input.expression).0,
finalize_arguments: input.finalize_arguments.map(|arguments| {
arguments
.into_iter()
.map(|argument| self.reconstruct_expression(argument).0)
.collect()
arguments.into_iter().map(|argument| self.reconstruct_expression(argument).0).collect()
}),
span: input.span,
});

View File

@ -18,8 +18,17 @@ use crate::Flattener;
use itertools::Itertools;
use leo_ast::{
AccessExpression, AssociatedFunction, Expression, ExpressionReconstructor, Member, MemberAccess, Statement,
StructExpression, StructVariableInitializer, TernaryExpression, TupleExpression,
AccessExpression,
AssociatedFunction,
Expression,
ExpressionReconstructor,
Member,
MemberAccess,
Statement,
StructExpression,
StructVariableInitializer,
TernaryExpression,
TupleExpression,
};
// TODO: Clean up logic. To be done in a follow-up PR (feat/tuples)
@ -36,11 +45,7 @@ impl ExpressionReconstructor for Flattener<'_> {
Expression::Access(AccessExpression::AssociatedFunction(AssociatedFunction {
ty: function.ty,
name: function.name,
args: function
.args
.into_iter()
.map(|arg| self.reconstruct_expression(arg).0)
.collect(),
args: function.args.into_iter().map(|arg| self.reconstruct_expression(arg).0).collect(),
span: function.span,
}))
}
@ -83,20 +88,10 @@ impl ExpressionReconstructor for Flattener<'_> {
// Accumulate any statements produced.
statements.extend(stmts);
// Accumulate the struct members.
members.push(StructVariableInitializer {
identifier: member.identifier,
expression: Some(expr),
});
members.push(StructVariableInitializer { identifier: member.identifier, expression: Some(expr) });
}
(
Expression::Struct(StructExpression {
name: input.name,
members,
span: input.span,
}),
statements,
)
(Expression::Struct(StructExpression { name: input.name, members, span: input.span }), statements)
}
/// Reconstructs ternary expressions over tuples and structs, accumulating any statements that are generated.
@ -224,8 +219,7 @@ impl ExpressionReconstructor for Flattener<'_> {
let (identifier, statement) = self.unique_simple_assign_statement(expr);
// Mark the lhs of the assignment as a struct.
self.structs
.insert(identifier.name, first_member_struct.identifier.name);
self.structs.insert(identifier.name, first_member_struct.identifier.name);
statements.push(statement);
@ -261,14 +255,8 @@ impl ExpressionReconstructor for Flattener<'_> {
(Expression::Identifier(first), Expression::Identifier(second))
if self.structs.contains_key(&first.name) && self.structs.contains_key(&second.name) =>
{
let first_struct = self
.symbol_table
.lookup_struct(*self.structs.get(&first.name).unwrap())
.unwrap();
let second_struct = self
.symbol_table
.lookup_struct(*self.structs.get(&second.name).unwrap())
.unwrap();
let first_struct = self.symbol_table.lookup_struct(*self.structs.get(&first.name).unwrap()).unwrap();
let second_struct = self.symbol_table.lookup_struct(*self.structs.get(&second.name).unwrap()).unwrap();
// Note that type checking guarantees that both expressions have the same same type. This is a sanity check.
assert_eq!(first_struct, second_struct);

View File

@ -19,9 +19,27 @@ use itertools::Itertools;
use std::borrow::Borrow;
use leo_ast::{
AssertStatement, AssertVariant, AssignStatement, BinaryExpression, BinaryOperation, Block, ConditionalStatement,
ConsoleStatement, DefinitionStatement, Expression, ExpressionReconstructor, Identifier, IterationStatement, Node,
ReturnStatement, Statement, StatementReconstructor, TupleExpression, Type, UnaryExpression, UnaryOperation,
AssertStatement,
AssertVariant,
AssignStatement,
BinaryExpression,
BinaryOperation,
Block,
ConditionalStatement,
ConsoleStatement,
DefinitionStatement,
Expression,
ExpressionReconstructor,
Identifier,
IterationStatement,
Node,
ReturnStatement,
Statement,
StatementReconstructor,
TupleExpression,
Type,
UnaryExpression,
UnaryOperation,
};
impl StatementReconstructor for Flattener<'_> {
@ -135,10 +153,7 @@ impl StatementReconstructor for Flattener<'_> {
{
// Lookup the entry in `self.tuples` and add it for the lhs of the assignment.
// Note that the `unwrap` is safe since the match arm checks that the entry exists.
self.tuples.insert(
lhs_identifier.name,
self.tuples.get(&rhs_identifier.name).unwrap().clone(),
);
self.tuples.insert(lhs_identifier.name, self.tuples.get(&rhs_identifier.name).unwrap().clone());
// Note that tuple assignments are removed from the AST.
(Statement::dummy(Default::default()), statements)
}
@ -205,10 +220,7 @@ impl StatementReconstructor for Flattener<'_> {
}
(Expression::Identifier(identifier), expression) => {
self.update_structs(&identifier, &expression);
(
self.assigner.simple_assign_statement(identifier, expression),
statements,
)
(self.assigner.simple_assign_statement(identifier, expression), statements)
}
// If the lhs is a tuple and the rhs is a function call, then return the reconstructed statement.
(Expression::Tuple(tuple), Expression::Call(call)) => {
@ -226,22 +238,16 @@ impl StatementReconstructor for Flattener<'_> {
_ => unreachable!("Type checking guarantees that the output type is a tuple."),
};
tuple
.elements
.iter()
.zip_eq(output_type.0.iter())
.for_each(|(identifier, type_)| {
let identifier = match identifier {
Expression::Identifier(identifier) => identifier,
_ => unreachable!(
"Type checking guarantees that a tuple element on the lhs is an identifier."
),
};
// If the output type is a struct, add it to `self.structs`.
if let Type::Identifier(struct_name) = type_ {
self.structs.insert(identifier.name, struct_name.name);
}
});
tuple.elements.iter().zip_eq(output_type.0.iter()).for_each(|(identifier, type_)| {
let identifier = match identifier {
Expression::Identifier(identifier) => identifier,
_ => unreachable!("Type checking guarantees that a tuple element on the lhs is an identifier."),
};
// If the output type is a struct, add it to `self.structs`.
if let Type::Identifier(struct_name) = type_ {
self.structs.insert(identifier.name, struct_name.name);
}
});
(
Statement::Assign(Box::new(AssignStatement {
@ -318,13 +324,7 @@ impl StatementReconstructor for Flattener<'_> {
statements.push(reconstructed_statement);
}
(
Block {
span: block.span,
statements,
},
Default::default(),
)
(Block { span: block.span, statements }, Default::default())
}
/// Flatten a conditional statement into a list of statements.
@ -390,14 +390,11 @@ impl StatementReconstructor for Flattener<'_> {
Expression::Identifier(identifier) if self.tuples.contains_key(&identifier.name) => {
// Note that the `unwrap` is safe since the match arm checks that the entry exists in `self.tuples`.
let tuple = self.tuples.get(&identifier.name).unwrap().clone();
self.returns.push((
guard,
ReturnStatement {
span: input.span,
expression: Expression::Tuple(tuple),
finalize_arguments: input.finalize_arguments,
},
));
self.returns.push((guard, ReturnStatement {
span: input.span,
expression: Expression::Tuple(tuple),
finalize_arguments: input.finalize_arguments,
}));
}
// Otherwise, add the expression directly.
_ => self.returns.push((guard, input)),

View File

@ -17,8 +17,19 @@
use crate::{Assigner, SymbolTable};
use leo_ast::{
AccessExpression, BinaryExpression, BinaryOperation, Block, Expression, ExpressionReconstructor, Identifier,
Member, ReturnStatement, Statement, TernaryExpression, TupleExpression, Type,
AccessExpression,
BinaryExpression,
BinaryOperation,
Block,
Expression,
ExpressionReconstructor,
Identifier,
Member,
ReturnStatement,
Statement,
TernaryExpression,
TupleExpression,
Type,
};
use leo_span::Symbol;
@ -92,10 +103,7 @@ impl<'a> Flattener<'a> {
// Helper to construct and store ternary assignments. e.g `$ret$0 = $var$0 ? $var$1 : $var$2`
let mut construct_ternary_assignment = |guard: Expression, if_true: Expression, if_false: Expression| {
let place = Identifier {
name: self.assigner.unique_symbol(prefix, "$"),
span: Default::default(),
};
let place = Identifier { name: self.assigner.unique_symbol(prefix, "$"), span: Default::default() };
let (value, stmts) = self.reconstruct_ternary(TernaryExpression {
condition: Box::new(guard),
if_true: Box::new(if_true),
@ -116,14 +124,11 @@ impl<'a> Flattener<'a> {
}
};
let expression = guards
.into_iter()
.rev()
.fold(last_expression, |acc, (guard, expr)| match guard {
None => unreachable!("All expressions except for the last one must have a guard."),
// Note that type checking guarantees that all expressions have the same type.
Some(guard) => construct_ternary_assignment(guard, expr, acc),
});
let expression = guards.into_iter().rev().fold(last_expression, |acc, (guard, expr)| match guard {
None => unreachable!("All expressions except for the last one must have a guard."),
// Note that type checking guarantees that all expressions have the same type.
Some(guard) => construct_ternary_assignment(guard, expr, acc),
});
(expression, statements)
}
@ -136,11 +141,8 @@ impl<'a> Flattener<'a> {
// The inner expression of an access expression is either an identifier or another access expression.
let name = self.lookup_struct_symbol(&access.inner).unwrap();
let struct_ = self.symbol_table.lookup_struct(name).unwrap();
let Member { type_, .. } = struct_
.members
.iter()
.find(|member| member.name() == access.name.name)
.unwrap();
let Member { type_, .. } =
struct_.members.iter().find(|member| member.name() == access.name.name).unwrap();
match type_ {
Type::Identifier(identifier) => Some(identifier.name),
_ => None,

View File

@ -16,8 +16,18 @@
use crate::{Assigner, RenameTable};
use leo_ast::{
AssignStatement, ConditionalStatement, ConsoleStatement, DefinitionStatement, Expression, ExpressionReconstructor,
Identifier, IterationStatement, ProgramReconstructor, Statement, StatementReconstructor, StructExpression,
AssignStatement,
ConditionalStatement,
ConsoleStatement,
DefinitionStatement,
Expression,
ExpressionReconstructor,
Identifier,
IterationStatement,
ProgramReconstructor,
Statement,
StatementReconstructor,
StructExpression,
StructVariableInitializer,
};
use leo_span::Symbol;
@ -34,11 +44,7 @@ pub struct AssignmentRenamer {
impl AssignmentRenamer {
/// Initialize a new `AssignmentRenamer`.
pub fn new(assigner: Assigner) -> Self {
Self {
assigner,
rename_table: RenameTable::new(None),
is_lhs: false,
}
Self { assigner, rename_table: RenameTable::new(None), is_lhs: false }
}
/// Load the internal rename table with a set of entries.
@ -56,6 +62,7 @@ impl AssignmentRenamer {
impl ExpressionReconstructor for AssignmentRenamer {
type AdditionalOutput = ();
/// Rename the identifier if it is the left-hand side of an assignment, otherwise look up for a new name in the internal rename table.
fn reconstruct_identifier(&mut self, input: Identifier) -> (Expression, Self::AdditionalOutput) {
let name = match self.is_lhs {
@ -72,10 +79,7 @@ impl ExpressionReconstructor for AssignmentRenamer {
false => *self.rename_table.lookup(input.name).unwrap_or(&input.name),
};
(
Expression::Identifier(Identifier { name, span: input.span }),
Default::default(),
)
(Expression::Identifier(Identifier { name, span: input.span }), Default::default())
}
/// Rename the variable initializers in the struct expression.
@ -115,14 +119,7 @@ impl StatementReconstructor for AssignmentRenamer {
let place = self.reconstruct_expression(input.place).0;
self.is_lhs = false;
(
Statement::Assign(Box::new(AssignStatement {
place,
value,
span: input.span,
})),
Default::default(),
)
(Statement::Assign(Box::new(AssignStatement { place, value, span: input.span })), Default::default())
}
/// Flattening removes conditional statements from the program.

View File

@ -17,8 +17,15 @@
use crate::{FunctionInliner, Replacer};
use leo_ast::{
CallExpression, Expression, ExpressionReconstructor, Identifier, ReturnStatement, Statement,
StatementReconstructor, UnitExpression, Variant,
CallExpression,
Expression,
ExpressionReconstructor,
Identifier,
ReturnStatement,
Statement,
StatementReconstructor,
UnitExpression,
Variant,
};
use indexmap::IndexMap;
@ -56,12 +63,8 @@ impl ExpressionReconstructor for FunctionInliner<'_> {
.collect::<IndexMap<_, _>>();
// Initializer `self.assignment_renamer` with the function parameters.
self.assignment_renamer.load(
callee
.input
.iter()
.map(|input| (input.identifier().name, input.identifier().name)),
);
self.assignment_renamer
.load(callee.input.iter().map(|input| (input.identifier().name, input.identifier().name)));
// Duplicate the body of the callee and create a unique assignment statement for each assignment in the body.
// This is necessary to ensure the inlined variables do not conflict with variables in the caller.
@ -86,9 +89,7 @@ impl ExpressionReconstructor for FunctionInliner<'_> {
_ => unreachable!("This branch checks that the last statement is a return statement."),
}
}
_ => Expression::Unit(UnitExpression {
span: Default::default(),
}),
_ => Expression::Unit(UnitExpression { span: Default::default() }),
};
(result, inlined_statements)

View File

@ -33,16 +33,12 @@ impl ProgramReconstructor for FunctionInliner<'_> {
// Reconstruct the function.
let reconstructed_function = self.reconstruct_function(function);
// Add the reconstructed function to the mapping.
self.reconstructed_functions
.insert(function_name, reconstructed_function);
self.reconstructed_functions.insert(function_name, reconstructed_function);
}
}
// Check that `input.functions` is empty.
// This is a sanity check to ensure that functions in the program scope have been processed.
assert!(
input.functions.is_empty(),
"All functions in the program scope should have been processed."
);
assert!(input.functions.is_empty(), "All functions in the program scope should have been processed.");
// Note that this intentionally clears `self.reconstructed_functions` for the next program scope.
let functions = core::mem::take(&mut self.reconstructed_functions);

View File

@ -17,8 +17,17 @@
use crate::FunctionInliner;
use leo_ast::{
AssignStatement, Block, ConditionalStatement, ConsoleStatement, DefinitionStatement, Expression,
ExpressionReconstructor, ExpressionStatement, IterationStatement, Statement, StatementReconstructor,
AssignStatement,
Block,
ConditionalStatement,
ConsoleStatement,
DefinitionStatement,
Expression,
ExpressionReconstructor,
ExpressionStatement,
IterationStatement,
Statement,
StatementReconstructor,
};
impl StatementReconstructor for FunctionInliner<'_> {
@ -29,29 +38,15 @@ impl StatementReconstructor for FunctionInliner<'_> {
match (input.place, value) {
// If the function call produces a tuple, we need to segment the tuple into multiple assignment statements.
(Expression::Tuple(left), Expression::Tuple(right)) if left.elements.len() == right.elements.len() => {
statements.extend(
left.elements
.into_iter()
.zip(right.elements.into_iter())
.map(|(lhs, rhs)| {
Statement::Assign(Box::new(AssignStatement {
place: lhs,
value: rhs,
span: Default::default(),
}))
}),
);
statements.extend(left.elements.into_iter().zip(right.elements.into_iter()).map(|(lhs, rhs)| {
Statement::Assign(Box::new(AssignStatement { place: lhs, value: rhs, span: Default::default() }))
}));
(Statement::dummy(Default::default()), statements)
}
(place, value) => (
Statement::Assign(Box::new(AssignStatement {
place,
value,
span: input.span,
})),
statements,
),
(place, value) => {
(Statement::Assign(Box::new(AssignStatement { place, value, span: input.span })), statements)
}
}
}
@ -65,13 +60,7 @@ impl StatementReconstructor for FunctionInliner<'_> {
statements.push(reconstructed_statement);
}
(
Block {
span: block.span,
statements,
},
Default::default(),
)
(Block { span: block.span, statements }, Default::default())
}
/// Flattening removes conditional statements from the program.
@ -98,10 +87,7 @@ impl StatementReconstructor for FunctionInliner<'_> {
// If the resulting expression is a unit expression, return a dummy statement.
let statement = match expression {
Expression::Unit(_) => Statement::dummy(Default::default()),
_ => Statement::Expression(ExpressionStatement {
expression,
span: input.span,
}),
_ => Statement::Expression(ExpressionStatement { expression, span: input.span }),
};
(statement, additional_statements)

View File

@ -15,8 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use num_traits::One;
use std::fmt::Display;
use std::ops::Add;
use std::{fmt::Display, ops::Add};
use leo_ast::Value;
use leo_errors::LeoError;
@ -47,11 +46,7 @@ pub(crate) struct RangeIterator<I: LoopBound> {
impl<I: LoopBound> RangeIterator<I> {
pub(crate) fn new(start: I, end: I, clusivity: Clusivity) -> Self {
Self {
end,
current: Some(start),
clusivity,
}
Self { end, current: Some(start), clusivity }
}
}

View File

@ -22,12 +22,7 @@ impl ProgramReconstructor for Unroller<'_> {
fn reconstruct_function(&mut self, function: Function) -> Function {
// Lookup function metadata in the symbol table.
// Note that this unwrap is safe since function metadata is stored in a prior pass.
let function_index = self
.symbol_table
.borrow()
.lookup_fn_symbol(function.identifier.name)
.unwrap()
.id;
let function_index = self.symbol_table.borrow().lookup_fn_symbol(function.identifier.name).unwrap().id;
// Enter the function's scope.
let previous_function_index = self.enter_scope(function_index);

View File

@ -18,8 +18,7 @@ use itertools::Itertools;
use leo_ast::*;
use leo_span::{Span, Symbol};
use crate::unroller::Unroller;
use crate::{VariableSymbol, VariableType};
use crate::{unroller::Unroller, VariableSymbol, VariableType};
impl StatementReconstructor for Unroller<'_> {
fn reconstruct_block(&mut self, input: Block) -> (Block, Self::AdditionalOutput) {
@ -29,11 +28,7 @@ impl StatementReconstructor for Unroller<'_> {
let previous_scope_index = self.enter_scope(scope_index);
let block = Block {
statements: input
.statements
.into_iter()
.map(|s| self.reconstruct_statement(s).0)
.collect(),
statements: input.statements.into_iter().map(|s| self.reconstruct_statement(s).0).collect(),
span: input.span,
};
@ -46,32 +41,28 @@ impl StatementReconstructor for Unroller<'_> {
fn reconstruct_definition(&mut self, input: DefinitionStatement) -> (Statement, Self::AdditionalOutput) {
// If we are unrolling a loop, then we need to repopulate the symbol table.
if self.is_unrolling {
let declaration = if input.declaration_type == DeclarationType::Const {
VariableType::Const
} else {
VariableType::Mut
};
let declaration =
if input.declaration_type == DeclarationType::Const { VariableType::Const } else { VariableType::Mut };
let insert_variable = |symbol: Symbol, type_: Type, span: Span, declaration: VariableType| {
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(
symbol,
VariableSymbol {
type_,
span,
declaration,
},
) {
if let Err(err) =
self.symbol_table.borrow_mut().insert_variable(symbol, VariableSymbol { type_, span, declaration })
{
self.handler.emit_err(err);
}
};
// Insert the variables in the into the symbol table.
match &input.place {
Expression::Identifier(identifier) => insert_variable(identifier.name, input.type_.clone(), identifier.span, declaration),
Expression::Identifier(identifier) => {
insert_variable(identifier.name, input.type_.clone(), identifier.span, declaration)
}
Expression::Tuple(tuple_expression) => {
let tuple_type = match input.type_ {
Type::Tuple(ref tuple_type) => tuple_type,
_ => unreachable!("Type checking guarantees that if the lhs is a tuple, its associated type is also a tuple.")
_ => unreachable!(
"Type checking guarantees that if the lhs is a tuple, its associated type is also a tuple."
),
};
tuple_expression.elements.iter().zip_eq(tuple_type.0.iter()).for_each(|(expression, type_)| {
let identifier = match expression {
@ -80,9 +71,10 @@ impl StatementReconstructor for Unroller<'_> {
};
insert_variable(identifier.name, type_.clone(), identifier.span, declaration)
});
},
_ => unreachable!("Type checking guarantees that the lhs of a `DefinitionStatement` is either an identifier or tuple.")
}
_ => unreachable!(
"Type checking guarantees that the lhs of a `DefinitionStatement` is either an identifier or tuple."
),
}
}
(Statement::Definition(input), Default::default())
@ -91,27 +83,22 @@ impl StatementReconstructor for Unroller<'_> {
fn reconstruct_iteration(&mut self, input: IterationStatement) -> (Statement, Self::AdditionalOutput) {
// We match on start and stop cause loops require
// bounds to be constants.
match (
input.start_value.clone().into_inner(),
input.stop_value.clone().into_inner(),
) {
match (input.start_value.clone().into_inner(), input.stop_value.clone().into_inner()) {
(Some(start), Some(stop)) => match (Type::from(&start), Type::from(&stop)) {
(Type::Integer(IntegerType::I8), Type::Integer(IntegerType::I8))
| (Type::Integer(IntegerType::I16), Type::Integer(IntegerType::I16))
| (Type::Integer(IntegerType::I32), Type::Integer(IntegerType::I32))
| (Type::Integer(IntegerType::I64), Type::Integer(IntegerType::I64))
| (Type::Integer(IntegerType::I128), Type::Integer(IntegerType::I128)) => (
self.unroll_iteration_statement::<i128>(input, start, stop),
Default::default(),
),
| (Type::Integer(IntegerType::I128), Type::Integer(IntegerType::I128)) => {
(self.unroll_iteration_statement::<i128>(input, start, stop), Default::default())
}
(Type::Integer(IntegerType::U8), Type::Integer(IntegerType::U8))
| (Type::Integer(IntegerType::U16), Type::Integer(IntegerType::U16))
| (Type::Integer(IntegerType::U32), Type::Integer(IntegerType::U32))
| (Type::Integer(IntegerType::U64), Type::Integer(IntegerType::U64))
| (Type::Integer(IntegerType::U128), Type::Integer(IntegerType::U128)) => (
self.unroll_iteration_statement::<u128>(input, start, stop),
Default::default(),
),
| (Type::Integer(IntegerType::U128), Type::Integer(IntegerType::U128)) => {
(self.unroll_iteration_statement::<u128>(input, start, stop), Default::default())
}
_ => unreachable!("Type checking ensures that `start` and `stop` have the same type."),
},
// If both loop bounds are not constant, then the loop is not unrolled.

View File

@ -15,8 +15,17 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::{
Block, DeclarationType, DefinitionStatement, Expression, IntegerType, IterationStatement, Literal, Statement,
StatementReconstructor, Type, Value,
Block,
DeclarationType,
DefinitionStatement,
Expression,
IntegerType,
IterationStatement,
Literal,
Statement,
StatementReconstructor,
Type,
Value,
};
use std::cell::RefCell;
@ -37,29 +46,19 @@ pub struct Unroller<'a> {
impl<'a> Unroller<'a> {
pub(crate) fn new(symbol_table: SymbolTable, handler: &'a Handler) -> Self {
Self {
symbol_table: RefCell::new(symbol_table),
scope_index: 0,
handler,
is_unrolling: false,
}
Self { symbol_table: RefCell::new(symbol_table), scope_index: 0, handler, is_unrolling: false }
}
/// Returns the index of the current scope.
/// Note that if we are in the midst of unrolling an IterationStatement, a new scope is created.
pub(crate) fn current_scope_index(&mut self) -> usize {
if self.is_unrolling {
self.symbol_table.borrow_mut().insert_block()
} else {
self.scope_index
}
if self.is_unrolling { self.symbol_table.borrow_mut().insert_block() } else { self.scope_index }
}
/// Enters a child scope.
pub(crate) fn enter_scope(&mut self, index: usize) -> usize {
let previous_symbol_table = std::mem::take(&mut self.symbol_table);
self.symbol_table
.swap(previous_symbol_table.borrow().lookup_scope_by_index(index).unwrap());
self.symbol_table.swap(previous_symbol_table.borrow().lookup_scope_by_index(index).unwrap());
self.symbol_table.borrow_mut().parent = Some(Box::new(previous_symbol_table.into_inner()));
core::mem::replace(&mut self.scope_index, 0)
}
@ -121,13 +120,11 @@ impl<'a> Unroller<'a> {
statements: match input.inclusive {
true => {
let iter = RangeIterator::new(start, stop, Clusivity::Inclusive);
iter.map(|iteration_count| self.unroll_single_iteration(&input, iteration_count))
.collect()
iter.map(|iteration_count| self.unroll_single_iteration(&input, iteration_count)).collect()
}
false => {
let iter = RangeIterator::new(start, stop, Clusivity::Exclusive);
iter.map(|iteration_count| self.unroll_single_iteration(&input, iteration_count))
.collect()
iter.map(|iteration_count| self.unroll_single_iteration(&input, iteration_count)).collect()
}
},
});
@ -201,10 +198,7 @@ impl<'a> Unroller<'a> {
statements.push(self.reconstruct_statement(s).0);
});
let block = Statement::Block(Block {
statements,
span: input.block.span,
});
let block = Statement::Block(Block { statements, span: input.block.span });
self.is_unrolling = prior_is_unrolling;

View File

@ -17,9 +17,24 @@
use crate::StaticSingleAssigner;
use leo_ast::{
AccessExpression, AssociatedFunction, BinaryExpression, CallExpression, Expression, ExpressionConsumer, Identifier,
Literal, MemberAccess, Statement, Struct, StructExpression, StructVariableInitializer, TernaryExpression,
TupleAccess, TupleExpression, UnaryExpression, UnitExpression,
AccessExpression,
AssociatedFunction,
BinaryExpression,
CallExpression,
Expression,
ExpressionConsumer,
Identifier,
Literal,
MemberAccess,
Statement,
Struct,
StructExpression,
StructVariableInitializer,
TernaryExpression,
TupleAccess,
TupleExpression,
UnaryExpression,
UnitExpression,
};
use leo_span::{sym, Symbol};
@ -100,14 +115,12 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
statements.append(&mut right_statements);
// Construct and accumulate a unique assignment statement storing the result of the binary expression.
let (place, statement) = self
.assigner
.unique_simple_assign_statement(Expression::Binary(BinaryExpression {
left: Box::new(left_expression),
right: Box::new(right_expression),
op: input.op,
span: input.span,
}));
let (place, statement) = self.assigner.unique_simple_assign_statement(Expression::Binary(BinaryExpression {
left: Box::new(left_expression),
right: Box::new(right_expression),
op: input.op,
span: input.span,
}));
statements.push(statement);
(Expression::Identifier(place), statements)
@ -129,16 +142,14 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
.collect();
// Construct and accumulate a new assignment statement for the call expression.
let (place, statement) = self
.assigner
.unique_simple_assign_statement(Expression::Call(CallExpression {
// Note that we do not rename the function name.
function: input.function,
// Consume the arguments.
arguments,
external: input.external,
span: input.span,
}));
let (place, statement) = self.assigner.unique_simple_assign_statement(Expression::Call(CallExpression {
// Note that we do not rename the function name.
function: input.function,
// Consume the arguments.
arguments,
external: input.external,
span: input.span,
}));
statements.push(statement);
(Expression::Identifier(place), statements)
@ -165,10 +176,7 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
statements.append(&mut stmts);
// Return the new member.
StructVariableInitializer {
identifier: arg.identifier,
expression: Some(expression),
}
StructVariableInitializer { identifier: arg.identifier, expression: Some(expression) }
})
.collect();
@ -182,10 +190,8 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
let mut reordered_members = Vec::with_capacity(members.len());
// Collect the members of the init expression into a map.
let mut member_map: IndexMap<Symbol, StructVariableInitializer> = members
.into_iter()
.map(|member| (member.identifier.name, member))
.collect();
let mut member_map: IndexMap<Symbol, StructVariableInitializer> =
members.into_iter().map(|member| (member.identifier.name, member)).collect();
// If we are initializing a record, add the `owner` and `gates` fields, first and second respectively.
// Note that type checking guarantees that the above fields exist.
@ -209,13 +215,11 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
}
// Construct and accumulate a new assignment statement for the struct expression.
let (place, statement) = self
.assigner
.unique_simple_assign_statement(Expression::Struct(StructExpression {
name: input.name,
span: input.span,
members: reordered_members,
}));
let (place, statement) = self.assigner.unique_simple_assign_statement(Expression::Struct(StructExpression {
name: input.name,
span: input.span,
members: reordered_members,
}));
statements.push(statement);
(Expression::Identifier(place), statements)
@ -237,13 +241,7 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
false => *self.rename_table.lookup(identifier.name).unwrap_or(&identifier.name),
};
(
Expression::Identifier(Identifier {
name,
span: identifier.span,
}),
Default::default(),
)
(Expression::Identifier(Identifier { name, span: identifier.span }), Default::default())
}
/// Consumes and returns the literal without making any modifications.
@ -265,14 +263,12 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
statements.append(&mut if_false_statements);
// Construct and accumulate a unique assignment statement storing the result of the ternary expression.
let (place, statement) = self
.assigner
.unique_simple_assign_statement(Expression::Ternary(TernaryExpression {
condition: Box::new(cond_expr),
if_true: Box::new(if_true_expr),
if_false: Box::new(if_false_expr),
span: input.span,
}));
let (place, statement) = self.assigner.unique_simple_assign_statement(Expression::Ternary(TernaryExpression {
condition: Box::new(cond_expr),
if_true: Box::new(if_true_expr),
if_false: Box::new(if_false_expr),
span: input.span,
}));
statements.push(statement);
(Expression::Identifier(place), statements)
@ -296,10 +292,7 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
// Construct and accumulate a new assignment statement for the tuple expression.
let (place, statement) = self
.assigner
.unique_simple_assign_statement(Expression::Tuple(TupleExpression {
elements,
span: input.span,
}));
.unique_simple_assign_statement(Expression::Tuple(TupleExpression { elements, span: input.span }));
statements.push(statement);
(Expression::Identifier(place), statements)
@ -311,13 +304,11 @@ impl ExpressionConsumer for StaticSingleAssigner<'_> {
let (receiver, mut statements) = self.consume_expression(*input.receiver);
// Construct and accumulate a new assignment statement for the unary expression.
let (place, statement) = self
.assigner
.unique_simple_assign_statement(Expression::Unary(UnaryExpression {
op: input.op,
receiver: Box::new(receiver),
span: input.span,
}));
let (place, statement) = self.assigner.unique_simple_assign_statement(Expression::Unary(UnaryExpression {
op: input.op,
receiver: Box::new(receiver),
span: input.span,
}));
statements.push(statement);
(Expression::Identifier(place), statements)

View File

@ -17,8 +17,18 @@
use crate::StaticSingleAssigner;
use leo_ast::{
Block, Finalize, Function, FunctionConsumer, Member, Program, ProgramConsumer, ProgramScope, ProgramScopeConsumer,
StatementConsumer, Struct, StructConsumer,
Block,
Finalize,
Function,
FunctionConsumer,
Member,
Program,
ProgramConsumer,
ProgramScope,
ProgramScopeConsumer,
StatementConsumer,
Struct,
StructConsumer,
};
use leo_span::{sym, Symbol};
@ -33,11 +43,8 @@ impl StructConsumer for StaticSingleAssigner<'_> {
false => struct_,
true => {
let mut members = Vec::with_capacity(struct_.members.len());
let mut member_map: IndexMap<Symbol, Member> = struct_
.members
.into_iter()
.map(|member| (member.identifier.name, member))
.collect();
let mut member_map: IndexMap<Symbol, Member> =
struct_.members.into_iter().map(|member| (member.identifier.name, member)).collect();
// Add the owner field to the beginning of the members list.
// Note that type checking ensures that the owner field exists.
@ -67,14 +74,10 @@ impl FunctionConsumer for StaticSingleAssigner<'_> {
// There is no need to reconstruct `function.inputs`.
// However, for each input, we must add each symbol to the rename table.
for input_variable in function.input.iter() {
self.rename_table
.update(input_variable.identifier().name, input_variable.identifier().name);
self.rename_table.update(input_variable.identifier().name, input_variable.identifier().name);
}
let block = Block {
span: function.block.span,
statements: self.consume_block(function.block),
};
let block = Block { span: function.block.span, statements: self.consume_block(function.block) };
// Remove the `RenameTable` for the function.
self.pop();
@ -86,14 +89,10 @@ impl FunctionConsumer for StaticSingleAssigner<'_> {
// There is no need to reconstruct `finalize.inputs`.
// However, for each input, we must add each symbol to the rename table.
for input_variable in finalize.input.iter() {
self.rename_table
.update(input_variable.identifier().name, input_variable.identifier().name);
self.rename_table.update(input_variable.identifier().name, input_variable.identifier().name);
}
let block = Block {
span: finalize.block.span,
statements: self.consume_block(finalize.block),
};
let block = Block { span: finalize.block.span, statements: self.consume_block(finalize.block) };
// Remove the `RenameTable` for the finalize block.
self.pop();
@ -128,17 +127,9 @@ impl ProgramScopeConsumer for StaticSingleAssigner<'_> {
fn consume_program_scope(&mut self, input: ProgramScope) -> Self::Output {
ProgramScope {
program_id: input.program_id,
structs: input
.structs
.into_iter()
.map(|(i, s)| (i, self.consume_struct(s)))
.collect(),
structs: input.structs.into_iter().map(|(i, s)| (i, self.consume_struct(s))).collect(),
mappings: input.mappings,
functions: input
.functions
.into_iter()
.map(|(i, f)| (i, self.consume_function(f)))
.collect(),
functions: input.functions.into_iter().map(|(i, f)| (i, self.consume_function(f))).collect(),
span: input.span,
}
}

View File

@ -17,9 +17,25 @@
use crate::{RenameTable, StaticSingleAssigner};
use leo_ast::{
AssertStatement, AssertVariant, AssignStatement, Block, CallExpression, ConditionalStatement, ConsoleStatement,
DecrementStatement, DefinitionStatement, Expression, ExpressionConsumer, ExpressionStatement, Identifier,
IncrementStatement, IterationStatement, ReturnStatement, Statement, StatementConsumer, TernaryExpression,
AssertStatement,
AssertVariant,
AssignStatement,
Block,
CallExpression,
ConditionalStatement,
ConsoleStatement,
DecrementStatement,
DefinitionStatement,
Expression,
ExpressionConsumer,
ExpressionStatement,
Identifier,
IncrementStatement,
IterationStatement,
ReturnStatement,
Statement,
StatementConsumer,
TernaryExpression,
TupleExpression,
};
use leo_span::Symbol;
@ -59,10 +75,7 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
};
// Add the assert statement to the list of produced statements.
statements.push(Statement::Assert(AssertStatement {
variant,
span: input.span,
}));
statements.push(Statement::Assert(AssertStatement { variant, span: input.span }));
statements
}
@ -88,11 +101,7 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
/// Consumes a `Block`, flattening its constituent `ConditionalStatement`s.
fn consume_block(&mut self, block: Block) -> Self::Output {
block
.statements
.into_iter()
.flat_map(|statement| self.consume_statement(statement))
.collect()
block.statements.into_iter().flat_map(|statement| self.consume_statement(statement)).collect()
}
/// Consumes a `ConditionalStatement`, producing phi functions (assign statements) for variables written in the then-block and otherwise-block.
@ -110,10 +119,7 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
self.push();
// Consume the then-block.
let then = Block {
span: conditional.then.span,
statements: self.consume_block(conditional.then),
};
let then = Block { span: conditional.then.span, statements: self.consume_block(conditional.then) };
// Remove the `RenameTable` for the then-block.
let if_table = self.pop();
@ -156,13 +162,9 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
if self.rename_table.lookup(**symbol).is_some() {
// Helper to lookup a symbol and create an argument for the phi function.
let create_phi_argument = |table: &RenameTable, symbol: Symbol| {
let name = *table
.lookup(symbol)
.unwrap_or_else(|| panic!("Symbol {symbol} should exist in the program."));
Box::new(Expression::Identifier(Identifier {
name,
span: Default::default(),
}))
let name =
*table.lookup(symbol).unwrap_or_else(|| panic!("Symbol {symbol} should exist in the program."));
Box::new(Expression::Identifier(Identifier { name, span: Default::default() }))
};
// Create a new name for the variable written to in the `ConditionalStatement`.
@ -178,13 +180,9 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
statements.extend(stmts);
// Create a new `AssignStatement` for the phi function.
let assignment = self.assigner.simple_assign_statement(
Identifier {
name: new_name,
span: Default::default(),
},
value,
);
let assignment = self
.assigner
.simple_assign_statement(Identifier { name: new_name, span: Default::default() }, value);
// Update the `RenameTable` with the new name of the variable.
self.rename_table.update(*(*symbol), new_name);
@ -251,15 +249,14 @@ impl StatementConsumer for StaticSingleAssigner<'_> {
}
}).collect();
statements.push(Statement::Assign(Box::new(AssignStatement {
place: Expression::Tuple(TupleExpression {
elements,
span: Default::default()
}),
place: Expression::Tuple(TupleExpression { elements, span: Default::default() }),
value,
span: Default::default()
span: Default::default(),
})));
}
_ => unreachable!("Type checking guarantees that the left-hand-side of a `DefinitionStatement` is an identifier or tuple."),
_ => unreachable!(
"Type checking guarantees that the left-hand-side of a `DefinitionStatement` is an identifier or tuple."
),
}
self.is_lhs = false;

View File

@ -30,12 +30,7 @@ pub struct StaticSingleAssigner<'a> {
impl<'a> StaticSingleAssigner<'a> {
/// Initializes a new `StaticSingleAssigner` with an empty `RenameTable`.
pub(crate) fn new(symbol_table: &'a SymbolTable) -> Self {
Self {
symbol_table,
rename_table: RenameTable::new(None),
is_lhs: false,
assigner: Assigner::default(),
}
Self { symbol_table, rename_table: RenameTable::new(None), is_lhs: false, assigner: Assigner::default() }
}
/// Pushes a new scope, setting the current scope as the new scope's parent.

View File

@ -31,10 +31,7 @@ pub struct SymbolTableCreator<'a> {
impl<'a> SymbolTableCreator<'a> {
pub fn new(handler: &'a Handler) -> Self {
Self {
symbol_table: Default::default(),
handler,
}
Self { symbol_table: Default::default(), handler }
}
}
@ -58,17 +55,14 @@ impl<'a> ProgramVisitor<'a> for SymbolTableCreator<'a> {
fn visit_mapping(&mut self, input: &'a Mapping) {
// Add the variable associated with the mapping to the symbol table.
if let Err(err) = self.symbol_table.insert_variable(
input.identifier.name,
VariableSymbol {
type_: Type::Mapping(MappingType {
key: Box::new(input.key_type.clone()),
value: Box::new(input.value_type.clone()),
}),
span: input.span,
declaration: VariableType::Mut,
},
) {
if let Err(err) = self.symbol_table.insert_variable(input.identifier.name, VariableSymbol {
type_: Type::Mapping(MappingType {
key: Box::new(input.key_type.clone()),
value: Box::new(input.value_type.clone()),
}),
span: input.span,
declaration: VariableType::Mut,
}) {
self.handler.emit_err(err);
}
}

View File

@ -17,8 +17,7 @@
use crate::TypeChecker;
use leo_ast::*;
use leo_errors::emitter::Handler;
use leo_errors::TypeCheckerError;
use leo_errors::{emitter::Handler, TypeCheckerError};
use leo_span::{sym, Span};
use std::str::FromStr;
@ -28,11 +27,7 @@ fn return_incorrect_type(t1: Option<Type>, t2: Option<Type>, expected: &Option<T
(Some(t1), Some(t2)) if t1 == t2 => Some(t1),
(Some(t1), Some(t2)) => {
if let Some(expected) = expected {
if &t1 != expected {
Some(t1)
} else {
Some(t2)
}
if &t1 != expected { Some(t1) } else { Some(t2) }
} else {
Some(t1)
}
@ -482,12 +477,9 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
}
// Check function argument types.
func.input
.iter()
.zip(input.arguments.iter())
.for_each(|(expected, argument)| {
self.visit_expression(argument, &Some(expected.type_()));
});
func.input.iter().zip(input.arguments.iter()).for_each(|(expected, argument)| {
self.visit_expression(argument, &Some(expected.type_()));
});
// Add the call to the call graph.
let caller_name = match self.function {
@ -524,11 +516,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
// Check struct member types.
struct_.members.iter().for_each(|Member { identifier, type_, .. }| {
// Lookup struct variable name.
if let Some(actual) = input
.members
.iter()
.find(|member| member.identifier.name == identifier.name)
{
if let Some(actual) = input.members.iter().find(|member| member.identifier.name == identifier.name) {
match &actual.expression {
// If `expression` is None, then the member uses the identifier shorthand, e.g. `Foo { a }`
None => self.visit_identifier(&actual.identifier, &Some(type_.clone())),
@ -546,11 +534,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
Some(ret)
} else {
self.emit_err(TypeCheckerError::unknown_sym(
"struct",
input.name.name,
input.name.span(),
));
self.emit_err(TypeCheckerError::unknown_sym("struct", input.name.name, input.name.span()));
None
}
}
@ -655,16 +639,13 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
));
}
expected_types
.iter()
.zip(input.elements.iter())
.for_each(|(expected, expr)| {
// Check that the component expression is not a tuple.
if matches!(expr, Expression::Tuple(_)) {
self.emit_err(TypeCheckerError::nested_tuple_expression(expr.span()))
}
self.visit_expression(expr, &Some(expected.clone()));
});
expected_types.iter().zip(input.elements.iter()).for_each(|(expected, expr)| {
// Check that the component expression is not a tuple.
if matches!(expr, Expression::Tuple(_)) {
self.emit_err(TypeCheckerError::nested_tuple_expression(expr.span()))
}
self.visit_expression(expr, &Some(expected.clone()));
});
Some(Type::Tuple(expected_types.clone()))
} else {
@ -727,9 +708,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
fn visit_unit(&mut self, input: &'a UnitExpression, _additional: &Self::AdditionalInput) -> Self::Output {
// Unit expression are only allowed inside a return statement.
if !self.is_return {
self.emit_err(TypeCheckerError::unit_expression_only_in_return_statements(
input.span(),
));
self.emit_err(TypeCheckerError::unit_expression_only_in_return_statements(input.span()));
}
Some(Type::Unit)
}

View File

@ -48,10 +48,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
}
// Typecheck the program scopes.
input
.program_scopes
.values()
.for_each(|scope| self.visit_program_scope(scope));
input.program_scopes.values().for_each(|scope| self.visit_program_scope(scope));
}
fn visit_program_scope(&mut self, input: &'a ProgramScope) {
@ -94,18 +91,11 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
// Check for conflicting struct/record member names.
let mut used = HashSet::new();
// TODO: Better span to target duplicate member.
if !input.members.iter().all(
|Member {
identifier,
type_,
span,
..
}| {
// Check that the member types are defined.
self.assert_type_is_defined(type_, *span);
used.insert(identifier.name)
},
) {
if !input.members.iter().all(|Member { identifier, type_, span, .. }| {
// Check that the member types are defined.
self.assert_type_is_defined(type_, *span);
used.insert(identifier.name)
}) {
self.emit_err(if input.is_record {
TypeCheckerError::duplicate_record_variable(input.name(), input.span())
} else {
@ -121,31 +111,17 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
}) {
Some((_, actual_ty)) if expected_ty.eq_flat(actual_ty) => {} // All good, found + right type!
Some((field, _)) => {
self.emit_err(TypeCheckerError::record_var_wrong_type(
field,
expected_ty,
input.span(),
));
self.emit_err(TypeCheckerError::record_var_wrong_type(field, expected_ty, input.span()));
}
None => {
self.emit_err(TypeCheckerError::required_record_variable(
need,
expected_ty,
input.span(),
));
self.emit_err(TypeCheckerError::required_record_variable(need, expected_ty, input.span()));
}
};
check_has_field(sym::owner, Type::Address);
check_has_field(sym::gates, Type::Integer(IntegerType::U64));
}
for Member {
mode,
identifier,
type_,
span,
} in input.members.iter()
{
for Member { mode, identifier, type_, span } in input.members.iter() {
// Check that the member type is not a tuple.
if matches!(type_, Type::Tuple(_)) {
self.emit_err(TypeCheckerError::composite_data_type_cannot_contain_tuple(
@ -201,12 +177,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
// Lookup function metadata in the symbol table.
// Note that this unwrap is safe since function metadata is stored in a prior pass.
let function_index = self
.symbol_table
.borrow()
.lookup_fn_symbol(function.identifier.name)
.unwrap()
.id;
let function_index = self.symbol_table.borrow().lookup_fn_symbol(function.identifier.name).unwrap().id;
// Enter the function's scope.
self.enter_scope(function_index);
@ -235,25 +206,24 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
// Note that this unwrap is safe since we assign to `self.variant` above.
match self.variant.unwrap() {
// If the function is a transition function, then check that the parameter mode is not a constant.
Variant::Transition if input_var.mode() == Mode::Constant => self.emit_err(
TypeCheckerError::transition_function_inputs_cannot_be_const(input_var.span()),
),
Variant::Transition if input_var.mode() == Mode::Constant => {
self.emit_err(TypeCheckerError::transition_function_inputs_cannot_be_const(input_var.span()))
}
// If the function is not a transition function, then check that the parameters do not have an associated mode.
Variant::Standard | Variant::Inline if input_var.mode() != Mode::None => self.emit_err(
TypeCheckerError::regular_function_inputs_cannot_have_modes(input_var.span()),
),
Variant::Standard | Variant::Inline if input_var.mode() != Mode::None => {
self.emit_err(TypeCheckerError::regular_function_inputs_cannot_have_modes(input_var.span()))
}
_ => {} // Do nothing.
}
// Check for conflicting variable names.
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(
input_var.identifier().name,
VariableSymbol {
if let Err(err) =
self.symbol_table.borrow_mut().insert_variable(input_var.identifier().name, VariableSymbol {
type_: input_var.type_(),
span: input_var.identifier().span(),
declaration: VariableType::Input(input_var.mode()),
},
) {
})
{
self.handler.emit_err(err);
}
});
@ -277,12 +247,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
// If the function is not a transition function, then it cannot output a record.
if let Type::Identifier(identifier) = function_output.type_ {
if !matches!(function.variant, Variant::Transition)
&& self
.symbol_table
.borrow()
.lookup_struct(identifier.name)
.unwrap()
.is_record
&& self.symbol_table.borrow().lookup_struct(identifier.name).unwrap().is_record
{
self.emit_err(TypeCheckerError::function_cannot_output_record(function_output.span));
}
@ -325,9 +290,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
// Check that the function is a transition function.
if !matches!(function.variant, Variant::Transition) {
self.emit_err(TypeCheckerError::only_transition_functions_can_have_finalize(
finalize.span,
));
self.emit_err(TypeCheckerError::only_transition_functions_can_have_finalize(finalize.span));
}
// Check that the name of the finalize block matches the function name.
@ -354,14 +317,13 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
self.emit_err(TypeCheckerError::finalize_input_mode_must_be_public(input_var.span()));
}
// Check for conflicting variable names.
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(
input_var.identifier().name,
VariableSymbol {
if let Err(err) =
self.symbol_table.borrow_mut().insert_variable(input_var.identifier().name, VariableSymbol {
type_: input_var.type_(),
span: input_var.identifier().span(),
declaration: VariableType::Input(input_var.mode()),
},
) {
})
{
self.handler.emit_err(err);
}
});
@ -378,9 +340,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
// Check that the mode of the output is valid.
// Note that a finalize block can have only public outputs.
if matches!(output_type.mode(), Mode::Constant | Mode::Private) {
self.emit_err(TypeCheckerError::finalize_output_mode_must_be_public(
output_type.span(),
));
self.emit_err(TypeCheckerError::finalize_output_mode_must_be_public(output_type.span()));
}
});

View File

@ -162,10 +162,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
self.assert_mapping_type(&mapping_type, input.span());
match mapping_type {
None => self.emit_err(TypeCheckerError::could_not_determine_type(
input.mapping,
input.mapping.span,
)),
None => self.emit_err(TypeCheckerError::could_not_determine_type(input.mapping, input.mapping.span)),
Some(Type::Mapping(mapping_type)) => {
// Check that the index matches the key type of the mapping.
let index_type = self.visit_expression(&input.index, &None);
@ -178,20 +175,15 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
// Check that the amount type is incrementable.
self.assert_field_group_scalar_int_type(&amount_type, input.amount.span());
}
Some(mapping_type) => self.emit_err(TypeCheckerError::expected_one_type_of(
"mapping",
mapping_type,
input.mapping.span,
)),
Some(mapping_type) => {
self.emit_err(TypeCheckerError::expected_one_type_of("mapping", mapping_type, input.mapping.span))
}
}
}
fn visit_definition(&mut self, input: &'a DefinitionStatement) {
let declaration = if input.declaration_type == DeclarationType::Const {
VariableType::Const
} else {
VariableType::Mut
};
let declaration =
if input.declaration_type == DeclarationType::Const { VariableType::Const } else { VariableType::Mut };
// Check that the type of the definition is defined.
self.assert_type_is_defined(&input.type_, input.span);
@ -220,14 +212,9 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
// TODO: Dedup with unrolling pass.
// Helper to insert the variables into the symbol table.
let insert_variable = |symbol: Symbol, type_: Type, span: Span, declaration: VariableType| {
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(
symbol,
VariableSymbol {
type_,
span,
declaration,
},
) {
if let Err(err) =
self.symbol_table.borrow_mut().insert_variable(symbol, VariableSymbol { type_, span, declaration })
{
self.handler.emit_err(err);
}
};
@ -244,21 +231,17 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
"Type checking guarantees that if the lhs is a tuple, its associated type is also a tuple."
),
};
tuple_expression
.elements
.iter()
.zip_eq(tuple_type.0.iter())
.for_each(|(expression, type_)| {
let identifier = match expression {
Expression::Identifier(identifier) => identifier,
_ => {
return self.emit_err(TypeCheckerError::lhs_tuple_element_must_be_an_identifier(
expression.span(),
))
}
};
insert_variable(identifier.name, type_.clone(), identifier.span, declaration)
});
tuple_expression.elements.iter().zip_eq(tuple_type.0.iter()).for_each(|(expression, type_)| {
let identifier = match expression {
Expression::Identifier(identifier) => identifier,
_ => {
return self.emit_err(TypeCheckerError::lhs_tuple_element_must_be_an_identifier(
expression.span(),
));
}
};
insert_variable(identifier.name, type_.clone(), identifier.span, declaration)
});
}
_ => self.emit_err(TypeCheckerError::lhs_must_be_identifier_or_tuple(input.place.span())),
}
@ -267,9 +250,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
fn visit_expression_statement(&mut self, input: &'a ExpressionStatement) {
// Expression statements can only be function calls.
if !matches!(input.expression, Expression::Call(_)) {
self.emit_err(TypeCheckerError::expression_statement_must_be_function_call(
input.span(),
));
self.emit_err(TypeCheckerError::expression_statement_must_be_function_call(input.span()));
} else {
// Check the expression.
// TODO: Should the output type be restricted to unit types?
@ -287,10 +268,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
self.assert_mapping_type(&mapping_type, input.span());
match mapping_type {
None => self.emit_err(TypeCheckerError::could_not_determine_type(
input.mapping,
input.mapping.span,
)),
None => self.emit_err(TypeCheckerError::could_not_determine_type(input.mapping, input.mapping.span)),
Some(Type::Mapping(mapping_type)) => {
// Check that the index matches the key type of the mapping.
let index_type = self.visit_expression(&input.index, &None);
@ -303,11 +281,9 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
// Check that the amount type is incrementable.
self.assert_field_group_scalar_int_type(&amount_type, input.amount.span());
}
Some(mapping_type) => self.emit_err(TypeCheckerError::expected_one_type_of(
"mapping",
mapping_type,
input.mapping.span,
)),
Some(mapping_type) => {
self.emit_err(TypeCheckerError::expected_one_type_of("mapping", mapping_type, input.mapping.span))
}
}
}
@ -319,14 +295,11 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
let scope_index = self.create_child_scope();
// Add the loop variable to the scope of the loop body.
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(
input.variable.name,
VariableSymbol {
type_: input.type_.clone(),
span: input.span(),
declaration: VariableType::Const,
},
) {
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(input.variable.name, VariableSymbol {
type_: input.type_.clone(),
span: input.span(),
declaration: VariableType::Const,
}) {
self.handler.emit_err(err);
}
@ -372,16 +345,12 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
// We can safely unwrap all self.parent instances because
// statements should always have some parent block
let parent = self.function.unwrap();
let return_type = &self
.symbol_table
.borrow()
.lookup_fn_symbol(parent)
.map(|f| match self.is_finalize {
// TODO: Check this.
// Note that this `unwrap()` is safe since we checked that the function has a finalize block.
true => f.finalize.as_ref().unwrap().output_type.clone(),
false => f.output_type.clone(),
});
let return_type = &self.symbol_table.borrow().lookup_fn_symbol(parent).map(|f| match self.is_finalize {
// TODO: Check this.
// Note that this `unwrap()` is safe since we checked that the function has a finalize block.
true => f.finalize.as_ref().unwrap().output_type.clone(),
false => f.output_type.clone(),
});
// Set the `has_return` flag.
self.has_return = true;
@ -413,13 +382,8 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
// Check that the function has a finalize block.
// Note that `self.function.unwrap()` is safe since every `self.function` is set for every function.
// Note that `(self.function.unwrap()).unwrap()` is safe since all functions have been checked to exist.
let finalize = self
.symbol_table
.borrow()
.lookup_fn_symbol(self.function.unwrap())
.unwrap()
.finalize
.clone();
let finalize =
self.symbol_table.borrow().lookup_fn_symbol(self.function.unwrap()).unwrap().finalize.clone();
match finalize {
None => self.emit_err(TypeCheckerError::finalize_without_finalize_block(input.span())),
Some(finalize) => {
@ -433,13 +397,9 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
}
// Check function argument types.
finalize
.input
.iter()
.zip(arguments.iter())
.for_each(|(expected, argument)| {
self.visit_expression(argument, &Some(expected.type_()));
});
finalize.input.iter().zip(arguments.iter()).for_each(|(expected, argument)| {
self.visit_expression(argument, &Some(expected.type_()));
});
}
}
}

View File

@ -87,11 +87,8 @@ const UNSIGNED_INT_TYPES: [Type; 5] = [
Type::Integer(IntegerType::U128),
];
const MAGNITUDE_TYPES: [Type; 3] = [
Type::Integer(IntegerType::U8),
Type::Integer(IntegerType::U16),
Type::Integer(IntegerType::U32),
];
const MAGNITUDE_TYPES: [Type; 3] =
[Type::Integer(IntegerType::U8), Type::Integer(IntegerType::U16), Type::Integer(IntegerType::U32)];
impl<'a> TypeChecker<'a> {
/// Returns a new type checker given a symbol table and error handler.
@ -119,8 +116,7 @@ impl<'a> TypeChecker<'a> {
/// Enters a child scope.
pub(crate) fn enter_scope(&mut self, index: usize) {
let previous_symbol_table = std::mem::take(&mut self.symbol_table);
self.symbol_table
.swap(previous_symbol_table.borrow().lookup_scope_by_index(index).unwrap());
self.symbol_table.swap(previous_symbol_table.borrow().lookup_scope_by_index(index).unwrap());
self.symbol_table.borrow_mut().parent = Some(Box::new(previous_symbol_table.into_inner()));
}
@ -137,8 +133,7 @@ impl<'a> TypeChecker<'a> {
/// Exits the current scope.
pub(crate) fn exit_scope(&mut self, index: usize) {
let previous_symbol_table = *self.symbol_table.borrow_mut().parent.take().unwrap();
self.symbol_table
.swap(previous_symbol_table.lookup_scope_by_index(index).unwrap());
self.symbol_table.swap(previous_symbol_table.lookup_scope_by_index(index).unwrap());
self.symbol_table = RefCell::new(previous_symbol_table);
}
@ -183,22 +178,12 @@ impl<'a> TypeChecker<'a> {
/// Emits an error to the error handler if the `actual` type is not equal to the `expected` type.
pub(crate) fn assert_type(&self, actual: &Option<Type>, expected: &Type, span: Span) {
self.check_type(
|actual: &Type| actual.eq_flat(expected),
expected.to_string(),
actual,
span,
)
self.check_type(|actual: &Type| actual.eq_flat(expected), expected.to_string(), actual, span)
}
/// Emits an error to the handler if the given type is not a boolean.
pub(crate) fn assert_bool_type(&self, type_: &Option<Type>, span: Span) {
self.check_type(
|type_: &Type| BOOLEAN_TYPE.eq(type_),
BOOLEAN_TYPE.to_string(),
type_,
span,
)
self.check_type(|type_: &Type| BOOLEAN_TYPE.eq(type_), BOOLEAN_TYPE.to_string(), type_, span)
}
/// Emits an error to the handler if the given type is not a field.
@ -213,22 +198,12 @@ impl<'a> TypeChecker<'a> {
/// Emits an error to the handler if the given type is not a scalar.
pub(crate) fn assert_scalar_type(&self, type_: &Option<Type>, span: Span) {
self.check_type(
|type_: &Type| SCALAR_TYPE.eq(type_),
SCALAR_TYPE.to_string(),
type_,
span,
)
self.check_type(|type_: &Type| SCALAR_TYPE.eq(type_), SCALAR_TYPE.to_string(), type_, span)
}
/// Emits an error to the handler if the given type is not an integer.
pub(crate) fn assert_int_type(&self, type_: &Option<Type>, span: Span) {
self.check_type(
|type_: &Type| INT_TYPES.contains(type_),
types_to_string(&INT_TYPES),
type_,
span,
)
self.check_type(|type_: &Type| INT_TYPES.contains(type_), types_to_string(&INT_TYPES), type_, span)
}
/// Emits an error to the handler if the given type is not a signed integer.
@ -253,12 +228,7 @@ impl<'a> TypeChecker<'a> {
/// Emits an error to the handler if the given type is not a magnitude (u8, u16, u32).
pub(crate) fn assert_magnitude_type(&self, type_: &Option<Type>, span: Span) {
self.check_type(
|type_: &Type| MAGNITUDE_TYPES.contains(type_),
types_to_string(&MAGNITUDE_TYPES),
type_,
span,
)
self.check_type(|type_: &Type| MAGNITUDE_TYPES.contains(type_), types_to_string(&MAGNITUDE_TYPES), type_, span)
}
/// Emits an error to the handler if the given type is not a boolean or an integer.
@ -327,13 +297,7 @@ impl<'a> TypeChecker<'a> {
|type_: &Type| {
FIELD_TYPE.eq(type_) | GROUP_TYPE.eq(type_) | SCALAR_TYPE.eq(type_) | INT_TYPES.contains(type_)
},
format!(
"{}, {}, {}, {}",
FIELD_TYPE,
GROUP_TYPE,
SCALAR_TYPE,
types_to_string(&INT_TYPES),
),
format!("{}, {}, {}, {}", FIELD_TYPE, GROUP_TYPE, SCALAR_TYPE, types_to_string(&INT_TYPES),),
type_,
span,
)
@ -347,11 +311,7 @@ impl<'a> TypeChecker<'a> {
match CoreInstruction::from_symbols(ident.name, function.name) {
None => {
// Not a core library struct.
self.emit_err(TypeCheckerError::invalid_core_function(
ident.name,
function.name,
ident.span(),
));
self.emit_err(TypeCheckerError::invalid_core_function(ident.name, function.name, ident.span()));
}
Some(core_instruction) => return Some(core_instruction),
}
@ -380,11 +340,7 @@ impl<'a> TypeChecker<'a> {
.lookup_struct(identifier.name)
.map_or(false, |struct_| struct_.is_record) =>
{
self.emit_err(TypeCheckerError::struct_or_record_cannot_contain_record(
parent,
identifier.name,
span,
))
self.emit_err(TypeCheckerError::struct_or_record_cannot_contain_record(parent, identifier.name, span))
}
Type::Tuple(tuple_type) => {
for type_ in tuple_type.iter() {
@ -423,12 +379,7 @@ impl<'a> TypeChecker<'a> {
/// Emits an error if the type is not a mapping.
pub(crate) fn assert_mapping_type(&self, type_: &Option<Type>, span: Span) {
self.check_type(
|type_| matches!(type_, Type::Mapping(_)),
"mapping".to_string(),
type_,
span,
)
self.check_type(|type_| matches!(type_, Type::Mapping(_)), "mapping".to_string(), type_, span)
}
}

View File

@ -17,7 +17,9 @@
use crate::span::{BytePos, CharPos, Pos, Span};
use std::{
cell::RefCell,
fmt, fs, io,
fmt,
fs,
io,
path::{Path, PathBuf},
rc::Rc,
};
@ -105,10 +107,7 @@ impl SourceMap {
if loc.line_start == loc.line_stop {
format!("{}:{}-{}", loc.line_start, loc.col_start, loc.col_stop)
} else {
format!(
"{}:{}-{}:{}",
loc.line_start, loc.col_start, loc.line_stop, loc.col_stop
)
format!("{}:{}-{}:{}", loc.line_start, loc.col_start, loc.line_stop, loc.col_stop)
}
}
@ -140,11 +139,7 @@ impl SourceMap {
let idx_lo = begin.lookup_line(span.lo).unwrap_or(0);
let idx_hi = begin.lookup_line(span.hi).unwrap_or(0) + 1;
let lo_line_pos = begin.lines[idx_lo];
let hi_line_pos = if idx_hi < begin.lines.len() {
begin.lines[idx_hi]
} else {
begin.end_pos
};
let hi_line_pos = if idx_hi < begin.lines.len() { begin.lines[idx_hi] } else { begin.end_pos };
Some(begin.contents_of_span(Span::new(lo_line_pos, hi_line_pos)))
}
}
@ -183,11 +178,7 @@ impl fmt::Display for FileName {
/// Is the env var `LEO_TESTFRAMEWORK` not enabled?
pub fn is_not_test_framework() -> bool {
std::env::var("LEO_TESTFRAMEWORK")
.unwrap_or_default()
.trim()
.to_owned()
.is_empty()
std::env::var("LEO_TESTFRAMEWORK").unwrap_or_default().trim().to_owned().is_empty()
}
/// A single source in the [`SourceMap`].
@ -215,14 +206,7 @@ impl SourceFile {
normalize_src(&mut src);
let end_pos = start_pos + BytePos::from_usize(src.len());
let (lines, multibyte_chars) = analyze_source_file(&src, start_pos);
Self {
name,
src,
start_pos,
end_pos,
lines,
multibyte_chars,
}
Self { name, src, start_pos, end_pos, lines, multibyte_chars }
}
/// Converts an absolute `BytePos` to a `CharPos` relative to the `SourceFile`.

View File

@ -42,10 +42,7 @@ impl Span {
/// Generates a dummy span with all defaults.
/// Should only be used in temporary situations.
pub const fn dummy() -> Self {
Self {
lo: BytePos(0),
hi: BytePos(0),
}
Self { lo: BytePos(0), hi: BytePos(0) }
}
/// Is the span a dummy?

View File

@ -18,9 +18,12 @@
use crate::Span;
use serde::de::{MapAccess, Visitor};
use serde::ser::SerializeMap;
use serde::{Deserializer, Serializer};
use serde::{
de::{MapAccess, Visitor},
ser::SerializeMap,
Deserializer,
Serializer,
};
use std::fmt;
/// The AST contains a few tuple-like enum variants that contain spans.

View File

@ -16,12 +16,15 @@
use crate::source_map::SourceMap;
use core::borrow::Borrow;
use core::cmp::PartialEq;
use core::hash::{Hash, Hasher};
use core::num::NonZeroU32;
use core::ops::Deref;
use core::{fmt, str};
use core::{
borrow::Borrow,
cmp::PartialEq,
fmt,
hash::{Hash, Hasher},
num::NonZeroU32,
ops::Deref,
str,
};
use fxhash::FxBuildHasher;
use indexmap::IndexSet;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
@ -289,10 +292,7 @@ pub struct SessionGlobals {
impl Default for SessionGlobals {
fn default() -> Self {
Self {
symbol_interner: Interner::prefilled(),
source_map: SourceMap::default(),
}
Self { symbol_interner: Interner::prefilled(), source_map: SourceMap::default() }
}
}
@ -381,9 +381,7 @@ impl Interner {
// arena: <_>::default(),
set: init.iter().copied().map(InternedStr::Static).collect(),
};
Self {
inner: RefCell::new(inner),
}
Self { inner: RefCell::new(inner) }
}
/// Interns `string`, returning a `Symbol` corresponding to it.

View File

@ -68,13 +68,7 @@ impl<'a> Processor<'a> {
// we need a hashmap to pull rules easily
let rules: HashMap<String, Rule> = abnf.into_iter().map(|rule| (rule.name().to_string(), rule)).collect();
Processor {
grammar,
line: 0,
out: String::new(),
rules,
scope: Scope::Free,
}
Processor { grammar, line: 0, out: String::new(), rules, scope: Scope::Free }
}
/// Main function for this struct.

View File

@ -64,15 +64,7 @@ impl Backtraced {
where
S: ToString,
{
Self {
message: message.to_string(),
help,
code,
code_identifier,
type_,
error,
backtrace,
}
Self { message: message.to_string(), help, code, code_identifier, type_, error, backtrace }
}
/// Gets the backtraced error exit code.
@ -113,11 +105,7 @@ impl Backtraced {
impl fmt::Display for Backtraced {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (kind, code) = if self.error {
("Error", self.error_code())
} else {
("Warning", self.warning_code())
};
let (kind, code) = if self.error { ("Error", self.error_code()) } else { ("Warning", self.warning_code()) };
let message = format!("{kind} [{code}]: {message}", message = self.message,);
// To avoid the color enabling characters for comparison with test expectations.
@ -144,17 +132,13 @@ impl fmt::Display for Backtraced {
"1" => {
let mut printer = BacktracePrinter::default();
printer = printer.lib_verbosity(Verbosity::Medium);
let trace = printer
.format_trace_to_string(&self.backtrace)
.map_err(|_| fmt::Error)?;
let trace = printer.format_trace_to_string(&self.backtrace).map_err(|_| fmt::Error)?;
write!(f, "{trace}")?;
}
"full" => {
let mut printer = BacktracePrinter::default();
printer = printer.lib_verbosity(Verbosity::Full);
let trace = printer
.format_trace_to_string(&self.backtrace)
.map_err(|_| fmt::Error)?;
let trace = printer.format_trace_to_string(&self.backtrace).map_err(|_| fmt::Error)?;
write!(f, "{trace}")?;
}
_ => {}

View File

@ -109,32 +109,20 @@ impl fmt::Display for Formatted {
let (loc, contents) = with_session_globals(|s| {
(
s.source_map
.span_to_location(self.span)
.unwrap_or_else(SpanLocation::dummy),
s.source_map
.line_contents_of_span(self.span)
.unwrap_or_else(|| "<contents unavailable>".to_owned()),
s.source_map.span_to_location(self.span).unwrap_or_else(SpanLocation::dummy),
s.source_map.line_contents_of_span(self.span).unwrap_or_else(|| "<contents unavailable>".to_owned()),
)
});
let underlined = underline(loc.col_start, loc.col_stop);
let (kind, code) = if self.backtrace.error {
("Error", self.error_code())
} else {
("Warning", self.warning_code())
};
let (kind, code) =
if self.backtrace.error { ("Error", self.error_code()) } else { ("Warning", self.warning_code()) };
let message = format!("{kind} [{code}]: {message}", message = self.backtrace.message,);
// To avoid the color enabling characters for comparison with test expectations.
if std::env::var("LEO_TESTFRAMEWORK")
.unwrap_or_default()
.trim()
.to_owned()
.is_empty()
{
if std::env::var("LEO_TESTFRAMEWORK").unwrap_or_default().trim().to_owned().is_empty() {
if self.backtrace.error {
write!(f, "{}", message.bold().red())?;
} else {
@ -180,18 +168,14 @@ impl fmt::Display for Formatted {
let mut printer = BacktracePrinter::default();
printer = printer.verbosity(Verbosity::Medium);
printer = printer.lib_verbosity(Verbosity::Medium);
let trace = printer
.format_trace_to_string(&self.backtrace.backtrace)
.map_err(|_| fmt::Error)?;
let trace = printer.format_trace_to_string(&self.backtrace.backtrace).map_err(|_| fmt::Error)?;
write!(f, "\n{trace}")?;
}
"full" => {
let mut printer = BacktracePrinter::default();
printer = printer.verbosity(Verbosity::Full);
printer = printer.lib_verbosity(Verbosity::Full);
let trace = printer
.format_trace_to_string(&self.backtrace.backtrace)
.map_err(|_| fmt::Error)?;
let trace = printer.format_trace_to_string(&self.backtrace.backtrace).map_err(|_| fmt::Error)?;
write!(f, "\n{trace}")?;
}
_ => {}

View File

@ -17,10 +17,8 @@
use crate::LeoWarning;
use super::LeoError;
use core::default::Default;
use core::fmt;
use std::cell::RefCell;
use std::rc::Rc;
use core::{default::Default, fmt};
use std::{cell::RefCell, rc::Rc};
/// Types that are sinks for compiler errors.
pub trait Emitter {
@ -182,11 +180,7 @@ impl Default for Handler {
impl Handler {
/// Construct a `Handler` using the given `emitter`.
pub fn new(emitter: Box<dyn Emitter>) -> Self {
let inner = RefCell::new(HandlerInner {
err_count: 0,
warn_count: 0,
emitter,
});
let inner = RefCell::new(HandlerInner { err_count: 0, warn_count: 0, emitter });
Self { inner }
}

View File

@ -14,14 +14,15 @@
// 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/>.
use crate::commands::ALEO_CLI_COMMAND;
use crate::{commands::Command, context::Context};
use crate::{
commands::{Command, ALEO_CLI_COMMAND},
context::Context,
};
use leo_ast::Struct;
use leo_compiler::{Compiler, CompilerOptions, InputAst};
use leo_errors::{CliError, CompilerError, PackageError, Result};
use leo_package::source::SourceDirectory;
use leo_package::{inputs::InputFile, outputs::OutputsDirectory};
use leo_package::{inputs::InputFile, outputs::OutputsDirectory, source::SourceDirectory};
use leo_span::symbol::with_session_globals;
use aleo::commands::Build as AleoBuild;
@ -29,12 +30,13 @@ use aleo::commands::Build as AleoBuild;
use clap::StructOpt;
use indexmap::IndexMap;
use snarkvm::prelude::{ProgramID, Testnet3};
use std::io::Write;
use std::path::{Path, PathBuf};
use std::{
io::Write,
path::{Path, PathBuf},
};
use leo_errors::emitter::Handler;
use leo_package::build::BuildDirectory;
use leo_package::imports::ImportsDirectory;
use leo_package::{build::BuildDirectory, imports::ImportsDirectory};
use leo_span::Symbol;
use tracing::span::Span;
@ -226,19 +228,14 @@ fn compile_leo_file(
is_import: bool,
) -> Result<IndexMap<Symbol, Struct>> {
// Construct the Leo file name with extension `foo.leo`.
let file_name = file_path
.file_name()
.and_then(|name| name.to_str())
.ok_or_else(PackageError::failed_to_get_file_name)?;
let file_name =
file_path.file_name().and_then(|name| name.to_str()).ok_or_else(PackageError::failed_to_get_file_name)?;
// If the program is an import, construct program name from file_path
// Otherwise, use the program_id found in `package.json`.
let program_name = match is_import {
false => program_id.name().to_string(),
true => file_name
.strip_suffix(".leo")
.ok_or_else(PackageError::failed_to_get_file_name)?
.to_string(),
true => file_name.strip_suffix(".leo").ok_or_else(PackageError::failed_to_get_file_name)?.to_string(),
};
// Create the path to the Aleo file.

View File

@ -16,8 +16,7 @@
use crate::{commands::Command, context::Context};
use leo_errors::Result;
use leo_package::build::BuildDirectory;
use leo_package::outputs::OutputsDirectory;
use leo_package::{build::BuildDirectory, outputs::OutputsDirectory};
use clap::StructOpt;
use colored::Colorize;

View File

@ -14,8 +14,10 @@
// 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/>.
use crate::commands::ALEO_CLI_COMMAND;
use crate::{commands::Command, context::Context};
use crate::{
commands::{Command, ALEO_CLI_COMMAND},
context::Context,
};
use leo_errors::{CliError, PackageError, Result};
use leo_package::build::BuildDirectory;

View File

@ -14,14 +14,12 @@
// 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/>.
use crate::commands::Network;
use crate::{
commands::{Command, ALEO_CLI_COMMAND},
commands::{Command, Network, ALEO_CLI_COMMAND},
context::Context,
};
use leo_errors::{CliError, PackageError, Result};
use leo_package::build::BUILD_DIRECTORY_NAME;
use leo_package::package::Package;
use leo_package::{build::BUILD_DIRECTORY_NAME, package::Package};
use snarkvm::file::AleoFile;
use aleo::commands::New as AleoNew;
@ -97,9 +95,7 @@ impl Command for New {
aleo_file_path.push(AleoFile::<Network>::main_file_name());
// Remove the Aleo file from the package directory.
aleo_file
.remove(&aleo_file_path)
.map_err(PackageError::failed_to_remove_aleo_file)?;
aleo_file.remove(&aleo_file_path).map_err(PackageError::failed_to_remove_aleo_file)?;
Ok(())
}

View File

@ -15,9 +15,8 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use super::build::BuildOptions;
use crate::commands::ALEO_CLI_COMMAND;
use crate::{
commands::{Build, Command},
commands::{Build, Command, ALEO_CLI_COMMAND},
context::Context,
};
use leo_errors::{CliError, PackageError, Result};
@ -34,10 +33,7 @@ pub struct Run {
#[structopt(name = "NAME", help = "The name of the program to run.", default_value = "main")]
name: String,
#[structopt(
name = "INPUTS",
help = "The inputs to the program. If none are provided, the input file is used."
)]
#[structopt(name = "INPUTS", help = "The inputs to the program. If none are provided, the input file is used.")]
inputs: Vec<String>,
#[structopt(flatten)]
@ -53,10 +49,7 @@ impl Command for Run {
}
fn prelude(&self, context: Context) -> Result<Self::Input> {
(Build {
options: self.compiler_options.clone(),
})
.execute(context)
(Build { options: self.compiler_options.clone() }).execute(context)
}
fn apply(self, context: Context, input: Self::Input) -> Result<Self::Output> {

View File

@ -19,10 +19,10 @@ use leo_errors::{CliError, PackageError, Result};
use snarkvm::file::Manifest;
use leo_package::build::{BuildDirectory, BUILD_DIRECTORY_NAME};
use std::fs::File;
use std::io::Write;
use std::{
env::current_dir,
fs::File,
io::Write,
path::{Path, PathBuf},
};

View File

@ -125,10 +125,7 @@ impl<F, T> Format<F, T> {
///
/// [thread ID]: https://doc.rust-lang.org/stable/std/thread/struct.ThreadId.html
pub fn with_thread_ids(self, display_thread_id: bool) -> Format<F, T> {
Format {
display_thread_id,
..self
}
Format { display_thread_id, ..self }
}
/// Sets whether or not the [name] of the current thread is displayed
@ -136,10 +133,7 @@ impl<F, T> Format<F, T> {
///
/// [name]: https://doc.rust-lang.org/stable/std/thread/index.html#naming-threads
pub fn with_thread_names(self, display_thread_name: bool) -> Format<F, T> {
Format {
display_thread_name,
..self
}
Format { display_thread_name, ..self }
}
}

View File

@ -19,14 +19,12 @@ pub mod context;
pub mod logger;
pub mod updater;
use crate::commands::*;
use crate::context::*;
use crate::{commands::*, context::*};
use leo_errors::Result;
use leo_span::symbol::create_session_if_not_set_then;
use clap::StructOpt;
use std::path::PathBuf;
use std::process::exit;
use std::{path::PathBuf, process::exit};
/// CLI Arguments entry point - includes global parameters and subcommands
#[derive(StructOpt, Debug)]
@ -44,12 +42,7 @@ pub struct CLI {
#[structopt(help = "Custom Aleo PM backend URL", env = "APM_URL")]
api: Option<String>,
#[structopt(
long,
global = true,
help = "Optional path to Leo program root folder",
parse(from_os_str)
)]
#[structopt(long, global = true, help = "Optional path to Leo program root folder", parse(from_os_str))]
path: Option<PathBuf>,
}
@ -95,15 +88,13 @@ fn set_panic_hook() {
#[cfg(not(debug_assertions))]
std::panic::set_hook({
Box::new(move |e| {
eprintln!(
"thread `{}` {}",
std::thread::current().name().unwrap_or("<unnamed>"),
e
);
eprintln!("thread `{}` {}", std::thread::current().name().unwrap_or("<unnamed>"), e);
eprintln!("stack backtrace: \n{:?}", backtrace::Backtrace::new());
eprintln!("error: internal compiler error: unexpected panic\n");
eprintln!("note: the compiler unexpectedly panicked. this is a bug.\n");
eprintln!("note: we would appreciate a bug report: https://github.com/AleoHQ/leo/issues/new?labels=bug,panic&template=bug.md&title=[Bug]\n");
eprintln!(
"note: we would appreciate a bug report: https://github.com/AleoHQ/leo/issues/new?labels=bug,panic&template=bug.md&title=[Bug]\n"
);
eprintln!(
"note: {} {} running on {} {}\n",
env!("CARGO_PKG_NAME"),
@ -111,10 +102,7 @@ fn set_panic_hook() {
sys_info::os_type().unwrap_or_else(|e| e.to_string()),
sys_info::os_release().unwrap_or_else(|e| e.to_string()),
);
eprintln!(
"note: compiler args: {}\n",
std::env::args().collect::<Vec<_>>().join(" ")
);
eprintln!("note: compiler args: {}\n", std::env::args().collect::<Vec<_>>().join(" "));
eprintln!("note: compiler flags: {:?}\n", CLI::parse());
})
});
@ -134,13 +122,10 @@ pub fn handle_error<T>(res: Result<T>) -> T {
pub fn run_with_args(cli: CLI) -> Result<()> {
if !cli.quiet {
// Init logger with optional debug flag.
logger::init_logger(
"leo",
match cli.debug {
false => 1,
true => 2,
},
)?;
logger::init_logger("leo", match cli.debug {
false => 1,
true => 2,
})?;
}
// Get custom root folder and create context for it.

View File

@ -16,8 +16,11 @@
use leo_errors::{PackageError, Result};
use std::path::PathBuf;
use std::{borrow::Cow, fs, path::Path};
use std::{
borrow::Cow,
fs,
path::{Path, PathBuf},
};
pub static BUILD_DIRECTORY_NAME: &str = "build/";

View File

@ -17,8 +17,11 @@
use crate::parse_file_paths;
use leo_errors::{PackageError, Result};
use std::path::PathBuf;
use std::{borrow::Cow, fs, path::Path};
use std::{
borrow::Cow,
fs,
path::{Path, PathBuf},
};
pub static IMPORTS_DIRECTORY_NAME: &str = "imports/";

View File

@ -24,7 +24,8 @@ use serde::Deserialize;
use std::{
borrow::Cow,
fs::{
File, {self},
File,
{self},
},
io::Write,
path::Path,
@ -39,9 +40,7 @@ pub struct InputFile {
impl InputFile {
pub fn new(package_name: &str) -> Self {
Self {
package_name: package_name.to_string(),
}
Self { package_name: package_name.to_string() }
}
pub fn filename(&self) -> String {
@ -67,8 +66,7 @@ impl InputFile {
let path = self.setup_file_path(path);
let mut file = File::create(path).map_err(PackageError::io_error_input_file)?;
file.write_all(self.template().as_bytes())
.map_err(PackageError::io_error_input_file)?;
file.write_all(self.template().as_bytes()).map_err(PackageError::io_error_input_file)?;
Ok(())
}
@ -89,8 +87,7 @@ b: u32 = 2u32;
if !path.ends_with(INPUTS_DIRECTORY_NAME) {
path.to_mut().push(INPUTS_DIRECTORY_NAME);
}
path.to_mut()
.push(format!("{}{INPUT_FILE_EXTENSION}", self.package_name));
path.to_mut().push(format!("{}{INPUT_FILE_EXTENSION}", self.package_name));
}
path
}

View File

@ -27,8 +27,7 @@ pub mod source;
use leo_errors::{PackageError, Result};
use std::fs::ReadDir;
use std::{fs, path::PathBuf};
use std::{fs, fs::ReadDir, path::PathBuf};
pub static LEO_FILE_EXTENSION: &str = ".leo";

View File

@ -33,16 +33,12 @@ pub enum Snapshot {
impl fmt::Display for Snapshot {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}",
match self {
Self::Initial => "initial_ast",
Self::ImportsResolved => "imports_resolved_ast",
Self::TypeInference => "type_inferenced_ast",
Self::Canonicalization => "canonicalization_ast",
}
)
write!(f, "{}", match self {
Self::Initial => "initial_ast",
Self::ImportsResolved => "imports_resolved_ast",
Self::TypeInference => "type_inferenced_ast",
Self::Canonicalization => "canonicalization_ast",
})
}
}
@ -58,10 +54,7 @@ pub struct SnapshotFile {
impl SnapshotFile {
pub fn new(package_name: &str, snapshot: Snapshot) -> Self {
Self {
package_name: package_name.to_string(),
snapshot,
}
Self { package_name: package_name.to_string(), snapshot }
}
pub fn exists_at(&self, path: &Path) -> bool {
@ -97,8 +90,7 @@ impl SnapshotFile {
if !path.ends_with(OUTPUTS_DIRECTORY_NAME) {
path.to_mut().push(OUTPUTS_DIRECTORY_NAME);
}
path.to_mut()
.push(format!("{}{AST_SNAPSHOT_FILE_EXTENSION}", self.snapshot));
path.to_mut().push(format!("{}{AST_SNAPSHOT_FILE_EXTENSION}", self.snapshot));
}
path
}

View File

@ -23,7 +23,8 @@ use serde::Deserialize;
use std::{
borrow::Cow,
fs::{
File, {self},
File,
{self},
},
io::Write,
path::Path,
@ -38,9 +39,7 @@ pub struct ChecksumFile {
impl ChecksumFile {
pub fn new(package_name: &str) -> Self {
Self {
package_name: package_name.to_string(),
}
Self { package_name: package_name.to_string() }
}
pub fn exists_at(&self, path: &Path) -> bool {
@ -62,8 +61,7 @@ impl ChecksumFile {
let path = self.setup_file_path(path);
let mut file = File::create(path).map_err(PackageError::io_error_checksum_file)?;
file.write_all(checksum.as_bytes())
.map_err(PackageError::io_error_checksum_file)?;
file.write_all(checksum.as_bytes()).map_err(PackageError::io_error_checksum_file)?;
Ok(())
}
@ -85,8 +83,7 @@ impl ChecksumFile {
if !path.ends_with(OUTPUTS_DIRECTORY_NAME) {
path.to_mut().push(OUTPUTS_DIRECTORY_NAME);
}
path.to_mut()
.push(format!("{}{CHECKSUM_FILE_EXTENSION}", self.package_name));
path.to_mut().push(format!("{}{CHECKSUM_FILE_EXTENSION}", self.package_name));
}
path
}

View File

@ -23,7 +23,8 @@ use serde::Deserialize;
use std::{
borrow::Cow,
fs::{
File, {self},
File,
{self},
},
io::Write,
path::Path,
@ -38,9 +39,7 @@ pub struct CircuitFile {
impl CircuitFile {
pub fn new(package_name: &str) -> Self {
Self {
package_name: package_name.to_string(),
}
Self { package_name: package_name.to_string() }
}
pub fn exists_at(&self, path: &Path) -> bool {
@ -62,8 +61,7 @@ impl CircuitFile {
let path = self.setup_file_path(path);
let mut file = File::create(path).map_err(PackageError::io_error_circuit_file)?;
file.write_all(circuit.as_bytes())
.map_err(PackageError::io_error_circuit_file)?;
file.write_all(circuit.as_bytes()).map_err(PackageError::io_error_circuit_file)?;
Ok(())
}
@ -85,8 +83,7 @@ impl CircuitFile {
if !path.ends_with(OUTPUTS_DIRECTORY_NAME) {
path.to_mut().push(OUTPUTS_DIRECTORY_NAME);
}
path.to_mut()
.push(format!("{}{CIRCUIT_FILE_EXTENSION}", self.package_name));
path.to_mut().push(format!("{}{CIRCUIT_FILE_EXTENSION}", self.package_name));
}
path
}

View File

@ -16,8 +16,11 @@
use leo_errors::{PackageError, Result};
use std::path::PathBuf;
use std::{borrow::Cow, fs, path::Path};
use std::{
borrow::Cow,
fs,
path::{Path, PathBuf},
};
pub static OUTPUTS_DIRECTORY_NAME: &str = "outputs/";

View File

@ -41,12 +41,7 @@ impl Package {
return Err(PackageError::invalid_package_name(package_name).into());
}
Ok(Self {
name: package_name.to_owned(),
version: "0.1.0".to_owned(),
description: None,
license: None,
})
Ok(Self { name: package_name.to_owned(), version: "0.1.0".to_owned(), description: None, license: None })
}
/// Returns `true` if the package name is valid.

View File

@ -46,8 +46,7 @@ impl Gitignore {
}
let mut file = File::create(&path).map_err(PackageError::io_error_gitignore_file)?;
file.write_all(self.template().as_bytes())
.map_err(PackageError::io_error_gitignore_file)?;
file.write_all(self.template().as_bytes()).map_err(PackageError::io_error_gitignore_file)?;
Ok(())
}

View File

@ -31,9 +31,7 @@ pub struct MainFile {
impl MainFile {
pub fn new(package_name: &str) -> Self {
Self {
package_name: package_name.to_string(),
}
Self { package_name: package_name.to_string() }
}
pub fn filename() -> String {
@ -61,9 +59,7 @@ impl MainFile {
}
let mut file = File::create(&path).map_err(PackageError::io_error_main_file)?;
Ok(file
.write_all(self.template().as_bytes())
.map_err(PackageError::io_error_main_file)?)
Ok(file.write_all(self.template().as_bytes()).map_err(PackageError::io_error_main_file)?)
}
// TODO: Generalize to other networks.

View File

@ -104,10 +104,7 @@ impl Sample {
/// Leverages the test-framework to grab all tests
/// that are passing compiler tests or marked as benchmark tests.
fn load_samples() -> Vec<Self> {
get_benches()
.into_iter()
.map(|(name, input)| Self { name, input })
.collect()
get_benches().into_iter().map(|(name, input)| Self { name, input }).collect()
}
fn data(&self) -> (&str, FileName) {
@ -147,9 +144,7 @@ impl Sample {
fn bencher_after_parse(&self, c: &mut Criterion, mode: &str, mut logic: impl FnMut(Compiler) -> Duration) {
self.bencher(c, mode, |mut compiler| {
let (input, name) = self.data();
compiler
.parse_program_from_string(input, name)
.expect("Failed to parse program");
compiler.parse_program_from_string(input, name).expect("Failed to parse program");
logic(compiler)
});
}
@ -189,9 +184,8 @@ impl Sample {
fn bench_loop_unroller(&self, c: &mut Criterion) {
self.bencher_after_parse(c, "loop unrolling pass", |mut compiler| {
let symbol_table = compiler.symbol_table_pass().expect("failed to generate symbol table");
let (symbol_table, _struct_graph, _call_graph) = compiler
.type_checker_pass(symbol_table)
.expect("failed to run type check pass");
let (symbol_table, _struct_graph, _call_graph) =
compiler.type_checker_pass(symbol_table).expect("failed to run type check pass");
let start = Instant::now();
let out = compiler.loop_unrolling_pass(symbol_table);
let time = start.elapsed();
@ -203,12 +197,9 @@ impl Sample {
fn bench_ssa(&self, c: &mut Criterion) {
self.bencher_after_parse(c, "full", |mut compiler| {
let symbol_table = compiler.symbol_table_pass().expect("failed to generate symbol table");
let (symbol_table, _struct_graph, _call_graph) = compiler
.type_checker_pass(symbol_table)
.expect("failed to run type check pass");
let symbol_table = compiler
.loop_unrolling_pass(symbol_table)
.expect("failed to run loop unrolling pass");
let (symbol_table, _struct_graph, _call_graph) =
compiler.type_checker_pass(symbol_table).expect("failed to run type check pass");
let symbol_table = compiler.loop_unrolling_pass(symbol_table).expect("failed to run loop unrolling pass");
let start = Instant::now();
let out = compiler.static_single_assignment_pass(&symbol_table);
let time = start.elapsed();
@ -220,15 +211,10 @@ impl Sample {
fn bench_flattener(&self, c: &mut Criterion) {
self.bencher_after_parse(c, "flattener pass", |mut compiler| {
let symbol_table = compiler.symbol_table_pass().expect("failed to generate symbol table");
let (symbol_table, _struct_graph, _call_graph) = compiler
.type_checker_pass(symbol_table)
.expect("failed to run type check pass");
let symbol_table = compiler
.loop_unrolling_pass(symbol_table)
.expect("failed to run loop unrolling pass");
let assigner = compiler
.static_single_assignment_pass(&symbol_table)
.expect("failed to run ssa pass");
let (symbol_table, _struct_graph, _call_graph) =
compiler.type_checker_pass(symbol_table).expect("failed to run type check pass");
let symbol_table = compiler.loop_unrolling_pass(symbol_table).expect("failed to run loop unrolling pass");
let assigner = compiler.static_single_assignment_pass(&symbol_table).expect("failed to run ssa pass");
let start = Instant::now();
let out = compiler.flattening_pass(&symbol_table, assigner);
let time = start.elapsed();
@ -240,18 +226,11 @@ impl Sample {
fn bench_inline(&self, c: &mut Criterion) {
self.bencher_after_parse(c, "inliner pass", |mut compiler| {
let symbol_table = compiler.symbol_table_pass().expect("failed to generate symbol table");
let (symbol_table, _struct_graph, call_graph) = compiler
.type_checker_pass(symbol_table)
.expect("failed to run type check pass");
let symbol_table = compiler
.loop_unrolling_pass(symbol_table)
.expect("failed to run loop unrolling pass");
let assigner = compiler
.static_single_assignment_pass(&symbol_table)
.expect("failed to run ssa pass");
let assigner = compiler
.flattening_pass(&symbol_table, assigner)
.expect("failed to run flattener pass");
let (symbol_table, _struct_graph, call_graph) =
compiler.type_checker_pass(symbol_table).expect("failed to run type check pass");
let symbol_table = compiler.loop_unrolling_pass(symbol_table).expect("failed to run loop unrolling pass");
let assigner = compiler.static_single_assignment_pass(&symbol_table).expect("failed to run ssa pass");
let assigner = compiler.flattening_pass(&symbol_table, assigner).expect("failed to run flattener pass");
let start = Instant::now();
let out = compiler.function_inlining_pass(&call_graph, assigner);
let time = start.elapsed();
@ -263,21 +242,12 @@ impl Sample {
fn bench_dce(&self, c: &mut Criterion) {
self.bencher_after_parse(c, "inliner pass", |mut compiler| {
let symbol_table = compiler.symbol_table_pass().expect("failed to generate symbol table");
let (symbol_table, _struct_graph, call_graph) = compiler
.type_checker_pass(symbol_table)
.expect("failed to run type check pass");
let symbol_table = compiler
.loop_unrolling_pass(symbol_table)
.expect("failed to run loop unrolling pass");
let assigner = compiler
.static_single_assignment_pass(&symbol_table)
.expect("failed to run ssa pass");
let assigner = compiler
.flattening_pass(&symbol_table, assigner)
.expect("failed to run flattener pass");
let _ = compiler
.function_inlining_pass(&call_graph, assigner)
.expect("failed to run inliner pass");
let (symbol_table, _struct_graph, call_graph) =
compiler.type_checker_pass(symbol_table).expect("failed to run type check pass");
let symbol_table = compiler.loop_unrolling_pass(symbol_table).expect("failed to run loop unrolling pass");
let assigner = compiler.static_single_assignment_pass(&symbol_table).expect("failed to run ssa pass");
let assigner = compiler.flattening_pass(&symbol_table, assigner).expect("failed to run flattener pass");
let _ = compiler.function_inlining_pass(&call_graph, assigner).expect("failed to run inliner pass");
let start = Instant::now();
let out = compiler.dead_code_elimination_pass();
let time = start.elapsed();
@ -289,21 +259,12 @@ impl Sample {
fn bench_codegen(&self, c: &mut Criterion) {
self.bencher_after_parse(c, "inliner pass", |mut compiler| {
let symbol_table = compiler.symbol_table_pass().expect("failed to generate symbol table");
let (symbol_table, struct_graph, call_graph) = compiler
.type_checker_pass(symbol_table)
.expect("failed to run type check pass");
let symbol_table = compiler
.loop_unrolling_pass(symbol_table)
.expect("failed to run loop unrolling pass");
let assigner = compiler
.static_single_assignment_pass(&symbol_table)
.expect("failed to run ssa pass");
let assigner = compiler
.flattening_pass(&symbol_table, assigner)
.expect("failed to run flattener pass");
let _ = compiler
.function_inlining_pass(&call_graph, assigner)
.expect("failed to run inliner pass");
let (symbol_table, struct_graph, call_graph) =
compiler.type_checker_pass(symbol_table).expect("failed to run type check pass");
let symbol_table = compiler.loop_unrolling_pass(symbol_table).expect("failed to run loop unrolling pass");
let assigner = compiler.static_single_assignment_pass(&symbol_table).expect("failed to run ssa pass");
let assigner = compiler.flattening_pass(&symbol_table, assigner).expect("failed to run flattener pass");
let _ = compiler.function_inlining_pass(&call_graph, assigner).expect("failed to run inliner pass");
compiler.dead_code_elimination_pass().expect("failed to run dce pass");
let start = Instant::now();
let out = compiler.code_generation_pass(&symbol_table, &struct_graph, &call_graph);
@ -317,25 +278,14 @@ impl Sample {
self.bencher(c, "full", |mut compiler| {
let (input, name) = self.data();
let start = Instant::now();
compiler
.parse_program_from_string(input, name)
.expect("Failed to parse program");
compiler.parse_program_from_string(input, name).expect("Failed to parse program");
let symbol_table = compiler.symbol_table_pass().expect("failed to generate symbol table");
let (symbol_table, struct_graph, call_graph) = compiler
.type_checker_pass(symbol_table)
.expect("failed to run type check pass");
let symbol_table = compiler
.loop_unrolling_pass(symbol_table)
.expect("failed to run loop unrolling pass");
let assigner = compiler
.static_single_assignment_pass(&symbol_table)
.expect("failed to run ssa pass");
let assigner = compiler
.flattening_pass(&symbol_table, assigner)
.expect("failed to run flattening pass");
compiler
.function_inlining_pass(&call_graph, assigner)
.expect("failed to run function inlining pass");
let (symbol_table, struct_graph, call_graph) =
compiler.type_checker_pass(symbol_table).expect("failed to run type check pass");
let symbol_table = compiler.loop_unrolling_pass(symbol_table).expect("failed to run loop unrolling pass");
let assigner = compiler.static_single_assignment_pass(&symbol_table).expect("failed to run ssa pass");
let assigner = compiler.flattening_pass(&symbol_table, assigner).expect("failed to run flattening pass");
compiler.function_inlining_pass(&call_graph, assigner).expect("failed to run function inlining pass");
compiler.dead_code_elimination_pass().expect("failed to run dce pass");
compiler
.code_generation_pass(&symbol_table, &struct_graph, &call_graph)

View File

@ -27,32 +27,11 @@ pub struct TestFailure {
#[derive(Debug)]
pub enum TestError {
Panicked {
test: String,
index: usize,
error: String,
},
UnexpectedOutput {
test: String,
index: usize,
expected: Value,
output: Value,
},
PassedAndShouldntHave {
test: String,
index: usize,
},
FailedAndShouldntHave {
test: String,
index: usize,
error: String,
},
UnexpectedError {
test: String,
index: usize,
expected: String,
output: String,
},
Panicked { test: String, index: usize, error: String },
UnexpectedOutput { test: String, index: usize, expected: Value, output: Value },
PassedAndShouldntHave { test: String, index: usize },
FailedAndShouldntHave { test: String, index: usize, error: String },
UnexpectedError { test: String, index: usize, expected: String, output: String },
MismatchedTestExpectationLength,
MissingTestConfig,
}
@ -60,28 +39,13 @@ pub enum TestError {
impl fmt::Display for TestError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let format_test = |test: &str| -> String {
if test.len() > 50 {
String::new()
} else {
format!("\n\n{test}\n\n")
}
if test.len() > 50 { String::new() } else { format!("\n\n{test}\n\n") }
};
match self {
TestError::Panicked { test, index, error } => {
write!(
f,
"test #{}: {}encountered a rust panic:\n{}",
index + 1,
format_test(test),
error
)
write!(f, "test #{}: {}encountered a rust panic:\n{}", index + 1, format_test(test), error)
}
TestError::UnexpectedOutput {
test,
index,
expected,
output,
} => {
TestError::UnexpectedOutput { test, index, expected, output } => {
write!(
f,
"test #{}: {}expected\n{}\ngot\n{}",
@ -95,28 +59,10 @@ impl fmt::Display for TestError {
write!(f, "test #{}: {}passed and shouldn't have", index + 1, format_test(test))
}
TestError::FailedAndShouldntHave { test, index, error } => {
write!(
f,
"test #{}: {}failed and shouldn't have:\n{}",
index + 1,
format_test(test),
error
)
write!(f, "test #{}: {}failed and shouldn't have:\n{}", index + 1, format_test(test), error)
}
TestError::UnexpectedError {
test,
expected,
output,
index,
} => {
write!(
f,
"test #{}: {}expected error\n{}\ngot\n{}",
index + 1,
format_test(test),
expected,
output
)
TestError::UnexpectedError { test, expected, output, index } => {
write!(f, "test #{}: {}expected error\n{}\ngot\n{}", index + 1, format_test(test), expected, output)
}
TestError::MismatchedTestExpectationLength => write!(f, "invalid number of test expectations"),
TestError::MissingTestConfig => write!(f, "missing test config"),
@ -132,11 +78,7 @@ pub fn emit_errors(
test_index: usize,
) -> Option<TestError> {
match (output, mode) {
(Err(e), _) => Some(TestError::Panicked {
test: test.to_string(),
index: test_index,
error: e.to_string(),
}),
(Err(e), _) => Some(TestError::Panicked { test: test.to_string(), index: test_index, error: e.to_string() }),
(Ok(Ok(output)), TestExpectationMode::Pass) => {
// passed and should have
if let Some(expected_output) = expected_output.as_ref() {
@ -152,15 +94,12 @@ pub fn emit_errors(
}
None
}
(Ok(Ok(_tokens)), TestExpectationMode::Fail) => Some(TestError::PassedAndShouldntHave {
test: test.to_string(),
index: test_index,
}),
(Ok(Err(err)), TestExpectationMode::Pass) => Some(TestError::FailedAndShouldntHave {
test: test.to_string(),
error: err.to_string(),
index: test_index,
}),
(Ok(Ok(_tokens)), TestExpectationMode::Fail) => {
Some(TestError::PassedAndShouldntHave { test: test.to_string(), index: test_index })
}
(Ok(Err(err)), TestExpectationMode::Pass) => {
Some(TestError::FailedAndShouldntHave { test: test.to_string(), error: err.to_string(), index: test_index })
}
(Ok(Err(err)), TestExpectationMode::Fail) => {
let expected_output: Option<String> =
expected_output.map(|x| serde_yaml::from_value(x).expect("test expectation deserialize failed"));

Some files were not shown because too many files have changed in this diff Show More