Introduce TypeTable

This commit is contained in:
Pranav Gaddamadugu 2023-10-10 22:05:09 -04:00 committed by Pranav Gaddamadugu
parent 621a2f2a95
commit a3446d3aea
8 changed files with 32 additions and 31 deletions

View File

@ -173,12 +173,16 @@ impl<'a> Compiler<'a> {
}
/// Runs the type checker pass.
pub fn type_checker_pass(&'a self, symbol_table: SymbolTable) -> Result<(SymbolTable, StructGraph, CallGraph)> {
let (symbol_table, struct_graph, call_graph) = TypeChecker::do_pass((&self.ast, self.handler, symbol_table))?;
pub fn type_checker_pass(
&'a self,
symbol_table: SymbolTable,
) -> Result<(SymbolTable, TypeTable, StructGraph, CallGraph)> {
let (symbol_table, type_table, struct_graph, call_graph) =
TypeChecker::do_pass((&self.ast, self.handler, symbol_table))?;
if self.compiler_options.output.type_checked_symbol_table {
self.write_symbol_table_to_json("type_checked_symbol_table.json", &symbol_table)?;
}
Ok((symbol_table, struct_graph, call_graph))
Ok((symbol_table, type_table, struct_graph, call_graph))
}
/// Runs the loop unrolling pass.
@ -265,7 +269,7 @@ impl<'a> Compiler<'a> {
/// Runs the compiler stages.
pub fn compiler_stages(&mut self) -> Result<(SymbolTable, StructGraph, CallGraph)> {
let st = self.symbol_table_pass()?;
let (st, struct_graph, call_graph) = self.type_checker_pass(st)?;
let (st, _, struct_graph, call_graph) = self.type_checker_pass(st)?;
// TODO: Make this pass optional.
let st = self.loop_unrolling_pass(st)?;

View File

@ -226,7 +226,7 @@ pub fn compile_and_process<'a>(parsed: &'a mut Compiler<'a>) -> Result<String, L
CheckUniqueNodeIds::new().visit_program(&parsed.ast.ast);
let (st, struct_graph, call_graph) = parsed.type_checker_pass(st)?;
let (st, _, struct_graph, call_graph) = parsed.type_checker_pass(st)?;
CheckUniqueNodeIds::new().visit_program(&parsed.ast.ast);

View File

@ -27,6 +27,12 @@ pub mod replacer;
pub use replacer::*;
pub mod constant_propagation_table;
pub mod symbol_table;
pub use constant_propagation_table::*;
pub mod symbol_table;
pub use symbol_table::*;
pub type TypeTable = IndexMap<NodeID, Type>;
use indexmap::IndexMap;
use leo_ast::{NodeID, Type};

View File

@ -22,7 +22,7 @@ pub use variable_symbol::*;
use std::cell::RefCell;
use leo_ast::{normalize_json_value, remove_key_from_json, Function, NodeID, Struct, Type};
use leo_ast::{normalize_json_value, remove_key_from_json, Function, Struct};
use leo_errors::{AstError, Result};
use leo_span::{Span, Symbol};
@ -50,8 +50,6 @@ pub struct SymbolTable {
pub(crate) scope_index: usize,
/// The sub-scopes of this scope.
pub(crate) scopes: Vec<RefCell<SymbolTable>>,
/// A mapping from node IDs to types.
pub(crate) types: IndexMap<NodeID, Type>,
}
impl SymbolTable {
@ -105,11 +103,6 @@ impl SymbolTable {
Ok(())
}
/// Inserts a type for a node ID into the symbol table.
pub fn insert_type(&mut self, node_id: NodeID, type_: Type) {
self.types.insert(node_id, type_);
}
/// Removes a variable from the symbol table.
pub fn remove_variable_from_current_scope(&mut self, symbol: Symbol) {
self.variables.remove(&symbol);
@ -189,11 +182,6 @@ impl SymbolTable {
self.scopes.get(index)
}
/// Returns the type associated with the node ID, if it exists in the symbol table.
pub fn lookup_type(&self, node_id: NodeID) -> Option<&Type> {
self.types.get(&node_id)
}
/// Serializes the symbol table into a JSON string.
pub fn to_json_string(&self) -> Result<String> {
Ok(serde_json::to_string_pretty(&self)

View File

@ -59,7 +59,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
};
// If the output type is known, add the expression and its associated type to the symbol table.
if let Some(type_) = &output {
self.symbol_table.borrow_mut().insert_type(input.id(), type_.clone());
self.type_table.insert(input.id(), type_.clone());
}
// Return the output type.
output

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::{CallGraph, StructGraph, SymbolTable};
use crate::{CallGraph, StructGraph, SymbolTable, TypeTable};
use leo_ast::{ArrayType, CoreConstant, CoreFunction, Identifier, IntegerType, MappingType, Node, Type, Variant};
use leo_errors::{emitter::Handler, TypeCheckerError};
@ -27,6 +27,8 @@ use std::cell::RefCell;
pub struct TypeChecker<'a> {
/// The symbol table for the program.
pub(crate) symbol_table: RefCell<SymbolTable>,
/// A mapping from nod IDs to their respective type.
pub(crate) type_table: TypeTable,
/// A dependency graph of the structs in program.
pub(crate) struct_graph: StructGraph,
/// The call graph for the program.
@ -104,6 +106,7 @@ impl<'a> TypeChecker<'a> {
// Note that the `struct_graph` and `call_graph` are initialized with their full node sets.
Self {
symbol_table: RefCell::new(symbol_table),
type_table: Default::default(),
struct_graph: StructGraph::new(struct_names),
call_graph: CallGraph::new(function_names),
handler,

View File

@ -27,20 +27,20 @@ pub use check_statements::*;
pub mod checker;
pub use checker::*;
use crate::{CallGraph, Pass, StructGraph, SymbolTable};
use crate::{CallGraph, Pass, StructGraph, SymbolTable, TypeTable};
use leo_ast::{Ast, ProgramVisitor};
use leo_errors::{emitter::Handler, Result};
impl<'a> Pass for TypeChecker<'a> {
type Input = (&'a Ast, &'a Handler, SymbolTable);
type Output = Result<(SymbolTable, StructGraph, CallGraph)>;
type Output = Result<(SymbolTable, TypeTable, StructGraph, CallGraph)>;
fn do_pass((ast, handler, st): Self::Input) -> Self::Output {
let mut visitor = TypeChecker::new(st, handler);
visitor.visit_program(ast.as_repr());
handler.last_err().map_err(|e| *e)?;
Ok((visitor.symbol_table.take(), visitor.struct_graph, visitor.call_graph))
Ok((visitor.symbol_table.take(), visitor.type_table, visitor.struct_graph, visitor.call_graph))
}
}

View File

@ -190,7 +190,7 @@ 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) =
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);
@ -203,7 +203,7 @@ 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) =
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();
@ -217,7 +217,7 @@ 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) =
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");
compiler.static_single_assignment_pass(&symbol_table).expect("failed to run ssa pass");
@ -232,7 +232,7 @@ 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) =
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");
compiler.static_single_assignment_pass(&symbol_table).expect("failed to run ssa pass");
@ -248,7 +248,7 @@ 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) =
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");
compiler.static_single_assignment_pass(&symbol_table).expect("failed to run ssa pass");
@ -265,7 +265,7 @@ 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) =
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");
compiler.static_single_assignment_pass(&symbol_table).expect("failed to run ssa pass");
@ -286,7 +286,7 @@ impl Sample {
let start = Instant::now();
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) =
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");
compiler.static_single_assignment_pass(&symbol_table).expect("failed to run ssa pass");