nac3standalone: allow classes without explicit init (#221)

Reviewed-on: M-Labs/nac3#304
Co-authored-by: z78078 <cc@m-labs.hk>
Co-committed-by: z78078 <cc@m-labs.hk>
issue-136
z78078 2022-07-07 10:36:25 +08:00 committed by sb10q
parent 96b3a3bf5c
commit ebd25af38b
4 changed files with 26 additions and 9 deletions

View File

@ -371,7 +371,7 @@ impl Nac3 {
});
let (name, def_id, ty) = composer
.register_top_level(stmt.clone(), Some(resolver.clone()), path.clone())
.register_top_level(stmt.clone(), Some(resolver.clone()), path.clone(), false)
.map_err(|e| {
CompileError::new_err(format!(
"compilation failed\n----------\n{}",
@ -451,7 +451,7 @@ impl Nac3 {
});
let resolver = Arc::new(Resolver(inner_resolver.clone())) as Arc<dyn SymbolResolver + Send + Sync>;
let (_, def_id, _) = composer
.register_top_level(synthesized.pop().unwrap(), Some(resolver.clone()), "".into())
.register_top_level(synthesized.pop().unwrap(), Some(resolver.clone()), "".into(), false)
.unwrap();
let fun_signature =

View File

@ -164,6 +164,7 @@ impl TopLevelComposer {
ast: ast::Stmt<()>,
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
mod_path: String,
allow_no_constructor: bool,
) -> Result<(StrRef, DefinitionId, Option<Type>), String> {
let defined_names = &mut self.defined_names;
match &ast.node {
@ -298,7 +299,7 @@ impl TopLevelComposer {
self.definition_ast_list.push((def, Some(ast)));
}
let result_ty = if contains_constructor { Some(constructor_ty) } else { None };
let result_ty = if allow_no_constructor || contains_constructor { Some(constructor_ty) } else { None };
Ok((class_name, DefinitionId(class_def_id), result_ty))
}

View File

@ -105,7 +105,7 @@ impl SymbolResolver for Resolver {
def __init__(self):
self.c: int32 = 4
self.a: bool = True
"}
"},
];
"register"
)]
@ -116,10 +116,26 @@ fn test_simple_register(source: Vec<&str>) {
let ast = parse_program(s, Default::default()).unwrap();
let ast = ast[0].clone();
composer.register_top_level(ast, None, "".into()).unwrap();
composer.register_top_level(ast, None, "".into(), false).unwrap();
}
}
#[test_case(
indoc! {"
class A:
def foo(self):
pass
a = A()
"};
"register"
)]
fn test_simple_register_without_constructor(source: &str) {
let mut composer: TopLevelComposer = Default::default();
let ast = parse_program(source, Default::default()).unwrap();
let ast = ast[0].clone();
composer.register_top_level(ast, None, "".into(), true).unwrap();
}
#[test_case(
vec![
indoc! {"
@ -163,7 +179,7 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
let ast = ast[0].clone();
let (id, def_id, ty) =
composer.register_top_level(ast, Some(resolver.clone()), "".into()).unwrap();
composer.register_top_level(ast, Some(resolver.clone()), "".into(), false).unwrap();
internal_resolver.add_id_def(id, def_id);
if let Some(ty) = ty {
internal_resolver.add_id_type(id, ty);
@ -515,7 +531,7 @@ fn test_analyze(source: Vec<&str>, res: Vec<&str>) {
let ast = ast[0].clone();
let (id, def_id, ty) = {
match composer.register_top_level(ast, Some(resolver.clone()), "".into()) {
match composer.register_top_level(ast, Some(resolver.clone()), "".into(), false) {
Ok(x) => x,
Err(msg) => {
if print {
@ -699,7 +715,7 @@ fn test_inference(source: Vec<&str>, res: Vec<&str>) {
let ast = ast[0].clone();
let (id, def_id, ty) = {
match composer.register_top_level(ast, Some(resolver.clone()), "".into()) {
match composer.register_top_level(ast, Some(resolver.clone()), "".into(), false) {
Ok(x) => x,
Err(msg) => {
if print {

View File

@ -208,7 +208,7 @@ fn main() {
if module == &Some("__future__".into()) && names.len() == 1 && names[0].name == "annotations".into() => (),
_ => {
let (name, def_id, ty) =
composer.register_top_level(stmt, Some(resolver.clone()), "__main__".into()).unwrap();
composer.register_top_level(stmt, Some(resolver.clone()), "__main__".into(), true).unwrap();
internal_resolver.add_id_def(name, def_id);
if let Some(ty) = ty {
internal_resolver.add_id_type(name, ty);