Skip to content

Commit ba432d5

Browse files
committed
Use new config scheme
Removed the trailing .value attrib!
1 parent f1d7640 commit ba432d5

22 files changed

Lines changed: 252 additions & 221 deletions

api/check.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def check_is_declared_explicit(lineno, id_, classname='variable'):
6969
7070
If not in strict mode, passes it silently.
7171
"""
72-
if not config.OPTIONS.explicit.value:
72+
if not config.OPTIONS.explicit:
7373
return True
7474

7575
entry = global_.SYMBOL_TABLE.check_is_declared(id_, lineno, classname)
@@ -80,7 +80,7 @@ def check_type_is_explicit(lineno: int, id_: str, type_):
8080
from symbols.type_ import SymbolTYPE
8181
assert isinstance(type_, SymbolTYPE)
8282
if type_.implicit:
83-
if config.OPTIONS.strict.value:
83+
if config.OPTIONS.strict:
8484
api.errmsg.syntax_error_undeclared_type(lineno, id_)
8585

8686

api/debug.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515

1616

1717
def __DEBUG__(msg, level=1):
18-
if level > OPTIONS.Debug.value:
18+
if level > OPTIONS.Debug:
1919
return
2020

2121
line = inspect.getouterframes(inspect.currentframe())[1][2]
2222
fname = os.path.basename(inspect.getouterframes(inspect.currentframe())[1][1])
23-
OPTIONS.stderr.value.write('debug: %s:%i %s\n' % (fname, line, msg))
23+
OPTIONS.stderr.write('debug: %s:%i %s\n' % (fname, line, msg))
2424

2525

2626
def __LINE__():

api/errmsg.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ def msg_output(msg):
2121
if msg in global_.error_msg_cache:
2222
return
2323

24-
OPTIONS.stderr.value.write("%s\n" % msg)
24+
OPTIONS.stderr.write("%s\n" % msg)
2525
global_.error_msg_cache.add(msg)
2626

2727

2828
def info(msg):
29-
if OPTIONS.Debug.value < 1:
29+
if OPTIONS.Debug < 1:
3030
return
31-
OPTIONS.stderr.value.write("info: %s\n" % msg)
31+
OPTIONS.stderr.write("info: %s\n" % msg)
3232

3333

3434
def error(lineno, msg, fname=None):
@@ -37,13 +37,13 @@ def error(lineno, msg, fname=None):
3737
if fname is None:
3838
fname = global_.FILENAME
3939

40-
if global_.has_errors > OPTIONS.max_syntax_errors.value:
40+
if global_.has_errors > OPTIONS.max_syntax_errors:
4141
msg = 'Too many errors. Giving up!'
4242

4343
msg = "%s:%i: error: %s" % (fname, lineno, msg)
4444
msg_output(msg)
4545

46-
if global_.has_errors > OPTIONS.max_syntax_errors.value:
46+
if global_.has_errors > OPTIONS.max_syntax_errors:
4747
sys.exit(1)
4848

4949
global_.has_errors += 1
@@ -63,7 +63,7 @@ def warning(lineno, msg, fname=None):
6363
def warning_implicit_type(lineno, id_, type_=None):
6464
""" Warning: Using default implicit type 'x'
6565
"""
66-
if OPTIONS.strict.value:
66+
if OPTIONS.strict:
6767
syntax_error_undeclared_type(lineno, id_)
6868
return
6969

@@ -99,7 +99,7 @@ def warning_empty_if(lineno):
9999

100100
# Emmits an optimization warning
101101
def warning_not_used(lineno, id_, kind='Variable'):
102-
if OPTIONS.optimization.value > 0:
102+
if OPTIONS.optimization > 0:
103103
warning(lineno, "%s '%s' is never used" % (kind, id_))
104104

105105

api/optimize.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def visit(self, node):
8585

8686
@property
8787
def O_LEVEL(self):
88-
return OPTIONS.optimization.value
88+
return OPTIONS.optimization
8989

9090
def visit_ADDRESS(self, node):
9191
if node.operand.token != 'ARRAYACCESS':

api/options.py

Lines changed: 78 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,18 @@
99
# the GNU General License
1010
# ----------------------------------------------------------------------
1111

12-
from .errors import Error
12+
import json
1313

14-
TRUE = true = True
15-
FALSE = false = False
14+
from typing import Dict
15+
from typing import List
16+
from typing import Any
1617

18+
from .errors import Error
1719

1820
__all__ = ['Option', 'Options', 'ANYTYPE']
1921

2022

21-
class ANYTYPE(object):
23+
class ANYTYPE:
2224
""" Dummy class to signal any value
2325
"""
2426
pass
@@ -64,31 +66,45 @@ def __str__(self):
6466
% (self.value, self.option, self.type)
6567

6668

69+
class InvalidConfigInitialization(Error):
70+
def __init__(self, invalid_value):
71+
self.invalid_value = invalid_value
72+
73+
def __str__(self):
74+
return "Invalid value for config initialization"
75+
76+
6777
# ----------------------------------------------------------------------
6878
# This class interfaces an Options Container
6979
# ----------------------------------------------------------------------
70-
class Option(object):
71-
""" A simple container
80+
class Option:
81+
""" A simple container for options with optional type checking
82+
on vale assignation.
7283
"""
73-
def __init__(self, name, type_, value=None):
84+
def __init__(self, name: str, type_, value=None):
7485
self.name = name
7586
self.type = type_
7687
self.value = value
77-
self.stack = [] # An option stack
88+
self.stack: List[Any] = [] # An option stack
7889

