Skip to content

Commit 17f981b

Browse files
authored
Merge pull request #166 from Glyphack/move-type-evaluator-tests
2 parents 8d071f8 + 7a75bc5 commit 17f981b

File tree

7 files changed

+97
-83
lines changed

7 files changed

+97
-83
lines changed

cli/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ fn symbols(path: &PathBuf) -> std::result::Result<(), anyhow::Error> {
3434
manager.build();
3535
let module = manager.modules.values().last().unwrap();
3636

37-
println!("{}", module.symbol_table);
37+
println!("{}", module.get_symbol_table());
3838

3939
Ok(())
4040
}

typechecker/src/build.rs

Lines changed: 5 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ impl BuildManager {
3636
let file = Box::new(Self::parse_file(&build_source.source, build_source.module));
3737
let symbol_table = SymbolTable::new(crate::symbol_table::SymbolTableType::Module, 0);
3838

39-
modules.insert(mod_name, State { file, symbol_table });
39+
modules.insert(mod_name, State::new(file));
4040
}
4141

4242
BuildManager {
@@ -75,24 +75,21 @@ impl BuildManager {
7575
}
7676
}
7777

78-
// TODO: separate this can build to be able to test pre analysis and type checking separately
7978
// Performs type checking passes over the code
8079
pub fn type_check(&mut self) {
8180
self.pre_analysis();
8281
for state in self.modules.iter_mut() {
8382
let mut checker = TypeChecker::new(state.1, &self.options);
84-
checker.type_check();
83+
for stmt in &state.1.file.body {
84+
checker.type_check(stmt);
85+
}
8586
self.errors.append(&mut checker.errors);
8687
}
8788
}
8889
}
8990

