meta: Apply clippy changes

This commit is contained in:
David Mak 2024-06-17 14:07:38 +08:00
parent 32919949e2
commit 82091b1be8
8 changed files with 218 additions and 239 deletions

View File

@ -118,7 +118,7 @@ mod tests {
use crate::fold::Fold; use crate::fold::Fold;
use crate::*; use crate::*;
let location = Location::new(0, 0, Default::default()); let location = Location::new(0, 0, FileName::default());
let custom = (); let custom = ();
let ast = Located { let ast = Located {
location, location,

View File

@ -15,11 +15,13 @@ use crate::{
typedef::{FunSignature, FuncArg, Type, TypeEnum, Unifier, VarMap}, typedef::{FunSignature, FuncArg, Type, TypeEnum, Unifier, VarMap},
}, },
}; };
use indexmap::IndexMap;
use indoc::indoc; use indoc::indoc;
use inkwell::{ use inkwell::{
targets::{InitializationConfig, Target}, targets::{InitializationConfig, Target},
OptimizationLevel, OptimizationLevel,
}; };
use nac3parser::ast::FileName;
use nac3parser::{ use nac3parser::{
ast::{fold::Fold, StrRef}, ast::{fold::Fold, StrRef},
parser::parse_program, parser::parse_program,
@ -55,13 +57,13 @@ impl SymbolResolver for Resolver {
_: &PrimitiveStore, _: &PrimitiveStore,
str: StrRef, str: StrRef,
) -> Result<Type, String> { ) -> Result<Type, String> {
self.id_to_type.get(&str).cloned().ok_or_else(|| format!("cannot find symbol `{}`", str)) self.id_to_type.get(&str).copied().ok_or_else(|| format!("cannot find symbol `{str}`"))
} }
fn get_symbol_value<'ctx, 'a>( fn get_symbol_value<'ctx>(
&self, &self,
_: StrRef, _: StrRef,
_: &mut CodeGenContext<'ctx, 'a>, _: &mut CodeGenContext<'ctx, '_>,
) -> Option<ValueEnum<'ctx>> { ) -> Option<ValueEnum<'ctx>> {
unimplemented!() unimplemented!()
} }
@ -70,8 +72,8 @@ impl SymbolResolver for Resolver {
self.id_to_def self.id_to_def
.read() .read()
.get(&id) .get(&id)
.cloned() .copied()
.ok_or_else(|| HashSet::from([format!("cannot find symbol `{}`", id)])) .ok_or_else(|| HashSet::from([format!("cannot find symbol `{id}`")]))
} }
fn get_string_id(&self, _: &str) -> i32 { fn get_string_id(&self, _: &str) -> i32 {
@ -90,7 +92,7 @@ fn test_primitives() {
d = a if c == 1 else 0 d = a if c == 1 else 0
return d return d
"}; "};
let statements = parse_program(source, Default::default()).unwrap(); let statements = parse_program(source, FileName::default()).unwrap();
let composer = TopLevelComposer::new(Vec::new(), ComposerConfig::default(), 32).0; let composer = TopLevelComposer::new(Vec::new(), ComposerConfig::default(), 32).0;
let mut unifier = composer.unifier.clone(); let mut unifier = composer.unifier.clone();
@ -101,7 +103,7 @@ fn test_primitives() {
let resolver = Arc::new(Resolver { let resolver = Arc::new(Resolver {
id_to_type: HashMap::new(), id_to_type: HashMap::new(),
id_to_def: RwLock::new(HashMap::new()), id_to_def: RwLock::new(HashMap::new()),
class_names: Default::default(), class_names: HashMap::default(),
}) as Arc<dyn SymbolResolver + Send + Sync>; }) as Arc<dyn SymbolResolver + Send + Sync>;
let threads = vec![DefaultCodeGenerator::new("test".into(), 32).into()]; let threads = vec![DefaultCodeGenerator::new("test".into(), 32).into()];
@ -126,12 +128,12 @@ fn test_primitives() {
}; };
let mut virtual_checks = Vec::new(); let mut virtual_checks = Vec::new();
let mut calls = HashMap::new(); let mut calls = HashMap::new();
let mut identifiers: HashSet<_> = ["a".into(), "b".into()].iter().cloned().collect(); let mut identifiers: HashSet<_> = ["a".into(), "b".into()].into();
let mut inferencer = Inferencer { let mut inferencer = Inferencer {
top_level: &top_level, top_level: &top_level,
function_data: &mut function_data, function_data: &mut function_data,
unifier: &mut unifier, unifier: &mut unifier,
variable_mapping: Default::default(), variable_mapping: HashMap::default(),
primitives: &primitives, primitives: &primitives,
virtual_checks: &mut virtual_checks, virtual_checks: &mut virtual_checks,
calls: &mut calls, calls: &mut calls,
@ -155,7 +157,7 @@ fn test_primitives() {
}); });
let task = CodeGenTask { let task = CodeGenTask {
subst: Default::default(), subst: Vec::default(),
symbol_name: "testing".into(), symbol_name: "testing".into(),
body: Arc::new(statements), body: Arc::new(statements),
unifier_index: 0, unifier_index: 0,
@ -237,12 +239,12 @@ fn test_simple_call() {
a = foo(a) a = foo(a)
return a * 2 return a * 2
"}; "};
let statements_1 = parse_program(source_1, Default::default()).unwrap(); let statements_1 = parse_program(source_1, FileName::default()).unwrap();
let source_2 = indoc! { " let source_2 = indoc! { "
return a + 1 return a + 1
"}; "};
let statements_2 = parse_program(source_2, Default::default()).unwrap(); let statements_2 = parse_program(source_2, FileName::default()).unwrap();
let composer = TopLevelComposer::new(Vec::new(), ComposerConfig::default(), 32).0; let composer = TopLevelComposer::new(Vec::new(), ComposerConfig::default(), 32).0;
let mut unifier = composer.unifier.clone(); let mut unifier = composer.unifier.clone();
@ -277,7 +279,7 @@ fn test_simple_call() {
let resolver = Resolver { let resolver = Resolver {
id_to_type: HashMap::new(), id_to_type: HashMap::new(),
id_to_def: RwLock::new(HashMap::new()), id_to_def: RwLock::new(HashMap::new()),
class_names: Default::default(), class_names: HashMap::default(),
}; };
resolver.add_id_def("foo".into(), DefinitionId(foo_id)); resolver.add_id_def("foo".into(), DefinitionId(foo_id));
let resolver = Arc::new(resolver) as Arc<dyn SymbolResolver + Send + Sync>; let resolver = Arc::new(resolver) as Arc<dyn SymbolResolver + Send + Sync>;
@ -298,12 +300,12 @@ fn test_simple_call() {
}; };
let mut virtual_checks = Vec::new(); let mut virtual_checks = Vec::new();
let mut calls = HashMap::new(); let mut calls = HashMap::new();
let mut identifiers: HashSet<_> = ["a".into(), "foo".into()].iter().cloned().collect(); let mut identifiers: HashSet<_> = ["a".into(), "foo".into()].into();
let mut inferencer = Inferencer { let mut inferencer = Inferencer {
top_level: &top_level, top_level: &top_level,
function_data: &mut function_data, function_data: &mut function_data,
unifier: &mut unifier, unifier: &mut unifier,
variable_mapping: Default::default(), variable_mapping: HashMap::default(),
primitives: &primitives, primitives: &primitives,
virtual_checks: &mut virtual_checks, virtual_checks: &mut virtual_checks,
calls: &mut calls, calls: &mut calls,
@ -332,11 +334,11 @@ fn test_simple_call() {
&mut *top_level.definitions.read()[foo_id].write() &mut *top_level.definitions.read()[foo_id].write()
{ {
instance_to_stmt.insert( instance_to_stmt.insert(
"".to_string(), String::new(),
FunInstance { FunInstance {
body: Arc::new(statements_2), body: Arc::new(statements_2),
calls: Arc::new(inferencer.calls.clone()), calls: Arc::new(inferencer.calls.clone()),
subst: Default::default(), subst: IndexMap::default(),
unifier_id: 0, unifier_id: 0,
}, },
); );
@ -352,7 +354,7 @@ fn test_simple_call() {
}); });
let task = CodeGenTask { let task = CodeGenTask {
subst: Default::default(), subst: Vec::default(),
symbol_name: "testing".to_string(), symbol_name: "testing".to_string(),
body: Arc::new(statements_1), body: Arc::new(statements_1),
calls: Arc::new(calls1), calls: Arc::new(calls1),

View File

@ -8,6 +8,7 @@ use crate::{
}, },
}; };
use indoc::indoc; use indoc::indoc;
use nac3parser::ast::FileName;
use nac3parser::{ast::fold::Fold, parser::parse_program}; use nac3parser::{ast::fold::Fold, parser::parse_program};
use parking_lot::Mutex; use parking_lot::Mutex;
use std::{collections::HashMap, sync::Arc}; use std::{collections::HashMap, sync::Arc};
@ -52,14 +53,14 @@ impl SymbolResolver for Resolver {
.id_to_type .id_to_type
.lock() .lock()
.get(&str) .get(&str)
.cloned() .copied()
.ok_or_else(|| format!("cannot find symbol `{}`", str)) .ok_or_else(|| format!("cannot find symbol `{str}`"))
} }
fn get_symbol_value<'ctx, 'a>( fn get_symbol_value<'ctx>(
&self, &self,
_: StrRef, _: StrRef,
_: &mut CodeGenContext<'ctx, 'a>, _: &mut CodeGenContext<'ctx, '_>,
) -> Option<ValueEnum<'ctx>> { ) -> Option<ValueEnum<'ctx>> {
unimplemented!() unimplemented!()
} }
@ -69,7 +70,7 @@ impl SymbolResolver for Resolver {
.id_to_def .id_to_def
.lock() .lock()
.get(&id) .get(&id)
.cloned() .copied()
.ok_or_else(|| HashSet::from(["Unknown identifier".to_string()])) .ok_or_else(|| HashSet::from(["Unknown identifier".to_string()]))
} }
@ -118,10 +119,10 @@ fn test_simple_register(source: Vec<&str>) {
let mut composer = TopLevelComposer::new(Vec::new(), ComposerConfig::default(), 64).0; let mut composer = TopLevelComposer::new(Vec::new(), ComposerConfig::default(), 64).0;
for s in source { for s in source {
let ast = parse_program(s, Default::default()).unwrap(); let ast = parse_program(s, FileName::default()).unwrap();
let ast = ast[0].clone(); let ast = ast[0].clone();
composer.register_top_level(ast, None, "".into(), false).unwrap(); composer.register_top_level(ast, None, "", false).unwrap();
} }
} }
@ -136,13 +137,13 @@ fn test_simple_register(source: Vec<&str>) {
)] )]
fn test_simple_register_without_constructor(source: &str) { fn test_simple_register_without_constructor(source: &str) {
let mut composer = TopLevelComposer::new(Vec::new(), ComposerConfig::default(), 64).0; let mut composer = TopLevelComposer::new(Vec::new(), ComposerConfig::default(), 64).0;
let ast = parse_program(source, Default::default()).unwrap(); let ast = parse_program(source, FileName::default()).unwrap();
let ast = ast[0].clone(); let ast = ast[0].clone();
composer.register_top_level(ast, None, "".into(), true).unwrap(); composer.register_top_level(ast, None, "", true).unwrap();
} }
#[test_case( #[test_case(
vec![ &[
indoc! {" indoc! {"
def fun(a: int32) -> int32: def fun(a: int32) -> int32:
return a return a
@ -156,35 +157,35 @@ fn test_simple_register_without_constructor(source: &str) {
return 3 return 3
"}, "},
], ],
vec![ &[
"fn[[a:0], 0]", "fn[[a:0], 0]",
"fn[[a:2], 4]", "fn[[a:2], 4]",
"fn[[b:1], 0]", "fn[[b:1], 0]",
], ],
vec![ &[
"fun", "fun",
"foo", "foo",
"f" "f"
]; ];
"function compose" "function compose"
)] )]
fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&str>) { fn test_simple_function_analyze(source: &[&str], tys: &[&str], names: &[&str]) {
let mut composer = TopLevelComposer::new(Vec::new(), ComposerConfig::default(), 64).0; let mut composer = TopLevelComposer::new(Vec::new(), ComposerConfig::default(), 64).0;
let internal_resolver = Arc::new(ResolverInternal { let internal_resolver = Arc::new(ResolverInternal {
id_to_def: Default::default(), id_to_def: Mutex::default(),
id_to_type: Default::default(), id_to_type: Mutex::default(),
class_names: Default::default(), class_names: Mutex::default(),
}); });
let resolver = let resolver =
Arc::new(Resolver(internal_resolver.clone())) as Arc<dyn SymbolResolver + Send + Sync>; Arc::new(Resolver(internal_resolver.clone())) as Arc<dyn SymbolResolver + Send + Sync>;
for s in source { for s in source {
let ast = parse_program(s, Default::default()).unwrap(); let ast = parse_program(s, FileName::default()).unwrap();
let ast = ast[0].clone(); let ast = ast[0].clone();
let (id, def_id, ty) = let (id, def_id, ty) =
composer.register_top_level(ast, Some(resolver.clone()), "".into(), false).unwrap(); composer.register_top_level(ast, Some(resolver.clone()), "", false).unwrap();
internal_resolver.add_id_def(id, def_id); internal_resolver.add_id_def(id, def_id);
if let Some(ty) = ty { if let Some(ty) = ty {
internal_resolver.add_id_type(id, ty); internal_resolver.add_id_type(id, ty);
@ -210,7 +211,7 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
} }
#[test_case( #[test_case(
vec![ &[
indoc! {" indoc! {"
class A(): class A():
a: int32 a: int32
@ -243,11 +244,11 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
pass pass
"} "}
], ],
vec![]; &[];
"simple class compose" "simple class compose"
)] )]
#[test_case( #[test_case(
vec![ &[
indoc! {" indoc! {"
class Generic_A(Generic[V], B): class Generic_A(Generic[V], B):
a: int64 a: int64
@ -265,11 +266,11 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
pass pass
"} "}
], ],
vec![]; &[];
"generic class" "generic class"
)] )]
#[test_case( #[test_case(
vec![ &[
indoc! {" indoc! {"
def foo(a: list[int32], b: tuple[T, float]) -> A[B, bool]: def foo(a: list[int32], b: tuple[T, float]) -> A[B, bool]:
pass pass
@ -294,11 +295,11 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
pass pass
"} "}
], ],
vec![]; &[];
"list tuple generic" "list tuple generic"
)] )]
#[test_case( #[test_case(
vec![ &[
indoc! {" indoc! {"
class A(Generic[T, V]): class A(Generic[T, V]):
a: A[float, bool] a: A[float, bool]
@ -319,11 +320,11 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
pass pass
"} "}
], ],
vec![]; &[];
"self1" "self1"
)] )]
#[test_case( #[test_case(
vec![ &[
indoc! {" indoc! {"
class A(Generic[T]): class A(Generic[T]):
a: int32 a: int32
@ -353,11 +354,11 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
pass pass
"} "}
], ],
vec![]; &[];
"inheritance_override" "inheritance_override"
)] )]
#[test_case( #[test_case(
vec![ &[
indoc! {" indoc! {"
class A(Generic[T]): class A(Generic[T]):
def __init__(self): def __init__(self):
@ -366,11 +367,11 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
pass pass
"} "}
], ],
vec!["application of type vars to generic class is not currently supported (at unknown:4:24)"]; &["application of type vars to generic class is not currently supported (at unknown:4:24)"];
"err no type var in generic app" "err no type var in generic app"
)] )]
#[test_case( #[test_case(
vec![ &[
indoc! {" indoc! {"
class A(B): class A(B):
def __init__(self): def __init__(self):
@ -382,11 +383,11 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
pass pass
"} "}
], ],
vec!["cyclic inheritance detected"]; &["cyclic inheritance detected"];
"cyclic1" "cyclic1"
)] )]
#[test_case( #[test_case(
vec![ &[
indoc! {" indoc! {"
class A(B[bool, int64]): class A(B[bool, int64]):
def __init__(self): def __init__(self):
@ -403,30 +404,30 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
pass pass
"}, "},
], ],
vec!["cyclic inheritance detected"]; &["cyclic inheritance detected"];
"cyclic2" "cyclic2"
)] )]
#[test_case( #[test_case(
vec![ &[
indoc! {" indoc! {"
class A: class A:
pass pass
"} "}
], ],
vec!["5: Class {\nname: \"A\",\ndef_id: DefinitionId(5),\nancestors: [CustomClassKind { id: DefinitionId(5), params: [] }],\nfields: [],\nmethods: [],\ntype_vars: []\n}"]; &["5: Class {\nname: \"A\",\ndef_id: DefinitionId(5),\nancestors: [CustomClassKind { id: DefinitionId(5), params: [] }],\nfields: [],\nmethods: [],\ntype_vars: []\n}"];
"simple pass in class" "simple pass in class"
)] )]
#[test_case( #[test_case(
vec![indoc! {" &[indoc! {"
class A: class A:
def __init__(): def __init__():
pass pass
"}], "}],
vec!["__init__ method must have a `self` parameter (at unknown:2:5)"]; &["__init__ method must have a `self` parameter (at unknown:2:5)"];
"err no self_1" "err no self_1"
)] )]
#[test_case( #[test_case(
vec![ &[
indoc! {" indoc! {"
class A(B, Generic[T], C): class A(B, Generic[T], C):
def __init__(self): def __init__(self):
@ -444,11 +445,11 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
"} "}
], ],
vec!["a class definition can only have at most one base class declaration and one generic declaration (at unknown:1:24)"]; &["a class definition can only have at most one base class declaration and one generic declaration (at unknown:1:24)"];
"err multiple inheritance" "err multiple inheritance"
)] )]
#[test_case( #[test_case(
vec![ &[
indoc! {" indoc! {"
class A(Generic[T]): class A(Generic[T]):
a: int32 a: int32
@ -469,11 +470,11 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
pass pass
"} "}
], ],
vec!["method fun has same name as ancestors' method, but incompatible type"]; &["method fun has same name as ancestors' method, but incompatible type"];
"err_incompatible_inheritance_method" "err_incompatible_inheritance_method"
)] )]
#[test_case( #[test_case(
vec![ &[
indoc! {" indoc! {"
class A(Generic[T]): class A(Generic[T]):
a: int32 a: int32
@ -495,11 +496,11 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
pass pass
"} "}
], ],
vec!["field `a` has already declared in the ancestor classes"]; &["field `a` has already declared in the ancestor classes"];
"err_incompatible_inheritance_field" "err_incompatible_inheritance_field"
)] )]
#[test_case( #[test_case(
vec![ &[
indoc! {" indoc! {"
class A: class A:
def __init__(self): def __init__(self):
@ -512,10 +513,10 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
pass pass
"} "}
], ],
vec!["duplicate definition of class `A` (at unknown:1:1)"]; &["duplicate definition of class `A` (at unknown:1:1)"];
"class same name" "class same name"
)] )]
fn test_analyze(source: Vec<&str>, res: Vec<&str>) { fn test_analyze(source: &[&str], res: &[&str]) {
let print = false; let print = false;
let mut composer = TopLevelComposer::new(Vec::new(), ComposerConfig::default(), 64).0; let mut composer = TopLevelComposer::new(Vec::new(), ComposerConfig::default(), 64).0;
@ -532,15 +533,15 @@ fn test_analyze(source: Vec<&str>, res: Vec<&str>) {
Arc::new(Resolver(internal_resolver.clone())) as Arc<dyn SymbolResolver + Send + Sync>; Arc::new(Resolver(internal_resolver.clone())) as Arc<dyn SymbolResolver + Send + Sync>;
for s in source { for s in source {
let ast = parse_program(s, Default::default()).unwrap(); let ast = parse_program(s, FileName::default()).unwrap();
let ast = ast[0].clone(); let ast = ast[0].clone();
let (id, def_id, ty) = { let (id, def_id, ty) = {
match composer.register_top_level(ast, Some(resolver.clone()), "".into(), false) { match composer.register_top_level(ast, Some(resolver.clone()), "", false) {
Ok(x) => x, Ok(x) => x,
Err(msg) => { Err(msg) => {
if print { if print {
println!("{}", msg); println!("{msg}");
} else { } else {
assert_eq!(res[0], msg); assert_eq!(res[0], msg);
} }
@ -586,7 +587,7 @@ fn test_analyze(source: Vec<&str>, res: Vec<&str>) {
return fib(n - 1) return fib(n - 1)
"} "}
], ],
vec![]; &[];
"simple function" "simple function"
)] )]
#[test_case( #[test_case(
@ -619,7 +620,7 @@ fn test_analyze(source: Vec<&str>, res: Vec<&str>) {
return a.fun() + 2 return a.fun() + 2
"} "}
], ],
vec![]; &[];
"simple class body" "simple class body"
)] )]
#[test_case( #[test_case(
@ -644,7 +645,7 @@ fn test_analyze(source: Vec<&str>, res: Vec<&str>) {
return [a, b] return [a, b]
"} "}
], ],
vec![]; &[];
"type var fun" "type var fun"
)] )]
#[test_case( #[test_case(
@ -665,7 +666,7 @@ fn test_analyze(source: Vec<&str>, res: Vec<&str>) {
return ret if self.b else self.fun(self.a) return ret if self.b else self.fun(self.a)
"} "}
], ],
vec![]; &[];
"type var class" "type var class"
)] )]
#[test_case( #[test_case(
@ -689,10 +690,10 @@ fn test_analyze(source: Vec<&str>, res: Vec<&str>) {
self.b = True self.b = True
"} "}
], ],
vec![]; &[];
"no_init_inst_check" "no_init_inst_check"
)] )]
fn test_inference(source: Vec<&str>, res: Vec<&str>) { fn test_inference(source: Vec<&str>, res: &[&str]) {
let print = true; let print = true;
let mut composer = TopLevelComposer::new(Vec::new(), ComposerConfig::default(), 64).0; let mut composer = TopLevelComposer::new(Vec::new(), ComposerConfig::default(), 64).0;
@ -716,15 +717,15 @@ fn test_inference(source: Vec<&str>, res: Vec<&str>) {
Arc::new(Resolver(internal_resolver.clone())) as Arc<dyn SymbolResolver + Send + Sync>; Arc::new(Resolver(internal_resolver.clone())) as Arc<dyn SymbolResolver + Send + Sync>;
for s in source { for s in source {
let ast = parse_program(s, Default::default()).unwrap(); let ast = parse_program(s, FileName::default()).unwrap();
let ast = ast[0].clone(); let ast = ast[0].clone();
let (id, def_id, ty) = { let (id, def_id, ty) = {
match composer.register_top_level(ast, Some(resolver.clone()), "".into(), false) { match composer.register_top_level(ast, Some(resolver.clone()), "", false) {
Ok(x) => x, Ok(x) => x,
Err(msg) => { Err(msg) => {
if print { if print {
println!("{}", msg); println!("{msg}");
} else { } else {
assert_eq!(res[0], msg); assert_eq!(res[0], msg);
} }
@ -747,9 +748,7 @@ fn test_inference(source: Vec<&str>, res: Vec<&str>) {
} else { } else {
// skip 5 to skip primitives // skip 5 to skip primitives
let mut stringify_folder = TypeToStringFolder { unifier: &mut composer.unifier }; let mut stringify_folder = TypeToStringFolder { unifier: &mut composer.unifier };
for (_i, (def, _)) in for (def, _) in composer.definition_ast_list.iter().skip(composer.builtin_num) {
composer.definition_ast_list.iter().skip(composer.builtin_num).enumerate()
{
let def = &*def.read(); let def = &*def.read();
if let TopLevelDef::Function { instance_to_stmt, name, .. } = def { if let TopLevelDef::Function { instance_to_stmt, name, .. } = def {
@ -758,7 +757,7 @@ fn test_inference(source: Vec<&str>, res: Vec<&str>) {
name, name,
instance_to_stmt.len() instance_to_stmt.len()
); );
for inst in instance_to_stmt.iter() { for inst in instance_to_stmt {
let ast = &inst.1.body; let ast = &inst.1.body;
for b in ast.iter() { for b in ast.iter() {
println!("{:?}", stringify_folder.fold_stmt(b.clone()).unwrap()); println!("{:?}", stringify_folder.fold_stmt(b.clone()).unwrap());
@ -777,7 +776,7 @@ fn make_internal_resolver_with_tvar(
print: bool, print: bool,
) -> Arc<ResolverInternal> { ) -> Arc<ResolverInternal> {
let res: Arc<ResolverInternal> = ResolverInternal { let res: Arc<ResolverInternal> = ResolverInternal {
id_to_def: Default::default(), id_to_def: Mutex::default(),
id_to_type: tvars id_to_type: tvars
.into_iter() .into_iter()
.map(|(name, range)| { .map(|(name, range)| {
@ -791,7 +790,7 @@ fn make_internal_resolver_with_tvar(
}) })
.collect::<HashMap<_, _>>() .collect::<HashMap<_, _>>()
.into(), .into(),
class_names: Default::default(), class_names: Mutex::default(),
} }
.into(); .into();
if print { if print {
@ -811,8 +810,8 @@ impl<'a> Fold<Option<Type>> for TypeToStringFolder<'a> {
Ok(if let Some(ty) = user { Ok(if let Some(ty) = user {
self.unifier.internal_stringify( self.unifier.internal_stringify(
ty, ty,
&mut |id| format!("class{}", id.to_string()), &mut |id| format!("class{id}"),
&mut |id| format!("typevar{}", id.to_string()), &mut |id| format!("typevar{id}"),
&mut None, &mut None,
) )
} else { } else {

View File

@ -5,7 +5,9 @@ use crate::{
symbol_resolver::ValueEnum, symbol_resolver::ValueEnum,
toplevel::{helper::PrimDef, DefinitionId, TopLevelDef}, toplevel::{helper::PrimDef, DefinitionId, TopLevelDef},
}; };
use indexmap::IndexMap;
use indoc::indoc; use indoc::indoc;
use nac3parser::ast::FileName;
use nac3parser::parser::parse_program; use nac3parser::parser::parse_program;
use parking_lot::RwLock; use parking_lot::RwLock;
use std::iter::zip; use std::iter::zip;
@ -32,13 +34,13 @@ impl SymbolResolver for Resolver {
_: &PrimitiveStore, _: &PrimitiveStore,
str: StrRef, str: StrRef,
) -> Result<Type, String> { ) -> Result<Type, String> {
self.id_to_type.get(&str).cloned().ok_or_else(|| format!("cannot find symbol `{}`", str)) self.id_to_type.get(&str).copied().ok_or_else(|| format!("cannot find symbol `{str}`"))
} }
fn get_symbol_value<'ctx, 'a>( fn get_symbol_value<'ctx>(
&self, &self,
_: StrRef, _: StrRef,
_: &mut CodeGenContext<'ctx, 'a>, _: &mut CodeGenContext<'ctx, '_>,
) -> Option<ValueEnum<'ctx>> { ) -> Option<ValueEnum<'ctx>> {
unimplemented!() unimplemented!()
} }
@ -46,7 +48,7 @@ impl SymbolResolver for Resolver {
fn get_identifier_def(&self, id: StrRef) -> Result<DefinitionId, HashSet<String>> { fn get_identifier_def(&self, id: StrRef) -> Result<DefinitionId, HashSet<String>> {
self.id_to_def self.id_to_def
.get(&id) .get(&id)
.cloned() .copied()
.ok_or_else(|| HashSet::from(["Unknown identifier".to_string()])) .ok_or_else(|| HashSet::from(["Unknown identifier".to_string()]))
} }
@ -163,7 +165,7 @@ impl TestEnvironment {
unifier.put_primitive_store(&primitives); unifier.put_primitive_store(&primitives);
set_primitives_magic_methods(&primitives, &mut unifier); set_primitives_magic_methods(&primitives, &mut unifier);
let id_to_name = [ let id_to_name: HashMap<_, _> = [
(0, "int32".into()), (0, "int32".into()),
(1, "int64".into()), (1, "int64".into()),
(2, "float".into()), (2, "float".into()),
@ -173,23 +175,21 @@ impl TestEnvironment {
(6, "str".into()), (6, "str".into()),
(7, "exception".into()), (7, "exception".into()),
] ]
.iter() .into();
.cloned()
.collect();
let mut identifier_mapping = HashMap::new(); let mut identifier_mapping = HashMap::new();
identifier_mapping.insert("None".into(), none); identifier_mapping.insert("None".into(), none);
let resolver = Arc::new(Resolver { let resolver = Arc::new(Resolver {
id_to_type: identifier_mapping.clone(), id_to_type: identifier_mapping.clone(),
id_to_def: Default::default(), id_to_def: HashMap::default(),
class_names: Default::default(), class_names: HashMap::default(),
}) as Arc<dyn SymbolResolver + Send + Sync>; }) as Arc<dyn SymbolResolver + Send + Sync>;
TestEnvironment { TestEnvironment {
top_level: TopLevelContext { top_level: TopLevelContext {
definitions: Default::default(), definitions: Arc::default(),
unifiers: Default::default(), unifiers: Arc::default(),
personality_symbol: None, personality_symbol: None,
}, },
unifier, unifier,
@ -287,10 +287,10 @@ impl TestEnvironment {
RwLock::new(TopLevelDef::Class { RwLock::new(TopLevelDef::Class {
name: (*name).into(), name: (*name).into(),
object_id: DefinitionId(i), object_id: DefinitionId(i),
type_vars: Default::default(), type_vars: Vec::default(),
fields: Default::default(), fields: Vec::default(),
methods: Default::default(), methods: Vec::default(),
ancestors: Default::default(), ancestors: Vec::default(),
resolver: None, resolver: None,
constructor: None, constructor: None,
loc: None, loc: None,
@ -322,7 +322,7 @@ impl TestEnvironment {
let foo_ty = unifier.add_ty(TypeEnum::TObj { let foo_ty = unifier.add_ty(TypeEnum::TObj {
obj_id: DefinitionId(defs + 1), obj_id: DefinitionId(defs + 1),
fields: [("a".into(), (tvar.ty, true))].iter().cloned().collect::<HashMap<_, _>>(), fields: [("a".into(), (tvar.ty, true))].into(),
params: into_var_map([tvar]), params: into_var_map([tvar]),
}); });
top_level_defs.push( top_level_defs.push(
@ -331,8 +331,8 @@ impl TestEnvironment {
object_id: DefinitionId(defs + 1), object_id: DefinitionId(defs + 1),
type_vars: vec![tvar.ty], type_vars: vec![tvar.ty],
fields: [("a".into(), tvar.ty, true)].into(), fields: [("a".into(), tvar.ty, true)].into(),
methods: Default::default(), methods: Vec::default(),
ancestors: Default::default(), ancestors: Vec::default(),
resolver: None, resolver: None,
constructor: None, constructor: None,
loc: None, loc: None,
@ -352,24 +352,21 @@ impl TestEnvironment {
let fun = unifier.add_ty(TypeEnum::TFunc(FunSignature { let fun = unifier.add_ty(TypeEnum::TFunc(FunSignature {
args: vec![], args: vec![],
ret: int32, ret: int32,
vars: Default::default(), vars: IndexMap::default(),
})); }));
let bar = unifier.add_ty(TypeEnum::TObj { let bar = unifier.add_ty(TypeEnum::TObj {
obj_id: DefinitionId(defs + 2), obj_id: DefinitionId(defs + 2),
fields: [("a".into(), (int32, true)), ("b".into(), (fun, true))] fields: [("a".into(), (int32, true)), ("b".into(), (fun, true))].into(),
.iter() params: IndexMap::default(),
.cloned()
.collect::<HashMap<_, _>>(),
params: Default::default(),
}); });
top_level_defs.push( top_level_defs.push(
RwLock::new(TopLevelDef::Class { RwLock::new(TopLevelDef::Class {
name: "Bar".into(), name: "Bar".into(),
object_id: DefinitionId(defs + 2), object_id: DefinitionId(defs + 2),
type_vars: Default::default(), type_vars: Vec::default(),
fields: [("a".into(), int32, true), ("b".into(), fun, true)].into(), fields: [("a".into(), int32, true), ("b".into(), fun, true)].into(),
methods: Default::default(), methods: Vec::default(),
ancestors: Default::default(), ancestors: Vec::default(),
resolver: None, resolver: None,
constructor: None, constructor: None,
loc: None, loc: None,
@ -381,26 +378,23 @@ impl TestEnvironment {
unifier.add_ty(TypeEnum::TFunc(FunSignature { unifier.add_ty(TypeEnum::TFunc(FunSignature {
args: vec![], args: vec![],
ret: bar, ret: bar,
vars: Default::default(), vars: IndexMap::default(),
})), })),
); );
let bar2 = unifier.add_ty(TypeEnum::TObj { let bar2 = unifier.add_ty(TypeEnum::TObj {
obj_id: DefinitionId(defs + 3), obj_id: DefinitionId(defs + 3),
fields: [("a".into(), (bool, true)), ("b".into(), (fun, false))] fields: [("a".into(), (bool, true)), ("b".into(), (fun, false))].into(),
.iter() params: IndexMap::default(),
.cloned()
.collect::<HashMap<_, _>>(),
params: Default::default(),
}); });
top_level_defs.push( top_level_defs.push(
RwLock::new(TopLevelDef::Class { RwLock::new(TopLevelDef::Class {
name: "Bar2".into(), name: "Bar2".into(),
object_id: DefinitionId(defs + 3), object_id: DefinitionId(defs + 3),
type_vars: Default::default(), type_vars: Vec::default(),
fields: [("a".into(), bool, true), ("b".into(), fun, false)].into(), fields: [("a".into(), bool, true), ("b".into(), fun, false)].into(),
methods: Default::default(), methods: Vec::default(),
ancestors: Default::default(), ancestors: Vec::default(),
resolver: None, resolver: None,
constructor: None, constructor: None,
loc: None, loc: None,
@ -412,10 +406,10 @@ impl TestEnvironment {
unifier.add_ty(TypeEnum::TFunc(FunSignature { unifier.add_ty(TypeEnum::TFunc(FunSignature {
args: vec![], args: vec![],
ret: bar2, ret: bar2,
vars: Default::default(), vars: IndexMap::default(),
})), })),
); );
let class_names = [("Bar".into(), bar), ("Bar2".into(), bar2)].iter().cloned().collect(); let class_names: HashMap<_, _> = [("Bar".into(), bar), ("Bar2".into(), bar2)].into();
let id_to_name = [ let id_to_name = [
"int32".into(), "int32".into(),
@ -430,14 +424,13 @@ impl TestEnvironment {
"Bar".into(), "Bar".into(),
"Bar2".into(), "Bar2".into(),
] ]
.iter() .into_iter()
.enumerate() .enumerate()
.map(|(a, b)| (a, *b))
.collect(); .collect();
let top_level = TopLevelContext { let top_level = TopLevelContext {
definitions: Arc::new(top_level_defs.into()), definitions: Arc::new(top_level_defs.into()),
unifiers: Default::default(), unifiers: Arc::default(),
personality_symbol: None, personality_symbol: None,
}; };
@ -448,9 +441,7 @@ impl TestEnvironment {
("Bar".into(), DefinitionId(defs + 2)), ("Bar".into(), DefinitionId(defs + 2)),
("Bar2".into(), DefinitionId(defs + 3)), ("Bar2".into(), DefinitionId(defs + 3)),
] ]
.iter() .into(),
.cloned()
.collect(),
class_names, class_names,
}) as Arc<dyn SymbolResolver + Send + Sync>; }) as Arc<dyn SymbolResolver + Send + Sync>;
@ -475,11 +466,11 @@ impl TestEnvironment {
top_level: &self.top_level, top_level: &self.top_level,
function_data: &mut self.function_data, function_data: &mut self.function_data,
unifier: &mut self.unifier, unifier: &mut self.unifier,
variable_mapping: Default::default(), variable_mapping: HashMap::default(),
primitives: &mut self.primitives, primitives: &mut self.primitives,
virtual_checks: &mut self.virtual_checks, virtual_checks: &mut self.virtual_checks,
calls: &mut self.calls, calls: &mut self.calls,
defined_identifiers: Default::default(), defined_identifiers: HashSet::default(),
in_handler: false, in_handler: false,
} }
} }
@ -491,7 +482,7 @@ impl TestEnvironment {
c = 1.234 c = 1.234
d = True d = True
"}, "},
[("a", "int32"), ("b", "int64"), ("c", "float"), ("d", "bool")].iter().cloned().collect(), &[("a", "int32"), ("b", "int64"), ("c", "float"), ("d", "bool")].into(),
&[] &[]
; "primitives test")] ; "primitives test")]
#[test_case(indoc! {" #[test_case(indoc! {"
@ -500,7 +491,7 @@ impl TestEnvironment {
c = 1.234 c = 1.234
d = b(c) d = b(c)
"}, "},
[("a", "fn[[x:float, y:float], float]"), ("b", "fn[[x:float], float]"), ("c", "float"), ("d", "float")].iter().cloned().collect(), &[("a", "fn[[x:float, y:float], float]"), ("b", "fn[[x:float], float]"), ("c", "float"), ("d", "float")].into(),
&[] &[]
; "lambda test")] ; "lambda test")]
#[test_case(indoc! {" #[test_case(indoc! {"
@ -509,7 +500,7 @@ impl TestEnvironment {
a = b a = b
c = b(1) c = b(1)
"}, "},
[("a", "fn[[x:int32], int32]"), ("b", "fn[[x:int32], int32]"), ("c", "int32")].iter().cloned().collect(), &[("a", "fn[[x:int32], int32]"), ("b", "fn[[x:int32], int32]"), ("c", "int32")].into(),
&[] &[]
; "lambda test 2")] ; "lambda test 2")]
#[test_case(indoc! {" #[test_case(indoc! {"
@ -525,15 +516,15 @@ impl TestEnvironment {
b(123) b(123)
"}, "},
[("a", "fn[[x:bool], bool]"), ("b", "fn[[x:int32], int32]"), ("c", "bool"), &[("a", "fn[[x:bool], bool]"), ("b", "fn[[x:int32], int32]"), ("c", "bool"),
("d", "int32"), ("foo1", "Foo[bool]"), ("foo2", "Foo[int32]")].iter().cloned().collect(), ("d", "int32"), ("foo1", "Foo[bool]"), ("foo2", "Foo[int32]")].into(),
&[] &[]
; "obj test")] ; "obj test")]
#[test_case(indoc! {" #[test_case(indoc! {"
a = [1, 2, 3] a = [1, 2, 3]
b = [x + x for x in a] b = [x + x for x in a]
"}, "},
[("a", "list[int32]"), ("b", "list[int32]")].iter().cloned().collect(), &[("a", "list[int32]"), ("b", "list[int32]")].into(),
&[] &[]
; "listcomp test")] ; "listcomp test")]
#[test_case(indoc! {" #[test_case(indoc! {"
@ -541,25 +532,25 @@ impl TestEnvironment {
b = a.b() b = a.b()
a = virtual(Bar2()) a = virtual(Bar2())
"}, "},
[("a", "virtual[Bar]"), ("b", "int32")].iter().cloned().collect(), &[("a", "virtual[Bar]"), ("b", "int32")].into(),
&[("Bar", "Bar"), ("Bar2", "Bar")] &[("Bar", "Bar"), ("Bar2", "Bar")]
; "virtual test")] ; "virtual test")]
#[test_case(indoc! {" #[test_case(indoc! {"
a = [virtual(Bar(), Bar), virtual(Bar2())] a = [virtual(Bar(), Bar), virtual(Bar2())]
b = [x.b() for x in a] b = [x.b() for x in a]
"}, "},
[("a", "list[virtual[Bar]]"), ("b", "list[int32]")].iter().cloned().collect(), &[("a", "list[virtual[Bar]]"), ("b", "list[int32]")].into(),
&[("Bar", "Bar"), ("Bar2", "Bar")] &[("Bar", "Bar"), ("Bar2", "Bar")]
; "virtual list test")] ; "virtual list test")]
fn test_basic(source: &str, mapping: HashMap<&str, &str>, virtuals: &[(&str, &str)]) { fn test_basic(source: &str, mapping: &HashMap<&str, &str>, virtuals: &[(&str, &str)]) {
println!("source:\n{}", source); println!("source:\n{source}");
let mut env = TestEnvironment::new(); let mut env = TestEnvironment::new();
let id_to_name = std::mem::take(&mut env.id_to_name); let id_to_name = std::mem::take(&mut env.id_to_name);
let mut defined_identifiers: HashSet<_> = env.identifier_mapping.keys().cloned().collect(); let mut defined_identifiers: HashSet<_> = env.identifier_mapping.keys().copied().collect();
defined_identifiers.insert("virtual".into()); defined_identifiers.insert("virtual".into());
let mut inferencer = env.get_inferencer(); let mut inferencer = env.get_inferencer();
inferencer.defined_identifiers = defined_identifiers.clone(); inferencer.defined_identifiers = defined_identifiers.clone();
let statements = parse_program(source, Default::default()).unwrap(); let statements = parse_program(source, FileName::default()).unwrap();
let statements = statements let statements = statements
.into_iter() .into_iter()
.map(|v| inferencer.fold_stmt(v)) .map(|v| inferencer.fold_stmt(v))
@ -568,37 +559,37 @@ fn test_basic(source: &str, mapping: HashMap<&str, &str>, virtuals: &[(&str, &st
inferencer.check_block(&statements, &mut defined_identifiers).unwrap(); inferencer.check_block(&statements, &mut defined_identifiers).unwrap();
for (k, v) in inferencer.variable_mapping.iter() { for (k, v) in &inferencer.variable_mapping {
let name = inferencer.unifier.internal_stringify( let name = inferencer.unifier.internal_stringify(
*v, *v,
&mut |v| (*id_to_name.get(&v).unwrap()).into(), &mut |v| (*id_to_name.get(&v).unwrap()).into(),
&mut |v| format!("v{}", v), &mut |v| format!("v{v}"),
&mut None, &mut None,
); );
println!("{}: {}", k, name); println!("{k}: {name}");
} }
for (k, v) in mapping.iter() { for (k, v) in mapping {
let ty = inferencer.variable_mapping.get(&(*k).into()).unwrap(); let ty = inferencer.variable_mapping.get(&(*k).into()).unwrap();
let name = inferencer.unifier.internal_stringify( let name = inferencer.unifier.internal_stringify(
*ty, *ty,
&mut |v| (*id_to_name.get(&v).unwrap()).into(), &mut |v| (*id_to_name.get(&v).unwrap()).into(),
&mut |v| format!("v{}", v), &mut |v| format!("v{v}"),
&mut None, &mut None,
); );
assert_eq!(format!("{}: {}", k, v), format!("{}: {}", k, name)); assert_eq!(format!("{k}: {v}"), format!("{k}: {name}"));
} }
assert_eq!(inferencer.virtual_checks.len(), virtuals.len()); assert_eq!(inferencer.virtual_checks.len(), virtuals.len());
for ((a, b, _), (x, y)) in zip(inferencer.virtual_checks.iter(), virtuals) { for ((a, b, _), (x, y)) in zip(inferencer.virtual_checks.iter(), virtuals) {
let a = inferencer.unifier.internal_stringify( let a = inferencer.unifier.internal_stringify(
*a, *a,
&mut |v| (*id_to_name.get(&v).unwrap()).into(), &mut |v| (*id_to_name.get(&v).unwrap()).into(),
&mut |v| format!("v{}", v), &mut |v| format!("v{v}"),
&mut None, &mut None,
); );
let b = inferencer.unifier.internal_stringify( let b = inferencer.unifier.internal_stringify(
*b, *b,
&mut |v| (*id_to_name.get(&v).unwrap()).into(), &mut |v| (*id_to_name.get(&v).unwrap()).into(),
&mut |v| format!("v{}", v), &mut |v| format!("v{v}"),
&mut None, &mut None,
); );
@ -617,14 +608,14 @@ fn test_basic(source: &str, mapping: HashMap<&str, &str>, virtuals: &[(&str, &st
g = a // b g = a // b
h = a % b h = a % b
"}, "},
[("a", "int32"), &[("a", "int32"),
("b", "int32"), ("b", "int32"),
("c", "int32"), ("c", "int32"),
("d", "int32"), ("d", "int32"),
("e", "int32"), ("e", "int32"),
("f", "float"), ("f", "float"),
("g", "int32"), ("g", "int32"),
("h", "int32")].iter().cloned().collect() ("h", "int32")].into()
; "int32")] ; "int32")]
#[test_case( #[test_case(
indoc! {" indoc! {"
@ -640,7 +631,7 @@ fn test_basic(source: &str, mapping: HashMap<&str, &str>, virtuals: &[(&str, &st
ii = 3 ii = 3
j = a ** b j = a ** b
"}, "},
[("a", "float"), &[("a", "float"),
("b", "float"), ("b", "float"),
("c", "float"), ("c", "float"),
("d", "float"), ("d", "float"),
@ -650,7 +641,7 @@ fn test_basic(source: &str, mapping: HashMap<&str, &str>, virtuals: &[(&str, &st
("h", "float"), ("h", "float"),
("i", "float"), ("i", "float"),
("ii", "int32"), ("ii", "int32"),
("j", "float")].iter().cloned().collect() ("j", "float")].into()
; "float" ; "float"
)] )]
#[test_case( #[test_case(
@ -668,7 +659,7 @@ fn test_basic(source: &str, mapping: HashMap<&str, &str>, virtuals: &[(&str, &st
k = a < b k = a < b
l = a != b l = a != b
"}, "},
[("a", "int64"), &[("a", "int64"),
("b", "int64"), ("b", "int64"),
("c", "int64"), ("c", "int64"),
("d", "int64"), ("d", "int64"),
@ -679,7 +670,7 @@ fn test_basic(source: &str, mapping: HashMap<&str, &str>, virtuals: &[(&str, &st
("i", "bool"), ("i", "bool"),
("j", "bool"), ("j", "bool"),
("k", "bool"), ("k", "bool"),
("l", "bool")].iter().cloned().collect() ("l", "bool")].into()
; "int64" ; "int64"
)] )]
#[test_case( #[test_case(
@ -690,22 +681,22 @@ fn test_basic(source: &str, mapping: HashMap<&str, &str>, virtuals: &[(&str, &st
d = not a d = not a
e = a != b e = a != b
"}, "},
[("a", "bool"), &[("a", "bool"),
("b", "bool"), ("b", "bool"),
("c", "bool"), ("c", "bool"),
("d", "bool"), ("d", "bool"),
("e", "bool")].iter().cloned().collect() ("e", "bool")].into()
; "boolean" ; "boolean"
)] )]
fn test_primitive_magic_methods(source: &str, mapping: HashMap<&str, &str>) { fn test_primitive_magic_methods(source: &str, mapping: &HashMap<&str, &str>) {
println!("source:\n{}", source); println!("source:\n{source}");
let mut env = TestEnvironment::basic_test_env(); let mut env = TestEnvironment::basic_test_env();
let id_to_name = std::mem::take(&mut env.id_to_name); let id_to_name = std::mem::take(&mut env.id_to_name);
let mut defined_identifiers: HashSet<_> = env.identifier_mapping.keys().cloned().collect(); let mut defined_identifiers: HashSet<_> = env.identifier_mapping.keys().copied().collect();
defined_identifiers.insert("virtual".into()); defined_identifiers.insert("virtual".into());
let mut inferencer = env.get_inferencer(); let mut inferencer = env.get_inferencer();
inferencer.defined_identifiers = defined_identifiers.clone(); inferencer.defined_identifiers = defined_identifiers.clone();
let statements = parse_program(source, Default::default()).unwrap(); let statements = parse_program(source, FileName::default()).unwrap();
let statements = statements let statements = statements
.into_iter() .into_iter()
.map(|v| inferencer.fold_stmt(v)) .map(|v| inferencer.fold_stmt(v))
@ -714,23 +705,23 @@ fn test_primitive_magic_methods(source: &str, mapping: HashMap<&str, &str>) {
inferencer.check_block(&statements, &mut defined_identifiers).unwrap(); inferencer.check_block(&statements, &mut defined_identifiers).unwrap();
for (k, v) in inferencer.variable_mapping.iter() { for (k, v) in &inferencer.variable_mapping {
let name = inferencer.unifier.internal_stringify( let name = inferencer.unifier.internal_stringify(
*v, *v,
&mut |v| (*id_to_name.get(&v).unwrap()).into(), &mut |v| (*id_to_name.get(&v).unwrap()).into(),
&mut |v| format!("v{}", v), &mut |v| format!("v{v}"),
&mut None, &mut None,
); );
println!("{}: {}", k, name); println!("{k}: {name}");
} }
for (k, v) in mapping.iter() { for (k, v) in mapping {
let ty = inferencer.variable_mapping.get(&(*k).into()).unwrap(); let ty = inferencer.variable_mapping.get(&(*k).into()).unwrap();
let name = inferencer.unifier.internal_stringify( let name = inferencer.unifier.internal_stringify(
*ty, *ty,
&mut |v| (*id_to_name.get(&v).unwrap()).into(), &mut |v| (*id_to_name.get(&v).unwrap()).into(),
&mut |v| format!("v{}", v), &mut |v| format!("v{v}"),
&mut None, &mut None,
); );
assert_eq!(format!("{}: {}", k, v), format!("{}: {}", k, name)); assert_eq!(format!("{k}: {v}"), format!("{k}: {name}"));
} }
} }

View File

@ -52,8 +52,8 @@ impl Unifier {
if map1.len() != map2.len() { if map1.len() != map2.len() {
return false; return false;
} }
for (k, v) in map1.iter() { for (k, v) in map1 {
if !map2.get(k).map(|v1| self.eq(*v, *v1)).unwrap_or(false) { if !map2.get(k).is_some_and(|v1| self.eq(*v, *v1)) {
return false; return false;
} }
} }
@ -67,8 +67,8 @@ impl Unifier {
if map1.len() != map2.len() { if map1.len() != map2.len() {
return false; return false;
} }
for (k, v) in map1.iter() { for (k, v) in map1 {
if !map2.get(k).map(|v1| self.eq(v.ty, v1.ty)).unwrap_or(false) { if !map2.get(k).is_some_and(|v1| self.eq(v.ty, v1.ty)) {
return false; return false;
} }
} }
@ -115,7 +115,7 @@ impl TestEnvironment {
"Foo".into(), "Foo".into(),
unifier.add_ty(TypeEnum::TObj { unifier.add_ty(TypeEnum::TObj {
obj_id: DefinitionId(3), obj_id: DefinitionId(3),
fields: [("a".into(), (tvar.ty, true))].iter().cloned().collect::<HashMap<_, _>>(), fields: [("a".into(), (tvar.ty, true))].into(),
params: into_var_map([tvar]), params: into_var_map([tvar]),
}), }),
); );
@ -129,13 +129,9 @@ impl TestEnvironment {
result.0 result.0
} }
fn internal_parse<'a, 'b>( fn internal_parse<'b>(&mut self, typ: &'b str, mapping: &Mapping<String>) -> (Type, &'b str) {
&'a mut self,
typ: &'b str,
mapping: &Mapping<String>,
) -> (Type, &'b str) {
// for testing only, so we can just panic when the input is malformed // for testing only, so we can just panic when the input is malformed
let end = typ.find(|c| ['[', ',', ']', '='].contains(&c)).unwrap_or_else(|| typ.len()); let end = typ.find(|c| ['[', ',', ']', '='].contains(&c)).unwrap_or(typ.len());
match &typ[..end] { match &typ[..end] {
"tuple" => { "tuple" => {
let mut s = &typ[end..]; let mut s = &typ[end..];
@ -149,7 +145,7 @@ impl TestEnvironment {
(self.unifier.add_ty(TypeEnum::TTuple { ty }), &s[1..]) (self.unifier.add_ty(TypeEnum::TTuple { ty }), &s[1..])
} }
"list" => { "list" => {
assert_eq!(&typ[end..end + 1], "["); assert_eq!(&typ[end..=end], "[");
let (ty, s) = self.internal_parse(&typ[end + 1..], mapping); let (ty, s) = self.internal_parse(&typ[end + 1..], mapping);
assert_eq!(&s[0..1], "]"); assert_eq!(&s[0..1], "]");
(self.unifier.add_ty(TypeEnum::TList { ty }), &s[1..]) (self.unifier.add_ty(TypeEnum::TList { ty }), &s[1..])
@ -169,12 +165,12 @@ impl TestEnvironment {
} }
x => { x => {
let mut s = &typ[end..]; let mut s = &typ[end..];
let ty = mapping.get(x).cloned().unwrap_or_else(|| { let ty = mapping.get(x).copied().unwrap_or_else(|| {
// mapping should be type variables, type_mapping should be concrete types // mapping should be type variables, type_mapping should be concrete types
// we should not resolve the type of type variables. // we should not resolve the type of type variables.
let mut ty = *self.type_mapping.get(x).unwrap(); let mut ty = *self.type_mapping.get(x).unwrap();
let te = self.unifier.get_ty(ty); let te = self.unifier.get_ty(ty);
if let TypeEnum::TObj { params, .. } = &*te.as_ref() { if let TypeEnum::TObj { params, .. } = &*te {
if !params.is_empty() { if !params.is_empty() {
assert_eq!(&s[0..1], "["); assert_eq!(&s[0..1], "[");
let mut p = Vec::new(); let mut p = Vec::new();
@ -186,7 +182,7 @@ impl TestEnvironment {
s = &s[1..]; s = &s[1..];
ty = self ty = self
.unifier .unifier
.subst(ty, &params.keys().cloned().zip(p.into_iter()).collect()) .subst(ty, &params.keys().copied().zip(p).collect())
.unwrap_or(ty); .unwrap_or(ty);
} }
} }
@ -250,12 +246,12 @@ fn test_unify(
let mut mapping = HashMap::new(); let mut mapping = HashMap::new();
for i in 1..=variable_count { for i in 1..=variable_count {
let v = env.unifier.get_dummy_var(); let v = env.unifier.get_dummy_var();
mapping.insert(format!("v{}", i), v.ty); mapping.insert(format!("v{i}"), v.ty);
} }
// unification may have side effect when we do type resolution, so freeze the types // unification may have side effect when we do type resolution, so freeze the types
// before doing unification. // before doing unification.
let mut pairs = Vec::new(); let mut pairs = Vec::new();
for (a, b) in perm.iter() { for (a, b) in &perm {
let t1 = env.parse(a, &mapping); let t1 = env.parse(a, &mapping);
let t2 = env.parse(b, &mapping); let t2 = env.parse(b, &mapping);
pairs.push((t1, t2)); pairs.push((t1, t2));
@ -263,8 +259,8 @@ fn test_unify(
for (t1, t2) in pairs { for (t1, t2) in pairs {
env.unifier.unify(t1, t2).unwrap(); env.unifier.unify(t1, t2).unwrap();
} }
for (a, b) in verify_pairs.iter() { for (a, b) in verify_pairs {
println!("{} = {}", a, b); println!("{a} = {b}");
let t1 = env.parse(a, &mapping); let t1 = env.parse(a, &mapping);
let t2 = env.parse(b, &mapping); let t2 = env.parse(b, &mapping);
println!("a = {}, b = {}", env.unifier.stringify(t1), env.unifier.stringify(t2)); println!("a = {}, b = {}", env.unifier.stringify(t1), env.unifier.stringify(t2));
@ -315,12 +311,12 @@ fn test_invalid_unification(
let mut mapping = HashMap::new(); let mut mapping = HashMap::new();
for i in 1..=variable_count { for i in 1..=variable_count {
let v = env.unifier.get_dummy_var(); let v = env.unifier.get_dummy_var();
mapping.insert(format!("v{}", i), v.ty); mapping.insert(format!("v{i}"), v.ty);
} }
// unification may have side effect when we do type resolution, so freeze the types // unification may have side effect when we do type resolution, so freeze the types
// before doing unification. // before doing unification.
let mut pairs = Vec::new(); let mut pairs = Vec::new();
for (a, b) in unify_pairs.iter() { for (a, b) in unify_pairs {
let t1 = env.parse(a, &mapping); let t1 = env.parse(a, &mapping);
let t2 = env.parse(b, &mapping); let t2 = env.parse(b, &mapping);
pairs.push((t1, t2)); pairs.push((t1, t2));
@ -363,10 +359,7 @@ fn test_virtual() {
})); }));
let bar = env.unifier.add_ty(TypeEnum::TObj { let bar = env.unifier.add_ty(TypeEnum::TObj {
obj_id: DefinitionId(5), obj_id: DefinitionId(5),
fields: [("f".into(), (fun, false)), ("a".into(), (int, false))] fields: [("f".into(), (fun, false)), ("a".into(), (int, false))].into(),
.iter()
.cloned()
.collect::<HashMap<StrRef, _>>(),
params: VarMap::new(), params: VarMap::new(),
}); });
let v0 = env.unifier.get_dummy_var().ty; let v0 = env.unifier.get_dummy_var().ty;
@ -374,21 +367,15 @@ fn test_virtual() {
let a = env.unifier.add_ty(TypeEnum::TVirtual { ty: bar }); let a = env.unifier.add_ty(TypeEnum::TVirtual { ty: bar });
let b = env.unifier.add_ty(TypeEnum::TVirtual { ty: v0 }); let b = env.unifier.add_ty(TypeEnum::TVirtual { ty: v0 });
let c = env let c = env.unifier.add_record([("f".into(), RecordField::new(v1, false, None))].into());
.unifier
.add_record([("f".into(), RecordField::new(v1, false, None))].iter().cloned().collect());
env.unifier.unify(a, b).unwrap(); env.unifier.unify(a, b).unwrap();
env.unifier.unify(b, c).unwrap(); env.unifier.unify(b, c).unwrap();
assert!(env.unifier.eq(v1, fun)); assert!(env.unifier.eq(v1, fun));
let d = env let d = env.unifier.add_record([("a".into(), RecordField::new(v1, true, None))].into());
.unifier
.add_record([("a".into(), RecordField::new(v1, true, None))].iter().cloned().collect());
assert_eq!(env.unify(b, d), Err("`virtual[5]::a` field/method does not exist".to_string())); assert_eq!(env.unify(b, d), Err("`virtual[5]::a` field/method does not exist".to_string()));
let d = env let d = env.unifier.add_record([("b".into(), RecordField::new(v1, true, None))].into());
.unifier
.add_record([("b".into(), RecordField::new(v1, true, None))].iter().cloned().collect());
assert_eq!(env.unify(b, d), Err("`virtual[5]::b` field/method does not exist".to_string())); assert_eq!(env.unify(b, d), Err("`virtual[5]::b` field/method does not exist".to_string()));
} }
@ -519,8 +506,7 @@ fn test_instantiation() {
let float = env.parse("float", &HashMap::new()); let float = env.parse("float", &HashMap::new());
let list_int = env.parse("list[int]", &HashMap::new()); let list_int = env.parse("list[int]", &HashMap::new());
let obj_map: HashMap<_, _> = let obj_map: HashMap<_, _> = [(0usize, "int"), (1, "float"), (2, "bool")].into();
[(0usize, "int"), (1, "float"), (2, "bool")].iter().cloned().collect();
let v = env.unifier.get_fresh_var_with_range(&[int, boolean], None, None).ty; let v = env.unifier.get_fresh_var_with_range(&[int, boolean], None, None).ty;
let list_v = env.unifier.add_ty(TypeEnum::TList { ty: v }); let list_v = env.unifier.add_ty(TypeEnum::TList { ty: v });
@ -559,8 +545,8 @@ fn test_instantiation() {
.map(|ty| { .map(|ty| {
env.unifier.internal_stringify( env.unifier.internal_stringify(
*ty, *ty,
&mut |i| obj_map.get(&i).unwrap().to_string(), &mut |i| (*obj_map.get(&i).unwrap()).to_string(),
&mut |i| format!("v{}", i), &mut |i| format!("v{i}"),
&mut None, &mut None,
) )
}) })

View File

@ -282,7 +282,7 @@ mod tests {
#[test] #[test]
fn test_parse_fstring() { fn test_parse_fstring() {
let source = "{a}{ b }{{foo}}"; let source = "{a}{ b }{{foo}}";
let parse_ast = parse_fstring(&source).unwrap(); let parse_ast = parse_fstring(source).unwrap();
insta::assert_debug_snapshot!(parse_ast); insta::assert_debug_snapshot!(parse_ast);
} }
@ -290,7 +290,7 @@ mod tests {
#[test] #[test]
fn test_parse_fstring_nested_spec() { fn test_parse_fstring_nested_spec() {
let source = "{foo:{spec}}"; let source = "{foo:{spec}}";
let parse_ast = parse_fstring(&source).unwrap(); let parse_ast = parse_fstring(source).unwrap();
insta::assert_debug_snapshot!(parse_ast); insta::assert_debug_snapshot!(parse_ast);
} }
@ -298,7 +298,7 @@ mod tests {
#[test] #[test]
fn test_parse_fstring_not_nested_spec() { fn test_parse_fstring_not_nested_spec() {
let source = "{foo:spec}"; let source = "{foo:spec}";
let parse_ast = parse_fstring(&source).unwrap(); let parse_ast = parse_fstring(source).unwrap();
insta::assert_debug_snapshot!(parse_ast); insta::assert_debug_snapshot!(parse_ast);
} }
@ -311,7 +311,7 @@ mod tests {
#[test] #[test]
fn test_fstring_parse_selfdocumenting_base() { fn test_fstring_parse_selfdocumenting_base() {
let src = "{user=}"; let src = "{user=}";
let parse_ast = parse_fstring(&src).unwrap(); let parse_ast = parse_fstring(src).unwrap();
insta::assert_debug_snapshot!(parse_ast); insta::assert_debug_snapshot!(parse_ast);
} }
@ -319,7 +319,7 @@ mod tests {
#[test] #[test]
fn test_fstring_parse_selfdocumenting_base_more() { fn test_fstring_parse_selfdocumenting_base_more() {
let src = "mix {user=} with text and {second=}"; let src = "mix {user=} with text and {second=}";
let parse_ast = parse_fstring(&src).unwrap(); let parse_ast = parse_fstring(src).unwrap();
insta::assert_debug_snapshot!(parse_ast); insta::assert_debug_snapshot!(parse_ast);
} }
@ -327,7 +327,7 @@ mod tests {
#[test] #[test]
fn test_fstring_parse_selfdocumenting_format() { fn test_fstring_parse_selfdocumenting_format() {
let src = "{user=:>10}"; let src = "{user=:>10}";
let parse_ast = parse_fstring(&src).unwrap(); let parse_ast = parse_fstring(src).unwrap();
insta::assert_debug_snapshot!(parse_ast); insta::assert_debug_snapshot!(parse_ast);
} }
@ -360,35 +360,35 @@ mod tests {
#[test] #[test]
fn test_parse_fstring_not_equals() { fn test_parse_fstring_not_equals() {
let source = "{1 != 2}"; let source = "{1 != 2}";
let parse_ast = parse_fstring(&source).unwrap(); let parse_ast = parse_fstring(source).unwrap();
insta::assert_debug_snapshot!(parse_ast); insta::assert_debug_snapshot!(parse_ast);
} }
#[test] #[test]
fn test_parse_fstring_equals() { fn test_parse_fstring_equals() {
let source = "{42 == 42}"; let source = "{42 == 42}";
let parse_ast = parse_fstring(&source).unwrap(); let parse_ast = parse_fstring(source).unwrap();
insta::assert_debug_snapshot!(parse_ast); insta::assert_debug_snapshot!(parse_ast);
} }
#[test] #[test]
fn test_parse_fstring_selfdoc_prec_space() { fn test_parse_fstring_selfdoc_prec_space() {
let source = "{x =}"; let source = "{x =}";
let parse_ast = parse_fstring(&source).unwrap(); let parse_ast = parse_fstring(source).unwrap();
insta::assert_debug_snapshot!(parse_ast); insta::assert_debug_snapshot!(parse_ast);
} }
#[test] #[test]
fn test_parse_fstring_selfdoc_trailing_space() { fn test_parse_fstring_selfdoc_trailing_space() {
let source = "{x= }"; let source = "{x= }";
let parse_ast = parse_fstring(&source).unwrap(); let parse_ast = parse_fstring(source).unwrap();
insta::assert_debug_snapshot!(parse_ast); insta::assert_debug_snapshot!(parse_ast);
} }
#[test] #[test]
fn test_parse_fstring_yield_expr() { fn test_parse_fstring_yield_expr() {
let source = "{yield}"; let source = "{yield}";
let parse_ast = parse_fstring(&source).unwrap(); let parse_ast = parse_fstring(source).unwrap();
insta::assert_debug_snapshot!(parse_ast); insta::assert_debug_snapshot!(parse_ast);
} }
} }

View File

@ -1284,13 +1284,14 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{make_tokenizer, NewlineHandler, Tok}; use super::{make_tokenizer, NewlineHandler, Tok};
use nac3ast::FileName;
const WINDOWS_EOL: &str = "\r\n"; const WINDOWS_EOL: &str = "\r\n";
const MAC_EOL: &str = "\r"; const MAC_EOL: &str = "\r";
const UNIX_EOL: &str = "\n"; const UNIX_EOL: &str = "\n";
pub fn lex_source(source: &str) -> Vec<Tok> { pub fn lex_source(source: &str) -> Vec<Tok> {
let lexer = make_tokenizer(source, Default::default()); let lexer = make_tokenizer(source, FileName::default());
lexer.map(|x| x.unwrap().1).collect() lexer.map(|x| x.unwrap().1).collect()
} }
@ -1370,7 +1371,7 @@ class Foo(A, B):
Dedent, Dedent,
Dedent Dedent
] ]
) );
} }
#[test] #[test]
@ -1726,7 +1727,7 @@ class Foo(A, B):
#[test] #[test]
fn test_escape_char_in_byte_literal() { fn test_escape_char_in_byte_literal() {
// backslash does not escape // backslash does not escape
let source = r##"b"omkmok\Xaa""##; let source = r#"b"omkmok\Xaa""#;
let tokens = lex_source(source); let tokens = lex_source(source);
let res = vec![111, 109, 107, 109, 111, 107, 92, 88, 97, 97]; let res = vec![111, 109, 107, 109, 111, 107, 92, 88, 97, 97];
assert_eq!(tokens, vec![Tok::Bytes { value: res }, Tok::Newline]); assert_eq!(tokens, vec![Tok::Bytes { value: res }, Tok::Newline]);
@ -1739,14 +1740,14 @@ class Foo(A, B):
assert_eq!(tokens, vec![Tok::Bytes { value: b"\\x1z".to_vec() }, Tok::Newline]); assert_eq!(tokens, vec![Tok::Bytes { value: b"\\x1z".to_vec() }, Tok::Newline]);
let source = r"rb'\\'"; let source = r"rb'\\'";
let tokens = lex_source(source); let tokens = lex_source(source);
assert_eq!(tokens, vec![Tok::Bytes { value: b"\\\\".to_vec() }, Tok::Newline]) assert_eq!(tokens, vec![Tok::Bytes { value: b"\\\\".to_vec() }, Tok::Newline]);
} }
#[test] #[test]
fn test_escape_octet() { fn test_escape_octet() {
let source = r##"b'\43a\4\1234'"##; let source = r"b'\43a\4\1234'";
let tokens = lex_source(source); let tokens = lex_source(source);
assert_eq!(tokens, vec![Tok::Bytes { value: b"#a\x04S4".to_vec() }, Tok::Newline]) assert_eq!(tokens, vec![Tok::Bytes { value: b"#a\x04S4".to_vec() }, Tok::Newline]);
} }
#[test] #[test]
@ -1756,6 +1757,6 @@ class Foo(A, B):
assert_eq!( assert_eq!(
tokens, tokens,
vec![Tok::String { value: "\u{2002}".to_owned(), is_fstring: false }, Tok::Newline] vec![Tok::String { value: "\u{2002}".to_owned(), is_fstring: false }, Tok::Newline]
) );
} }
} }

View File

@ -85,42 +85,42 @@ mod tests {
#[test] #[test]
fn test_parse_empty() { fn test_parse_empty() {
let parse_ast = parse_program("", Default::default()).unwrap(); let parse_ast = parse_program("", FileName::default()).unwrap();
insta::assert_debug_snapshot!(parse_ast); insta::assert_debug_snapshot!(parse_ast);
} }
#[test] #[test]
fn test_parse_print_hello() { fn test_parse_print_hello() {
let source = String::from("print('Hello world')"); let source = String::from("print('Hello world')");
let parse_ast = parse_program(&source, Default::default()).unwrap(); let parse_ast = parse_program(&source, FileName::default()).unwrap();
insta::assert_debug_snapshot!(parse_ast); insta::assert_debug_snapshot!(parse_ast);
} }
#[test] #[test]
fn test_parse_print_2() { fn test_parse_print_2() {
let source = String::from("print('Hello world', 2)"); let source = String::from("print('Hello world', 2)");
let parse_ast = parse_program(&source, Default::default()).unwrap(); let parse_ast = parse_program(&source, FileName::default()).unwrap();
insta::assert_debug_snapshot!(parse_ast); insta::assert_debug_snapshot!(parse_ast);
} }
#[test] #[test]
fn test_parse_kwargs() { fn test_parse_kwargs() {
let source = String::from("my_func('positional', keyword=2)"); let source = String::from("my_func('positional', keyword=2)");
let parse_ast = parse_program(&source, Default::default()).unwrap(); let parse_ast = parse_program(&source, FileName::default()).unwrap();
insta::assert_debug_snapshot!(parse_ast); insta::assert_debug_snapshot!(parse_ast);
} }
#[test] #[test]
fn test_parse_if_elif_else() { fn test_parse_if_elif_else() {
let source = String::from("if 1: 10\nelif 2: 20\nelse: 30"); let source = String::from("if 1: 10\nelif 2: 20\nelse: 30");
let parse_ast = parse_program(&source, Default::default()).unwrap(); let parse_ast = parse_program(&source, FileName::default()).unwrap();
insta::assert_debug_snapshot!(parse_ast); insta::assert_debug_snapshot!(parse_ast);
} }
#[test] #[test]
fn test_parse_lambda() { fn test_parse_lambda() {
let source = "lambda x, y: x * y"; // lambda(x, y): x * y"; let source = "lambda x, y: x * y"; // lambda(x, y): x * y";
let parse_ast = parse_program(source, Default::default()).unwrap(); let parse_ast = parse_program(source, FileName::default()).unwrap();
insta::assert_debug_snapshot!(parse_ast); insta::assert_debug_snapshot!(parse_ast);
} }
@ -128,7 +128,7 @@ mod tests {
fn test_parse_tuples() { fn test_parse_tuples() {
let source = "a, b = 4, 5"; let source = "a, b = 4, 5";
insta::assert_debug_snapshot!(parse_program(source, Default::default()).unwrap()); insta::assert_debug_snapshot!(parse_program(source, FileName::default()).unwrap());
} }
#[test] #[test]
@ -139,7 +139,7 @@ class Foo(A, B):
pass pass
def method_with_default(self, arg='default'): def method_with_default(self, arg='default'):
pass"; pass";
insta::assert_debug_snapshot!(parse_program(source, Default::default()).unwrap()); insta::assert_debug_snapshot!(parse_program(source, FileName::default()).unwrap());
} }
#[test] #[test]
@ -182,7 +182,7 @@ while i < 2: # nac3: 4
# nac3: if1 # nac3: if1
if 1: # nac3: if2 if 1: # nac3: if2
3"; 3";
insta::assert_debug_snapshot!(parse_program(source, Default::default()).unwrap()); insta::assert_debug_snapshot!(parse_program(source, FileName::default()).unwrap());
} }
#[test] #[test]
@ -195,7 +195,7 @@ while test: # nac3: while3
# nac3: simple assign0 # nac3: simple assign0
a = 3 # nac3: simple assign1 a = 3 # nac3: simple assign1
"; ";
insta::assert_debug_snapshot!(parse_program(source, Default::default()).unwrap()); insta::assert_debug_snapshot!(parse_program(source, FileName::default()).unwrap());
} }
#[test] #[test]
@ -214,7 +214,7 @@ if a: # nac3: small2
for i in a: # nac3: for1 for i in a: # nac3: for1
pass pass
"; ";
insta::assert_debug_snapshot!(parse_program(source, Default::default()).unwrap()); insta::assert_debug_snapshot!(parse_program(source, FileName::default()).unwrap());
} }
#[test] #[test]
@ -223,6 +223,6 @@ for i in a: # nac3: for1
if a: # nac3: something if a: # nac3: something
a = 3 a = 3
"; ";
assert!(parse_program(source, Default::default()).is_err()); assert!(parse_program(source, FileName::default()).is_err());
} }
} }