7990
@property
80-
def value(self):
91+
def value(self) -> Any:
8192
return self.__value
8293

8394
@value.setter
8495
def value(self, value):
85-
if self.type is not None and not isinstance(value, self.type):
96+
if value is not None and self.type is not None and not isinstance(value, self.type):
8697
try:
87-
value = eval(value)
98+
if isinstance(value, str) and self.type == bool:
99+
value = {'false': False, 'true': True}[value.lower()]
100+
else:
101+
value = self.type(value)
88102
except TypeError:
89103
pass
90104
except ValueError:
91105
pass
106+
except KeyError:
107+
pass
92108

93109
if value is not None and not isinstance(value, self.type):
94110
raise InvalidValueError(self.name, self.type, value)
@@ -102,63 +118,81 @@ def push(self, value=None):
102118
self.stack.append(self.value)
103119
self.value = value
104120

105-
def pop(self):
106-
result = self.value
107-
108-
try:
109-
self.value = self.stack.pop()
110-
except IndexError:
121+
def pop(self) -> Any:
122+
if not self.stack:
111123
raise OptionStackUnderflowError(self.name)
112124

125+
result = self.value
126+
self.value = self.stack.pop()
113127
return result
114128

115129

116130
# ----------------------------------------------------------------------
117131
# This class interfaces an Options Container
118132
# ----------------------------------------------------------------------
119-
class Options(object):
120-
def __init__(self):
121-
self.options = None
122-
self.reset()
133+
class Options:
134+
""" Class to store config options.
135+
"""
136+
def __init__(self, init_value=None):
137+
self._options: Dict[str, Option] = {}
123138

124-
def reset(self):
125-
if self.options is None:
126-
self.options = {}
139+
if init_value is not None:
140+
if isinstance(init_value, dict):
141+
self._options = init_value
142+
elif isinstance(init_value, str):
143+
self._options = json.loads(init_value)
144+
else:
145+
raise InvalidConfigInitialization(invalid_value=init_value)
127146

128-
for opt in list(self.options.keys()): # converts to list since dict will change size during iteration
129-
self.remove_option(opt)
147+
def reset(self):
148+
self._options.clear()
130149

131150
def add_option(self, name, type_=None, default_value=None):
132-
if name in self.options.keys():
151+
if name in self._options:
133152
raise DuplicatedOptionError(name)
134153

135154
if type_ is None and default_value is not None:
136155
type_ = type(default_value)
137156
elif type_ is ANYTYPE:
138157
type_ = None
139158

