Skip to content

Commit

Permalink
Add any type
Browse files Browse the repository at this point in the history
  • Loading branch information
Glyphack committed Nov 3, 2023
1 parent 3f3aad0 commit 16c02f1
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 19 deletions.
2 changes: 2 additions & 0 deletions typechecker/src/type_check/test_data/inputs/any.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def func(x):
return x + 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
source: typechecker/src/type_check/type_evaluator.rs
description: "def func(x):\n return x + 1\n"
expression: result
input_file: typechecker/src/type_check/test_data/inputs/any.py
---
[
(
"func",
"Int",
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
---
source: typechecker/src/type_check/type_evaluator.rs
description: "# define variables with various types for testing\na = 1\nb = 2\nc = True\nd = False\ne = \"hello\"\nf = \"world\"\njoined_str = f\"{e} {f}\"\n\ng = [1,2,3]\nh = (1,2,3)\ni = {1,2,3}\nj = {\"a\":1,\"b\":2,\"c\":3}\nk = None\n\nbool_op = True and False\n\nbin_op = a + b\nunary_op1 = -a\nunary_op2 = not c\nunaray_op3 = ~a\nunaray_op4 = +a\n\nnamed = (a := 1)\n\ngenerator = (x for x in g)\n\ngg = (1, \"str\")\n\n\n"
expression: result
input_file: typechecker/src/type_check/test_data/inputs/type_eval_vars.py
---
[
(
"a",
"Int",
),
(
"b",
"Int",
),
(
"bin_op",
"Int",
),
(
"bool_op",
"Bool",
),
(
"c",
"Bool",
),
(
"d",
"Bool",
),
(
"e",
"Str",
),
(
"f",
"Str",
),
(
"g",
"builtins.list[Int]",
),
(
"generator",
"Unknown",
),
(
"gg",
"builtins.tuple[Unknown]",
),
(
"h",
"builtins.tuple[Int]",
),
(
"i",
"builtins.set[Int]",
),
(
"j",
"builtins.dict[Str, Int]",
),
(
"joined_str",
"Str",
),
(
"k",
"None",
),
(
"named",
"Int",
),
(
"unaray_op3",
"Int",
),
(
"unaray_op4",
"Int",
),
(
"unary_op1",
"Int",
),
(
"unary_op2",
"Bool",
),
]
56 changes: 37 additions & 19 deletions typechecker/src/type_check/type_evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,14 @@ pub struct TypeEvalError {
pub position: usize,
}


/// Struct for evaluating the type of an expression
impl TypeEvaluator {
pub fn new(symbol_table: SymbolTable) -> Self {
Self { symbol_table }
}

/// Get the type of a symbol node based on declarations
pub fn get_symbol_node_type(
&self,
symbol: &SymbolTableNode,
Expand All @@ -43,7 +46,7 @@ impl TypeEvaluator {
};
match decl {
Some(decl) => self.get_type_from_declaration(decl),
None => Ok(PythonType::Unknown),
None => Ok(PythonType::Any),
}
}
pub fn get_type(&self, expr: &ast::Expression) -> Result<PythonType> {
Expand Down Expand Up @@ -357,7 +360,7 @@ impl TraversalVisitorImmutGeneric<PythonType> for TypeEvaluator {
}

fn visit_function_def(&self, f: &parser::ast::FunctionDef) -> PythonType {
PythonType::Unknown
PythonType::Any
}

fn visit_class_def(&self, c: &parser::ast::ClassDef) -> PythonType {
Expand Down Expand Up @@ -531,12 +534,15 @@ impl TraversalVisitorImmutGeneric<PythonType> for TypeEvaluator {

#[cfg(test)]
mod tests {
use insta::glob;

use crate::build_source::BuildSource;

use super::*;
use std::collections::HashMap;
use std::fs;
use std::path::PathBuf;
// TODO: refactor and move the test to type check mod

fn snapshot_type_eval(source: &str) -> String {
use crate::nodes::EnderpyFile;
use crate::state::State;
Expand Down Expand Up @@ -589,6 +595,21 @@ mod tests {
},
None => panic!("don't use this test for other expressions"),
}
},
parser::ast::Statement::FunctionDef(f) => {
// for over the body and get type for the return statement
for stmt in f.body {
match stmt {
parser::ast::Statement::Return(r) => {
let t = type_eval.get_type(&r.value.unwrap());
result.insert(
f.name.clone(),
t.unwrap_or(PythonType::Unknown).to_string(),
);
}
_ => {}
}
}
}
_ => {}
}
Expand All @@ -601,21 +622,18 @@ mod tests {
format!("{:#?}", result_sorted)
}

macro_rules! snap_type_eval {
($name:tt, $path:tt) => {
#[test]
fn $name() {
let contents = include_str!($path);
let result = snapshot_type_eval(contents);
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../testdata/output/");
settings.set_description(contents);
settings.bind(|| {
insta::assert_snapshot!(result);
});
}
};
}
#[test]
fn test_type_evaluator() {
glob!("test_data/inputs/", "*.py", |path| {
let contents = fs::read_to_string(path).unwrap();
let result = snapshot_type_eval(&contents);

snap_type_eval!(test_type_eval_vars, "./testdata/inputs/type_eval_vars.py");
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("./test_data/output/");
settings.set_description(fs::read_to_string(path).unwrap());
settings.bind(|| {
insta::assert_snapshot!(result);
});
})
}
}
5 changes: 5 additions & 0 deletions typechecker/src/type_check/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ use enderpy_python_parser::ast;
pub enum PythonType {
None,
Unknown,
/// representing that we know nothing about the value a node can contain.
/// For example, if a file contains only the function def f(x): return x, the name x will have an Anyas its value within the function
/// because there is no information to determine what value it can contain
Any,
Callable(Box<CallableType>),
Bool,
Int,
Expand Down Expand Up @@ -49,6 +53,7 @@ impl Display for PythonType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let type_str = match self {
PythonType::None => "None",
PythonType::Any=> "Any",
PythonType::Bool => "Bool",
PythonType::Int => "Int",
PythonType::Float => "Float",
Expand Down

0 comments on commit 16c02f1

Please sign in to comment.