rename static-check -> symbol-table 1

This commit is contained in:
collin 2020-10-30 10:25:44 -07:00
parent 833eb51c68
commit 20ac83265d
9 changed files with 99 additions and 49 deletions

View File

@ -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");

View File

@ -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),
_ => {}
}
}

View File

@ -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)

View File

@ -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)?;

View File

@ -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))
}
}

View File

@ -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)
}

View File

@ -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::*;

View File

@ -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::*;

View File

@ -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);
}