140-
self.options[name] = Option(name, type_, default_value)
141-
setattr(self, name, self.options[name])
142-
143-
def has_option(self, name):
144-
""" Returns whether the given option is defined in this class.
145-
"""
146-
return hasattr(self, name)
159+
self._options[name] = Option(name, type_, default_value)
147160

148161
def add_option_if_not_defined(self, name, type_=None, default_value=None):
149-
if self.has_option(name):
162+
if name in self._options:
150163
return
151164
self.add_option(name, type_, default_value)
152165

153-
def remove_option(self, name):
154-
if name not in self.options.keys():
155-
raise UndefinedOptionError(name)
166+
def __delattr__(self, item: str):
167+
del self[item]
168+
169+
def __getattr__(self, item: str):
170+
return self[item].value
171+
172+
def __setattr__(self, key: str, value: Any):
173+
if key == '_options':
174+
self.__dict__[key] = value
175+
return
176+
177+
self[key] = value
178+
179+
def __getitem__(self, item: str) -> Option:
180+
if item not in self._options:
181+
raise UndefinedOptionError(option_name=item)
182+
183+
return self._options[item]
184+
185+
def __delitem__(self, item):
186+
if item not in self._options:
187+
raise UndefinedOptionError(item)
188+
189+
del self._options[item]
156190

157-
del self.options[name]
158-
delattr(self, name)
191+
def __setitem__(self, key: str, value: Any):
192+
if key not in self._options:
193+
raise UndefinedOptionError(option_name=key)
159194

160-
def option(self, name):
161-
if name not in self.options.keys():
162-
raise UndefinedOptionError(name)
195+
self._options[key].value = value
163196

164-
return self.options[name]
197+
def __contains__(self, item: str):
198+
return item in self._options

api/symboltable.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,17 +111,17 @@ def __delitem__(self, key):
111111
del self.caseins[key.lower()]
112112

113113
def values(self, filter_by_opt=True):
114-
if filter_by_opt and OPTIONS.optimization.value > 1:
114+
if filter_by_opt and OPTIONS.optimization > 1:
115115
return [y for x, y in self.symbols.items() if y.accessed]
116116
return [y for x, y in self.symbols.items()]
117117

118118
def keys(self, filter_by_opt=True):
119-
if filter_by_opt and OPTIONS.optimization.value > 1:
119+
if filter_by_opt and OPTIONS.optimization > 1:
120120
return [x for x, y in self.symbols.items() if y.accessed]
121121
return self.symbols.keys()
122122

123123
def items(self, filter_by_opt=True):
124-
if filter_by_opt and OPTIONS.optimization.value > 1:
124+
if filter_by_opt and OPTIONS.optimization > 1:
125125
return [(x, y) for x, y in self.symbols.items() if y.accessed]
126126
return self.symbols.items()
127127

@@ -183,7 +183,7 @@ def declare(self, id_: str, lineno: int, entry):
183183
if self[self.current_scope][id2] is not None:
184184
return None
185185

186-
entry.caseins = OPTIONS.case_insensitive.value
186+
entry.caseins = OPTIONS.case_insensitive
187187
self[self.current_scope][id2] = entry
188188
entry.name = id2 # Removes DEPRECATED SUFFIXES if any
189189

arch/zx48k/backend/__init__.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ def _end(ins):
431431
FLAG_end_emitted = True
432432

433433
output.append('%s:' % END_LABEL)
434-
if OPTIONS.headerless.value:
434+
if OPTIONS.headerless:
435435
return output + ['ret']
436436

437437
output.append('di')
@@ -2233,21 +2233,21 @@ def __str__(self):
22332233
def emit_start():
22342234
output = list()
22352235
heap_init = ['%s:' % DATA_LABEL]
2236-
output.append('org %s' % OPTIONS.org.value)
2236+
output.append('org %s' % OPTIONS.org)
22372237

