def reduce_expressions(program: Node) -> Node: """Reduce expressions in a YOLOL program.""" assert program.kind == 'program' logger.debug('reducing expressions') clone = program.clone() while _propagate_constants(clone) or _fold_constants(clone): pass return clone
def mangle_names(program: Node, imported: Sequence[str], exported: Sequence[str]) -> Node: """Mangle names in a YOLOL program.""" assert program.kind == 'program' logger.debug('mangling names') clone = program.clone() pool = Pool([*imported, *exported]) variables = clone.find(lambda node: node.kind == 'variable') for var in variables: var.value = pool.replace(var.value) # type: ignore return clone
def resolve_aliases(env: Env, program: Node) -> Tuple[Node, Set[str], Set[str]]: """Resolve aliases to their targets in a YOLOL program.""" assert program.kind == 'program' logger.debug('resolving aliases') clone = program.clone() imported = set() exported = set() for alias, target in env.imports.items(): variables = clone.find( lambda node: node.kind == 'variable' and node.value == alias) for var in variables: var.value = target imported.add(target) for alias, target in env.exports.items(): var, index = env.var(alias) if type(var) == Number: num_prefix = '{}{}'.format(Number.PREFIX, index) num_variables = clone.find(lambda node: node.kind == 'variable' and node.value.startswith(num_prefix)) for var in num_variables: var.value = var.value.replace(num_prefix, target) # type: ignore exported.add(var.value) elif type(var) == Vector: vec_prefix = '{}{}'.format(Vector.PREFIX, index) vec_variables = clone.find(lambda node: node.kind == 'variable' and node.value.startswith(vec_prefix)) for var in vec_variables: var.value = var.value.replace(vec_prefix, target) # type: ignore exported.add(var.value) elif type(var) == Matrix: mat_prefix = '{}{}'.format(Matrix.PREFIX, index) mat_variables = clone.find(lambda node: node.kind == 'variable' and node.value.startswith(mat_prefix)) for var in mat_variables: var.value = var.value.replace(mat_prefix, target) # type: ignore exported.add(var.value) else: raise AssertionError('unexpected variable type: {}'.format( type(var))) return clone, imported, exported
def _remove_dead(program: Node, alive: Set[str]) -> Node: """Remove dead assignments.""" assert program.kind == 'program' logger.debug('removing dead assignments') clone = program.clone() assignments = clone.find(lambda node: node.kind == 'assignment') for asn in assignments: if asn.children[0].value not in alive: assert asn.parent is not None asn.parent.remove_child(asn) # type: ignore lines = clone.find(lambda node: node.kind == 'line') for line in lines: if len(line.children) == 0: assert line.parent is not None line.parent.remove_child(line) # type: ignore return clone