From 17e97acc472c26ee7782e86683cca1c718cc8ba0 Mon Sep 17 00:00:00 2001 From: MyeongGeun Shin Date: Wed, 9 Jun 2021 06:49:56 +0900 Subject: [PATCH 1/6] Bug fix --- ePYt/__init__.py | 1 + ePYt/epytlib/analysis.py | 4 +--- ePYt/epytlib/domain.py | 4 ++-- ePYt/epytlib/semantic.py | 7 ++++--- ePYt/epytlib/type_inferrer.py | 15 ++++++++++++--- sample.py | 7 ++++--- 6 files changed, 24 insertions(+), 14 deletions(-) diff --git a/ePYt/__init__.py b/ePYt/__init__.py index c8cbfae..0bf7ff6 100644 --- a/ePYt/__init__.py +++ b/ePYt/__init__.py @@ -2,3 +2,4 @@ from ePYt.epytlib import graph from ePYt.epytlib import preanalysis from ePYt.epytlib import analysis +from ePYt.epytlib import annotator diff --git a/ePYt/epytlib/analysis.py b/ePYt/epytlib/analysis.py index bf25c60..01f6fe9 100644 --- a/ePYt/epytlib/analysis.py +++ b/ePYt/epytlib/analysis.py @@ -2,7 +2,7 @@ from copy import deepcopy from itertools import chain from pathlib import Path -from . import domain, graph, type_inferrer +from . import graph, type_inferrer class FuncDef: @@ -50,8 +50,6 @@ def __init__(self, script_path): class Analyzer: - prim_types = [*map(domain.PrimitiveType, domain.PrimitiveType.prim_types)] - def __init__(self, dir_path): self.dir_path = Path(dir_path) self.type_inferrer = type_inferrer.TypeInferrer(self.dir_path) diff --git a/ePYt/epytlib/domain.py b/ePYt/epytlib/domain.py index 0ed5c77..eea7646 100644 --- a/ePYt/epytlib/domain.py +++ b/ePYt/epytlib/domain.py @@ -111,11 +111,11 @@ def __str__(self): class PrimitiveType(Typed): # TODO: To be filled - prim_types = [int, str, float, bool, list, dict] + prim_types = ["int", "str", "float", "bool", "list", "dict"] def __init__(self, type_): if type_ in self.prim_types: - super().__init__(preanalysis.TypeDef(type_)) + super().__init__(preanalysis.TypeDef(eval(type_))) def __str__(self): return f"Primitive " + super().__str__() diff --git a/ePYt/epytlib/semantic.py b/ePYt/epytlib/semantic.py index ed2145d..36844b6 100644 --- a/ePYt/epytlib/semantic.py +++ b/ePYt/epytlib/semantic.py @@ -49,19 +49,20 @@ class Lifter(ast.NodeVisitor): ast.UAdd: '__pos__', ast.USub: '__neg__', ast.Invert: '__invert__', ast.Not: '__not__', ast.Is: '__is__', ast.IsNot: '__isnot__', ast.Add: '__add__', ast.Sub: '__sub__', ast.Mult: '__mul__', - ast.Div: '__div__', ast.Mod: '__mod__', ast.Pow: '__pow__', + ast.Div: 'truediv', ast.Mod: '__mod__', ast.Pow: '__pow__', ast.LShift: '__lshift__', ast.RShift: '__rshift__', ast.BitOr: '__or__', ast.BitXor: '__xor__', ast.BitAnd: '__and__', ast.Eq: '__eq__', ast.NotEq: '__ne__', ast.Lt: '__lt__', ast.LtE: '__le__', ast.Gt: '__gt__', ast.GtE: '__ge__', - ast.In: '__contains__', ast.NotIn: '__contains__'} + ast.In: '__contains__', ast.NotIn: '__contains__', + ast.FloorDiv: 'floordiv'} func_to_method = { 'abs': '__abs__', 'len': '__len__', 'int': '__int__', 'oct': '__oct__', 'float': '__float__', 'complex': '__complex__', 'str': '__str__', 'hex': '__hex__', 'bool': '__nonzero__', 'dir': '__dir__', 'repr': '__repr__', 'unicode': '__unicode__', 'size': '__sizeof__', - 'hash': '__hash__'} + 'hash': '__hash__', 'divmod': 'divmod'} def __init__(self, args): self.lifted_values = [] diff --git a/ePYt/epytlib/type_inferrer.py b/ePYt/epytlib/type_inferrer.py index 4f96c44..2cfece8 100644 --- a/ePYt/epytlib/type_inferrer.py +++ b/ePYt/epytlib/type_inferrer.py @@ -1,10 +1,17 @@ -from . import preanalysis, semantic, memory +from . import preanalysis, semantic, memory, domain from functools import reduce class TypeInferrer: + prim_types = [*map(domain.PrimitiveType, domain.PrimitiveType.prim_types)] + def __init__(self, dir_path): - self.user_types = preanalysis.get_typedefs(dir_path) + self.prim_type_dicts = {} + for prim_type in domain.PrimitiveType.prim_types: + v = domain.PrimitiveType(prim_type) + self.prim_type_dicts[prim_type] = v.typedef + self.type_candidates = preanalysis.get_typedefs(dir_path) + self.type_candidates.update(self.prim_type_dicts) self.table = None @staticmethod @@ -18,11 +25,13 @@ def infer_table(self, table): memory.Memory()) inferred_user_types = {} for arg_key, lifted_value in joined_memory.memory.items(): + if arg_key == 'self': + continue inferred_user_types[arg_key] = list( filter( lambda x: self.match(x.type.attributes, lifted_value.attributes), - self.user_types.values())) + self.type_candidates.values())) return inferred_user_types def infer(self, func_def): diff --git a/sample.py b/sample.py index 55dcfb5..3d6eb0a 100644 --- a/sample.py +++ b/sample.py @@ -11,6 +11,7 @@ def method(self): print(self.prop) -analysis_result = ePYt.analysis.Analyzer("./sample_target") -print(analysis_result.table) -_ = input() +a = ePYt.analysis.Analyzer("./sample_target") +print(a.table) +analyzed_files = a.analyze(a.file_infos) +ePYt.annotator.Annotator.annotate_dir("./sample_target", analyzed_files) From c4dad8d7efb831a23735fe1379ef6680c5e013e3 Mon Sep 17 00:00:00 2001 From: Sihoon Lee Date: Wed, 9 Jun 2021 06:58:19 +0900 Subject: [PATCH 2/6] Fix annotator against inner class with ignoring --- ePYt/epytlib/annotator.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ePYt/epytlib/annotator.py b/ePYt/epytlib/annotator.py index 617319a..fb28c26 100644 --- a/ePYt/epytlib/annotator.py +++ b/ePYt/epytlib/annotator.py @@ -22,7 +22,9 @@ def annotate_FunctionDef(self, node, class_name=None): if class_name is None: func_defs = self.analyzed_file.func_defs else: - class_def = self.analyzed_file.class_defs[class_name] + class_def = self.analyzed_file.class_defs.get(class_name, None) + if class_def is None: + return node func_defs = class_def.func_defs func_def = func_defs.get(node.name, None) if func_def is None: From 88a8d61705c641b9637f1b4ac59c85d682473e92 Mon Sep 17 00:00:00 2001 From: Sihoon Lee Date: Wed, 9 Jun 2021 06:59:11 +0900 Subject: [PATCH 3/6] Update sample.py --- sample.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sample.py b/sample.py index 3d6eb0a..8bfd0da 100644 --- a/sample.py +++ b/sample.py @@ -14,4 +14,4 @@ def method(self): a = ePYt.analysis.Analyzer("./sample_target") print(a.table) analyzed_files = a.analyze(a.file_infos) -ePYt.annotator.Annotator.annotate_dir("./sample_target", analyzed_files) +ePYt.annotator.Annotator.annotate_dir(a.dir_path, analyzed_files) From 22ecd7e96178c8f46b9351985abfc37cfdb6ae41 Mon Sep 17 00:00:00 2001 From: yongwoo36 Date: Tue, 8 Jun 2021 15:11:46 -0700 Subject: [PATCH 4/6] Fix comparator --- ePYt/epytlib/semantic.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/ePYt/epytlib/semantic.py b/ePYt/epytlib/semantic.py index 36844b6..820dee3 100644 --- a/ePYt/epytlib/semantic.py +++ b/ePYt/epytlib/semantic.py @@ -47,7 +47,6 @@ class Lifter(ast.NodeVisitor): op_to_method = { ast.UAdd: '__pos__', ast.USub: '__neg__', ast.Invert: '__invert__', - ast.Not: '__not__', ast.Is: '__is__', ast.IsNot: '__isnot__', ast.Add: '__add__', ast.Sub: '__sub__', ast.Mult: '__mul__', ast.Div: 'truediv', ast.Mod: '__mod__', ast.Pow: '__pow__', ast.LShift: '__lshift__', ast.RShift: '__rshift__', @@ -61,8 +60,7 @@ class Lifter(ast.NodeVisitor): 'abs': '__abs__', 'len': '__len__', 'int': '__int__', 'oct': '__oct__', 'float': '__float__', 'complex': '__complex__', 'str': '__str__', 'hex': '__hex__', 'bool': '__nonzero__', 'dir': '__dir__', - 'repr': '__repr__', 'unicode': '__unicode__', 'size': '__sizeof__', - 'hash': '__hash__', 'divmod': 'divmod'} + 'repr': '__repr__', 'hash': '__hash__', 'divmod': 'divmod'} def __init__(self, args): self.lifted_values = [] @@ -103,8 +101,16 @@ def visit_BinOp(self, node): def visit_Compare(self, node): self.generic_visit(node) arg_key = ast.unparse(node.left) - if arg_key in self.args: - self._add_method(arg_key, self.op_to_method[type(node.ops[0])]) + for i in range(len(node.ops)): + # except ast.In and ast.NotIn + if arg_key in self.args: + if not (isinstance(node.ops[i], ast.In) or isinstance(node.ops[i], ast.NotIn)): + self._add_method(arg_key, self.op_to_method[type(node.ops[i])]) + # for ast.In and ast.NotIn + arg_key = ast.unparse(node.comparators[i]) + if arg_key in self.args: + if isinstance(node.ops[i], ast.In) or isinstance(node.ops[i], ast.NotIn): + self._add_method(node.comparators[i]) def visit_Call(self, node): fun_name = ast.unparse(node.func) From 05a79739b08fe986d30d8909324f8ce645e323a1 Mon Sep 17 00:00:00 2001 From: yongwoo36 Date: Tue, 8 Jun 2021 15:18:46 -0700 Subject: [PATCH 5/6] Minor fix --- ePYt/epytlib/semantic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ePYt/epytlib/semantic.py b/ePYt/epytlib/semantic.py index 820dee3..3c3de09 100644 --- a/ePYt/epytlib/semantic.py +++ b/ePYt/epytlib/semantic.py @@ -110,7 +110,7 @@ def visit_Compare(self, node): arg_key = ast.unparse(node.comparators[i]) if arg_key in self.args: if isinstance(node.ops[i], ast.In) or isinstance(node.ops[i], ast.NotIn): - self._add_method(node.comparators[i]) + self._add_method(arg_key, self.op_to_method(node.comparators[i])) def visit_Call(self, node): fun_name = ast.unparse(node.func) From 1359af69752a5aed6a9194ce8ddce873446b6014 Mon Sep 17 00:00:00 2001 From: yongwoo36 Date: Tue, 8 Jun 2021 15:19:44 -0700 Subject: [PATCH 6/6] Really minor fix --- ePYt/epytlib/semantic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ePYt/epytlib/semantic.py b/ePYt/epytlib/semantic.py index 3c3de09..158c19c 100644 --- a/ePYt/epytlib/semantic.py +++ b/ePYt/epytlib/semantic.py @@ -110,7 +110,7 @@ def visit_Compare(self, node): arg_key = ast.unparse(node.comparators[i]) if arg_key in self.args: if isinstance(node.ops[i], ast.In) or isinstance(node.ops[i], ast.NotIn): - self._add_method(arg_key, self.op_to_method(node.comparators[i])) + self._add_method(arg_key, self.op_to_method(node.ops[i])) def visit_Call(self, node): fun_name = ast.unparse(node.func)