diff --git a/api/check.py b/api/check.py index ac8c19d5e..007e0af2b 100644 --- a/api/check.py +++ b/api/check.py @@ -69,7 +69,7 @@ def check_is_declared_explicit(lineno, id_, classname='variable'): If not in strict mode, passes it silently. """ - if not config.OPTIONS.explicit.value: + if not config.OPTIONS.explicit: return True entry = global_.SYMBOL_TABLE.check_is_declared(id_, lineno, classname) @@ -80,7 +80,7 @@ def check_type_is_explicit(lineno: int, id_: str, type_): from symbols.type_ import SymbolTYPE assert isinstance(type_, SymbolTYPE) if type_.implicit: - if config.OPTIONS.strict.value: + if config.OPTIONS.strict: api.errmsg.syntax_error_undeclared_type(lineno, id_) diff --git a/api/debug.py b/api/debug.py index 8bcd10b7b..3613e9b93 100644 --- a/api/debug.py +++ b/api/debug.py @@ -15,12 +15,12 @@ def __DEBUG__(msg, level=1): - if level > OPTIONS.Debug.value: + if level > OPTIONS.Debug: return line = inspect.getouterframes(inspect.currentframe())[1][2] fname = os.path.basename(inspect.getouterframes(inspect.currentframe())[1][1]) - OPTIONS.stderr.value.write('debug: %s:%i %s\n' % (fname, line, msg)) + OPTIONS.stderr.write('debug: %s:%i %s\n' % (fname, line, msg)) def __LINE__(): diff --git a/api/errmsg.py b/api/errmsg.py index d5e4a6fda..6db0ac1fc 100644 --- a/api/errmsg.py +++ b/api/errmsg.py @@ -21,14 +21,14 @@ def msg_output(msg): if msg in global_.error_msg_cache: return - OPTIONS.stderr.value.write("%s\n" % msg) + OPTIONS.stderr.write("%s\n" % msg) global_.error_msg_cache.add(msg) def info(msg): - if OPTIONS.Debug.value < 1: + if OPTIONS.Debug < 1: return - OPTIONS.stderr.value.write("info: %s\n" % msg) + OPTIONS.stderr.write("info: %s\n" % msg) def error(lineno, msg, fname=None): @@ -37,13 +37,13 @@ def error(lineno, msg, fname=None): if fname is None: fname = global_.FILENAME - if global_.has_errors > OPTIONS.max_syntax_errors.value: + if global_.has_errors > OPTIONS.max_syntax_errors: msg = 'Too many errors. Giving up!' msg = "%s:%i: error: %s" % (fname, lineno, msg) msg_output(msg) - if global_.has_errors > OPTIONS.max_syntax_errors.value: + if global_.has_errors > OPTIONS.max_syntax_errors: sys.exit(1) global_.has_errors += 1 @@ -63,7 +63,7 @@ def warning(lineno, msg, fname=None): def warning_implicit_type(lineno, id_, type_=None): """ Warning: Using default implicit type 'x' """ - if OPTIONS.strict.value: + if OPTIONS.strict: syntax_error_undeclared_type(lineno, id_) return @@ -99,7 +99,7 @@ def warning_empty_if(lineno): # Emmits an optimization warning def warning_not_used(lineno, id_, kind='Variable'): - if OPTIONS.optimization.value > 0: + if OPTIONS.optimization > 0: warning(lineno, "%s '%s' is never used" % (kind, id_)) diff --git a/api/identityset.py b/api/identityset.py index 445edbee3..17a69e186 100644 --- a/api/identityset.py +++ b/api/identityset.py @@ -18,7 +18,7 @@ def add(self, elem): self._elems.add(elem) def remove(self, elem): - """ Removes an element if it exits. Otherwise does nothing. + """ Removes an element if it exists. Otherwise does nothing. Returns if the element was removed. """ if elem in self._elems: diff --git a/api/optimize.py b/api/optimize.py index d2ce1875e..de11d389b 100644 --- a/api/optimize.py +++ b/api/optimize.py @@ -85,7 +85,7 @@ def visit(self, node): @property def O_LEVEL(self): - return OPTIONS.optimization.value + return OPTIONS.optimization def visit_ADDRESS(self, node): if node.operand.token != 'ARRAYACCESS': diff --git a/api/options.py b/api/options.py index 541852699..ef6fb31c0 100644 --- a/api/options.py +++ b/api/options.py @@ -9,16 +9,18 @@ # the GNU General License # ---------------------------------------------------------------------- -from .errors import Error +import json -TRUE = true = True -FALSE = false = False +from typing import Dict +from typing import List +from typing import Any +from .errors import Error __all__ = ['Option', 'Options', 'ANYTYPE'] -class ANYTYPE(object): +class ANYTYPE: """ Dummy class to signal any value """ pass @@ -64,31 +66,45 @@ def __str__(self): % (self.value, self.option, self.type) +class InvalidConfigInitialization(Error): + def __init__(self, invalid_value): + self.invalid_value = invalid_value + + def __str__(self): + return "Invalid value for config initialization" + + # ---------------------------------------------------------------------- # This class interfaces an Options Container # ---------------------------------------------------------------------- -class Option(object): - """ A simple container +class Option: + """ A simple container for options with optional type checking + on vale assignation. """ - def __init__(self, name, type_, value=None): + def __init__(self, name: str, type_, value=None): self.name = name self.type = type_ self.value = value - self.stack = [] # An option stack + self.stack: List[Any] = [] # An option stack @property - def value(self): + def value(self) -> Any: return self.__value @value.setter def value(self, value): - if self.type is not None and not isinstance(value, self.type): + if value is not None and self.type is not None and not isinstance(value, self.type): try: - value = eval(value) + if isinstance(value, str) and self.type == bool: + value = {'false': False, 'true': True}[value.lower()] + else: + value = self.type(value) except TypeError: pass except ValueError: pass + except KeyError: + pass if value is not None and not isinstance(value, self.type): raise InvalidValueError(self.name, self.type, value) @@ -102,34 +118,37 @@ def push(self, value=None): self.stack.append(self.value) self.value = value - def pop(self): - result = self.value - - try: - self.value = self.stack.pop() - except IndexError: + def pop(self) -> Any: + if not self.stack: raise OptionStackUnderflowError(self.name) + result = self.value + self.value = self.stack.pop() return result # ---------------------------------------------------------------------- # This class interfaces an Options Container # ---------------------------------------------------------------------- -class Options(object): - def __init__(self): - self.options = None - self.reset() +class Options: + """ Class to store config options. + """ + def __init__(self, init_value=None): + self._options: Dict[str, Option] = {} - def reset(self): - if self.options is None: - self.options = {} + if init_value is not None: + if isinstance(init_value, dict): + self._options = init_value + elif isinstance(init_value, str): + self._options = json.loads(init_value) + else: + raise InvalidConfigInitialization(invalid_value=init_value) - for opt in list(self.options.keys()): # converts to list since dict will change size during iteration - self.remove_option(opt) + def reset(self): + self._options.clear() def add_option(self, name, type_=None, default_value=None): - if name in self.options.keys(): + if name in self._options: raise DuplicatedOptionError(name) if type_ is None and default_value is not None: @@ -137,28 +156,43 @@ def add_option(self, name, type_=None, default_value=None): elif type_ is ANYTYPE: type_ = None - self.options[name] = Option(name, type_, default_value) - setattr(self, name, self.options[name]) - - def has_option(self, name): - """ Returns whether the given option is defined in this class. - """ - return hasattr(self, name) + self._options[name] = Option(name, type_, default_value) def add_option_if_not_defined(self, name, type_=None, default_value=None): - if self.has_option(name): + if name in self._options: return self.add_option(name, type_, default_value) - def remove_option(self, name): - if name not in self.options.keys(): - raise UndefinedOptionError(name) + def __delattr__(self, item: str): + del self[item] + + def __getattr__(self, item: str): + return self[item].value + + def __setattr__(self, key: str, value: Any): + if key == '_options': + self.__dict__[key] = value + return + + self[key] = value + + def __getitem__(self, item: str) -> Option: + if item not in self._options: + raise UndefinedOptionError(option_name=item) + + return self._options[item] + + def __delitem__(self, item): + if item not in self._options: + raise UndefinedOptionError(item) + + del self._options[item] - del self.options[name] - delattr(self, name) + def __setitem__(self, key: str, value: Any): + if key not in self._options: + raise UndefinedOptionError(option_name=key) - def option(self, name): - if name not in self.options.keys(): - raise UndefinedOptionError(name) + self._options[key].value = value - return self.options[name] + def __contains__(self, item: str): + return item in self._options diff --git a/api/symboltable.py b/api/symboltable.py index c341928fe..92042076a 100644 --- a/api/symboltable.py +++ b/api/symboltable.py @@ -111,17 +111,17 @@ def __delitem__(self, key): del self.caseins[key.lower()] def values(self, filter_by_opt=True): - if filter_by_opt and OPTIONS.optimization.value > 1: + if filter_by_opt and OPTIONS.optimization > 1: return [y for x, y in self.symbols.items() if y.accessed] return [y for x, y in self.symbols.items()] def keys(self, filter_by_opt=True): - if filter_by_opt and OPTIONS.optimization.value > 1: + if filter_by_opt and OPTIONS.optimization > 1: return [x for x, y in self.symbols.items() if y.accessed] return self.symbols.keys() def items(self, filter_by_opt=True): - if filter_by_opt and OPTIONS.optimization.value > 1: + if filter_by_opt and OPTIONS.optimization > 1: return [(x, y) for x, y in self.symbols.items() if y.accessed] return self.symbols.items() @@ -183,7 +183,7 @@ def declare(self, id_: str, lineno: int, entry): if self[self.current_scope][id2] is not None: return None - entry.caseins = OPTIONS.case_insensitive.value + entry.caseins = OPTIONS.case_insensitive self[self.current_scope][id2] = entry entry.name = id2 # Removes DEPRECATED SUFFIXES if any diff --git a/arch/zx48k/backend/__init__.py b/arch/zx48k/backend/__init__.py index 9c41a2e73..ef7a89fef 100644 --- a/arch/zx48k/backend/__init__.py +++ b/arch/zx48k/backend/__init__.py @@ -431,7 +431,7 @@ def _end(ins): FLAG_end_emitted = True output.append('%s:' % END_LABEL) - if OPTIONS.headerless.value: + if OPTIONS.headerless: return output + ['ret'] output.append('di') @@ -2233,13 +2233,13 @@ def __str__(self): def emit_start(): output = list() heap_init = ['%s:' % DATA_LABEL] - output.append('org %s' % OPTIONS.org.value) + output.append('org %s' % OPTIONS.org) if REQUIRES.intersection(MEMINITS) or '__MEM_INIT' in INITS: - heap_init.append('; Defines HEAP SIZE\n' + OPTIONS.heap_size_label.value + ' EQU ' + - str(OPTIONS.heap_size.value)) - heap_init.append(OPTIONS.heap_start_label.value + ':') - heap_init.append('DEFS %s' % str(OPTIONS.heap_size.value)) + heap_init.append('; Defines HEAP SIZE\n' + OPTIONS.heap_size_label + ' EQU ' + + str(OPTIONS.heap_size)) + heap_init.append(OPTIONS.heap_start_label + ':') + heap_init.append('DEFS %s' % str(OPTIONS.heap_size)) heap_init.append('; Defines USER DATA Length in bytes\n' + 'ZXBASIC_USER_DATA_LEN EQU ZXBASIC_USER_DATA_END - ZXBASIC_USER_DATA') @@ -2247,7 +2247,7 @@ def emit_start(): heap_init.append('.__LABEL__.ZXBASIC_USER_DATA EQU ZXBASIC_USER_DATA') output.append('%s:' % START_LABEL) - if OPTIONS.headerless.value: + if OPTIONS.headerless: output.extend(heap_init) return output @@ -2275,7 +2275,7 @@ def convertToBool(): """ Convert a byte value to boolean (0 or 1) if the global flag strictBool is True """ - if not OPTIONS.strictBool.value: + if not OPTIONS.strictBool: return [] REQUIRES.add('strictbool.asm') @@ -2297,7 +2297,7 @@ def emit_end(): output.extend(AT_END) # if REQUIRES.intersection(MEMINITS) or '__MEM_INIT' in INITS: - # output.append(OPTIONS.heap_start_label.value + ':') + # output.append(OPTIONS.heap_start_label + ':') # output.append('; Defines DATA END\n' + 'ZXBASIC_USER_DATA_END EQU ZXBASIC_MEM_HEAP + ZXBASIC_HEAP_SIZE') # else: # output.append('; Defines DATA END --> HEAP size is 0\n' + 'ZXBASIC_USER_DATA_END:') @@ -2307,7 +2307,7 @@ def emit_end(): # output.append('.__LABEL__.ZXBASIC_USER_DATA_LEN EQU ZXBASIC_USER_DATA_LEN') # output.append('.__LABEL__.ZXBASIC_USER_DATA EQU ZXBASIC_USER_DATA') - if OPTIONS.autorun.value: + if OPTIONS.autorun: output.append('END %s' % START_LABEL) else: output.append('END') @@ -2323,7 +2323,7 @@ def emit(mem, optimize=True): 'output' array """ # Optimization patterns: at this point no more than -O2 - patterns = [x for x in engine.PATTERNS if x.level <= min(OPTIONS.optimization.value, 2)] + patterns = [x for x in engine.PATTERNS if x.level <= min(OPTIONS.optimization, 2)] def output_join(output, new_chunk, optimize=True): """ Extends output instruction list @@ -2345,7 +2345,7 @@ def output_join(output, new_chunk, optimize=True): 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 output_join(output, convertToBool(), optimize=optimize) - if optimize and OPTIONS.optimization.value > 1: + if optimize and OPTIONS.optimization > 1: # Remove unused labels while True: to_remove = [] diff --git a/arch/zx48k/optimizer/__init__.py b/arch/zx48k/optimizer/__init__.py index c20b0812c..8b18fe2d9 100644 --- a/arch/zx48k/optimizer/__init__.py +++ b/arch/zx48k/optimizer/__init__.py @@ -183,10 +183,10 @@ def optimize(initial_memory): PROC_COUNTER = 0 cleanupmem(initial_memory) - if OPTIONS.optimization.value <= 2: # if -O2 or lower, do nothing and return + if OPTIONS.optimization <= 2: # if -O2 or lower, do nothing and return return '\n'.join(x for x in initial_memory if not RE_PRAGMA.match(x)) - basicblock.BasicBlock.clean_asm_args = OPTIONS.optimization.value > 3 + basicblock.BasicBlock.clean_asm_args = OPTIONS.optimization > 3 bb = basicblock.BasicBlock(initial_memory) cleanup_local_labels(bb) initialize_memory(bb) @@ -234,7 +234,7 @@ def optimize(initial_memory): for x in basic_blocks: x.compute_cpu_state() - filtered_patterns_list = [p for p in engine.PATTERNS if OPTIONS.optimization.value >= p.level >= 3] + filtered_patterns_list = [p for p in engine.PATTERNS if OPTIONS.optimization >= p.level >= 3] for x in basic_blocks: x.optimize(filtered_patterns_list) diff --git a/arch/zx48k/optimizer/basicblock.py b/arch/zx48k/optimizer/basicblock.py index 81a3aa1a7..fa8f6a6cf 100644 --- a/arch/zx48k/optimizer/basicblock.py +++ b/arch/zx48k/optimizer/basicblock.py @@ -565,7 +565,7 @@ def optimize(self, patterns_list): 'z': str(self.cpu.Z) if self.cpu.Z is not None else helpers.new_tmp_val() }.get(x.lower(), helpers.new_tmp_val()) - if api.config.OPTIONS.optimization.value > 3: + if api.config.OPTIONS.optimization > 3: regs, mems = self.guesses_initial_state_from_origin_blocks() else: regs, mems = {}, {} diff --git a/arch/zx48k/translator.py b/arch/zx48k/translator.py index 3911d4989..a4fad57ce 100644 --- a/arch/zx48k/translator.py +++ b/arch/zx48k/translator.py @@ -194,7 +194,7 @@ def visit_ARGLIST(self, node): for i in range(len(node) - 1, -1, -1): # visit in reverse order yield node[i] - if isinstance(node.parent, symbols.ARRAYACCESS) and OPTIONS.arrayCheck.value: + if isinstance(node.parent, symbols.ARRAYACCESS) and OPTIONS.arrayCheck: upper = node.parent.entry.bounds[i].upper lower = node.parent.entry.bounds[i].lower self.ic_param(gl.PTR_TYPE, upper - lower) diff --git a/arch/zx48k/translatorvisitor.py b/arch/zx48k/translatorvisitor.py index f10617878..f4d509112 100644 --- a/arch/zx48k/translatorvisitor.py +++ b/arch/zx48k/translatorvisitor.py @@ -78,7 +78,7 @@ def add_string_label(self, str_): @property def O_LEVEL(self): - return OPTIONS.optimization.value + return OPTIONS.optimization @staticmethod def TYPE(type_): diff --git a/libzxbasm/asmlex.py b/libzxbasm/asmlex.py index 4bea4b81f..a576d8260 100755 --- a/libzxbasm/asmlex.py +++ b/libzxbasm/asmlex.py @@ -300,7 +300,7 @@ def t_INITIAL_ID(self, t): if t.type is not None: return t - if OPTIONS.zxnext.value: + if OPTIONS.zxnext: t.type = zx_next_mnemonics.get(id_) if t.type is not None: return t @@ -326,13 +326,13 @@ def t_ADDR(self, t): def t_LP(self, t): r'[\[(]' - if t.value != '[' and OPTIONS.bracket.value: + if t.value != '[' and OPTIONS.bracket: t.type = 'LPP' return t def t_RP(self, t): r'[])]' - if t.value != ']' and OPTIONS.bracket.value: + if t.value != ']' and OPTIONS.bracket: t.type = 'RPP' return t diff --git a/libzxbasm/asmparse.py b/libzxbasm/asmparse.py index 762c75aaa..0bc025cc3 100755 --- a/libzxbasm/asmparse.py +++ b/libzxbasm/asmparse.py @@ -1477,7 +1477,7 @@ def p_error(p): else: error(p.lineno, "Syntax error. Unexpected end of line [NEWLINE]") else: - OPTIONS.stderr.value.write("General syntax error at assembler (unexpected End of File?)") + OPTIONS.stderr.write("General syntax error at assembler (unexpected End of File?)") gl.has_errors += 1 @@ -1490,12 +1490,12 @@ def assemble(input_): if MEMORY is None: MEMORY = Memory() - if OPTIONS.zxnext.value: + if OPTIONS.zxnext: parser_ = zxnext_parser else: parser_ = parser - parser_.parse(input_, lexer=LEXER, debug=OPTIONS.Debug.value > 1) + parser_.parse(input_, lexer=LEXER, debug=OPTIONS.Debug > 1) if len(MEMORY.scopes): error(MEMORY.scopes[-1], 'Missing ENDP to close this scope') @@ -1536,14 +1536,13 @@ def generate_binary(outputfname, format_, progname='', binary_files=None, headle if not progname: progname = os.path.basename(outputfname)[:10] - if OPTIONS.use_loader.value: - + if OPTIONS.use_loader: program = basic.Basic() if org > 16383: # Only for zx48k: CLEAR if above 16383 program.add_line([['CLEAR', org - 1]]) program.add_line([['LOAD', '""', program.token('CODE')]]) - if OPTIONS.autorun.value: + if OPTIONS.autorun: program.add_line([['RANDOMIZE', program.token('USR'), AUTORUN_ADDR]]) else: program.add_line([['REM'], ['RANDOMIZE', program.token('USR'), AUTORUN_ADDR]]) @@ -1555,7 +1554,7 @@ def generate_binary(outputfname, format_, progname='', binary_files=None, headle emitter = outfmt.BinaryEmitter() loader_bytes = None - if OPTIONS.use_loader.value: + if OPTIONS.use_loader: loader_bytes = program.bytes assert isinstance(emitter, outfmt.CodeEmitter) @@ -1573,13 +1572,13 @@ def main(argv): """ init() - if OPTIONS.StdErrFileName.value: - OPTIONS.stderr.value = open('wt', OPTIONS.StdErrFileName.value) + if OPTIONS.StdErrFileName: + OPTIONS.stderr = open('wt', OPTIONS.StdErrFileName) - asmlex.FILENAME = OPTIONS.inputFileName.value = argv[0] - input_ = open(OPTIONS.inputFileName.value, 'rt').read() + asmlex.FILENAME = OPTIONS.inputFileName = argv[0] + input_ = open(OPTIONS.inputFileName, 'rt').read() assemble(input_) - generate_binary(OPTIONS.outputFileName.value, OPTIONS.output_file_type) + generate_binary(OPTIONS.outputFileName, OPTIONS.output_file_type) # Z80 only ASM parser diff --git a/libzxbasm/zxbasm.py b/libzxbasm/zxbasm.py index 48eaabb39..38c01c8d4 100755 --- a/libzxbasm/zxbasm.py +++ b/libzxbasm/zxbasm.py @@ -35,11 +35,11 @@ def main(args=None): # Create option parser o_parser = argparse.ArgumentParser() o_parser.add_argument('PROGRAM', type=str, help='ASM program file') - o_parser.add_argument("-d", "--debug", action="count", default=OPTIONS.Debug.value, + o_parser.add_argument("-d", "--debug", action="count", default=OPTIONS.Debug, help="Enable verbosity/debugging output") o_parser.add_argument("-O", "--optimize", type=int, dest="optimization_level", - help="Sets optimization level. 0 = None", default=OPTIONS.optimization.value) + help="Sets optimization level. 0 = None", default=OPTIONS.optimization) o_parser.add_argument("-o", "--output", type=str, dest="output_file", help="Sets output file. Default is input filename with .bin extension", default=None) @@ -56,7 +56,7 @@ def main(args=None): o_parser.add_argument("-a", "--autorun", action="store_true", default=False, help="Sets the program to auto run once loaded (implies --BASIC)") - o_parser.add_argument("-e", "--errmsg", type=str, dest="stderr", default=OPTIONS.StdErrFileName.value, + o_parser.add_argument("-e", "--errmsg", type=str, dest="stderr", default=OPTIONS.StdErrFileName, help="Error messages file (standard error console by default") o_parser.add_argument("-M", "--mmap", type=str, dest="memory_map", default=None, @@ -76,34 +76,34 @@ def main(args=None): o_parser.error("No such file or directory: '%s'" % options.PROGRAM) sys.exit(2) - OPTIONS.Debug.value = int(options.debug) - OPTIONS.inputFileName.value = options.PROGRAM - OPTIONS.outputFileName.value = options.output_file - OPTIONS.optimization.value = options.optimization_level - OPTIONS.use_loader.value = options.autorun or options.basic - OPTIONS.autorun.value = options.autorun - OPTIONS.StdErrFileName.value = options.stderr - OPTIONS.memory_map.value = options.memory_map - OPTIONS.bracket.value = options.bracket - OPTIONS.zxnext.value = options.zxnext + OPTIONS.Debug = int(options.debug) + OPTIONS.inputFileName = options.PROGRAM + OPTIONS.outputFileName = options.output_file + OPTIONS.optimization = options.optimization_level + OPTIONS.use_loader = options.autorun or options.basic + OPTIONS.autorun = options.autorun + OPTIONS.StdErrFileName = options.stderr + OPTIONS.memory_map = options.memory_map + OPTIONS.bracket = options.bracket + OPTIONS.zxnext = options.zxnext if options.tzx: - OPTIONS.output_file_type.value = 'tzx' + OPTIONS.output_file_type = 'tzx' elif options.tap: - OPTIONS.output_file_type.value = 'tap' + OPTIONS.output_file_type = 'tap' - if not OPTIONS.outputFileName.value: - OPTIONS.outputFileName.value = os.path.splitext( - os.path.basename(OPTIONS.inputFileName.value))[0] + os.path.extsep + OPTIONS.output_file_type.value + if not OPTIONS.outputFileName: + OPTIONS.outputFileName = os.path.splitext( + os.path.basename(OPTIONS.inputFileName))[0] + os.path.extsep + OPTIONS.output_file_type - if OPTIONS.StdErrFileName.value: - OPTIONS.stderr.value = open(OPTIONS.StdErrFileName.value, 'wt') + if OPTIONS.StdErrFileName: + OPTIONS.stderr = open(OPTIONS.StdErrFileName, 'wt') if int(options.tzx) + int(options.tap) > 1: o_parser.error("Options --tap, --tzx and --asm are mutually exclusive") return 3 - if OPTIONS.use_loader.value and not options.tzx and not options.tap: + if OPTIONS.use_loader and not options.tzx and not options.tap: o_parser.error('Option --BASIC and --autorun requires --tzx or tap format') return 4 @@ -111,7 +111,7 @@ def main(args=None): zxbpp.setMode('asm') # Now filter them against the preprocessor - zxbpp.main([OPTIONS.inputFileName.value]) + zxbpp.main([OPTIONS.inputFileName]) # Now output the result asm_output = zxbpp.OUTPUT @@ -138,11 +138,11 @@ def main(args=None): asmparse.AUTORUN_ADDR = current_org - if OPTIONS.memory_map.value: - with open(OPTIONS.memory_map.value, 'wt') as f: + if OPTIONS.memory_map: + with open(OPTIONS.memory_map, 'wt') as f: f.write(asmparse.MEMORY.memory_map) - asmparse.generate_binary(OPTIONS.outputFileName.value, OPTIONS.output_file_type.value) + asmparse.generate_binary(OPTIONS.outputFileName, OPTIONS.output_file_type) return global_.has_errors diff --git a/libzxbc/zxb.py b/libzxbc/zxb.py index d2c21bdf2..d882c06cd 100755 --- a/libzxbc/zxb.py +++ b/libzxbc/zxb.py @@ -86,11 +86,11 @@ def main(args=None, emitter=None): parser = argparse.ArgumentParser() parser.add_argument('PROGRAM', type=str, help='BASIC program file') - parser.add_argument('-d', '--debug', dest='debug', default=OPTIONS.Debug.value, action='count', + parser.add_argument('-d', '--debug', dest='debug', default=OPTIONS.Debug, action='count', help='Enable verbosity/debugging output. Additional -d increase verbosity/debug level') - parser.add_argument('-O', '--optimize', type=int, default=OPTIONS.optimization.value, + parser.add_argument('-O', '--optimize', type=int, default=OPTIONS.optimization, help='Sets optimization level. ' - '0 = None (default level is {0})'.format(OPTIONS.optimization.value)) + '0 = None (default level is {0})'.format(OPTIONS.optimization)) parser.add_argument('-o', '--output', type=str, dest='output_file', default=None, help='Sets output file. Default is input filename with .bin extension') parser.add_argument('-T', '--tzx', action='store_true', @@ -103,19 +103,19 @@ def main(args=None, emitter=None): help="Sets the program to be run once loaded") parser.add_argument('-A', '--asm', action='store_true', help="Sets output format to asm") - parser.add_argument('-S', '--org', type=str, default=str(OPTIONS.org.value), - help="Start of machine code. By default %i" % OPTIONS.org.value) - parser.add_argument('-e', '--errmsg', type=str, dest='stderr', default=OPTIONS.StdErrFileName.value, + parser.add_argument('-S', '--org', type=str, default=str(OPTIONS.org), + help="Start of machine code. By default %i" % OPTIONS.org) + parser.add_argument('-e', '--errmsg', type=str, dest='stderr', default=OPTIONS.StdErrFileName, help='Error messages file (standard error console by default)') - parser.add_argument('--array-base', type=int, default=OPTIONS.array_base.value, - help='Default lower index for arrays ({0} by default)'.format(OPTIONS.array_base.value)) - parser.add_argument('--string-base', type=int, default=OPTIONS.string_base.value, - help='Default lower index for strings ({0} by default)'.format(OPTIONS.array_base.value)) + parser.add_argument('--array-base', type=int, default=OPTIONS.array_base, + help='Default lower index for arrays ({0} by default)'.format(OPTIONS.array_base)) + parser.add_argument('--string-base', type=int, default=OPTIONS.string_base, + help='Default lower index for strings ({0} by default)'.format(OPTIONS.array_base)) parser.add_argument('-Z', '--sinclair', action='store_true', help='Enable by default some more original ZX Spectrum Sinclair BASIC features: ATTR, SCREEN$, ' 'POINT') - parser.add_argument('-H', '--heap-size', type=int, default=OPTIONS.heap_size.value, - help='Sets heap size in bytes (default {0} bytes)'.format(OPTIONS.heap_size.value)) + parser.add_argument('-H', '--heap-size', type=int, default=OPTIONS.heap_size, + help='Sets heap size in bytes (default {0} bytes)'.format(OPTIONS.heap_size)) parser.add_argument('--debug-memory', action='store_true', help='Enables out-of-memory debug') parser.add_argument('--debug-array', action='store_true', @@ -159,34 +159,34 @@ def main(args=None, emitter=None): # Setting of internal parameters according to command line # ------------------------------------------------------------ - OPTIONS.Debug.value = options.debug - OPTIONS.optimization.value = options.optimize - OPTIONS.outputFileName.value = options.output_file - OPTIONS.StdErrFileName.value = options.stderr - OPTIONS.array_base.value = options.array_base - OPTIONS.string_base.value = options.string_base - OPTIONS.Sinclair.value = options.sinclair - OPTIONS.heap_size.value = options.heap_size - OPTIONS.memoryCheck.value = options.debug_memory - OPTIONS.strictBool.value = options.strict_bool or OPTIONS.Sinclair.value - OPTIONS.arrayCheck.value = options.debug_array - OPTIONS.emitBackend.value = options.emit_backend - OPTIONS.enableBreak.value = options.enable_break - OPTIONS.explicit.value = options.explicit - OPTIONS.memory_map.value = options.memory_map - OPTIONS.strict.value = options.strict - OPTIONS.headerless.value = options.headerless - OPTIONS.zxnext.value = options.zxnext + OPTIONS.Debug = options.debug + OPTIONS.optimization = options.optimize + OPTIONS.outputFileName = options.output_file + OPTIONS.StdErrFileName = options.stderr + OPTIONS.array_base = options.array_base + OPTIONS.string_base = options.string_base + OPTIONS.Sinclair = options.sinclair + OPTIONS.heap_size = options.heap_size + OPTIONS.memoryCheck = options.debug_memory + OPTIONS.strictBool = options.strict_bool or OPTIONS.Sinclair + OPTIONS.arrayCheck = options.debug_array + OPTIONS.emitBackend = options.emit_backend + OPTIONS.enableBreak = options.enable_break + OPTIONS.explicit = options.explicit + OPTIONS.memory_map = options.memory_map + OPTIONS.strict = options.strict + OPTIONS.headerless = options.headerless + OPTIONS.zxnext = options.zxnext if options.arch not in arch.AVAILABLE_ARCHITECTURES: parser.error(f"Invalid architecture '{options.arch}'") return 2 - OPTIONS.architecture.value = options.arch + OPTIONS.architecture = options.arch arch.set_target_arch(options.arch) backend = arch.target.backend - OPTIONS.org.value = api.utils.parse_int(options.org) - if OPTIONS.org.value is None: + OPTIONS.org = api.utils.parse_int(options.org) + if OPTIONS.org is None: parser.error("Invalid --org option '{}'".format(options.org)) if options.defines: @@ -194,19 +194,19 @@ def main(args=None, emitter=None): macro = list(i.split('=', 1)) name = macro[0] val = ''.join(macro[1:]) - OPTIONS.__DEFINES.value[name] = val + OPTIONS.__DEFINES[name] = val zxbpp.ID_TABLE.define(name, value=val, lineno=0) - if OPTIONS.Sinclair.value: - OPTIONS.array_base.value = 1 - OPTIONS.string_base.value = 1 - OPTIONS.strictBool.value = True - OPTIONS.case_insensitive.value = True + if OPTIONS.Sinclair: + OPTIONS.array_base = 1 + OPTIONS.string_base = 1 + OPTIONS.strictBool = True + OPTIONS.case_insensitive = True if options.ignore_case: - OPTIONS.case_insensitive.value = True + OPTIONS.case_insensitive = True - debug.ENABLED = OPTIONS.Debug.value + debug.ENABLED = OPTIONS.Debug if int(options.tzx) + int(options.tap) + int(options.asm) + int(options.emit_backend) + \ int(options.parse_only) > 1: @@ -225,46 +225,46 @@ def main(args=None, emitter=None): parser.error('Option --asm and --mmap cannot be used together') return 6 - OPTIONS.use_loader.value = options.basic - OPTIONS.autorun.value = options.autorun + OPTIONS.use_loader = options.basic + OPTIONS.autorun = options.autorun if options.tzx: - OPTIONS.output_file_type.value = 'tzx' + OPTIONS.output_file_type = 'tzx' elif options.tap: - OPTIONS.output_file_type.value = 'tap' + OPTIONS.output_file_type = 'tap' elif options.asm: - OPTIONS.output_file_type.value = 'asm' + OPTIONS.output_file_type = 'asm' elif options.emit_backend: - OPTIONS.output_file_type.value = 'ic' + OPTIONS.output_file_type = 'ic' args = [options.PROGRAM] if not os.path.exists(options.PROGRAM): parser.error("No such file or directory: '%s'" % args[0]) return 2 - if OPTIONS.memoryCheck.value: - OPTIONS.__DEFINES.value['__MEMORY_CHECK__'] = '' + if OPTIONS.memoryCheck: + OPTIONS.__DEFINES['__MEMORY_CHECK__'] = '' zxbpp.ID_TABLE.define('__MEMORY_CHECK__', lineno=0) - if OPTIONS.arrayCheck.value: - OPTIONS.__DEFINES.value['__CHECK_ARRAY_BOUNDARY__'] = '' + if OPTIONS.arrayCheck: + OPTIONS.__DEFINES['__CHECK_ARRAY_BOUNDARY__'] = '' zxbpp.ID_TABLE.define('__CHECK_ARRAY_BOUNDARY__', lineno=0) - if OPTIONS.enableBreak.value: - OPTIONS.__DEFINES.value['__ENABLE_BREAK__'] = '' + if OPTIONS.enableBreak: + OPTIONS.__DEFINES['__ENABLE_BREAK__'] = '' zxbpp.ID_TABLE.define('__ENABLE_BREAK__', lineno=0) - OPTIONS.include_path.value = options.include_path - OPTIONS.inputFileName.value = zxbparser.FILENAME = \ + OPTIONS.include_path = options.include_path + OPTIONS.inputFileName = zxbparser.FILENAME = \ os.path.basename(args[0]) - if not OPTIONS.outputFileName.value: - OPTIONS.outputFileName.value = \ - os.path.splitext(os.path.basename(OPTIONS.inputFileName.value))[0] + os.path.extsep + \ - OPTIONS.output_file_type.value + if not OPTIONS.outputFileName: + OPTIONS.outputFileName = \ + os.path.splitext(os.path.basename(OPTIONS.inputFileName))[0] + os.path.extsep + \ + OPTIONS.output_file_type - if OPTIONS.StdErrFileName.value: - OPTIONS.stderr.value = open_file(OPTIONS.StdErrFileName.value, 'wt', 'utf-8') + if OPTIONS.StdErrFileName: + OPTIONS.stderr = open_file(OPTIONS.StdErrFileName, 'wt', 'utf-8') zxbpp.setMode('basic') zxbpp.main(args) @@ -275,7 +275,7 @@ def main(args=None, emitter=None): input_ = zxbpp.OUTPUT zxbparser.parser.parse(input_, lexer=zxblex.lexer, tracking=True, - debug=(OPTIONS.Debug.value > 1)) + debug=(OPTIONS.Debug > 1)) if gl.has_errors: debug.__DEBUG__("exiting due to errors.") return 1 # Exit with errors @@ -302,8 +302,8 @@ def main(args=None, emitter=None): # Emits jump tables translator.emit_jump_tables() - if OPTIONS.emitBackend.value: - with open_file(OPTIONS.outputFileName.value, 'wt', 'utf-8') as output_file: + if OPTIONS.emitBackend: + with open_file(OPTIONS.outputFileName, 'wt', 'utf-8') as output_file: for quad in translator.dumpMemory(backend.MEMORY): output_file.write(str(quad) + '\n') @@ -317,7 +317,7 @@ def main(args=None, emitter=None): return 0 # Exit success # Join all lines into a single string and ensures an INTRO at end of file - asm_output = backend.emit(backend.MEMORY, optimize=OPTIONS.optimization.value > 0) + asm_output = backend.emit(backend.MEMORY, optimize=OPTIONS.optimization > 0) asm_output = arch.target.optimizer.optimize(asm_output) + '\n' # invoke the -O3 asm_output = asm_output.split('\n') @@ -353,23 +353,23 @@ def main(args=None, emitter=None): + asm_output + backend.emit_end() if options.asm: # Only output assembler file - with open_file(OPTIONS.outputFileName.value, 'wt', 'utf-8') as output_file: + with open_file(OPTIONS.outputFileName, 'wt', 'utf-8') as output_file: output(asm_output, output_file) elif not options.parse_only: fout = StringIO() output(asm_output, fout) asmparse.assemble(fout.getvalue()) fout.close() - asmparse.generate_binary(OPTIONS.outputFileName.value, OPTIONS.output_file_type.value, + asmparse.generate_binary(OPTIONS.outputFileName, OPTIONS.output_file_type, binary_files=options.append_binary, headless_binary_files=options.append_headless_binary, emitter=emitter) if gl.has_errors: return 5 # Error in assembly - if OPTIONS.memory_map.value: + if OPTIONS.memory_map: if asmparse.MEMORY is not None: - with open_file(OPTIONS.memory_map.value, 'wt', 'utf-8') as f: + with open_file(OPTIONS.memory_map, 'wt', 'utf-8') as f: f.write(asmparse.MEMORY.memory_map) return gl.has_errors # Exit success diff --git a/libzxbc/zxbparser.py b/libzxbc/zxbparser.py index 4aa49b282..fb28c76eb 100755 --- a/libzxbc/zxbparser.py +++ b/libzxbc/zxbparser.py @@ -287,7 +287,7 @@ def make_argument(expr, lineno, byref=None): return # There were a syntax / semantic error if byref is None: - byref = OPTIONS.byref.value + byref = OPTIONS.byref return symbols.ARGUMENT(expr, lineno=lineno, byref=byref) @@ -348,8 +348,8 @@ def make_array_substr_assign(lineno, id_, arg_list, substr, expr_): if s1 is None: return None # There were errors - if OPTIONS.string_base.value: - base = make_number(OPTIONS.string_base.value, lineno, _TYPE(gl.STR_INDEX_TYPE)) + if OPTIONS.string_base: + base = make_number(OPTIONS.string_base, lineno, _TYPE(gl.STR_INDEX_TYPE)) s0 = make_binary(lineno, 'MINUS', s0, base, func=lambda x, y: x - y) s1 = make_binary(lineno, 'MINUS', s1, base, func=lambda x, y: x - y) @@ -457,7 +457,7 @@ def make_break(lineno, p): checked """ global last_brk_linenum - if not OPTIONS.enableBreak.value or lineno == last_brk_linenum or is_null(p): + if not OPTIONS.enableBreak or lineno == last_brk_linenum or is_null(p): return None last_brk_linenum = lineno @@ -855,7 +855,7 @@ def p_bound_list_bound(p): def p_bound(p): """ bound : expr """ - p[0] = make_bound(make_number(OPTIONS.array_base.value, + p[0] = make_bound(make_number(OPTIONS.array_base, lineno=p.lineno(1)), p[1], p.lexer.lineno) @@ -1209,7 +1209,7 @@ def p_substr_assignment_no_let(p): api.errmsg.syntax_error_expected_string(p.lineno(5), p[6].type_) lineno = p.lineno(2) - base = make_number(OPTIONS.string_base.value, lineno, _TYPE(gl.STR_INDEX_TYPE)) + base = make_number(OPTIONS.string_base, lineno, _TYPE(gl.STR_INDEX_TYPE)) substr = make_typecast(_TYPE(gl.STR_INDEX_TYPE), p[3], lineno) p[0] = make_sentence('LETSUBSTR', entry, make_binary(lineno, 'MINUS', substr, base, func=lambda x, y: x - y), @@ -1262,7 +1262,7 @@ def p_substr_assignment(p): p.lineno(2))) lineno = p.lineno(2) - base = make_number(OPTIONS.string_base.value, lineno, _TYPE(gl.STR_INDEX_TYPE)) + base = make_number(OPTIONS.string_base, lineno, _TYPE(gl.STR_INDEX_TYPE)) p[0] = make_sentence('LETSUBSTR', entry, make_binary(lineno, 'MINUS', substr[0], base, func=lambda x, y: x - y), make_binary(lineno, 'MINUS', substr[1], base, func=lambda x, y: x - y), @@ -3055,7 +3055,7 @@ def p_param_definition(p): if param_def.class_ == CLASS.array: param_def.byref = True else: - param_def.byref = OPTIONS.byref.value + param_def.byref = OPTIONS.byref def p_param_def_array(p): @@ -3176,19 +3176,19 @@ def p_preproc_line_option(p): | _PRAGMA ID EQ STRING | _PRAGMA ID EQ INTEGER """ - OPTIONS.option(p[2]).value = p[4] + setattr(OPTIONS, p[2], p[4]) def p_preproc_line_push(p): """ preproc_line : _PRAGMA _PUSH LP ID RP """ - OPTIONS.option(p[4]).push() + OPTIONS[p[4]].push() def p_preproc_line_pop(p): """ preproc_line : _PRAGMA _POP LP ID RP """ - OPTIONS.option(p[4]).pop() + OPTIONS[p[4]].pop() # region INTERNAL FUNCTIONS diff --git a/libzxbpp/zxbpp.py b/libzxbpp/zxbpp.py index b95c8ca08..dbc4711b4 100755 --- a/libzxbpp/zxbpp.py +++ b/libzxbpp/zxbpp.py @@ -31,7 +31,6 @@ import arch - OUTPUT = '' INCLUDED = {} # Already included files (with lines) SPACES = re.compile(r'[ \t]+') @@ -59,7 +58,6 @@ class IfDef(NamedTuple): # IFDEFS array IFDEFS: List[IfDef] = [] # Push (Line, state here) - precedence = ( ('left', 'DUMMY'), ('left', 'EQ', 'NE', 'LT', 'LE', 'GT', 'GE'), @@ -99,7 +97,7 @@ def get_include_path(): os.path.dirname(__file__), os.path.pardir, 'arch', - OPTIONS.architecture.value or '') + OPTIONS.architecture or '') ) @@ -129,7 +127,7 @@ def search_filename(fname, lineno, local_first): """ fname = api.utils.sanitize_filename(fname) i_path = [CURRENT_DIR] + INCLUDEPATH if local_first else list(INCLUDEPATH) - i_path.extend(OPTIONS.include_path.value.split(':') if OPTIONS.include_path.value else []) + i_path.extend(OPTIONS.include_path.split(':') if OPTIONS.include_path else []) if os.path.isabs(fname): if os.path.isfile(fname): return fname @@ -744,8 +742,8 @@ def p_error(p): error(p.lineno, "syntax error. Unexpected token '%s' [%s]" % (value, p.type)) else: - OPTIONS.stderr.value.write("General syntax error at preprocessor " - "(unexpected End of File?)") + OPTIONS.stderr.write("General syntax error at preprocessor " + "(unexpected End of File?)") global_.has_errors += 1 @@ -760,7 +758,7 @@ def filter_(input_, filename='', state='INITIAL'): CURRENT_DIR = os.path.dirname(CURRENT_FILE[-1]) LEXER.input(input_, filename) LEXER.lex.begin(state) - parser.parse(lexer=LEXER, debug=OPTIONS.debug_zxbpp.value) + parser.parse(lexer=LEXER, debug=OPTIONS.debug_zxbpp) CURRENT_FILE.pop() CURRENT_DIR = prev_dir @@ -778,7 +776,7 @@ def main(argv): CURRENT_FILE.append(global_.FILENAME) CURRENT_DIR = os.path.dirname(CURRENT_FILE[-1]) - if OPTIONS.Sinclair.value: + if OPTIONS.Sinclair: included_file = search_filename('sinclair.bas', 0, local_first=False) if not included_file: return @@ -787,7 +785,7 @@ def main(argv): if len(OUTPUT) and OUTPUT[-1] != '\n': OUTPUT += '\n' - parser.parse(lexer=LEXER, debug=OPTIONS.debug_zxbpp.value) + parser.parse(lexer=LEXER, debug=OPTIONS.debug_zxbpp) CURRENT_FILE.pop() CURRENT_DIR = os.path.dirname(CURRENT_FILE[-1]) @@ -797,7 +795,7 @@ def main(argv): if len(OUTPUT) and OUTPUT[-1] != '\n': OUTPUT += '\n' - parser.parse(lexer=LEXER, debug=OPTIONS.debug_zxbpp.value) + parser.parse(lexer=LEXER, debug=OPTIONS.debug_zxbpp) CURRENT_FILE.pop() global_.FILENAME = prev_file return global_.has_errors @@ -821,7 +819,7 @@ def entry_point(args=None): parser = argparse.ArgumentParser() parser.add_argument('-o', '--output', type=str, dest='output_file', default=None, help='Sets output file. Default is to output to console (STDOUT)') - parser.add_argument('-d', '--debug', dest='debug', default=OPTIONS.Debug.value, action='count', + parser.add_argument('-d', '--debug', dest='debug', default=OPTIONS.Debug, action='count', help='Enable verbosity/debugging output. Additional -d increases verbosity/debug level') parser.add_argument('-e', '--errmsg', type=str, dest='stderr', default=None, help='Error messages file. Standard error console by default (STDERR)') @@ -832,17 +830,17 @@ def entry_point(args=None): f"Available architectures: {','.join(arch.AVAILABLE_ARCHITECTURES)}") options = parser.parse_args(args=args) - OPTIONS.Debug.value = options.debug - OPTIONS.debug_zxbpp.value = OPTIONS.Debug.value > 0 + OPTIONS.Debug = options.debug + OPTIONS.debug_zxbpp = OPTIONS.Debug > 0 if options.arch not in arch.AVAILABLE_ARCHITECTURES: parser.error(f"Invalid architecture '{options.arch}'") return 2 - OPTIONS.architecture.value = options.arch + OPTIONS.architecture = options.arch if options.stderr: - OPTIONS.StdErrFileName.value = options.stderr - OPTIONS.stderr.value = api.utils.open_file(OPTIONS.StdErrFileName.value, 'wt', 'utf-8') + OPTIONS.StdErrFileName = options.stderr + OPTIONS.stderr = api.utils.open_file(OPTIONS.StdErrFileName, 'wt', 'utf-8') result = main([options.input_file] if options.input_file else []) if not global_.has_errors: # ok? @@ -850,7 +848,7 @@ def entry_point(args=None): with api.utils.open_file(options.output_file, 'wt', 'utf-8') as output_file: output_file.write(OUTPUT) else: - OPTIONS.stdout.value.write(OUTPUT) + OPTIONS.stdout.write(OUTPUT) return result diff --git a/symbols/argument.py b/symbols/argument.py index 1d156f7a4..7239d0ae6 100644 --- a/symbols/argument.py +++ b/symbols/argument.py @@ -28,7 +28,7 @@ def __init__(self, value, lineno, byref=None): """ super(SymbolARGUMENT, self).__init__(value) self.lineno = lineno - self.byref = byref if byref is not None else OPTIONS.byref.value + self.byref = byref if byref is not None else OPTIONS.byref @property def t(self): diff --git a/symbols/paramdecl.py b/symbols/paramdecl.py index 0ebe6cc85..75c5f3c31 100644 --- a/symbols/paramdecl.py +++ b/symbols/paramdecl.py @@ -22,7 +22,7 @@ class SymbolPARAMDECL(SymbolVAR): """ def __init__(self, varname, lineno, type_=None): super(SymbolPARAMDECL, self).__init__(varname, lineno, type_=type_, class_=CLASS.var) - self.byref = OPTIONS.byref.value # By default all params By value (false) + self.byref = OPTIONS.byref # By default all params By value (false) self.offset = None # Set by PARAMLIST, contains positive offset from top of the stack self.scope = SCOPE.parameter diff --git a/symbols/strslice.py b/symbols/strslice.py index 47fbca2ac..831c6e874 100644 --- a/symbols/strslice.py +++ b/symbols/strslice.py @@ -28,7 +28,7 @@ class SymbolSTRSLICE(Symbol): """ def __init__(self, string, lower, upper, lineno): - super(SymbolSTRSLICE, self).__init__(string, lower, upper) + super().__init__(string, lower, upper) self.string = string # Ensures is STRING via setter self.lower = lower self.upper = upper @@ -80,7 +80,7 @@ def make_node(cls, lineno, s, lower, upper): return None lo = up = None - base = NUMBER(api.config.OPTIONS.string_base.value, lineno=lineno) + base = NUMBER(api.config.OPTIONS.string_base, lineno=lineno) lower = TYPECAST.make_node(gl.SYMBOL_TABLE.basic_types[gl.STR_INDEX_TYPE], BINARY.make_node('MINUS', lower, base, lineno=lineno, func=lambda x, y: x - y), lineno) diff --git a/symbols/type_.py b/symbols/type_.py index 8c15e8b16..d49b4113d 100644 --- a/symbols/type_.py +++ b/symbols/type_.py @@ -28,7 +28,7 @@ def __init__(self, name, lineno, *children): self.name = name # typename self.lineno = lineno # The line the type was defined. Line 0 = basic type self.final = self # self.final always return the original aliased type (if this type is an alias) - self.caseins = OPTIONS.case_insensitive.value # Whether this ID is case insensitive or not + self.caseins = OPTIONS.case_insensitive # Whether this ID is case insensitive or not self.class_ = CLASS.type_ self.accessed = False # Whether this type has been used or not diff --git a/symbols/var.py b/symbols/var.py index 8a2ab4389..8f88b71c6 100644 --- a/symbols/var.py +++ b/symbols/var.py @@ -47,7 +47,7 @@ def __init__(self, varname, lineno, offset=None, type_=None, class_=None): self.alias = None # If not None, this var is an alias of another self.aliased_by = [] # Which variables are an alias of this one self._accessed = False # Where this object has been accessed (if false it might be not compiled) - self.caseins = OPTIONS.case_insensitive.value # Whether this ID is case insensitive or not + self.caseins = OPTIONS.case_insensitive # Whether this ID is case insensitive or not self._t = global_.optemps.new_t() self.scopeRef = None # Must be set by the Symbol Table. PTR to the scope self.callable = None # For functions, subs, arrays and strings this will be True diff --git a/tests/api/test_config.py b/tests/api/test_config.py index 55d9a9c47..185134daf 100644 --- a/tests/api/test_config.py +++ b/tests/api/test_config.py @@ -15,63 +15,65 @@ def setUp(self): def test_init(self): config.init() - self.assertEqual(config.OPTIONS.Debug.value, 0) - self.assertEqual(config.OPTIONS.stdin.value, sys.stdin) - self.assertEqual(config.OPTIONS.stdout.value, sys.stdout) - self.assertEqual(config.OPTIONS.stderr.value, sys.stderr) - self.assertEqual(config.OPTIONS.optimization.value, global_.DEFAULT_OPTIMIZATION_LEVEL) - self.assertEqual(config.OPTIONS.case_insensitive.value, False) - self.assertEqual(config.OPTIONS.array_base.value, 0) - self.assertEqual(config.OPTIONS.byref.value, False) - self.assertEqual(config.OPTIONS.max_syntax_errors.value, global_.DEFAULT_MAX_SYNTAX_ERRORS) - self.assertEqual(config.OPTIONS.string_base.value, 0) - self.assertEqual(config.OPTIONS.memory_map.value, None) - self.assertEqual(config.OPTIONS.bracket.value, False) - self.assertEqual(config.OPTIONS.use_loader.value, False) - self.assertEqual(config.OPTIONS.autorun.value, False) - self.assertEqual(config.OPTIONS.output_file_type.value, 'bin') - self.assertEqual(config.OPTIONS.include_path.value, '') - self.assertEqual(config.OPTIONS.memoryCheck.value, False) - self.assertEqual(config.OPTIONS.strictBool.value, False) - self.assertEqual(config.OPTIONS.arrayCheck.value, False) - self.assertEqual(config.OPTIONS.enableBreak.value, False) - self.assertEqual(config.OPTIONS.emitBackend.value, False) - self.assertEqual(config.OPTIONS.architecture.value, None) + self.assertEqual(config.OPTIONS.Debug, 0) + self.assertEqual(config.OPTIONS.stdin, sys.stdin) + self.assertEqual(config.OPTIONS.stdout, sys.stdout) + self.assertEqual(config.OPTIONS.stderr, sys.stderr) + self.assertEqual(config.OPTIONS.optimization, global_.DEFAULT_OPTIMIZATION_LEVEL) + self.assertEqual(config.OPTIONS.case_insensitive, False) + self.assertEqual(config.OPTIONS.array_base, 0) + self.assertEqual(config.OPTIONS.byref, False) + self.assertEqual(config.OPTIONS.max_syntax_errors, global_.DEFAULT_MAX_SYNTAX_ERRORS) + self.assertEqual(config.OPTIONS.string_base, 0) + self.assertIsNone(config.OPTIONS.memory_map) + self.assertEqual(config.OPTIONS.bracket, False) + self.assertEqual(config.OPTIONS.use_loader, False) + self.assertEqual(config.OPTIONS.autorun, False) + self.assertEqual(config.OPTIONS.output_file_type, 'bin') + self.assertEqual(config.OPTIONS.include_path, '') + self.assertEqual(config.OPTIONS.memoryCheck, False) + self.assertEqual(config.OPTIONS.strictBool, False) + self.assertEqual(config.OPTIONS.arrayCheck, False) + self.assertEqual(config.OPTIONS.enableBreak, False) + self.assertEqual(config.OPTIONS.emitBackend, False) + self.assertIsNone(config.OPTIONS.architecture) # private options that cannot be accessed with #pragma - self.assertEqual(config.OPTIONS.option('__DEFINES').value, {}) - self.assertEqual(config.OPTIONS.explicit.value, False) - self.assertEqual(config.OPTIONS.Sinclair.value, False) - self.assertEqual(config.OPTIONS.strict.value, False) + self.assertEqual(config.OPTIONS['__DEFINES'].value, {}) + self.assertEqual(config.OPTIONS.explicit, False) + self.assertEqual(config.OPTIONS.Sinclair, False) + self.assertEqual(config.OPTIONS.strict, False) def test_initted_values(self): config.init() - self.assertEqual(sorted(config.OPTIONS.options.keys()), ['Debug', - 'Sinclair', - 'StdErrFileName', - '__DEFINES', - 'architecture', - 'arrayCheck', - 'array_base', - 'autorun', - 'bracket', - 'byref', - 'case_insensitive', - 'emitBackend', - 'enableBreak', - 'explicit', - 'include_path', - 'inputFileName', - 'max_syntax_errors', - 'memoryCheck', - 'memory_map', - 'optimization', - 'outputFileName', - 'output_file_type', - 'stderr', - 'stdin', - 'stdout', - 'strict', - 'strictBool', - 'string_base', - 'use_loader', - 'zxnext']) + self.assertEqual(sorted(config.OPTIONS._options.keys()), [ + 'Debug', + 'Sinclair', + 'StdErrFileName', + '__DEFINES', + 'architecture', + 'arrayCheck', + 'array_base', + 'autorun', + 'bracket', + 'byref', + 'case_insensitive', + 'emitBackend', + 'enableBreak', + 'explicit', + 'include_path', + 'inputFileName', + 'max_syntax_errors', + 'memoryCheck', + 'memory_map', + 'optimization', + 'outputFileName', + 'output_file_type', + 'stderr', + 'stdin', + 'stdout', + 'strict', + 'strictBool', + 'string_base', + 'use_loader', + 'zxnext' + ]) diff --git a/tests/api/test_symbolTable.py b/tests/api/test_symbolTable.py index f38ec1424..5d2948c84 100644 --- a/tests/api/test_symbolTable.py +++ b/tests/api/test_symbolTable.py @@ -28,15 +28,15 @@ def setUp(self): def test__init__(self): """ Tests symbol table initialization """ - OPTIONS.optimization.push() - OPTIONS.optimization.value = 0 + OPTIONS['optimization'].push() + OPTIONS.optimization = 0 self.assertEqual(len(self.s.types), len(TYPE.types)) for type_ in self.s.types: self.assertTrue(type_.is_basic) self.assertIsInstance(type_, symbols.BASICTYPE) self.assertEqual(self.s.current_scope, self.s.global_scope) - OPTIONS.optimization.pop() + OPTIONS['optimization'].pop() def test_is_declared(self): # Checks variable 'a' is not declared yet @@ -180,12 +180,12 @@ def btyperef(self, type_): return symbols.TYPEREF(symbols.BASICTYPE(type_), 0) def clearOutput(self): - OPTIONS.remove_option('stderr') + del OPTIONS.stderr OPTIONS.add_option('stderr', default_value=StringIO()) @property def OUTPUT(self): - return OPTIONS.stderr.value.getvalue() + return OPTIONS.stderr.getvalue() if __name__ == '__main__': diff --git a/tests/cmdline/test_zxb.py b/tests/cmdline/test_zxb.py index 6d2d77f90..8465fdae5 100644 --- a/tests/cmdline/test_zxb.py +++ b/tests/cmdline/test_zxb.py @@ -48,4 +48,4 @@ def test_org_allows_0xnnnn_format(file_bas, file_bin): """ with EnsureRemoveFile(file_bin): zxb.main(['--parse-only', '--org', '0xC000', file_bas, '-o', file_bin]) - assert zxb.OPTIONS.org.value == 0xC000, 'Should set ORG to 0xC000' + assert zxb.OPTIONS.org == 0xC000, 'Should set ORG to 0xC000' diff --git a/tests/symbols/test_symbolARRAYACCESS.py b/tests/symbols/test_symbolARRAYACCESS.py index a991f3a8a..a8bdef490 100644 --- a/tests/symbols/test_symbolARRAYACCESS.py +++ b/tests/symbols/test_symbolARRAYACCESS.py @@ -28,13 +28,13 @@ def setUp(self): symbols.ARGUMENT(symbols.NUMBER(3, 1, type_=Type.uinteger), 1)) gl.SYMBOL_TABLE = SymbolTable() # Clears stderr and prepares for capturing it - config.OPTIONS.remove_option('stderr') + del config.OPTIONS.stderr config.OPTIONS.add_option('stderr', None, StringIO()) config.OPTIONS.add_option_if_not_defined('explicit', None, False) @property def OUTPUT(self): - return config.OPTIONS.stderr.value.getvalue() + return config.OPTIONS.stderr.getvalue() def test__init__(self): aa = symbols.ARRAYACCESS(self.arr, self.arg, 2) diff --git a/tests/symbols/test_symbolBINARY.py b/tests/symbols/test_symbolBINARY.py index 6f4081ce9..511b50d98 100644 --- a/tests/symbols/test_symbolBINARY.py +++ b/tests/symbols/test_symbolBINARY.py @@ -17,8 +17,8 @@ def setUp(self): self.r = symbols.NUMBER(3, lineno=2) self.b = symbols.BINARY('PLUS', self.l, self.r, lineno=3) self.st = symbols.STRING("ZXBASIC", lineno=1) - if OPTIONS.has_option('stderr'): - OPTIONS.remove_option('stderr') + if 'stderr' in OPTIONS: + del OPTIONS.stderr OPTIONS.add_option('stderr', type_=None, default_value=StringIO()) def test_left_getter(self): @@ -69,4 +69,4 @@ def test_make_node_PLUS_STR2(self): @property def OUTPUT(self): - return OPTIONS.stderr.value.getvalue() + return OPTIONS.stderr.getvalue() diff --git a/tests/symbols/test_symbolBOUND.py b/tests/symbols/test_symbolBOUND.py index 219acaabb..1751cf19c 100644 --- a/tests/symbols/test_symbolBOUND.py +++ b/tests/symbols/test_symbolBOUND.py @@ -55,12 +55,12 @@ def test__repr__(self): self.assertEqual(b.__repr__(), b.token + '(1 TO 3)') def clearOutput(self): - OPTIONS.remove_option('stderr') + del OPTIONS.stderr OPTIONS.add_option('stderr', default_value=StringIO()) @property def stderr(self): - return OPTIONS.stderr.value.getvalue() + return OPTIONS.stderr.getvalue() if __name__ == '__main__': diff --git a/tests/symbols/test_symbolTYPECAST.py b/tests/symbols/test_symbolTYPECAST.py index d0ac73b2d..6a922ce74 100644 --- a/tests/symbols/test_symbolTYPECAST.py +++ b/tests/symbols/test_symbolTYPECAST.py @@ -19,8 +19,8 @@ def setUp(self): zxbpp.init() self.t = TYPECAST(Type.float_, NUMBER(3, lineno=1), lineno=2) - if OPTIONS.has_option('stderr'): - OPTIONS.remove_option('stderr') + if 'stderr' in OPTIONS: + del OPTIONS.stderr OPTIONS.add_option('stderr', type_=None, default_value=StringIO()) def test_operand(self): @@ -84,4 +84,4 @@ def test_make_node_loose_byte4(self): @property def OUTPUT(self): - return OPTIONS.stderr.value.getvalue() + return OPTIONS.stderr.getvalue()