def FnExpression(self, node): expr_result, expr_jump_stmt = self.accept(node.expr) arguments_result, arguments_jump_stmt = self.accept(node.arguments) if all(argument.__class__ is ast.Const for argument in node.arguments.childs): if expr_result.__class__ is Function: node.result = expr_result.run(*arguments_result) else: if not node.initialized: node.body = expr_result.body.clone() func_scope = SymbolTable(expr_result, self.global_scope) self.push_scope(func_scope) for i, parameter in enumerate( expr_result.parameterGroup.childs): func_scope.define(parameter.name, parameter.type, parameter.linespan[0], arguments_result[i], None) node.initialized = True body_result, body_jump_stmt = self.accept(node.body) self.pop_scope() node.result = body_result if self.get_scope().is_pure_function( expr_result.name) and node.result is not None: self.replace(node, ast.Const(node.result, node.linespan)) else: self.set_used(expr_result.name) return node.result, None else: self.set_used(expr_result.name) return None, None
def VaExpression(self, node): scope = self.get_scope() node.result = scope.get(node.name) if self.is_constant(node.name): self.replace(node, ast.Const(node.result, node.linespan)) else: self.set_used(node.name) return node.result, None
def UnaryOp(self, node): expr_result, expr_jump_stmt = self.accept(node.expr) if expr_result is None: node.result = None return node.result, None if node.op == '+': node.result = expr_result elif node.op == '-': node.result = -expr_result else: raise ValueError if node.expr.__class__ is ast.Const: self.replace(node, ast.Const(node.result, node.expr.linespan)) return node.result, None
def p_const_expression_4(self, p): '''const_expression : STRING''' p[0] = ast.Const(p[1][1:-1], linespan=p.linespan(1))
def BinaryOp(self, node): prev_freeze_constant_folding = self.freeze_constant_folding if node.op == '++' or node.op == '--': self.freeze_constant_folding = True left_result, left_jump_stmt = self.accept(node.left) if node.op == '++' or node.op == '--': self.freeze_constant_folding = prev_freeze_constant_folding right_result, right_jump_stmt = self.accept(node.right) if (left_result is None) or (right_result is None): node.result = None return node.result, None if node.op == '==': node.result = left_result == right_result elif node.op == '!=': node.result = left_result != right_result elif node.op == '<': node.result = left_result < right_result elif node.op == '>': node.result = left_result > right_result elif node.op == '<=': node.result = left_result <= right_result elif node.op == '>=': node.result = left_result >= right_result elif node.op == '+': node.result = left_result + right_result elif node.op == '-': node.result = left_result - right_result elif node.op == '&&': node.result = left_result and right_result elif node.op == '||': node.result = left_result or right_result elif node.op == '*': node.result = left_result * right_result elif node.op == '/': node.result = left_result / right_result elif node.op == '%': node.result = left_result % right_result elif node.op == '++': node.result = left_result + right_result elif node.op == '--': node.result = left_result - right_result else: raise ValueError if node.result is True: node.result = 1 elif node.result is False: node.result = 0 if node.op == '++' or node.op == '--': scope = self.get_scope() if node.left.__class__ is ast.VaExpression: scope.add(node.left.name, node.linespan[0], node.result, node) self.set_constant(node.left.name, self.is_constant(node.left.name)) elif (node.left.__class__ is ast.Const): self.replace(node, ast.Const(node.result, node.linespan)) elif node.left.__class__ is ast.Const and node.right.__class__ is ast.Const: linespan = (node.left.linespan[0], node.right.linespan[1]) self.replace(node, ast.Const(node.result, linespan)) return node.result, None
def p_const_expression_3(self, p): '''const_expression : CHARACTER''' p[0] = ast.Const(p[1][1:-1], linespan=p.linespan(1))
def p_const_expression_2(self, p): '''const_expression : NUMBER_INT''' p[0] = ast.Const(int(p[1]), linespan=p.linespan(1))
def p_const_expression_1(self, p): '''const_expression : NUMBER_FLOAT''' p[0] = ast.Const(float(p[1]), linespan=p.linespan(1))
def p_unary_expression_4(self, p): '''unary_expression : DOUBLE_PLUS function_expression | DOUBLE_MINUS function_expression''' linespan = (p.linespan(1)[0], p[2].linespan[1]) p[0] = ast.BinaryOp(p[1], p[2], ast.Const(1), linespan=linespan)
def p_unary_expression_3(self, p): '''unary_expression : function_expression DOUBLE_PLUS | function_expression DOUBLE_MINUS''' linespan = (p[1].linespan[0], p.linespan(2)[1]) p[0] = ast.BinaryOp(p[2], p[1], ast.Const(1), linespan=linespan)