9091
#[cfg(test)]
9192
mod tests {
92-
use parser::ast::GetNode;
93-
94-
use crate::type_check::type_evaluator::TypeEvaluator;
95-
9693
use super::*;
9794
fn snapshot_symbol_table(source: &str) -> String {
9895
let mut manager = BuildManager::new(
@@ -108,7 +105,7 @@ mod tests {
108105

109106
let module = manager.modules.values().last().unwrap();
110107

111-
format!("{}", module.symbol_table)
108+
format!("{}", module.get_symbol_table())
112109
}
113110

114111
fn snapshot_type_check(source: &str) -> String {
@@ -126,50 +123,6 @@ mod tests {
126123
manager.errors.join("\n").to_string()
127124
}
128125

129-
// TODO: refactor and move the test to type check mod
130-
fn snapshot_type_eval(source: &str) -> String {
131-
let mut manager = BuildManager::new(
132-
vec![BuildSource {
133-
path: PathBuf::from("test.py"),
134-
module: String::from("test"),
135-
source: source.to_string(),
136-
followed: false,
137-
}],
138-
Settings::test_settings(),
139-
);
140-
141-
manager.build();
142-
143-
let module = manager.modules.values().last().unwrap();
144-
let symbol_table = module.symbol_table.clone();
145-
let enderpy_file = module.file.clone();
146-
147-
let type_eval = TypeEvaluator::new(symbol_table);
148-
149-
let mut result = HashMap::new();
150-
151-
for stmt in enderpy_file.body {
152-
match stmt {
153-
parser::ast::Statement::ExpressionStatement(e) => {
154-
let t = type_eval.get_type(&e);
155-
match e {
156-
parser::ast::Expression::Name(n) => {
157-
result.insert(n.id, t.to_string());
158-
}
159-
_ => panic!("don't use this test for other expressions"),
160-
}
161-
}
162-
_ => {}
163-
}
164-
}
165-
166-
// sort result by key
167-
let mut result_sorted = result.clone().into_iter().collect::<Vec<_>>();
168-
result_sorted.sort_by(|a, b| a.0.cmp(&b.0));
169-
170-
return format!("{:#?}", result_sorted);
171-
}
172-
173126
macro_rules! snap {
174127
($name:tt, $path:tt) => {
175128
#[test]
@@ -202,22 +155,6 @@ mod tests {
202155
};
203156
}
204157

205-
macro_rules! snap_type_eval {
206-
($name:tt, $path:tt) => {
207-
#[test]
208-
fn $name() {
209-
let contents = include_str!($path);
210-
let result = snapshot_type_eval(contents);
211-
let mut settings = insta::Settings::clone_current();
212-
settings.set_snapshot_path("../testdata/output/");
213-
settings.set_description(contents);
214-
settings.bind(|| {
215-
insta::assert_snapshot!(result);
216-
});
217-
}
218-
};
219-
}
220-
221158
snap!(
222159
test_simple_var_assignments,
223160
"../testdata/inputs/simple_var_assignment.py"
@@ -239,6 +176,4 @@ mod tests {
239176
test_type_check_list,
240177
"../testdata/inputs/type_check_list.py"
241178
);
242-
243-
snap_type_eval!(test_type_eval_vars, "../testdata/inputs/type_eval_vars.py");
244179
}

typechecker/src/state.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,16 @@ use crate::{
55

66
pub struct State {
77
pub file: Box<EnderpyFile>,
8-
pub symbol_table: SymbolTable,
8+
symbol_table: SymbolTable,
99
}
1010

1111
impl State {
12+
pub fn new(file: Box<EnderpyFile>) -> Self {
13+
Self {
14+
file,
15+
symbol_table: SymbolTable::new(crate::symbol_table::SymbolTableType::Module, 0),
16+
}
17+
}
1218
/// entry point to fill up the symbol table from the global definitions
1319
pub fn populate_symbol_table(&mut self) {
1420
let mut sem_anal = SemanticAnalyzer::new(self.file.clone());
@@ -17,4 +23,8 @@ impl State {
1723
}
1824
self.symbol_table = sem_anal.globals
1925
}
26+
27+
pub fn get_symbol_table(&self) -> SymbolTable {
28+
self.symbol_table.clone()
29+
}
2030
}

typechecker/testdata/output/typechecker__build__tests__type_eval_vars.snap renamed to typechecker/src/testdata/output/typechecker__type_check__type_evaluator__tests__type_eval_vars.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
source: typechecker/src/build.rs
2+
source: typechecker/src/type_check/type_evaluator.rs
33
description: "# define variables with various types for testing\na = 1\nb = 2\nc = True\nd = False\ne = \"hello\"\nf = \"world\"\n# g = [1,2,3]\n# h = (1,2,3)\n# i = {1,2,3}\n# j = {\"a\":1,\"b\":2,\"c\":3}\n# k = None\n\na\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\n\n"
44
expression: result
55
---

typechecker/src/type_check/checker.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,39 @@ use ast::{Expression, Statement};
22
use parser::ast::{self, *};
33

44
use crate::{
5-
ast_visitor::TraversalVisitor, settings::Settings, state::State,
5+
ast_visitor::TraversalVisitor, settings::Settings, state::State, symbol_table::SymbolTable,
66
type_check::rules::is_reassignment_valid,
77
};
88

99
use super::{type_evaluator::TypeEvaluator, type_inference::type_check_bin_op, types::Type};
1010

11+
// TODO: currently only supporting a single file
1112
pub struct TypeChecker<'a> {
1213
pub errors: Vec<String>,
13-
// TODO: currently only supporting a single file
14-
pub module: &'a State,
14+
// The symbol table of the module being type checked
15+
symbol_table: SymbolTable,
16+
// statements to type check
17+
statements: Vec<Statement>,
1518
pub options: &'a Settings,
1619
type_evaluator: TypeEvaluator,
1720
}
1821

1922
#[allow(unused)]
2023
impl<'a> TypeChecker<'a> {
2124
pub fn new(module: &'a State, options: &'a Settings) -> Self {
25+
let symbol_table = module.get_symbol_table();
26+
let statements = module.file.body.clone();
2227
TypeChecker {
2328
errors: vec![],
24-
module,
29+
symbol_table,
30+
statements,
2531
options,
26-
type_evaluator: TypeEvaluator::new(module.symbol_table.clone()),
32+
type_evaluator: TypeEvaluator::new(module.get_symbol_table()),
2733
}
2834
}
2935

30-
pub fn type_check(&mut self) {
31-
for stmt in &self.module.file.body {
32-
self.visit_stmt(stmt);
33-
}
36+
pub fn type_check(&mut self, statement: &Statement) {
37+
self.visit_stmt(statement);
3438
}
3539

3640
fn infer_expr_type(&mut self, expr: &Expression) -> Type {
@@ -325,7 +329,7 @@ impl<'a> TraversalVisitor for TypeChecker<'a> {
325329
for target in &_a.targets {
326330
match target {
327331
ast::Expression::Name(n) => {
328-
let symbol = self.module.symbol_table.lookup_in_scope(&n.id);
332+
let symbol = self.symbol_table.lookup_in_scope(&n.id);
329333
if let Some(symbol) = symbol {
330334
let prev_target_type = self
331335
.type_evaluator
File renamed without changes.

typechecker/src/type_check/type_evaluator.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,3 +421,68 @@ impl TraversalVisitorImmutGeneric<Type> for TypeEvaluator {
421421
todo!()
422422
}
423423
}
424+
425+
#[cfg(test)]
426+
mod tests {
427+
use std::collections::HashMap;
428+
429+
use super::*;
430+
// TODO: refactor and move the test to type check mod
431+
fn snapshot_type_eval(source: &str) -> String {
432+
use crate::nodes::EnderpyFile;
433+
use crate::state::State;
434+
use parser::Parser;
435+
436+
let mut parser = Parser::new(source.to_string());
437+
let ast_module = parser.parse();
438+
439+
let enderpy_file = EnderpyFile::from(ast_module, "test".to_string());
440+
441+
let mut module = State::new(Box::new(enderpy_file));
442+
module.populate_symbol_table();
443+
let symbol_table = module.get_symbol_table();
444+
445+
let type_eval = TypeEvaluator::new(symbol_table);
446+
447+
let mut result = HashMap::new();
448+
449+
for stmt in module.file.body {
450+
match stmt {
451+
parser::ast::Statement::ExpressionStatement(e) => {
452+
let t = type_eval.get_type(&e);
453+
match e {
454+
parser::ast::Expression::Name(n) => {
455+
result.insert(n.id, t.to_string());
456+
}
457+
_ => panic!("don't use this test for other expressions"),
458+
}
459+
}
460+
_ => {}
461+
}
462+
}
463+
464+
// sort result by key
465+
let mut result_sorted = result.clone().into_iter().collect::<Vec<_>>();
466+
result_sorted.sort_by(|a, b| a.0.cmp(&b.0));
467+
468+
return format!("{:#?}", result_sorted);
469+
}
470+
471+
macro_rules! snap_type_eval {
472+
($name:tt, $path:tt) => {
473+
#[test]
474+
fn $name() {
475+
let contents = include_str!($path);
476+
let result = snapshot_type_eval(contents);
477+
let mut settings = insta::Settings::clone_current();
478+
settings.set_snapshot_path("../testdata/output/");
479+
settings.set_description(contents);
480+
settings.bind(|| {
481+
insta::assert_snapshot!(result);
482+
});
483+
}
484+
};
485+
}
486+
487+
snap_type_eval!(test_type_eval_vars, "./testdata/inputs/type_eval_vars.py");
488+
}

0 commit comments

Comments
 (0)