Skip to content

Commit 351b76a

Browse files
authored
Merge pull request #547 from boriel/refact/code_refact
Refact/code refact
2 parents 77e8ef2 + 409e966 commit 351b76a

12 files changed

Lines changed: 92 additions & 141 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ scratch/
1616
.coverage
1717
htmlcov/
1818
build/
19+
venv/

src/api/constants.py

Lines changed: 51 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
# the GNU General License
1010
# ----------------------------------------------------------------------
1111

12+
import enum
1213
import os
1314

15+
from typing import Optional
16+
1417
from .decorator import classproperty
1518

1619

@@ -28,7 +31,7 @@
2831
# ----------------------------------------------------------------------
2932

3033

31-
class CLASS(object):
34+
class CLASS:
3235
""" Enums class constants
3336
"""
3437
unknown = 'unknown' # 0
@@ -69,115 +72,114 @@ def to_string(cls, class_):
6972
return cls._CLASS_NAMES[class_]
7073

7174

72-
class ARRAY(object):
75+
class ARRAY:
7376
""" Enums array constants
7477
"""
7578
bound_size = 2 # This might change depending on arch, program, etc..
7679
bound_count = 2 # Size of bounds counter
7780
array_type_size = 1 # Size of array type
7881

7982

80-
class TYPE(object):
81-
""" Enums type constants
83+
@enum.unique
84+
class TYPE(enum.IntEnum):
85+
""" Enums primary type constants
8286
"""
83-
auto = unknown = None
84-
byte_ = 1
87+
unknown = 0
88+
byte = 1
8589
ubyte = 2
8690
integer = 3
8791
uinteger = 4
88-
long_ = 5
92+
long = 5
8993
ulong = 6
9094
fixed = 7
91-
float_ = 8
95+
float = 8
9296
string = 9
9397

94-
TYPE_SIZES = {
95-
byte_: 1, ubyte: 1,
96-
integer: 2, uinteger: 2,
97-
long_: 4, ulong: 4,
98-
fixed: 4, float_: 5,
99-
string: 2, unknown: 0
100-
}
101-
102-
TYPE_NAMES = {
103-
byte_: 'byte', ubyte: 'ubyte',
104-
integer: 'integer', uinteger: 'uinteger',
105-
long_: 'long', ulong: 'ulong',
106-
fixed: 'fixed', float_: 'float',
107-
string: 'string', unknown: 'none'
108-
}
98+
@classmethod
99+
def type_size(cls, type_: 'TYPE'):
100+
type_sizes = {
101+
cls.byte: 1, cls.ubyte: 1,
102+
cls.integer: 2, cls.uinteger: 2,
103+
cls.long: 4, cls.ulong: 4,
104+
cls.fixed: 4, cls.float: 5,
105+
cls.string: 2, cls.unknown: 0
106+
}
107+
return type_sizes[type_]
109108

110109
@classproperty
111110
def types(cls):
112-
return tuple(cls.TYPE_SIZES.keys())
111+
return set(TYPE)
113112

114113
@classmethod
115-
def size(cls, type_):
116-
return cls.TYPE_SIZES.get(type_, None)
114+
def size(cls, type_: 'TYPE'):
115+
return cls.type_size(type_)
117116

118117
@classproperty
119118
def integral(cls):
120-
return (cls.byte_, cls.ubyte, cls.integer, cls.uinteger,
121-
cls.long_, cls.ulong)
119+
return {cls.byte, cls.ubyte, cls.integer, cls.uinteger,
120+
cls.long, cls.ulong}
122121

123122
@classproperty
124123
def signed(cls):
125-
return (cls.byte_, cls.integer, cls.long_, cls.fixed, cls.float_)
124+
return {cls.byte, cls.integer, cls.long, cls.fixed, cls.float}
126125

127126
@classproperty
128127
def unsigned(cls):
129-
return (cls.ubyte, cls.uinteger, cls.ulong)
128+
return {cls.ubyte, cls.uinteger, cls.ulong}
130129

131130
@classproperty
132131
def decimals(cls):
133-
return (cls.fixed, cls.float_)
132+
return {cls.fixed, cls.float}
134133

135134
@classproperty
136135
def numbers(cls):
137-
return tuple(list(cls.integral) + list(cls.decimals))
136+
return set(cls.integral) | set(cls.decimals)
138137

139138
@classmethod
140-
def is_valid(cls, type_):
139+
def is_valid(cls, type_: 'TYPE'):
141140
""" Whether the given type is
142141
valid or not.
143142
"""
144143
return type_ in cls.types
145144

146145
@classmethod
147-
def is_signed(cls, type_):
146+
def is_signed(cls, type_: 'TYPE'):
148147
return type_ in cls.signed
149148

150149
@classmethod
151-
def is_unsigned(cls, type_):
150+
def is_unsigned(cls, type_: 'TYPE'):
152151
return type_ in cls.unsigned
153152

154153
@classmethod
155-
def to_signed(cls, type_):
154+
def to_signed(cls, type_: 'TYPE'):
156155
""" Return signed type or equivalent
157156
"""
158157
if type_ in cls.unsigned:
159-
return {TYPE.ubyte: TYPE.byte_,
158+
return {TYPE.ubyte: TYPE.byte,
160159
TYPE.uinteger: TYPE.integer,
161-
TYPE.ulong: TYPE.long_}[type_]
160+
TYPE.ulong: TYPE.long}[type_]
162161
if type_ in cls.decimals or type_ in cls.signed:
163162
return type_
164163
return cls.unknown
165164

166-
@classmethod
167-
def to_string(cls, type_):
165+
@staticmethod
166+
def to_string(type_: 'TYPE'):
168167
""" Return ID representation (string) of a type
169168
"""
170-
return cls.TYPE_NAMES[type_]
169+
return type_.name
171170

172-
@classmethod
173-
def to_type(cls, typename):
171+
@staticmethod
172+
def to_type(typename: str) -> Optional['TYPE']:
174173
""" Converts a type ID to name. On error returns None
175174
"""
176-
NAME_TYPES = {cls.TYPE_NAMES[x]: x for x in cls.TYPE_NAMES}
177-
return NAME_TYPES.get(typename, None)
175+
for t in TYPE:
176+
if t.name == typename:
177+
return t
178+
179+
return None
178180

179181

180-
class SCOPE(object):
182+
class SCOPE:
181183
""" Enum scopes
182184
"""
183185
unknown = None
@@ -202,7 +204,7 @@ def to_string(cls, scope):
202204
return cls._names[scope]
203205

204206

205-
class KIND(object):
207+
class KIND:
206208
""" Enum kind
207209
"""
208210
unknown = None
@@ -229,7 +231,7 @@ def to_string(cls, kind):
229231
return cls._NAMES.get(kind)
230232

231233

232-
class CONVENTION(object):
234+
class CONVENTION:
233235
unknown = None
234236
fastcall = '__fastcall__'
235237
stdcall = '__stdcall__'
@@ -268,4 +270,4 @@ def to_string(cls, convention):
268270
ID_TYPES = TYPE.types
269271

270272
# Maps deprecated suffixes to types
271-
SUFFIX_TYPE = {'$': TYPE.string, '%': TYPE.integer, '&': TYPE.long_}
273+
SUFFIX_TYPE = {'$': TYPE.string, '%': TYPE.integer, '&': TYPE.long}

src/api/decorator.py

Lines changed: 5 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,16 @@
11
#!/usr/bin/env python
22
# -*- coding: utf-8 -*-
33

4-
import collections
5-
import inspect
6-
import os
4+
from typing import Callable
75

86

9-
class classproperty(object):
10-
''' Decorator for class properties.
7+
class classproperty:
8+
""" Decorator for class properties.
119
Use @classproperty instead of @property to add properties
1210
to the class object.
13-
'''
14-
def __init__(self, fget):
11+
"""
12+
def __init__(self, fget: Callable):
1513
self.fget = fget
1614

1715
def __get__(self, owner_self, owner_cls):
1816
return self.fget(owner_cls)
19-
20-
21-
def check_type(*args, **kwargs):
22-
''' Checks the function types
23-
'''
24-
args = tuple(x if isinstance(x, collections.Iterable) else (x,) for x in args)
25-
kwargs = {x: kwargs[x] if isinstance(kwargs[x], collections.Iterable) else (kwargs[x],) for x in kwargs}
26-
27-
def decorate(func):
28-
types = args
29-
kwtypes = kwargs
30-
gi = "Got <{}> instead"
31-
errmsg1 = "to be of type <{}>. " + gi
32-
errmsg2 = "to be one of type ({}). " + gi
33-
errar = "{}:{} expected '{}' "
34-
errkw = "{}:{} expected {} "
35-
36-
def check(*ar, **kw):
37-
line = inspect.getouterframes(inspect.currentframe())[1][2]
38-
fname = os.path.basename(inspect.getouterframes(inspect.currentframe())[1][1])
39-
40-
for arg, type_ in zip(ar, types):
41-
if type(arg) not in type_:
42-
if len(type_) == 1:
43-
raise TypeError((errar + errmsg1).format(fname, line, arg, type_[0].__name__,
44-
type(arg).__name__))
45-
else:
46-
raise TypeError((errar + errmsg2).format(fname, line, arg,
47-
', '.join('<%s>' % x.__name__ for x in type_),
48-
type(arg).__name__))
49-
for kwarg in kw:
50-
if kwtypes.get(kwarg, None) is None:
51-
continue
52-
if type(kw[kwarg]) not in kwtypes[kwarg]:
53-
if len(kwtypes[kwarg]) == 1:
54-
raise TypeError((errkw + errmsg1).format(fname, line, kwarg, kwtypes[kwarg][0].__name__,
55-
type(kw[kwarg]).__name__))
56-
else:
57-
raise TypeError((errkw + errmsg2).format(
58-
fname,
59-
line,
60-
kwarg,
61-
', '.join('<%s>' % x.__name__ for x in kwtypes[kwarg]),
62-
type(kw[kwarg]).__name__)
63-
)
64-
65-
return func(*ar, **kw)
66-
67-
return check
68-
69-
return decorate

src/api/global_.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,13 @@
5757
# ----------------------------------------------------------------------
5858
# Default var type when not specified (implicit) an can't be guessed
5959
# ----------------------------------------------------------------------
60-
DEFAULT_TYPE = TYPE.float_
60+
DEFAULT_TYPE = TYPE.float
6161

6262
# ----------------------------------------------------------------------
6363
# Default variable type when not specified in DIM.
6464
# 'auto' => try to guess and if not, fallback to DEFAULT_TYPE
6565
# ----------------------------------------------------------------------
66-
DEFAULT_IMPLICIT_TYPE = TYPE.auto # Use TYPE.auto for smart type guessing
66+
DEFAULT_IMPLICIT_TYPE = TYPE.unknown # Use TYPE.auto for smart type guessing
6767

6868
# ----------------------------------------------------------------------
6969
# Maximum number of errors to report before giving up.

src/api/optimize.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import src.api.check as chk
1212

1313
from src import symbols
14-
from src.ast import Ast
1514
from src.ast import NodeVisitor
1615
from src.api import errmsg
1716

@@ -65,7 +64,7 @@ def _visit(self, node: ToVisit):
6564
meth = getattr(self, f"visit_{node.obj.token}", self.generic_visit)
6665
return meth(node.obj)
6766

68-
def generic_visit(self, node: Ast):
67+
def generic_visit(self, node: symbols.SYMBOL):
6968
for i, child in enumerate(node.children):
7069
node.children[i] = (yield self.visit(child))
7170

@@ -86,6 +85,8 @@ def _visit(self, node: ToVisit):
8685

8786

8887
class UnreachableCodeVisitor(UniqueVisitor):
88+
""" Visitor to optimize unreachable code (and prune it).
89+
"""
8990
def visit_FUNCTION(self, node):
9091
if node.kind == KIND.function and node.body.token == 'BLOCK' and \
9192
(not node.body or node.body[-1].token != 'RETURN'):
@@ -203,7 +204,7 @@ def visit_ADDRESS(self, node):
203204
)
204205
yield node
205206

206-
def visit_BINARY(self, node):
207+
def visit_BINARY(self, node: symbols.BINARY):
207208
node = (yield self.generic_visit(node)) # This might convert consts to numbers if possible
208209
# Retry folding
209210
yield symbols.BINARY.make_node(node.operator, node.left, node.right, node.lineno, node.func, node.type_)
@@ -370,10 +371,10 @@ def _visit_LABEL(self, node):
370371
else:
371372
yield node
372373

373-
@staticmethod
374-
def generic_visit(node):
374+
def generic_visit(self, node: symbols.SYMBOL):
375375
for i in range(len(node.children)):
376376
node.children[i] = (yield ToVisit(node.children[i]))
377+
377378
yield node
378379

379380
def _check_if_any_arg_is_an_array_and_needs_lbound_or_ubound(self, params: symbols.PARAMLIST,
@@ -417,12 +418,12 @@ class VariableVisitor(GenericVisitor):
417418
_parent_variable = None
418419
_visited: Set[symbols.SYMBOL] = set()
419420

420-
@staticmethod
421-
def generic_visit(node: symbols.SYMBOL): # type: ignore
421+
def generic_visit(self, node: symbols.SYMBOL):
422422
if node not in VariableVisitor._visited:
423423
VariableVisitor._visited.add(node)
424424
for i in range(len(node.children)):
425425
node.children[i] = yield ToVisit(node.children[i])
426+
426427
yield node
427428

428429
def has_circular_dependency(self, var_dependency: VarDependency) -> bool:

src/api/symboltable.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ def access_id(self, id_: str, lineno: int, scope=None, default_type=None, defaul
435435

436436
# The entry was already declared. If it's type is auto and the default type is not None,
437437
# update its type.
438-
if default_type is not None and result.type_ == self.basic_types[TYPE.auto]:
438+
if default_type is not None and result.type_ == self.basic_types[TYPE.unknown]:
439439
result.type_ = default_type
440440
warning_implicit_type(lineno, id_, default_type.name)
441441

@@ -493,8 +493,8 @@ def access_func(self, id_: str, lineno: int, scope=None, default_type=None):
493493
result = self.get_entry(id_, scope)
494494
if result is None:
495495
if default_type is None:
496-
if global_.DEFAULT_IMPLICIT_TYPE == TYPE.auto:
497-
default_type = symbols.TYPEREF(self.basic_types[TYPE.auto], lineno, implicit=True)
496+
if global_.DEFAULT_IMPLICIT_TYPE == TYPE.unknown:
497+
default_type = symbols.TYPEREF(self.basic_types[TYPE.unknown], lineno, implicit=True)
498498
else:
499499
default_type = symbols.TYPEREF(self.basic_types[global_.DEFAULT_TYPE], lineno, implicit=True)
500500

0 commit comments

Comments
 (0)