Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions api/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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_)


Expand Down
4 changes: 2 additions & 2 deletions api/debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__():
Expand Down
14 changes: 7 additions & 7 deletions api/errmsg.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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
Expand All @@ -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

Expand Down Expand Up @@ -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_))


Expand Down
2 changes: 1 addition & 1 deletion api/identityset.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion api/optimize.py
Original file line number Diff line number Diff line change
Expand Up @@ -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':
Expand Down
122 changes: 78 additions & 44 deletions api/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -102,63 +118,81 @@ 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:
type_ = type(default_value)
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
8 changes: 4 additions & 4 deletions api/symboltable.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down Expand Up @@ -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

Expand Down
Loading