forked from M-Labs/nac3
meta: Apply clippy changes
This commit is contained in:
parent
32919949e2
commit
82091b1be8
|
@ -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,
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, ¶ms.keys().cloned().zip(p.into_iter()).collect())
|
.subst(ty, ¶ms.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,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue