import random from xml.etree import ElementTree as ET from constants import GAZ_VAR_TAG, GAZ_ARG_TAG class Variable: def __init__(self, name: str, type: str, qualifier: str, value: any = None): self.name = name self.type = type self.value = value self.qualifier = qualifier self.xml = self._build_xml() def _build_xml(self): args = [ ('name', self.name), ('type', self.type), ('mut', self.qualifier), ] return build_xml_element(args, name=GAZ_VAR_TAG) class Argument: def __init__(self, name: str, type: str): self.name = name self.type = type self.xml = self._build_xml() def __str__(self): return self.type + " " + self.name def _build_xml(self): args = [ ('name', self.name), ('type', self.type), ] return build_xml_element(args, name=GAZ_ARG_TAG) class Routine: def __init__(self, name: str, type: str, return_type: str, args: list[Argument], xml: ET.Element = None): self.name = name self.type = type self.return_type = return_type self.arguments = args self.xml = xml self.xml = xml class Scope: def __init__(self, enclosing_scope, child_scope=None, associated_xml: ET.Element = None): self.symbols = {} self.enclosing_scope = enclosing_scope self.child_scope = child_scope self.xml = associated_xml def resolve(self, name) -> ET.Element or None: if name in self.symbols: return self.symbols[name] else: return None def append(self, name, item: Variable or Argument or Routine): self.symbols[name] = item def append_element(self, name, value: ET.Element): self.symbols[name] = value def set(self, name, value: ET.Element): self.symbols[name] = value def get_all_defined_mutable_vars(self) -> list[Variable]: if self.enclosing_scope is None: return self._get_mutable_vars() else: return self.enclosing_scope.get_all_defined_mutable_vars() + self._get_mutable_vars() def _get_mutable_vars(self) -> list[Variable]: mutable_vars = [] for name, var in self.symbols.items(): if not isinstance(var, Variable): continue if var.qualifier != 'const': mutable_vars.append(self.symbols[name]) return mutable_vars def get_top_scope(self): if self.enclosing_scope is None: return self else: return self.enclosing_scope.get_top_scope() def build_xml_element(*keys, name): elem = ET.Element(name) for key in list(keys)[0]: # TODO refactor elem.set(key[0], key[1]) return elem def get_numberlines(settings_section: str, subsettings: list[str], excluded_values, settings): assert len(subsettings) == len(excluded_values) number_line = 0 cutoffs = [] cutoff = 0 options = {} option = 0 valid_settings = [] for key, value in settings[settings_section].items(): if key in subsettings and key not in excluded_values: # this check needs to be done recursively if isinstance(value, int): t = { key: value } valid_settings.append(t) elif isinstance(value, dict): valid_settings.append(value) else: raise TypeError("invalid setting type. Found " + str(value) + " instead of expected int or dict") for v in range(len(valid_settings)): for i in excluded_values: for j in i: if j in valid_settings[v]: valid_settings[v].pop(j) for v in valid_settings: if isinstance(v, dict): for key, value in v.items(): number_line += value cutoffs.append(cutoff + value) cutoff += value options[option] = key option += 1 elif isinstance(v, int): number_line += v cutoffs.append(cutoff + v) cutoff += v options[option] = v option += 1 else: raise TypeError("invalid setting type. Found " + str(v) + " instead of expected int") return options, cutoffs, number_line def filter_options(exclude, include, options, opts): if include is not None and exclude is not None: raise ValueError("Cannot specify both include and exclude") elif include is not None and include in opts: for i in range(len(opts)): if opts[i] in include: continue else: options.pop(opts.index(opts[i])) elif exclude is not None and exclude in opts: options.pop(opts.index(exclude)) elif include is None and exclude is None: pass else: raise ValueError("Invalid include/exclude options " + str(include) + " " + str(exclude)) def _choose_option(cutoffs, number_line, options): op = "" a = random.randint(0, number_line - 1) i = 0 for i in range(len(cutoffs) - 1): if i == 0: if a < cutoffs[i]: op = options[i] break if cutoffs[i] <= a < cutoffs[i + 1]: op = options[i] break return op