def __init__(self, module_ast, used_variables): ASTModifier.__init__(self, modify_expressions=False) self.dummy_assign = None # dummy assignment statement, eg. $i = $i (using some variable $i that it finds in the script) self.pass_num = 1 self.traverse(module_ast) self.pass_num = 2 self.traverse(module_ast)
def modifyIfStmt(self, node): statements = ASTModifier.modifyIfStmt(self, node) if len(statements) == 1: node = statements[0] condition_stmts_tuples = [] for (i, (condition, stmts)) in enumerate(node.condition_stmts_tuples): try: value = None if condition: value = evaluate_expression(condition) except ParseException: pass if value is True: # since the condition is always true it can be replaced with None, # but don't do this for if 1=1 statements since they are used as a workaround for the Kontakt 2 parser buffer overflow if not self.is1equals1(condition): condition = None if len(stmts) > 0: condition_stmts_tuples.append((condition, stmts)) break if not (value is False or len(stmts) == 0): condition_stmts_tuples.append((condition, stmts)) # if there's just an else statement left, return its statement list if len(condition_stmts_tuples) == 1 and condition_stmts_tuples[0][0] is None: return condition_stmts_tuples[0][1] elif len(condition_stmts_tuples) == 0: return [] else: node.condition_stmts_tuples = condition_stmts_tuples return [node] else: return flatten([self.modify(stmt) for stmt in statements])
def modifyIfStmt(self, node): statements = ASTModifier.modifyIfStmt(self, node) if len(statements) == 1: node = statements[0] condition_stmts_tuples = [] for (i, (condition, stmts)) in enumerate(node.condition_stmts_tuples): try: value = None if condition: value = evaluate_expression(condition) except ParseException: pass if value is True: # since the condition is always true it can be replaced with None, # but don't do this for if 1=1 statements since they are used as a workaround for the Kontakt 2 parser buffer overflow if not self.is1equals1(condition): condition = None if len(stmts) > 0: condition_stmts_tuples.append((condition, stmts)) break if not (value is False or len(stmts) == 0): condition_stmts_tuples.append((condition, stmts)) # if there's just an else statement left, return its statement list if len(condition_stmts_tuples ) == 1 and condition_stmts_tuples[0][0] is None: return condition_stmts_tuples[0][1] elif len(condition_stmts_tuples) == 0: return [] else: node.condition_stmts_tuples = condition_stmts_tuples return [node] else: return flatten([self.modify(stmt) for stmt in statements])
def modifyIfStmt(self, node): if self.pass_num == 2: node = ASTModifier.modifyIfStmt(self, node)[0] node.condition_stmts_tuples = [ (condition, self.fixStatementList(stmts)) for (condition, stmts) in node.condition_stmts_tuples ] return [node]
def modifySelectStmt(self, node): if self.pass_num == 2: node = ASTModifier.modifySelectStmt(self, node)[0] node.range_stmts_tuples = [ (range, self.fixStatementList(statements)) for (range, statements) in node.range_stmts_tuples ] return [node]
def modifyVarRef(self, node): node = ASTModifier.modifyVarRef(self, node) if self.replace_constants and not mark_constant_re.match( node.identifier.identifier ): # MARK_%d constants are included in the symbol table in order to be possible to use on declaration lines, don't replace them with their values return self.evaluate_expression_or_same(node) else: return node
def modifyDeclareStmt(self, node): ''' only keep used variables ''' statements = ASTModifier.modifyDeclareStmt(self, node) if len(statements) == 1: node = statements[0] is_ui_variable = node.modifiers is not None and any([m.lower().startswith('ui_') for m in node.modifiers]) if not str(node.variable).lower() in self.used_variables and not is_ui_variable: return [] else: return [node] else: return flatten([self.modify(stmt) for stmt in statements])
def modifyWhileStmt(self, node): statements = ASTModifier.modifyWhileStmt(self, node) if len(statements) == 1: node = statements[0] try: value = evaluate_expression(node.condition) if value is False: return [] except ParseException: pass return [node] else: return flatten([self.modify(stmt) for stmt in statements])
def modifyDeclareStmt(self, node): ''' only keep used variables ''' statements = ASTModifier.modifyDeclareStmt(self, node) if len(statements) == 1: node = statements[0] is_ui_variable = node.modifiers is not None and any( [m.lower().startswith('ui_') for m in node.modifiers]) if not str(node.variable).lower( ) in self.used_variables and not is_ui_variable: return [] else: return [node] else: return flatten([self.modify(stmt) for stmt in statements])
def modifyBinOp(self, node): node = ASTModifier.modifyBinOp(self, node) node.left = self.evaluate_expression_or_same(node.left) node.right = self.evaluate_expression_or_same(node.right) if node.op == '*': if isinstance(node.left, (Integer, Real)): if node.left.value == 0: return node.left elif node.left.value == 1: return node.right if isinstance(node.right, (Integer, Real)): if node.right.value == 0: return node.right elif node.right.value == 1: return node.left if node.op == '+': if isinstance(node.left, (Integer, Real)): if node.left.value == 0: return node.right if isinstance(node.right, (Integer, Real)): if node.right.value == 0: return node.left if node.op == 'or': if isinstance(node.left, Boolean): if node.left.value: return node.left else: return node.right elif isinstance(node.right, Boolean): if node.right.value: return node.right else: return node.left elif node.op == 'and': if isinstance(node.left, Boolean): if node.left.value: return node.right else: return node.left elif isinstance(node.right, Boolean): if node.right.value: return node.left else: return node.right return self.evaluate_expression_or_same(node)
def modifySelectStmt(self, node): statements = ASTModifier.modifySelectStmt(self, node) if len(statements) == 1: node = statements[0] try: value = evaluate_expression(node.expression) if value is None: return [node] for ((start, stop), stmts) in node.range_stmts_tuples: start = evaluate_expression(start) stop = evaluate_expression(stop) if (stop is not None and start <= value <= stop) or (start == value): return stmts except ParseException: pass return [node] else: return flatten([self.modify(stmt) for stmt in statements])
def __init__(self, module_ast): ASTModifier.__init__(self) self.traverse(module_ast)
def modifyUnaryOp(self, node): node = ASTModifier.modifyUnaryOp(self, node) node.right = self.evaluate_expression_or_same(node.right) return self.evaluate_expression_or_same(node)
def modifyDeclareStmt(self, node): ASTModifier.modifyDeclareStmt(self, node) if 'const' in node.modifiers and self.replace_constants: return [] else: return [node]
def __init__(self, module_ast, used_functions): ASTModifier.__init__(self, modify_expressions=False) self.used_functions = used_functions self.traverse(module_ast)
def modifyVarRef(self, node): node = ASTModifier.modifyVarRef(self, node) if self.replace_constants and not mark_constant_re.match(node.identifier.identifier): # MARK_%d constants are included in the symbol table in order to be possible to use on declaration lines, don't replace them with their values return self.evaluate_expression_or_same(node) else: return node
def __init__(self, module_ast, replace_constants=True): ASTModifier.__init__(self) self.replace_constants = replace_constants self.traverse(module_ast)
def modifyIfStmt(self, node): if self.pass_num == 2: node = ASTModifier.modifyIfStmt(self, node)[0] node.condition_stmts_tuples = [(condition, self.fixStatementList(stmts)) for (condition, stmts) in node.condition_stmts_tuples] return [node]
def __init__(self, module_ast, used_variables): ASTModifier.__init__(self) self.used_variables = used_variables self.traverse(module_ast)
def modifyWhileStmt(self, node): if self.pass_num == 2: node = ASTModifier.modifyWhileStmt(self, node)[0] node.statements = self.fixStatementList(node.statements) return [node]
def modifySelectStmt(self, node): if self.pass_num == 2: node = ASTModifier.modifySelectStmt(self, node)[0] node.range_stmts_tuples = [(range, self.fixStatementList(statements)) for (range, statements) in node.range_stmts_tuples] return [node]
def modifyFunctionDef(self, node): if self.pass_num == 2: node = ASTModifier.modifyFunctionDef(self, node) node.lines = self.fixStatementList(node.lines) return node
def modifyDeclareStmt(self, node): ASTModifier.modifyDeclareStmt(self, node) return [node]