add new dynamic check protocol

This commit is contained in:
collin 2020-10-13 09:06:52 -07:00
parent d29d01f4ff
commit cc6cf4e6a5
6 changed files with 91 additions and 42 deletions

View File

@ -103,8 +103,11 @@ impl FunctionBody {
///
pub fn new(function: Function, symbol_table: SymbolTable) -> Self {
let name = &function.identifier.name;
// Get function type from symbol table.
let function_type = symbol_table.get_function(name).unwrap().clone();
// Create new function body struct.
let mut function_body = Self {
function_type,
symbol_table,
@ -112,6 +115,10 @@ impl FunctionBody {
type_variables: HashSet::new(),
};
// Build symbol table for variables.
// Initialize function inputs as variables.
// Update inputs when encountering let/const variable definitions.
// Create type assertions for function statements
function_body.parse_statements(&function.statements);

View File

@ -17,7 +17,7 @@
use leo_ast::LeoAst;
use leo_dynamic_check::DynamicCheck;
use leo_symbol_table::OldSymbolTable;
use leo_static_check::StaticCheck;
use leo_typed::LeoTypedAst;
use std::path::PathBuf;
@ -44,16 +44,11 @@ impl TestDynamicCheck {
let typed = LeoTypedAst::new(TEST_PROGRAM_NAME, &ast);
let program = typed.into_repr();
// Create symbol table.
let mut symbol_table = OldSymbolTable::new(None);
// Load symbols into symbol table.
symbol_table.pass_one(&program).unwrap();
symbol_table.pass_two(&program).unwrap();
// Create static check.
let mut static_check = StaticCheck::new(&program).unwrap();
// Create dynamic check
let dynamic_check = DynamicCheck::new(&program, symbol_table);
let dynamic_check = DynamicCheck::new(&program, static_check);
Self { dynamic_check }
}

View File

@ -23,6 +23,9 @@ pub use self::attributes::*;
pub mod errors;
pub use self::errors::*;
pub mod static_check;
pub use self::static_check::*;
pub mod symbol_table;
pub use self::symbol_table::*;

View File

@ -0,0 +1,75 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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, SymbolTableError};
use leo_typed::Program as UnresolvedProgram;
/// Performs a static type check over a program.
pub struct StaticCheck {
table: SymbolTable,
}
impl StaticCheck {
///
/// Return a new `StaticCheck` from a given program.
///
pub fn new(program: &UnresolvedProgram) -> Result<SymbolTable, SymbolTableError> {
let mut check = Self {
table: SymbolTable::new(None),
};
// Run pass one checks
check.pass_one(program)?;
// Run pass two checks
check.pass_two(program)?;
Ok(check.table)
}
///
/// Checks for duplicate circuit and function names given an unresolved program.
///
/// 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 pass_one(&mut self, program: &UnresolvedProgram) -> Result<(), SymbolTableError> {
// Check unresolved program circuit names.
self.table.check_duplicate_circuits(&program.circuits)?;
// Check unresolved program function names.
self.table.check_duplicate_functions(&program.functions)?;
Ok(())
}
///
/// Checks for unknown types in circuit and function definitions given an unresolved program.
///
/// If a circuit or function definition only contains known types, then it is inserted into the
/// symbol table. Variables defined later in the unresolved program can lookup the definition and
/// refer to its expected types.
///
pub fn pass_two(&mut self, program: &UnresolvedProgram) -> Result<(), SymbolTableError> {
// Check unresolved program circuit definitions.
self.table.check_unknown_types_circuits(&program.circuits)?;
// Check unresolved program function definitions.
self.table.check_unknown_types_functions(&program.functions)?;
Ok(())
}
}

View File

@ -254,37 +254,4 @@ impl SymbolTable {
Ok(())
}
///
/// Checks for duplicate circuit and function names given an unresolved program.
///
/// 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 pass_one(&mut self, program: &UnresolvedProgram) -> Result<(), SymbolTableError> {
// Check unresolved program circuit names.
self.check_duplicate_circuits(&program.circuits)?;
// Check unresolved program function names.
self.check_duplicate_functions(&program.functions)?;
Ok(())
}
///
/// Checks for unknown types in circuit and function definitions given an unresolved program.
///
/// If a circuit or function definition only contains known types, then it is inserted into the
/// symbol table. Variables defined later in the unresolved program can lookup the definition and
/// refer to its expected types.
///
pub fn pass_two(&mut self, program: &UnresolvedProgram) -> Result<(), SymbolTableError> {
// Check unresolved program circuit definitions.
self.check_unknown_types_circuits(&program.circuits)?;
// Check unresolved program function definitions.
self.check_unknown_types_functions(&program.functions)?;
Ok(())
}
}

View File

@ -45,6 +45,8 @@ impl Type {
///
/// Return a new type from the given unresolved type.
///
/// Performs a lookup in the given symbol table if the type is user-defined.
///
pub fn new(table: &SymbolTable, type_: UnresolvedType, span: Span) -> Result<Self, TypeError> {
Ok(match type_ {
UnresolvedType::Address => Type::Address,