From 8dbb4ad58a6d73b9ad766c0f1c331b42295a6568 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Fri, 5 Nov 2021 20:28:21 +0800 Subject: [PATCH 1/2] nac3core/toplevel: make test less fragile test results should not depend on internal states if possible --- nac3core/src/toplevel/helper.rs | 27 +++++++------------ ...el__test__test_analyze__generic_class.snap | 12 ++++----- ...t__test_analyze__inheritance_override.snap | 18 ++++++------- ...est__test_analyze__list_tuple_generic.snap | 14 +++++----- ...__toplevel__test__test_analyze__self1.snap | 14 +++++----- ...t__test_analyze__simple_class_compose.snap | 22 +++++++-------- ...t__test_analyze__simple_pass_in_class.snap | 2 +- nac3core/src/toplevel/test.rs | 24 ++++------------- nac3core/src/toplevel/type_annotation.rs | 22 +++++++++++++++ nac3core/src/typecheck/typedef/mod.rs | 8 +++--- 10 files changed, 82 insertions(+), 81 deletions(-) diff --git a/nac3core/src/toplevel/helper.rs b/nac3core/src/toplevel/helper.rs index ec4bd184..ac997b51 100644 --- a/nac3core/src/toplevel/helper.rs +++ b/nac3core/src/toplevel/helper.rs @@ -1,48 +1,41 @@ use super::*; impl TopLevelDef { - pub fn to_string( + pub fn to_string( &self, unifier: &mut Unifier, - obj_to_name: &mut F, - var_to_name: &mut G, ) -> String - where - F: FnMut(usize) -> String, - G: FnMut(u32) -> String, { match self { TopLevelDef::Class { - name, ancestors, fields, methods, object_id, type_vars, .. + name, ancestors, fields, methods, type_vars, .. } => { let fields_str = fields .iter() .map(|(n, ty)| { - (n.to_string(), unifier.stringify(*ty, obj_to_name, var_to_name)) + (n.to_string(), unifier.default_stringify(*ty)) }) .collect_vec(); let methods_str = methods .iter() .map(|(n, ty, id)| { - (n.to_string(), unifier.stringify(*ty, obj_to_name, var_to_name), *id) + (n.to_string(), unifier.default_stringify(*ty), *id) }) .collect_vec(); - format!( - "Class {{\nname: {:?},\ndef_id: {:?},\nancestors: {:?},\nfields: {:?},\nmethods: {:?},\ntype_vars: {:?}\n}}", + "Class {{\nname: {:?},\nancestors: {:?},\nfields: {:?},\nmethods: {:?},\ntype_vars: {:?}\n}}", name, - object_id, - ancestors, - fields_str, - methods_str, - type_vars, + ancestors.iter().map(|ancestor| ancestor.stringify(unifier)).collect_vec(), + fields_str.iter().map(|(a, _)| a).collect_vec(), + methods_str.iter().map(|(a, b, _)| (a, b)).collect_vec(), + type_vars.iter().map(|id| unifier.default_stringify(*id)).collect_vec(), ) } TopLevelDef::Function { name, signature, var_id, .. } => format!( "Function {{\nname: {:?},\nsig: {:?},\nvar_id: {:?}\n}}", name, - unifier.stringify(*signature, obj_to_name, var_to_name), + unifier.default_stringify(*signature), { // preserve the order for debug output and test let mut r = var_id.clone(); diff --git a/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__generic_class.snap b/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__generic_class.snap index c7944a61..869c5078 100644 --- a/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__generic_class.snap +++ b/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__generic_class.snap @@ -4,10 +4,10 @@ expression: res_vec --- [ - "14: Class {\nname: \"Generic_A\",\ndef_id: DefinitionId(14),\nancestors: [CustomClassKind { id: DefinitionId(14), params: [TypeVarKind(UnificationKey(111))] }, CustomClassKind { id: DefinitionId(17), params: [] }],\nfields: [(\"aa\", \"class3\"), (\"a\", \"class1\")],\nmethods: [(\"__init__\", \"fn[[], class4]\", DefinitionId(15)), (\"foo\", \"fn[[b=tvar3], class4]\", DefinitionId(19)), (\"fun\", \"fn[[a=class0], tvar4]\", DefinitionId(16))],\ntype_vars: [UnificationKey(111)]\n}\n", - "15: Function {\nname: \"Generic_A.__init__\",\nsig: \"fn[[], class4]\",\nvar_id: [4]\n}\n", - "16: Function {\nname: \"Generic_A.fun\",\nsig: \"fn[[a=class0], tvar4]\",\nvar_id: [4]\n}\n", - "17: Class {\nname: \"B\",\ndef_id: DefinitionId(17),\nancestors: [CustomClassKind { id: DefinitionId(17), params: [] }],\nfields: [(\"aa\", \"class3\")],\nmethods: [(\"__init__\", \"fn[[], class4]\", DefinitionId(18)), (\"foo\", \"fn[[b=tvar3], class4]\", DefinitionId(19))],\ntype_vars: []\n}\n", - "18: Function {\nname: \"B.__init__\",\nsig: \"fn[[], class4]\",\nvar_id: []\n}\n", - "19: Function {\nname: \"B.foo\",\nsig: \"fn[[b=tvar3], class4]\",\nvar_id: [3]\n}\n", + "Class {\nname: \"Generic_A\",\nancestors: [\"{class: Generic_A, params: [\\\"var4\\\"]}\", \"{class: B, params: []}\"],\nfields: [\"aa\", \"a\"],\nmethods: [(\"__init__\", \"fn[[], none]\"), (\"foo\", \"fn[[b=var3], none]\"), (\"fun\", \"fn[[a=int32], var4]\")],\ntype_vars: [\"var4\"]\n}\n", + "Function {\nname: \"Generic_A.__init__\",\nsig: \"fn[[], none]\",\nvar_id: [4]\n}\n", + "Function {\nname: \"Generic_A.fun\",\nsig: \"fn[[a=int32], var4]\",\nvar_id: [4]\n}\n", + "Class {\nname: \"B\",\nancestors: [\"{class: B, params: []}\"],\nfields: [\"aa\"],\nmethods: [(\"__init__\", \"fn[[], none]\"), (\"foo\", \"fn[[b=var3], none]\")],\ntype_vars: []\n}\n", + "Function {\nname: \"B.__init__\",\nsig: \"fn[[], none]\",\nvar_id: []\n}\n", + "Function {\nname: \"B.foo\",\nsig: \"fn[[b=var3], none]\",\nvar_id: [3]\n}\n", ] diff --git a/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__inheritance_override.snap b/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__inheritance_override.snap index c683c255..2de87dab 100644 --- a/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__inheritance_override.snap +++ b/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__inheritance_override.snap @@ -4,13 +4,13 @@ expression: res_vec --- [ - "14: Class {\nname: \"A\",\ndef_id: DefinitionId(14),\nancestors: [CustomClassKind { id: DefinitionId(14), params: [TypeVarKind(UnificationKey(110))] }],\nfields: [(\"a\", \"class0\"), (\"b\", \"tvar3\"), (\"c\", \"class14[3->class1]\")],\nmethods: [(\"__init__\", \"fn[[t=tvar3], class4]\", DefinitionId(15)), (\"fun\", \"fn[[a=class0, b=tvar3], list[virtual[class18[4->class3]]]]\", DefinitionId(16)), (\"foo\", \"fn[[c=class21], class4]\", DefinitionId(17))],\ntype_vars: [UnificationKey(110)]\n}\n", - "15: Function {\nname: \"A.__init__\",\nsig: \"fn[[t=tvar3], class4]\",\nvar_id: [3]\n}\n", - "16: Function {\nname: \"A.fun\",\nsig: \"fn[[a=class0, b=tvar3], list[virtual[class18[4->class3]]]]\",\nvar_id: [3]\n}\n", - "17: Function {\nname: \"A.foo\",\nsig: \"fn[[c=class21], class4]\",\nvar_id: [3]\n}\n", - "18: Class {\nname: \"B\",\ndef_id: DefinitionId(18),\nancestors: [CustomClassKind { id: DefinitionId(18), params: [TypeVarKind(UnificationKey(111))] }, CustomClassKind { id: DefinitionId(14), params: [PrimitiveKind(UnificationKey(2))] }],\nfields: [(\"a\", \"class0\"), (\"b\", \"tvar3\"), (\"c\", \"class14[3->class1]\"), (\"d\", \"class21\")],\nmethods: [(\"__init__\", \"fn[[], class4]\", DefinitionId(19)), (\"fun\", \"fn[[a=class0, b=tvar3], list[virtual[class18[4->class3]]]]\", DefinitionId(20)), (\"foo\", \"fn[[c=class21], class4]\", DefinitionId(17))],\ntype_vars: [UnificationKey(111)]\n}\n", - "19: Function {\nname: \"B.__init__\",\nsig: \"fn[[], class4]\",\nvar_id: [4]\n}\n", - "20: Function {\nname: \"B.fun\",\nsig: \"fn[[a=class0, b=tvar3], list[virtual[class18[4->class3]]]]\",\nvar_id: [3, 4]\n}\n", - "21: Class {\nname: \"C\",\ndef_id: DefinitionId(21),\nancestors: [CustomClassKind { id: DefinitionId(21), params: [] }, CustomClassKind { id: DefinitionId(18), params: [PrimitiveKind(UnificationKey(3))] }, CustomClassKind { id: DefinitionId(14), params: [PrimitiveKind(UnificationKey(2))] }],\nfields: [(\"a\", \"class0\"), (\"b\", \"tvar3\"), (\"c\", \"class14[3->class1]\"), (\"d\", \"class21\"), (\"e\", \"class1\")],\nmethods: [(\"__init__\", \"fn[[], class4]\", DefinitionId(22)), (\"fun\", \"fn[[a=class0, b=tvar3], list[virtual[class18[4->class3]]]]\", DefinitionId(20)), (\"foo\", \"fn[[c=class21], class4]\", DefinitionId(17))],\ntype_vars: []\n}\n", - "22: Function {\nname: \"C.__init__\",\nsig: \"fn[[], class4]\",\nvar_id: []\n}\n", + "Class {\nname: \"A\",\nancestors: [\"{class: A, params: [\\\"var3\\\"]}\"],\nfields: [\"a\", \"b\", \"c\"],\nmethods: [(\"__init__\", \"fn[[t=var3], none]\"), (\"fun\", \"fn[[a=int32, b=var3], list[virtual[B[4->bool]]]]\"), (\"foo\", \"fn[[c=C], none]\")],\ntype_vars: [\"var3\"]\n}\n", + "Function {\nname: \"A.__init__\",\nsig: \"fn[[t=var3], none]\",\nvar_id: [3]\n}\n", + "Function {\nname: \"A.fun\",\nsig: \"fn[[a=int32, b=var3], list[virtual[B[4->bool]]]]\",\nvar_id: [3]\n}\n", + "Function {\nname: \"A.foo\",\nsig: \"fn[[c=C], none]\",\nvar_id: [3]\n}\n", + "Class {\nname: \"B\",\nancestors: [\"{class: B, params: [\\\"var4\\\"]}\", \"{class: A, params: [\\\"float\\\"]}\"],\nfields: [\"a\", \"b\", \"c\", \"d\"],\nmethods: [(\"__init__\", \"fn[[], none]\"), (\"fun\", \"fn[[a=int32, b=var3], list[virtual[B[4->bool]]]]\"), (\"foo\", \"fn[[c=C], none]\")],\ntype_vars: [\"var4\"]\n}\n", + "Function {\nname: \"B.__init__\",\nsig: \"fn[[], none]\",\nvar_id: [4]\n}\n", + "Function {\nname: \"B.fun\",\nsig: \"fn[[a=int32, b=var3], list[virtual[B[4->bool]]]]\",\nvar_id: [3, 4]\n}\n", + "Class {\nname: \"C\",\nancestors: [\"{class: C, params: []}\", \"{class: B, params: [\\\"bool\\\"]}\", \"{class: A, params: [\\\"float\\\"]}\"],\nfields: [\"a\", \"b\", \"c\", \"d\", \"e\"],\nmethods: [(\"__init__\", \"fn[[], none]\"), (\"fun\", \"fn[[a=int32, b=var3], list[virtual[B[4->bool]]]]\"), (\"foo\", \"fn[[c=C], none]\")],\ntype_vars: []\n}\n", + "Function {\nname: \"C.__init__\",\nsig: \"fn[[], none]\",\nvar_id: []\n}\n", ] diff --git a/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__list_tuple_generic.snap b/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__list_tuple_generic.snap index 4bc6dcbb..58d1e088 100644 --- a/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__list_tuple_generic.snap +++ b/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__list_tuple_generic.snap @@ -4,11 +4,11 @@ expression: res_vec --- [ - "14: Function {\nname: \"foo\",\nsig: \"fn[[a=list[class0], b=tuple[tvar3, class2]], class15[3->class19, 4->class3]]\",\nvar_id: [3]\n}\n", - "15: Class {\nname: \"A\",\ndef_id: DefinitionId(15),\nancestors: [CustomClassKind { id: DefinitionId(15), params: [TypeVarKind(UnificationKey(110)), TypeVarKind(UnificationKey(111))] }],\nfields: [(\"a\", \"tvar3\"), (\"b\", \"tvar4\")],\nmethods: [(\"__init__\", \"fn[[v=tvar4], class4]\", DefinitionId(16)), (\"fun\", \"fn[[a=tvar3], tvar4]\", DefinitionId(17))],\ntype_vars: [UnificationKey(110), UnificationKey(111)]\n}\n", - "16: Function {\nname: \"A.__init__\",\nsig: \"fn[[v=tvar4], class4]\",\nvar_id: [3, 4]\n}\n", - "17: Function {\nname: \"A.fun\",\nsig: \"fn[[a=tvar3], tvar4]\",\nvar_id: [3, 4]\n}\n", - "18: Function {\nname: \"gfun\",\nsig: \"fn[[a=class15[3->list[class2], 4->class0]], class4]\",\nvar_id: []\n}\n", - "19: Class {\nname: \"B\",\ndef_id: DefinitionId(19),\nancestors: [CustomClassKind { id: DefinitionId(19), params: [] }],\nfields: [],\nmethods: [(\"__init__\", \"fn[[], class4]\", DefinitionId(20))],\ntype_vars: []\n}\n", - "20: Function {\nname: \"B.__init__\",\nsig: \"fn[[], class4]\",\nvar_id: []\n}\n", + "Function {\nname: \"foo\",\nsig: \"fn[[a=list[int32], b=tuple[var3, float]], A[3->B, 4->bool]]\",\nvar_id: [3]\n}\n", + "Class {\nname: \"A\",\nancestors: [\"{class: A, params: [\\\"var3\\\", \\\"var4\\\"]}\"],\nfields: [\"a\", \"b\"],\nmethods: [(\"__init__\", \"fn[[v=var4], none]\"), (\"fun\", \"fn[[a=var3], var4]\")],\ntype_vars: [\"var3\", \"var4\"]\n}\n", + "Function {\nname: \"A.__init__\",\nsig: \"fn[[v=var4], none]\",\nvar_id: [3, 4]\n}\n", + "Function {\nname: \"A.fun\",\nsig: \"fn[[a=var3], var4]\",\nvar_id: [3, 4]\n}\n", + "Function {\nname: \"gfun\",\nsig: \"fn[[a=A[3->list[float], 4->int32]], none]\",\nvar_id: []\n}\n", + "Class {\nname: \"B\",\nancestors: [\"{class: B, params: []}\"],\nfields: [],\nmethods: [(\"__init__\", \"fn[[], none]\")],\ntype_vars: []\n}\n", + "Function {\nname: \"B.__init__\",\nsig: \"fn[[], none]\",\nvar_id: []\n}\n", ] diff --git a/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__self1.snap b/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__self1.snap index 26b36ebb..a482fafd 100644 --- a/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__self1.snap +++ b/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__self1.snap @@ -4,11 +4,11 @@ expression: res_vec --- [ - "14: Class {\nname: \"A\",\ndef_id: DefinitionId(14),\nancestors: [CustomClassKind { id: DefinitionId(14), params: [TypeVarKind(UnificationKey(110)), TypeVarKind(UnificationKey(111))] }],\nfields: [(\"a\", \"class14[3->class2, 4->class3]\"), (\"b\", \"class17\")],\nmethods: [(\"__init__\", \"fn[[a=class14[3->class2, 4->class3], b=class17], class4]\", DefinitionId(15)), (\"fun\", \"fn[[a=class14[3->class2, 4->class3]], class14[3->class3, 4->class0]]\", DefinitionId(16))],\ntype_vars: [UnificationKey(110), UnificationKey(111)]\n}\n", - "15: Function {\nname: \"A.__init__\",\nsig: \"fn[[a=class14[3->class2, 4->class3], b=class17], class4]\",\nvar_id: [3, 4]\n}\n", - "16: Function {\nname: \"A.fun\",\nsig: \"fn[[a=class14[3->class2, 4->class3]], class14[3->class3, 4->class0]]\",\nvar_id: [3, 4]\n}\n", - "17: Class {\nname: \"B\",\ndef_id: DefinitionId(17),\nancestors: [CustomClassKind { id: DefinitionId(17), params: [] }, CustomClassKind { id: DefinitionId(14), params: [PrimitiveKind(UnificationKey(1)), PrimitiveKind(UnificationKey(3))] }],\nfields: [(\"a\", \"class14[3->class2, 4->class3]\"), (\"b\", \"class17\")],\nmethods: [(\"__init__\", \"fn[[], class4]\", DefinitionId(18)), (\"fun\", \"fn[[a=class14[3->class2, 4->class3]], class14[3->class3, 4->class0]]\", DefinitionId(16)), (\"foo\", \"fn[[b=class17], class17]\", DefinitionId(19)), (\"bar\", \"fn[[a=class14[3->list[class17], 4->class0]], tuple[class14[3->virtual[class14[3->class17, 4->class0]], 4->class3], class17]]\", DefinitionId(20))],\ntype_vars: []\n}\n", - "18: Function {\nname: \"B.__init__\",\nsig: \"fn[[], class4]\",\nvar_id: []\n}\n", - "19: Function {\nname: \"B.foo\",\nsig: \"fn[[b=class17], class17]\",\nvar_id: []\n}\n", - "20: Function {\nname: \"B.bar\",\nsig: \"fn[[a=class14[3->list[class17], 4->class0]], tuple[class14[3->virtual[class14[3->class17, 4->class0]], 4->class3], class17]]\",\nvar_id: []\n}\n", + "Class {\nname: \"A\",\nancestors: [\"{class: A, params: [\\\"var3\\\", \\\"var4\\\"]}\"],\nfields: [\"a\", \"b\"],\nmethods: [(\"__init__\", \"fn[[a=A[3->float, 4->bool], b=B], none]\"), (\"fun\", \"fn[[a=A[3->float, 4->bool]], A[3->bool, 4->int32]]\")],\ntype_vars: [\"var3\", \"var4\"]\n}\n", + "Function {\nname: \"A.__init__\",\nsig: \"fn[[a=A[3->float, 4->bool], b=B], none]\",\nvar_id: [3, 4]\n}\n", + "Function {\nname: \"A.fun\",\nsig: \"fn[[a=A[3->float, 4->bool]], A[3->bool, 4->int32]]\",\nvar_id: [3, 4]\n}\n", + "Class {\nname: \"B\",\nancestors: [\"{class: B, params: []}\", \"{class: A, params: [\\\"int64\\\", \\\"bool\\\"]}\"],\nfields: [\"a\", \"b\"],\nmethods: [(\"__init__\", \"fn[[], none]\"), (\"fun\", \"fn[[a=A[3->float, 4->bool]], A[3->bool, 4->int32]]\"), (\"foo\", \"fn[[b=B], B]\"), (\"bar\", \"fn[[a=A[3->list[B], 4->int32]], tuple[A[3->virtual[A[3->B, 4->int32]], 4->bool], B]]\")],\ntype_vars: []\n}\n", + "Function {\nname: \"B.__init__\",\nsig: \"fn[[], none]\",\nvar_id: []\n}\n", + "Function {\nname: \"B.foo\",\nsig: \"fn[[b=B], B]\",\nvar_id: []\n}\n", + "Function {\nname: \"B.bar\",\nsig: \"fn[[a=A[3->list[B], 4->int32]], tuple[A[3->virtual[A[3->B, 4->int32]], 4->bool], B]]\",\nvar_id: []\n}\n", ] diff --git a/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__simple_class_compose.snap b/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__simple_class_compose.snap index c436efd3..42569f36 100644 --- a/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__simple_class_compose.snap +++ b/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__simple_class_compose.snap @@ -4,15 +4,15 @@ expression: res_vec --- [ - "14: Class {\nname: \"A\",\ndef_id: DefinitionId(14),\nancestors: [CustomClassKind { id: DefinitionId(14), params: [] }],\nfields: [(\"a\", \"class0\")],\nmethods: [(\"__init__\", \"fn[[], class4]\", DefinitionId(15)), (\"fun\", \"fn[[b=class18], class4]\", DefinitionId(16)), (\"foo\", \"fn[[a=tvar3, b=tvar4], class4]\", DefinitionId(17))],\ntype_vars: []\n}\n", - "15: Function {\nname: \"A.__init__\",\nsig: \"fn[[], class4]\",\nvar_id: []\n}\n", - "16: Function {\nname: \"A.fun\",\nsig: \"fn[[b=class18], class4]\",\nvar_id: []\n}\n", - "17: Function {\nname: \"A.foo\",\nsig: \"fn[[a=tvar3, b=tvar4], class4]\",\nvar_id: [3, 4]\n}\n", - "18: Class {\nname: \"B\",\ndef_id: DefinitionId(18),\nancestors: [CustomClassKind { id: DefinitionId(18), params: [] }, CustomClassKind { id: DefinitionId(20), params: [] }, CustomClassKind { id: DefinitionId(14), params: [] }],\nfields: [(\"a\", \"class0\")],\nmethods: [(\"__init__\", \"fn[[], class4]\", DefinitionId(19)), (\"fun\", \"fn[[b=class18], class4]\", DefinitionId(22)), (\"foo\", \"fn[[a=tvar3, b=tvar4], class4]\", DefinitionId(17))],\ntype_vars: []\n}\n", - "19: Function {\nname: \"B.__init__\",\nsig: \"fn[[], class4]\",\nvar_id: []\n}\n", - "20: Class {\nname: \"C\",\ndef_id: DefinitionId(20),\nancestors: [CustomClassKind { id: DefinitionId(20), params: [] }, CustomClassKind { id: DefinitionId(14), params: [] }],\nfields: [(\"a\", \"class0\")],\nmethods: [(\"__init__\", \"fn[[], class4]\", DefinitionId(21)), (\"fun\", \"fn[[b=class18], class4]\", DefinitionId(22)), (\"foo\", \"fn[[a=tvar3, b=tvar4], class4]\", DefinitionId(17))],\ntype_vars: []\n}\n", - "21: Function {\nname: \"C.__init__\",\nsig: \"fn[[], class4]\",\nvar_id: []\n}\n", - "22: Function {\nname: \"C.fun\",\nsig: \"fn[[b=class18], class4]\",\nvar_id: []\n}\n", - "23: Function {\nname: \"foo\",\nsig: \"fn[[a=class14], class4]\",\nvar_id: []\n}\n", - "24: Function {\nname: \"ff\",\nsig: \"fn[[a=tvar3], tvar4]\",\nvar_id: [3, 4]\n}\n", + "Class {\nname: \"A\",\nancestors: [\"{class: A, params: []}\"],\nfields: [\"a\"],\nmethods: [(\"__init__\", \"fn[[], none]\"), (\"fun\", \"fn[[b=B], none]\"), (\"foo\", \"fn[[a=var3, b=var4], none]\")],\ntype_vars: []\n}\n", + "Function {\nname: \"A.__init__\",\nsig: \"fn[[], none]\",\nvar_id: []\n}\n", + "Function {\nname: \"A.fun\",\nsig: \"fn[[b=B], none]\",\nvar_id: []\n}\n", + "Function {\nname: \"A.foo\",\nsig: \"fn[[a=var3, b=var4], none]\",\nvar_id: [3, 4]\n}\n", + "Class {\nname: \"B\",\nancestors: [\"{class: B, params: []}\", \"{class: C, params: []}\", \"{class: A, params: []}\"],\nfields: [\"a\"],\nmethods: [(\"__init__\", \"fn[[], none]\"), (\"fun\", \"fn[[b=B], none]\"), (\"foo\", \"fn[[a=var3, b=var4], none]\")],\ntype_vars: []\n}\n", + "Function {\nname: \"B.__init__\",\nsig: \"fn[[], none]\",\nvar_id: []\n}\n", + "Class {\nname: \"C\",\nancestors: [\"{class: C, params: []}\", \"{class: A, params: []}\"],\nfields: [\"a\"],\nmethods: [(\"__init__\", \"fn[[], none]\"), (\"fun\", \"fn[[b=B], none]\"), (\"foo\", \"fn[[a=var3, b=var4], none]\")],\ntype_vars: []\n}\n", + "Function {\nname: \"C.__init__\",\nsig: \"fn[[], none]\",\nvar_id: []\n}\n", + "Function {\nname: \"C.fun\",\nsig: \"fn[[b=B], none]\",\nvar_id: []\n}\n", + "Function {\nname: \"foo\",\nsig: \"fn[[a=A], none]\",\nvar_id: []\n}\n", + "Function {\nname: \"ff\",\nsig: \"fn[[a=var3], var4]\",\nvar_id: [3, 4]\n}\n", ] diff --git a/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__simple_pass_in_class.snap b/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__simple_pass_in_class.snap index fc148008..e9b20454 100644 --- a/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__simple_pass_in_class.snap +++ b/nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__simple_pass_in_class.snap @@ -4,5 +4,5 @@ expression: res_vec --- [ - "14: Class {\nname: \"A\",\ndef_id: DefinitionId(14),\nancestors: [CustomClassKind { id: DefinitionId(14), params: [] }],\nfields: [],\nmethods: [],\ntype_vars: []\n}\n", + "Class {\nname: \"A\",\nancestors: [\"{class: A, params: []}\"],\nfields: [],\nmethods: [],\ntype_vars: []\n}\n", ] diff --git a/nac3core/src/toplevel/test.rs b/nac3core/src/toplevel/test.rs index 25a39c42..e2795474 100644 --- a/nac3core/src/toplevel/test.rs +++ b/nac3core/src/toplevel/test.rs @@ -9,8 +9,8 @@ use crate::{ }, }; use indoc::indoc; -use parking_lot::Mutex; use nac3parser::{ast::fold::Fold, parser::parse_program}; +use parking_lot::Mutex; use std::{collections::HashMap, sync::Arc}; use test_case::test_case; @@ -43,9 +43,6 @@ impl SymbolResolver for Resolver { str: StrRef, ) -> Option { let ret = self.0.id_to_type.lock().get(&str).cloned(); - if ret.is_none() { - // println!("unknown here resolver {}", str); - } ret } @@ -529,19 +526,9 @@ fn test_analyze(source: Vec<&str>, res: Vec<&str>) { } else { // skip 5 to skip primitives let mut res_vec: Vec = Vec::new(); - for (i, (def, _)) in - composer.definition_ast_list.iter().skip(composer.built_in_num).enumerate() - { + for (def, _) in composer.definition_ast_list.iter().skip(composer.built_in_num) { let def = &*def.read(); - res_vec.push(format!( - "{}: {}\n", - i + composer.built_in_num, - def.to_string( - composer.unifier.borrow_mut(), - &mut |id| format!("class{}", id), - &mut |id| format!("tvar{}", id) - ) - )); + res_vec.push(format!("{}\n", def.to_string(composer.unifier.borrow_mut()))); } insta::assert_debug_snapshot!(res_vec); } @@ -688,9 +675,8 @@ fn test_inference(source: Vec<&str>, res: Vec<&str>) { &mut composer.unifier, print, ); - let resolver = Arc::new( - Resolver(internal_resolver.clone()) - ) as Arc; + let resolver = + Arc::new(Resolver(internal_resolver.clone())) as Arc; for s in source { let ast = parse_program(s).unwrap(); diff --git a/nac3core/src/toplevel/type_annotation.rs b/nac3core/src/toplevel/type_annotation.rs index 1731be21..8db0951e 100644 --- a/nac3core/src/toplevel/type_annotation.rs +++ b/nac3core/src/toplevel/type_annotation.rs @@ -20,6 +20,28 @@ pub enum TypeAnnotation { TupleKind(Vec), } +impl TypeAnnotation { + pub fn stringify(&self, unifier: &mut Unifier) -> String { + use TypeAnnotation::*; + match self { + PrimitiveKind(ty) | TypeVarKind(ty) => unifier.default_stringify(*ty), + CustomClassKind { id, params } => { + let class_name = match unifier.top_level { + Some(ref top) => if let TopLevelDef::Class { name, .. } = &*top.definitions.read()[id.0].read() { + (*name).into() + } else { + format!("def_{}", id.0) + } + None => format!("def_{}", id.0) + }; + format!("{{class: {}, params: {:?}}}", class_name, params.iter().map(|p| p.stringify(unifier)).collect_vec()) + } + VirtualKind(ty) | ListKind(ty) => ty.stringify(unifier), + TupleKind(types) => format!("({:?})", types.iter().map(|p| p.stringify(unifier)).collect_vec()), + } + } +} + pub fn parse_ast_to_type_annotation_kinds( resolver: &(dyn SymbolResolver + Send + Sync), top_level_defs: &[Arc>], diff --git a/nac3core/src/typecheck/typedef/mod.rs b/nac3core/src/typecheck/typedef/mod.rs index aa2c4517..5692723a 100644 --- a/nac3core/src/typecheck/typedef/mod.rs +++ b/nac3core/src/typecheck/typedef/mod.rs @@ -598,7 +598,7 @@ impl Unifier { Ok(()) } - fn internal_stringify(&mut self, ty: Type) -> String { + pub fn default_stringify(&mut self, ty: Type) -> String { let top_level = self.top_level.clone(); self.stringify( ty, @@ -698,8 +698,8 @@ impl Unifier { fn incompatible_types(&mut self, a: Type, b: Type) -> Result<(), String> { Err(format!( "Cannot unify {} with {}", - self.internal_stringify(a), - self.internal_stringify(b) + self.default_stringify(a), + self.default_stringify(b) )) } @@ -982,7 +982,7 @@ impl Unifier { return Err(format!( "Cannot unify variable {} with {} due to incompatible value range", id, - self.internal_stringify(b) + self.default_stringify(b) )); } } From 3db95b120b51988795ab6ec660ca1c2f136cf05d Mon Sep 17 00:00:00 2001 From: pca006132 Date: Fri, 5 Nov 2021 20:34:34 +0800 Subject: [PATCH 2/2] nac3core: implements bool conversion function --- nac3core/src/toplevel/composer.rs | 60 ++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/nac3core/src/toplevel/composer.rs b/nac3core/src/toplevel/composer.rs index 604262dd..cb8a4d4f 100644 --- a/nac3core/src/toplevel/composer.rs +++ b/nac3core/src/toplevel/composer.rs @@ -1,6 +1,7 @@ use std::cell::RefCell; use nac3parser::ast::fold::Fold; +use inkwell::FloatPredicate; use crate::{ symbol_resolver::SymbolValue, @@ -78,12 +79,7 @@ impl TopLevelComposer { "range".into(), None, ))), - Arc::new(RwLock::new(Self::make_top_level_class_def( - 6, - None, - "str".into(), - None, - ))), + Arc::new(RwLock::new(Self::make_top_level_class_def(6, None, "str".into(), None))), Arc::new(RwLock::new(TopLevelDef::Function { name: "int32".into(), simple_name: "int32".into(), @@ -391,8 +387,56 @@ impl TopLevelComposer { instance_to_symbol: Default::default(), instance_to_stmt: Default::default(), resolver: None, - codegen_callback: Some(Arc::new(GenCall::new(Box::new(|_, _, _, args| + codegen_callback: Some(Arc::new(GenCall::new(Box::new(|_, _, _, args| { Some(args[0].1) + })))), + })), + Arc::new(RwLock::new(TopLevelDef::Function { + name: "bool".into(), + simple_name: "bool".into(), + signature: primitives.1.add_ty(TypeEnum::TFunc(RefCell::new(FunSignature { + args: vec![FuncArg { name: "_".into(), ty: num_ty.0, default_value: None }], + ret: primitives.0.bool, + vars: Default::default(), + }))), + var_id: Default::default(), + instance_to_symbol: Default::default(), + instance_to_stmt: Default::default(), + resolver: None, + codegen_callback: Some(Arc::new(GenCall::new(Box::new( + |ctx, _, fun, args| { + let int32 = ctx.primitives.int32; + let int64 = ctx.primitives.int64; + let float = ctx.primitives.float; + let boolean = ctx.primitives.bool; + let arg_ty = fun.0.args[0].ty; + let arg = args[0].1; + if ctx.unifier.unioned(arg_ty, boolean) { + Some(arg) + } else if ctx.unifier.unioned(arg_ty, int32) || ctx.unifier.unioned(arg_ty, int64) { + Some( + ctx.builder + .build_int_truncate( + arg.into_int_value(), + ctx.ctx.bool_type(), + "trunc", + ) + .into(), + ) + } else if ctx.unifier.unioned(arg_ty, float) { + let val = ctx.builder. + build_float_compare( + // UEQ as bool(nan) is True + FloatPredicate::UEQ, + arg.into_float_value(), + ctx.ctx.f64_type().const_zero(), + "bool" + ).into(); + Some(val) + } else { + unreachable!() + } + }, )))), })), ]; @@ -426,7 +470,7 @@ impl TopLevelComposer { let mut built_in_ty: HashMap = Default::default(); for (id, name) in - ["int32", "int64", "float", "round", "round64", "range", "str"].iter().rev().enumerate() + ["int32", "int64", "float", "round", "round64", "range", "str", "bool"].iter().rev().enumerate() { let name = (**name).into(); let id = definition_ast_list.len() - id - 1;