Skip to content

Commit 37b28ed

Browse files
committed
Add typing to preprocessor
1 parent ee1977d commit 37b28ed

3 files changed

Lines changed: 56 additions & 44 deletions

File tree

src/libzxbpp/prepro/definestable.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
import sys
1010
import re
1111

12+
from typing import Dict
13+
from typing import Union
14+
1215
from .id_ import ID
1316
from .exceptions import PreprocError
1417
from .output import warning
@@ -17,18 +20,16 @@
1720
RE_ID = re.compile(r'[a-zA-Z_][a-zA-Z0-9_]*')
1821

1922

20-
class DefinesTable(object):
21-
""" A class which will store
22-
define labels, and its values.
23-
It will also susbtitute the current value
24-
of a label for the given value.
23+
class DefinesTable:
24+
""" A class which will store define labels, and its values.
25+
It will also replace the current value of a label for the given value.
2526
"""
2627
def __init__(self):
2728
""" Initializes table
2829
"""
29-
self.table = {}
30+
self.table: Dict[str, ID] = {}
3031

31-
def define(self, id_, lineno, value='', fname=None, args=None):
32+
def define(self, id_: str, lineno: int, value: str = '', fname: str = None, args=None):
3233
""" Defines the value of a macro.
3334
Issues a warning if the macro is already defined.
3435
"""
@@ -44,7 +45,7 @@ def define(self, id_, lineno, value='', fname=None, args=None):
4445
(i.name, i.fname, i.lineno))
4546
self.set(id_, lineno, value, fname, args)
4647

47-
def set(self, id_, lineno, value='', fname=None, args=None):
48+
def set(self, id_: str, lineno: int, value: str = '', fname: str = None, args=None):
4849
""" Like the above, but issues no warning on duplicate macro
4950
definitions.
5051
"""
@@ -59,20 +60,20 @@ def undef(self, id_):
5960
if self.defined(id_):
6061
del self.table[id_]
6162

62-
def defined(self, id_):
63+
def defined(self, id_: str) -> bool:
6364
""" Returns if the given ID
6465
is defined
6566
"""
66-
return id_.strip() in self.table.keys()
67+
return id_.strip() in self.table
6768

68-
def __getitem__(self, key):
69+
def __getitem__(self, key: str) -> Union[str, ID]:
6970
""" Returns the ID instance given it's
7071
_id. If it does not exist, return the _id
7172
itself.
7273
"""
7374
return self.table.get(key.strip(), key)
7475

75-
def __setitem__(self, key, value):
76+
def __setitem__(self, key: str, value):
7677
""" Assigns the value to the given table entry
7778
"""
7879
k = key.strip()

src/libzxbpp/prepro/id_.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@
77
"""
88

99
import sys
10-
1110
import copy
11+
12+
from typing import Optional
13+
1214
from .macrocall import MacroCall
1315
from src.api.debug import __DEBUG__
1416
from .output import CURRENT_FILE
17+
import src.libzxbpp.prepro as prepro
1518

1619
DEBUG_LEVEL = 3 # Which -d level is required to show debug info
1720

@@ -20,7 +23,9 @@ class ID:
2023
""" This class represents an identifier. It stores a string
2124
(the ID name and value by default).
2225
"""
23-
def __init__(self, id_, args=None, value=None, lineno=None, fname=None):
26+
__slots__ = 'name', 'value', 'lineno', 'fname', 'args'
27+
28+
def __init__(self, id_: str, args=None, value=None, lineno: int = None, fname: str = None):
2429
if fname is None:
2530
fname = CURRENT_FILE[-1]
2631

@@ -30,30 +35,30 @@ def __init__(self, id_, args=None, value=None, lineno=None, fname=None):
3035
if not isinstance(value, list):
3136
value = [value]
3237

33-
self.name = id_
34-
self.value = value
35-
self.lineno = lineno # line number at which de ID was defined
36-
self.fname = fname # file name in which the ID was defined
38+
self.name: str = id_
39+
self.value: list = value
40+
self.lineno: Optional[int] = lineno # line number at which de ID was defined
41+
self.fname: str = fname # file name in which the ID was defined
3742
self.args = args
3843

3944
@property
40-
def hasArgs(self):
45+
def hasArgs(self) -> bool:
4146
return self.args is not None
4247

4348
def __str__(self):
4449
return self.name
4550

4651
@staticmethod
47-
def __dumptable(table):
52+
def __dumptable(table: 'prepro.DefinesTable') -> None:
4853
""" Dumps table on screen for debugging purposes
4954
"""
50-
for x in table.table.keys():
51-
sys.stdout.write("{0}\t<--- {1} {2}".format(x, table[x], type(table[x])))
52-
if isinstance(table[x], ID):
53-
sys.stdout.write(" {0}".format(table[x].value)),
55+
for k, v in table.table.items():
56+
sys.stdout.write("{0}\t<--- {1} {2}".format(k, v, type(v)))
57+
if isinstance(v, ID):
58+
sys.stdout.write(" {0}".format(v.value)),
5459
sys.stdout.write("\n")
5560