22382238
if REQUIRES.intersection(MEMINITS) or '__MEM_INIT' in INITS:
2239-
heap_init.append('; Defines HEAP SIZE\n' + OPTIONS.heap_size_label.value + ' EQU ' +
2240-
str(OPTIONS.heap_size.value))
2241-
heap_init.append(OPTIONS.heap_start_label.value + ':')
2242-
heap_init.append('DEFS %s' % str(OPTIONS.heap_size.value))
2239+
heap_init.append('; Defines HEAP SIZE\n' + OPTIONS.heap_size_label + ' EQU ' +
2240+
str(OPTIONS.heap_size))
2241+
heap_init.append(OPTIONS.heap_start_label + ':')
2242+
heap_init.append('DEFS %s' % str(OPTIONS.heap_size))
22432243

22442244
heap_init.append('; Defines USER DATA Length in bytes\n' +
22452245
'ZXBASIC_USER_DATA_LEN EQU ZXBASIC_USER_DATA_END - ZXBASIC_USER_DATA')
22462246
heap_init.append('.__LABEL__.ZXBASIC_USER_DATA_LEN EQU ZXBASIC_USER_DATA_LEN')
22472247
heap_init.append('.__LABEL__.ZXBASIC_USER_DATA EQU ZXBASIC_USER_DATA')
22482248

22492249
output.append('%s:' % START_LABEL)
2250-
if OPTIONS.headerless.value:
2250+
if OPTIONS.headerless:
22512251
output.extend(heap_init)
22522252
return output
22532253

@@ -2275,7 +2275,7 @@ def convertToBool():
22752275
""" Convert a byte value to boolean (0 or 1) if
22762276
the global flag strictBool is True
22772277
"""
2278-
if not OPTIONS.strictBool.value:
2278+
if not OPTIONS.strictBool:
22792279
return []
22802280

22812281
REQUIRES.add('strictbool.asm')
@@ -2297,7 +2297,7 @@ def emit_end():
22972297
output.extend(AT_END)
22982298

22992299
# if REQUIRES.intersection(MEMINITS) or '__MEM_INIT' in INITS:
2300-
# output.append(OPTIONS.heap_start_label.value + ':')
2300+
# output.append(OPTIONS.heap_start_label + ':')
23012301
# output.append('; Defines DATA END\n' + 'ZXBASIC_USER_DATA_END EQU ZXBASIC_MEM_HEAP + ZXBASIC_HEAP_SIZE')
23022302
# else:
23032303
# output.append('; Defines DATA END --> HEAP size is 0\n' + 'ZXBASIC_USER_DATA_END:')
@@ -2307,7 +2307,7 @@ def emit_end():
23072307
# output.append('.__LABEL__.ZXBASIC_USER_DATA_LEN EQU ZXBASIC_USER_DATA_LEN')
23082308
# output.append('.__LABEL__.ZXBASIC_USER_DATA EQU ZXBASIC_USER_DATA')
23092309

2310-
if OPTIONS.autorun.value:
2310+
if OPTIONS.autorun:
23112311
output.append('END %s' % START_LABEL)
23122312
else:
23132313
output.append('END')
@@ -2323,7 +2323,7 @@ def emit(mem, optimize=True):
23232323
'output' array
23242324
"""
23252325
# Optimization patterns: at this point no more than -O2
2326-
patterns = [x for x in engine.PATTERNS if x.level <= min(OPTIONS.optimization.value, 2)]
2326+
patterns = [x for x in engine.PATTERNS if x.level <= min(OPTIONS.optimization, 2)]
23272327

23282328
def output_join(output, new_chunk, optimize=True):
23292329
""" Extends output instruction list
@@ -2345,7 +2345,7 @@ def output_join(output, new_chunk, optimize=True):
23452345
if RE_BOOL.match(i.quad[0]): # If it is a boolean operation convert it to 0/1 if the STRICT_BOOL flag is True
23462346
output_join(output, convertToBool(), optimize=optimize)
23472347

2348-
if optimize and OPTIONS.optimization.value > 1:
2348+
if optimize and OPTIONS.optimization > 1:
23492349
# Remove unused labels
23502350
while True:
23512351
to_remove = []

0 commit comments

Comments
 (0)