mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-24 07:48:04 +03:00
rename static-check -> symbol-table 1
This commit is contained in:
parent
833eb51c68
commit
20ac83265d
@ -29,7 +29,7 @@ use leo_imports::ImportParser;
|
||||
use leo_input::LeoInputParser;
|
||||
use leo_package::inputs::InputPairs;
|
||||
use leo_state::verify_local_data_commitment;
|
||||
use leo_static_check::StaticCheck;
|
||||
use leo_static_check::{StaticCheck, SymbolTable};
|
||||
use leo_typed::{Input, LeoTypedAst, MainInput, Program};
|
||||
|
||||
use snarkos_dpc::{base_dpc::instantiated::Components, SystemParameters};
|
||||
@ -190,11 +190,20 @@ impl<F: Field + PrimeField, G: GroupType<F>> Compiler<F, G> {
|
||||
/// Runs static and dynamic type checks on the program, imports, and input.
|
||||
///
|
||||
pub(crate) fn check_program(&self) -> Result<(), CompilerError> {
|
||||
// Run static check on program.
|
||||
let symbol_table = StaticCheck::new(&self.program, &self.imported_programs, &self.program_input)?;
|
||||
// Create a new symbol table from the program, imported_programs, and program_input.
|
||||
let symbol_table =
|
||||
SymbolTable::run(&self.program, &self.imported_programs, &self.program_input).map_err(|mut e| {
|
||||
e.set_path(&self.main_file_path);
|
||||
|
||||
e
|
||||
})?;
|
||||
|
||||
// Run dynamic check on program.
|
||||
DynamicCheck::new(&self.program, symbol_table)?;
|
||||
DynamicCheck::new(&self.program, symbol_table).map_err(|mut e| {
|
||||
e.set_path(&self.main_file_path);
|
||||
|
||||
e
|
||||
})?;
|
||||
|
||||
tracing::debug!("Program checks complete");
|
||||
|
||||
|
@ -22,7 +22,7 @@ use leo_state::LocalDataVerificationError;
|
||||
|
||||
use bincode::Error as SerdeError;
|
||||
use leo_dynamic_check::DynamicCheckError;
|
||||
use leo_static_check::StaticCheckError;
|
||||
use leo_static_check::{StaticCheckError, SymbolTableError};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
@ -74,14 +74,19 @@ pub enum CompilerError {
|
||||
|
||||
#[error("{}", _0)]
|
||||
StaticCheckError(#[from] StaticCheckError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
SymbolTableError(#[from] SymbolTableError),
|
||||
}
|
||||
|
||||
impl CompilerError {
|
||||
pub fn set_path(&mut self, path: &Path) {
|
||||
match self {
|
||||
CompilerError::DynamicCheckError(error) => error.set_path(path),
|
||||
CompilerError::InputParserError(error) => error.set_path(path),
|
||||
CompilerError::FunctionError(error) => error.set_path(path),
|
||||
CompilerError::OutputStringError(error) => error.set_path(path),
|
||||
CompilerError::SymbolTableError(error) => error.set_path(path),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +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::{ParameterType, TypeError};
|
||||
use crate::{TypeError, UserDefinedType};
|
||||
use leo_core::{CorePackageListError, LeoCoreError};
|
||||
use leo_typed::{Error as FormattedError, ImportSymbol, Program, Span};
|
||||
|
||||
@ -59,7 +59,7 @@ impl SymbolTableError {
|
||||
///
|
||||
/// Two circuits have been defined with the same name.
|
||||
///
|
||||
pub fn duplicate_circuit(variable: ParameterType) -> Self {
|
||||
pub fn duplicate_circuit(variable: UserDefinedType) -> Self {
|
||||
let message = format!("Duplicate circuit definition found for `{}`", variable.identifier);
|
||||
|
||||
Self::new_from_span(message, variable.identifier.span)
|
||||
@ -68,7 +68,7 @@ impl SymbolTableError {
|
||||
///
|
||||
/// Two functions have been defined with the same name.
|
||||
///
|
||||
pub fn duplicate_function(variable: ParameterType) -> Self {
|
||||
pub fn duplicate_function(variable: UserDefinedType) -> Self {
|
||||
let message = format!("Duplicate function definition found for `{}`", variable.identifier);
|
||||
|
||||
Self::new_from_span(message, variable.identifier.span)
|
||||
|
@ -14,7 +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::{CircuitType, CircuitVariableType, FunctionType, ImportedSymbols, ParameterType, SymbolTableError};
|
||||
use crate::{CircuitType, CircuitVariableType, FunctionType, ImportedSymbols, SymbolTableError, UserDefinedType};
|
||||
use leo_core::CorePackageList;
|
||||
use leo_imports::ImportParser;
|
||||
use leo_typed::{Circuit, Function, Identifier, ImportStatement, ImportSymbol, Input, Package, Program};
|
||||
@ -33,10 +33,10 @@ pub const STATE_LEAF_VARIABLE_NAME: &str = "state_leaf";
|
||||
/// parent's symbol table.
|
||||
/// A symbol table cannot access names in its child's symbol table.
|
||||
/// Children cannot access names in another sibling's symbol table.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default)]
|
||||
pub struct SymbolTable {
|
||||
/// Maps name -> parameter type.
|
||||
names: HashMap<String, ParameterType>,
|
||||
names: HashMap<String, UserDefinedType>,
|
||||
|
||||
/// Maps circuit name -> circuit type.
|
||||
circuits: HashMap<String, CircuitType>,
|
||||
@ -61,6 +61,35 @@ impl SymbolTable {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns a new `SymbolTable` from a given, program, imported programs, and program input.
|
||||
///
|
||||
/// Checks that each circuit or function name is unique.
|
||||
/// Unique names are added to a table of name -> user defined type.
|
||||
///
|
||||
/// Checks that each circuit or function definition contains valid types.
|
||||
///
|
||||
///
|
||||
pub fn run(
|
||||
program: &Program,
|
||||
import_parser: &ImportParser,
|
||||
input: &Input,
|
||||
) -> Result<SymbolTable, SymbolTableError> {
|
||||
// Create a new symbol table.
|
||||
let mut table = Self::default();
|
||||
|
||||
// Insert input types into symbol table.
|
||||
table.insert_input(input)?;
|
||||
|
||||
// Check for duplicate program and import names.
|
||||
table.check_names(program, import_parser)?;
|
||||
|
||||
// Check for unknown or invalid types.
|
||||
table.check_types(program)?;
|
||||
|
||||
Ok(table)
|
||||
}
|
||||
|
||||
///
|
||||
/// Insert a function or circuit name into the symbol table from a given name and variable type.
|
||||
///
|
||||
@ -68,7 +97,7 @@ impl SymbolTable {
|
||||
/// If the symbol table did have this name present, the variable type is updated, and the old
|
||||
/// variable type is returned.
|
||||
///
|
||||
pub fn insert_name(&mut self, name: String, variable_type: ParameterType) -> Option<ParameterType> {
|
||||
pub fn insert_name(&mut self, name: String, variable_type: UserDefinedType) -> Option<UserDefinedType> {
|
||||
self.names.insert(name, variable_type)
|
||||
}
|
||||
|
||||
@ -77,7 +106,11 @@ impl SymbolTable {
|
||||
///
|
||||
/// Returns an error if the circuit name is a duplicate.
|
||||
///
|
||||
pub fn insert_circuit_name(&mut self, name: String, variable_type: ParameterType) -> Result<(), SymbolTableError> {
|
||||
pub fn insert_circuit_name(
|
||||
&mut self,
|
||||
name: String,
|
||||
variable_type: UserDefinedType,
|
||||
) -> Result<(), SymbolTableError> {
|
||||
// Check that the circuit name is unique.
|
||||
match self.insert_name(name, variable_type) {
|
||||
Some(duplicate) => Err(SymbolTableError::duplicate_circuit(duplicate)),
|
||||
@ -90,7 +123,11 @@ impl SymbolTable {
|
||||
///
|
||||
/// Returns an error if the function name is a duplicate.
|
||||
///
|
||||
pub fn insert_function_name(&mut self, name: String, variable_type: ParameterType) -> Result<(), SymbolTableError> {
|
||||
pub fn insert_function_name(
|
||||
&mut self,
|
||||
name: String,
|
||||
variable_type: UserDefinedType,
|
||||
) -> Result<(), SymbolTableError> {
|
||||
// Check that the circuit name is unique.
|
||||
match self.insert_name(name, variable_type) {
|
||||
Some(duplicate) => Err(SymbolTableError::duplicate_function(duplicate)),
|
||||
@ -172,11 +209,7 @@ impl SymbolTable {
|
||||
/// If a circuit or function name has no duplicates, then it is inserted into the symbol table.
|
||||
/// Variables defined later in the unresolved program cannot have the same name.
|
||||
///
|
||||
pub fn check_program_names(
|
||||
&mut self,
|
||||
program: &Program,
|
||||
import_parser: &ImportParser,
|
||||
) -> Result<(), SymbolTableError> {
|
||||
pub fn check_names(&mut self, program: &Program, import_parser: &ImportParser) -> Result<(), SymbolTableError> {
|
||||
// Check unresolved program import names.
|
||||
self.check_import_names(&program.imports, import_parser)?;
|
||||
|
||||
@ -199,7 +232,7 @@ impl SymbolTable {
|
||||
// Iterate over circuit names and definitions.
|
||||
for (identifier, circuit) in circuits.iter() {
|
||||
// Attempt to insert the circuit name into the symbol table.
|
||||
self.insert_circuit_name(identifier.to_string(), ParameterType::from(circuit.clone()))?;
|
||||
self.insert_circuit_name(identifier.to_string(), UserDefinedType::from(circuit.clone()))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -215,7 +248,7 @@ impl SymbolTable {
|
||||
// Iterate over function names and definitions.
|
||||
for (identifier, function) in functions.iter() {
|
||||
// Attempt to insert the function name into the symbol table.
|
||||
self.insert_function_name(identifier.to_string(), ParameterType::from(function.clone()))?;
|
||||
self.insert_function_name(identifier.to_string(), UserDefinedType::from(function.clone()))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -279,7 +312,7 @@ impl SymbolTable {
|
||||
// Insert name and type information for each core package symbol.
|
||||
for (name, circuit) in symbol_list.symbols() {
|
||||
// Store name of symbol.
|
||||
self.insert_circuit_name(name.to_string(), ParameterType::from(circuit.clone()))?;
|
||||
self.insert_circuit_name(name.to_string(), UserDefinedType::from(circuit.clone()))?;
|
||||
|
||||
// Create new circuit type for symbol.
|
||||
let circuit_type = CircuitType::new(&self, circuit.to_owned())?;
|
||||
@ -323,10 +356,10 @@ impl SymbolTable {
|
||||
};
|
||||
|
||||
// Check the imported program for duplicate types.
|
||||
self.check_program_names(program, import_parser)?;
|
||||
self.check_names(program, import_parser)?;
|
||||
|
||||
// Check the imported program for undefined types.
|
||||
self.check_types_program(program)?;
|
||||
self.check_types(program)?;
|
||||
|
||||
// Store the imported symbol.
|
||||
// self.insert_import_symbol(symbol, program)?; // TODO (collinc97) uncomment this line when public/private import scopes are implemented.
|
||||
@ -354,14 +387,17 @@ impl SymbolTable {
|
||||
match program.circuits.get(&symbol.symbol) {
|
||||
Some(circuit) => {
|
||||
// Insert imported circuit.
|
||||
self.insert_circuit_name(identifier.to_string(), ParameterType::from(circuit.to_owned()))
|
||||
self.insert_circuit_name(identifier.to_string(), UserDefinedType::from(circuit.to_owned()))
|
||||
}
|
||||
None => {
|
||||
// Check if the imported symbol is a function.
|
||||
match program.functions.get(&symbol.symbol) {
|
||||
Some(function) => {
|
||||
// Insert the imported function.
|
||||
self.insert_function_name(identifier.to_string(), ParameterType::from(function.to_owned()))
|
||||
self.insert_function_name(
|
||||
identifier.to_string(),
|
||||
UserDefinedType::from(function.to_owned()),
|
||||
)
|
||||
}
|
||||
None => Err(SymbolTableError::unknown_symbol(&symbol, program)),
|
||||
}
|
||||
@ -377,7 +413,7 @@ impl SymbolTable {
|
||||
/// symbol table. Variables defined later in the unresolved program can lookup the definition and
|
||||
/// refer to its expected types.
|
||||
///
|
||||
pub fn check_types_program(&mut self, program: &Program) -> Result<(), SymbolTableError> {
|
||||
pub fn check_types(&mut self, program: &Program) -> Result<(), SymbolTableError> {
|
||||
// Check unresolved program circuit definitions.
|
||||
self.check_types_circuits(&program.circuits)?;
|
||||
|
||||
|
@ -73,7 +73,7 @@ impl StaticCheck {
|
||||
///
|
||||
pub fn pass_one(&mut self, program: &Program, import_parser: &ImportParser) -> Result<(), StaticCheckError> {
|
||||
self.table
|
||||
.check_program_names(program, import_parser)
|
||||
.check_names(program, import_parser)
|
||||
.map_err(|err| StaticCheckError::SymbolTableError(err))
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ impl StaticCheck {
|
||||
///
|
||||
pub fn pass_two(&mut self, program: &Program) -> Result<(), StaticCheckError> {
|
||||
self.table
|
||||
.check_types_program(program)
|
||||
.check_types(program)
|
||||
.map_err(|err| StaticCheckError::SymbolTableError(err))
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +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::{Attribute, ParameterType, SymbolTable, Type, TypeError};
|
||||
use crate::{Attribute, SymbolTable, Type, TypeError, UserDefinedType};
|
||||
use leo_typed::{FunctionInputVariable, Identifier, Span};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -96,9 +96,9 @@ impl FunctionInputVariableType {
|
||||
///
|
||||
/// If the symbol table did not have this name present, `None` is returned.
|
||||
///
|
||||
pub fn insert(&self, table: &mut SymbolTable) -> Option<ParameterType> {
|
||||
pub fn insert(&self, table: &mut SymbolTable) -> Option<UserDefinedType> {
|
||||
let key = self.identifier.name.clone();
|
||||
let value = ParameterType::from(self.clone());
|
||||
let value = UserDefinedType::from(self.clone());
|
||||
|
||||
table.insert_name(key, value)
|
||||
}
|
||||
|
@ -26,5 +26,5 @@ pub use self::type_::*;
|
||||
pub mod type_variable;
|
||||
pub use self::type_variable::*;
|
||||
|
||||
pub mod parameters;
|
||||
pub use self::parameters::*;
|
||||
pub mod user_defined;
|
||||
pub use self::user_defined::*;
|
||||
|
@ -14,5 +14,5 @@
|
||||
// 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/>.
|
||||
|
||||
pub mod parameter;
|
||||
pub use self::parameter::*;
|
||||
pub mod user_defined_type;
|
||||
pub use self::user_defined_type::*;
|
@ -21,21 +21,21 @@ use std::{
|
||||
hash::{Hash, Hasher},
|
||||
};
|
||||
|
||||
/// Stores variable definition details.
|
||||
/// Stores information for a user defined type.
|
||||
///
|
||||
/// This type should be added to the variable symbol table for a resolved syntax tree.
|
||||
/// User defined types include circuits and functions in a Leo program.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ParameterType {
|
||||
pub struct UserDefinedType {
|
||||
pub identifier: Identifier,
|
||||
pub type_: Type,
|
||||
pub attribute: Option<Attribute>,
|
||||
}
|
||||
|
||||
impl From<Circuit> for ParameterType {
|
||||
impl From<Circuit> for UserDefinedType {
|
||||
fn from(value: Circuit) -> Self {
|
||||
let identifier = value.circuit_name;
|
||||
|
||||
ParameterType {
|
||||
UserDefinedType {
|
||||
identifier: identifier.clone(),
|
||||
type_: Type::Circuit(identifier),
|
||||
attribute: None,
|
||||
@ -43,11 +43,11 @@ impl From<Circuit> for ParameterType {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Function> for ParameterType {
|
||||
impl From<Function> for UserDefinedType {
|
||||
fn from(value: Function) -> Self {
|
||||
let identifier = value.identifier;
|
||||
|
||||
ParameterType {
|
||||
UserDefinedType {
|
||||
identifier: identifier.clone(),
|
||||
type_: Type::Function(identifier),
|
||||
attribute: None,
|
||||
@ -55,9 +55,9 @@ impl From<Function> for ParameterType {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FunctionInputVariableType> for ParameterType {
|
||||
impl From<FunctionInputVariableType> for UserDefinedType {
|
||||
fn from(value: FunctionInputVariableType) -> Self {
|
||||
ParameterType {
|
||||
UserDefinedType {
|
||||
identifier: value.identifier,
|
||||
type_: value.type_,
|
||||
attribute: value.attribute,
|
||||
@ -65,21 +65,21 @@ impl From<FunctionInputVariableType> for ParameterType {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ParameterType {
|
||||
impl fmt::Display for UserDefinedType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.identifier)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for ParameterType {
|
||||
impl PartialEq for UserDefinedType {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.identifier.eq(&other.identifier)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for ParameterType {}
|
||||
impl Eq for UserDefinedType {}
|
||||
|
||||
impl Hash for ParameterType {
|
||||
impl Hash for UserDefinedType {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.identifier.hash(state);
|
||||
}
|
Loading…
Reference in New Issue
Block a user