56-
def __call__(self, table):
61+
def __call__(self, table) -> str:
5762
__DEBUG__("evaluating id '%s'" % self.name, DEBUG_LEVEL)
5863
if self.value is None:
5964
__DEBUG__("undefined (null) value. BUG?", DEBUG_LEVEL)
@@ -78,7 +83,7 @@ def __call__(self, table):
7883
tmp = token(table)
7984
else:
8085
if isinstance(token, ID):
81-
__DEBUG__("token '%s' is an ID" % token.id_, DEBUG_LEVEL)
86+
__DEBUG__("token '%s' is an ID" % token.name, DEBUG_LEVEL)
8287
token = token(table)
8388
tmp = token
8489

src/libzxbpp/prepro/macrocall.py

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from .exceptions import PreprocError
77
from src.api.debug import __DEBUG__
88

9+
import src.libzxbpp.prepro as prepro
10+
911

1012
DEBUG_LEVEL = 3 # Which -d level is required to show debug info
1113

@@ -15,24 +17,26 @@ class MacroCall:
1517
Every time the macro() is called, the macro returns
1618
it value.
1719
"""
18-
def __init__(self, lineno, table, id_, args=None):
20+
__slots__ = 'table', 'id_', 'callargs', 'lineno'
21+
22+
def __init__(self, lineno: int, table: 'prepro.DefinesTable', id_: str, args=None):
1923
""" Initializes the object with the ID table, the ID name and
2024
optionally, the passed args.
2125
"""
22-
self.table = table
23-
self.id_ = id_
26+
self.table: 'prepro.DefinesTable' = table
27+
self.id_: str = id_
2428
self.callargs = args
25-
self.lineno = lineno
29+
self.lineno: int = lineno
2630

2731
@staticmethod
28-
def eval(arg):
32+
def eval(arg) -> str:
2933
""" Evaluates a given argument. The token will be returned by default
3034
"as is", except if it's a macrocall. In such case it will be evaluated
3135
recursively.
3236
"""
3337
return str(arg()) # Evaluate the arg (could be a macrocall)
3438

35-
def __call__(self, symbolTable=None):
39+
def __call__(self, symbolTable: 'prepro.DefinesTable' = None) -> str:
3640
""" Execute the macro call using LAZY evaluation
3741
"""
3842
__DEBUG__("evaluating '%s'" % self.id_, DEBUG_LEVEL)
@@ -50,47 +54,49 @@ def __call__(self, symbolTable=None):
5054

5155
# The macro is defined
5256
__DEBUG__("macro '%s' defined" % self.id_, DEBUG_LEVEL)
53-
TABLE = copy.deepcopy(symbolTable)
54-
ID = TABLE[self.id_] # Get the defined macro
55-
if ID.hasArgs and self.callargs is None:
57+
table = copy.deepcopy(symbolTable)
58+
id_ = table[self.id_] # Get the defined macro
59+
assert isinstance(id_, prepro.ID)
60+
if id_.hasArgs and self.callargs is None:
5661
return self.id_ # If no args passed, returned as is
5762

63+
args = []
5864
if self.callargs: # has args. Evaluate them removing spaces
5965
__DEBUG__("'%s' has args defined" % self.id_, DEBUG_LEVEL)
6066
__DEBUG__("evaluating %i arg(s) for '%s'" %
6167
(len(self.callargs), self.id_), DEBUG_LEVEL)
62-
args = [x(TABLE).strip() for x in self.callargs]
68+
args = [x(table).strip() for x in self.callargs]
6369
__DEBUG__("macro call: %s%s" %
6470
(self.id_, '(' + ', '.join(args) + ')'), DEBUG_LEVEL)
6571

66-
if not ID.hasArgs: # The macro doesn't need args
72+
if not id_.hasArgs: # The macro doesn't need args
6773
__DEBUG__("'%s' has no args defined" % self.id_, DEBUG_LEVEL)
68-
tmp = ID(TABLE) # If no args passed, returned as is
74+
tmp = id_(table) # If no args passed, returned as is
6975
if self.callargs is not None:
7076
tmp += '(' + ', '.join(args) + ')'
7177

7278
__DEBUG__("evaluation result: %s" % tmp, DEBUG_LEVEL)
7379
return tmp
7480

7581
# Now ensure both args and callargs have the same length
76-
if len(self.callargs) != len(ID.args):
82+
if len(self.callargs) != len(id_.args):
7783
raise PreprocError('Macro "%s" expected %i params, got %i' %
78-
(str(self.id_), len(ID.args),
84+
(str(self.id_), len(id_.args),
7985
len(self.callargs)), self.lineno)
8086

8187
# Carry out unification
8288
__DEBUG__('carrying out args unification', DEBUG_LEVEL)
8389
for i in range(len(self.callargs)):
84-
__DEBUG__("arg '%s' = '%s'" % (ID.args[i].name, args[i]), DEBUG_LEVEL)
85-
TABLE.set(ID.args[i].name, self.lineno, args[i])
90+
__DEBUG__("arg '%s' = '%s'" % (id_.args[i].name, args[i]), DEBUG_LEVEL)
91+
table.set(id_.args[i].name, self.lineno, args[i])
8692

87-
tmp = ID(TABLE)
93+
tmp = id_(table)
8894
if '\n' in tmp:
8995
tmp += '\n#line %i\n' % self.lineno
9096

9197
return tmp
9298

93-
def is_defined(self, symbolTable=None):
99+
def is_defined(self, symbolTable: 'prepro.DefinesTable' = None) -> bool:
94100
""" True if this macro has been defined
95101
"""
96102
if symbolTable is None:

0 commit comments

Comments
 (0)