def _parse_dowhile(self, doWhilestatement, node): node_startDoWhile = self._new_node(NodeType.STARTLOOP, doWhilestatement['src']) node_condition = self._new_node(NodeType.IFLOOP, doWhilestatement['src']) if self.is_compact_ast: node_condition.add_unparsed_expression( doWhilestatement['condition']) statement = self._parse_statement(doWhilestatement['body'], node_condition) else: children = doWhilestatement[self.get_children('children')] # same order in the AST as while expression = children[0] node_condition.add_unparsed_expression(expression) statement = self._parse_statement(children[1], node_condition) node_endDoWhile = self._new_node(NodeType.ENDLOOP, doWhilestatement['src']) link_nodes(node, node_startDoWhile) # empty block, loop from the start to the condition if not node_condition.sons: link_nodes(node_startDoWhile, node_condition) else: link_nodes(node_startDoWhile, node_condition.sons[0]) link_nodes(statement, node_condition) link_nodes(node_condition, node_endDoWhile) return node_endDoWhile
def _parse_statement(self, statement, node): name = statement['name'] if name == 'PlaceholderStatement': placeholder_node = self._new_node(NodeType.PLACEHOLDER) link_nodes(node, placeholder_node) return placeholder_node return super(ModifierSolc, self)._parse_statement(statement, node)
def _parse_if(self, ifStatement, node): # IfStatement = 'if' '(' Expression ')' Statement ( 'else' Statement )? falseStatement = None if self.is_compact_ast: condition = ifStatement['condition'] # Note: check if the expression could be directly # parsed here condition_node = self._new_node(NodeType.IF, ifStatement['src']) condition_node.add_unparsed_expression(condition) link_nodes(node, condition_node) trueStatement = self._parse_statement(ifStatement['trueBody'], condition_node) if ifStatement['falseBody']: falseStatement = self._parse_statement(ifStatement['falseBody'], condition_node) else: children = ifStatement[self.get_children('children')] condition = children[0] # Note: check if the expression could be directly # parsed here condition_node = self._new_node(NodeType.IF, ifStatement['src']) condition_node.add_unparsed_expression(condition) link_nodes(node, condition_node) trueStatement = self._parse_statement(children[1], condition_node) if len(children) == 3: falseStatement = self._parse_statement(children[2], condition_node) endIf_node = self._new_node(NodeType.ENDIF, ifStatement['src']) link_nodes(trueStatement, endIf_node) if falseStatement: link_nodes(falseStatement, endIf_node) else: link_nodes(condition_node, endIf_node) return endIf_node
def _parse_statement(self, statement: Dict, node: NodeSolc) -> NodeSolc: name = statement[self.get_key()] if name == "PlaceholderStatement": placeholder_node = self._new_node(NodeType.PLACEHOLDER, statement["src"]) link_nodes(node.underlying_node, placeholder_node.underlying_node) return placeholder_node return super(ModifierSolc, self)._parse_statement(statement, node)
def _parse_statement( self, statement: Dict, node: NodeSolc, scope: Union[Scope, "Function"] ) -> NodeSolc: name = statement[self.get_key()] if name == "PlaceholderStatement": placeholder_node = self._new_node_id(NodeType.PLACEHOLDER, statement["src"], scope, statement["id"]) link_nodes(node.underlying_node, placeholder_node.underlying_node) return placeholder_node return super()._parse_statement(statement, node, scope)
def _parse_variable_definition_init_tuple(self, statement, index, node): local_var = LocalVariableInitFromTupleSolc(statement, index) #local_var = LocalVariableSolc(statement['children'][0], statement['children'][1::]) local_var.set_function(self) local_var.set_offset(statement['src']) self._variables[local_var.name] = local_var # local_var.analyze(self) new_node = self._new_node(NodeType.VARIABLE) new_node.add_variable_declaration(local_var) link_nodes(node, new_node) return new_node
def _parse_variable_definition_init_tuple(self, statement, index, node): local_var = LocalVariableInitFromTupleSolc(statement, index) #local_var = LocalVariableSolc(statement[self.get_children('children')][0], statement[self.get_children('children')][1::]) local_var.set_function(self) local_var.set_offset(statement['src'], self.contract.slither) self._add_local_variable(local_var) # local_var.analyze(self) new_node = self._new_node(NodeType.VARIABLE, statement['src']) new_node.add_variable_declaration(local_var) link_nodes(node, new_node) return new_node
def _parse_if(self, ifStatement, node): # IfStatement = 'if' '(' Expression ')' Statement ( 'else' Statement )? children = ifStatement['children'] condition_node = self._new_node(NodeType.IF) #condition = parse_expression(children[0], self) condition = children[0] condition_node.add_unparsed_expression(condition) link_nodes(node, condition_node) trueStatement = self._parse_statement(children[1], condition_node) endIf_node = self._new_node(NodeType.ENDIF) link_nodes(trueStatement, endIf_node) if len(children) == 3: falseStatement = self._parse_statement(children[2], condition_node) link_nodes(falseStatement, endIf_node) else: link_nodes(condition_node, endIf_node) return endIf_node
def split_ternary_node(self, node, condition, true_expr, false_expr): condition_node = self._new_node(NodeType.IF) condition_node.add_expression(condition) condition_node.analyze_expressions(self) true_node = self._new_node(node.type) true_node.add_expression(true_expr) true_node.analyze_expressions(self) false_node = self._new_node(node.type) false_node.add_expression(false_expr) false_node.analyze_expressions(self) endif_node = self._new_node(NodeType.ENDIF) for father in node.fathers: father.remove_son(node) father.add_son(condition_node) condition_node.add_father(father) for son in node.sons: son.remove_father(node) son.add_father(endif_node) endif_node.add_son(son) link_nodes(condition_node, true_node) link_nodes(condition_node, false_node) link_nodes(true_node, endif_node) link_nodes(false_node, endif_node) self._nodes = [n for n in self._nodes if n.node_id != node.node_id]
def _parse_while(self, whileStatement, node): # WhileStatement = 'while' '(' Expression ')' Statement node_startWhile = self._new_node(NodeType.STARTLOOP, whileStatement['src']) node_condition = self._new_node(NodeType.IFLOOP, whileStatement['src']) if self.is_compact_ast: node_condition.add_unparsed_expression(whileStatement['condition']) statement = self._parse_statement(whileStatement['body'], node_condition) else: children = whileStatement[self.get_children('children')] expression = children[0] node_condition.add_unparsed_expression(expression) statement = self._parse_statement(children[1], node_condition) node_endWhile = self._new_node(NodeType.ENDLOOP, whileStatement['src']) link_nodes(node, node_startWhile) link_nodes(node_startWhile, node_condition) link_nodes(statement, node_condition) link_nodes(node_condition, node_endWhile) return node_endWhile
def _parse_while(self, whileStatement, node): # WhileStatement = 'while' '(' Expression ')' Statement node_startWhile = self._new_node(NodeType.STARTLOOP, whileStatement['src']) if self.is_compact_ast: node_condition = self._new_node(NodeType.IFLOOP, whileStatement['condition']['src']) node_condition.add_unparsed_expression(whileStatement['condition']) statement = self._parse_statement(whileStatement['body'], node_condition) # print('yufeng hack while....', whileStatement['body']) stmt_number = 0 for stmt in whileStatement['body']['statements']: stmt_number = stmt_number + self.count_stmts(stmt) # print('nodeType:', stmt['nodeType'], stmt['expression'], ('kind' in stmt['expression'])) print('find out a while-loop---: ', stmt_number) else: children = whileStatement[self.get_children('children')] expression = children[0] node_condition = self._new_node(NodeType.IFLOOP, expression['src']) node_condition.add_unparsed_expression(expression) statement = self._parse_statement(children[1], node_condition) node_endWhile = self._new_node(NodeType.ENDLOOP, whileStatement['src']) link_nodes(node, node_startWhile) link_nodes(node_startWhile, node_condition) link_nodes(statement, node_condition) link_nodes(node_condition, node_endWhile) return node_endWhile
def _parse_try_catch(self, statement, node): externalCall = statement.get('externalCall', None) if externalCall is None: raise ParsingError('Try/Catch not correctly parsed by Slither %s' % statement) new_node = self._new_node(NodeType.TRY, statement['src']) new_node.add_unparsed_expression(externalCall) link_nodes(node, new_node) node = new_node for clause in statement.get('clauses', []): self._parse_catch(clause, node) return node
def _parse_catch(self, statement, node): block = statement.get('block', None) if block is None: raise ParsingError('Catch not correctly parsed by Slither %s' % statement) try_node = self._new_node(NodeType.CATCH, statement['src']) link_nodes(node, try_node) if self.is_compact_ast: params = statement['parameters'] else: params = statement[self.get_children('children')] for param in params.get('parameters', []): assert param[self.get_key()] == 'VariableDeclaration' self._add_param(param) return self._parse_statement(block, try_node)
def _parse_modifier(self, modifier): m = parse_expression(modifier, self) self._expression_modifiers.append(m) for m in ExportValues(m).result(): if isinstance(m, Function): entry_point = self._new_node(NodeType.OTHER_ENTRYPOINT, modifier['src']) node = self._new_node(NodeType.EXPRESSION, modifier['src']) node.add_unparsed_expression(modifier) link_nodes(entry_point, node) self._modifiers.append(ModifierStatements(modifier=m, entry_point=entry_point, nodes=[entry_point, node])) elif isinstance(m, Contract): entry_point = self._new_node(NodeType.OTHER_ENTRYPOINT, modifier['src']) node = self._new_node(NodeType.EXPRESSION, modifier['src']) node.add_unparsed_expression(modifier) link_nodes(entry_point, node) self._explicit_base_constructor_calls.append(ModifierStatements(modifier=m, entry_point=entry_point, nodes=[entry_point, node]))
def split_ternary_node(self, node, condition, true_expr, false_expr): condition_node = self._new_node(NodeType.IF, node.source_mapping) condition_node.add_expression(condition) condition_node.analyze_expressions(self) if node.type == NodeType.VARIABLE: condition_node.add_variable_declaration(node.variable_declaration) true_node = self._new_node(NodeType.EXPRESSION, node.source_mapping) if node.type == NodeType.VARIABLE: assert isinstance(true_expr, AssignmentOperation) #true_expr = true_expr.expression_right elif node.type == NodeType.RETURN: true_node.type = NodeType.RETURN true_node.add_expression(true_expr) true_node.analyze_expressions(self) false_node = self._new_node(NodeType.EXPRESSION, node.source_mapping) if node.type == NodeType.VARIABLE: assert isinstance(false_expr, AssignmentOperation) elif node.type == NodeType.RETURN: false_node.type = NodeType.RETURN #false_expr = false_expr.expression_right false_node.add_expression(false_expr) false_node.analyze_expressions(self) endif_node = self._new_node(NodeType.ENDIF, node.source_mapping) for father in node.fathers: father.remove_son(node) father.add_son(condition_node) condition_node.add_father(father) for son in node.sons: son.remove_father(node) son.add_father(endif_node) endif_node.add_son(son) link_nodes(condition_node, true_node) link_nodes(condition_node, false_node) if not true_node.type in [NodeType.THROW, NodeType.RETURN]: link_nodes(true_node, endif_node) if not false_node.type in [NodeType.THROW, NodeType.RETURN]: link_nodes(false_node, endif_node) self._nodes = [n for n in self._nodes if n.node_id != node.node_id]
def _parse_dowhile(self, doWhilestatement, node): children = doWhilestatement['children'] node_startDoWhile = self._new_node(NodeType.STARTLOOP) # same order in the AST as while node_condition = self._new_node(NodeType.IFLOOP) #expression = parse_expression(children[0], self) expression = children[0] node_condition.add_unparsed_expression(expression) statement = self._parse_statement(children[1], node_condition) node_endDoWhile = self._new_node(NodeType.ENDLOOP) link_nodes(node, node_startDoWhile) link_nodes(node_startDoWhile, node_condition) link_nodes(statement, node_condition) link_nodes(node_condition, node_endDoWhile) return node_endDoWhile
def _parse_while(self, whileStatement, node): # WhileStatement = 'while' '(' Expression ')' Statement children = whileStatement['children'] node_startWhile = self._new_node(NodeType.STARTLOOP) node_condition = self._new_node(NodeType.IFLOOP) #expression = parse_expression(children[0], self) expression = children[0] node_condition.add_unparsed_expression(expression) statement = self._parse_statement(children[1], node_condition) node_endWhile = self._new_node(NodeType.ENDLOOP) link_nodes(node, node_startWhile) link_nodes(node_startWhile, node_condition) link_nodes(statement, node_condition) link_nodes(node_condition, node_endWhile) return node_endWhile
def split_ternary_node(self, node, condition, true_expr, false_expr): condition_node = self._new_node(NodeType.IF, node.source_mapping) condition_node.add_expression(condition) condition_node.analyze_expressions(self) true_node = self._new_node(node.type, node.source_mapping) if node.type == NodeType.VARIABLE: true_node.add_variable_declaration(node.variable_declaration) true_node.add_expression(true_expr) true_node.analyze_expressions(self) false_node = self._new_node(node.type, node.source_mapping) if node.type == NodeType.VARIABLE: false_node.add_variable_declaration(node.variable_declaration) false_node.add_expression(false_expr) false_node.analyze_expressions(self) endif_node = self._new_node(NodeType.ENDIF, node.source_mapping) for father in node.fathers: father.remove_son(node) father.add_son(condition_node) condition_node.add_father(father) for son in node.sons: son.remove_father(node) son.add_father(endif_node) endif_node.add_son(son) link_nodes(condition_node, true_node) link_nodes(condition_node, false_node) if not true_node.type in [NodeType.THROW, NodeType.RETURN]: link_nodes(true_node, endif_node) if not false_node.type in [NodeType.THROW, NodeType.RETURN]: link_nodes(false_node, endif_node) self._nodes = [n for n in self._nodes if n.node_id != node.node_id]
def _parse_variable_definition(self, statement, node): #assert len(statement['children']) == 1 # if there is, parse default value #assert not 'attributes' in statement try: local_var = LocalVariableSolc(statement) #local_var = LocalVariableSolc(statement['children'][0], statement['children'][1::]) local_var.set_function(self) local_var.set_offset(statement['src'], self.contract.slither) self._variables[local_var.name] = local_var #local_var.analyze(self) new_node = self._new_node(NodeType.VARIABLE) new_node.add_variable_declaration(local_var) link_nodes(node, new_node) return new_node except MultipleVariablesDeclaration: # Custom handling of var (a,b) = .. style declaration # We split the variabledeclaration in multiple declarations count = 0 children = statement['children'] child = children[0] while child['name'] == 'VariableDeclaration': count = count +1 child = children[count] assert len(children) == (count + 1) tuple_vars = children[count] variables_declaration = children[0:count] i = 0 new_node = node if tuple_vars['name'] == 'TupleExpression': assert len(tuple_vars['children']) == count for variable in variables_declaration: init = tuple_vars['children'][i] src = variable['src'] i= i+1 # Create a fake statement to be consistent new_statement = {'name':'VariableDefinitionStatement', 'src': src, 'children':[variable, init]} new_node = self._parse_variable_definition(new_statement, new_node) else: # If we have # var (a, b) = f() # we can split in multiple declarations, keep the init value and use LocalVariableSolc # We use LocalVariableInitFromTupleSolc class assert tuple_vars['name'] in ['FunctionCall', 'Conditional'] for variable in variables_declaration: src = variable['src'] i= i+1 # Create a fake statement to be consistent new_statement = {'name':'VariableDefinitionStatement', 'src': src, 'children':[variable, tuple_vars]} new_node = self._parse_variable_definition_init_tuple(new_statement, i, new_node) return new_node
def _parse_for_compact_ast(self, statement, node): body = statement['body'] init_expression = statement['initializationExpression'] condition = statement['condition'] loop_expression = statement['loopExpression'] stmt_number = 0 for stmt in body['statements']: stmt_number = stmt_number + self.count_stmts(stmt) print('find out a for-loop---: ', stmt_number) node_startLoop = self._new_node(NodeType.STARTLOOP, statement['src']) node_endLoop = self._new_node(NodeType.ENDLOOP, statement['src']) if init_expression: node_init_expression = self._parse_statement(init_expression, node) link_nodes(node_init_expression, node_startLoop) else: link_nodes(node, node_startLoop) if condition: node_condition = self._new_node(NodeType.IFLOOP, condition['src']) node_condition.add_unparsed_expression(condition) link_nodes(node_startLoop, node_condition) link_nodes(node_condition, node_endLoop) else: node_condition = node_startLoop node_body = self._parse_statement(body, node_condition) if loop_expression: node_LoopExpression = self._parse_statement(loop_expression, node_body) link_nodes(node_LoopExpression, node_condition) else: link_nodes(node_body, node_condition) if not condition: if not loop_expression: # TODO: fix case where loop has no expression link_nodes(node_startLoop, node_endLoop) else: link_nodes(node_LoopExpression, node_endLoop) return node_endLoop
def _parse_statement(self, statement, node): """ Return: node """ # Statement = IfStatement | WhileStatement | ForStatement | Block | InlineAssemblyStatement | # ( DoWhileStatement | PlaceholderStatement | Continue | Break | Return | # Throw | EmitStatement | SimpleStatement ) ';' # SimpleStatement = VariableDefinition | ExpressionStatement name = statement[self.get_key()] # SimpleStatement = VariableDefinition | ExpressionStatement if name == 'IfStatement': node = self._parse_if(statement, node) elif name == 'WhileStatement': node = self._parse_while(statement, node) elif name == 'ForStatement': node = self._parse_for(statement, node) elif name == 'Block': node = self._parse_block(statement, node) elif name == 'InlineAssembly': break_node = self._new_node(NodeType.ASSEMBLY, statement['src']) self._contains_assembly = True link_nodes(node, break_node) node = break_node elif name == 'DoWhileStatement': node = self._parse_dowhile(statement, node) # For Continue / Break / Return / Throw # The is fixed later elif name == 'Continue': continue_node = self._new_node(NodeType.CONTINUE, statement['src']) link_nodes(node, continue_node) node = continue_node elif name == 'Break': break_node = self._new_node(NodeType.BREAK, statement['src']) link_nodes(node, break_node) node = break_node elif name == 'Return': return_node = self._new_node(NodeType.RETURN, statement['src']) link_nodes(node, return_node) if self.is_compact_ast: if statement['expression']: return_node.add_unparsed_expression( statement['expression']) else: if self.get_children('children') in statement and statement[ self.get_children('children')]: assert len(statement[self.get_children('children')]) == 1 expression = statement[self.get_children('children')][0] return_node.add_unparsed_expression(expression) node = return_node elif name == 'Throw': throw_node = self._new_node(NodeType.THROW, statement['src']) link_nodes(node, throw_node) node = throw_node elif name == 'EmitStatement': #expression = parse_expression(statement[self.get_children('children')][0], self) if self.is_compact_ast: expression = statement['eventCall'] else: expression = statement[self.get_children('children')][0] new_node = self._new_node(NodeType.EXPRESSION, statement['src']) new_node.add_unparsed_expression(expression) link_nodes(node, new_node) node = new_node elif name in [ 'VariableDefinitionStatement', 'VariableDeclarationStatement' ]: node = self._parse_variable_definition(statement, node) elif name == 'ExpressionStatement': #assert len(statement[self.get_children('expression')]) == 1 #assert not 'attributes' in statement #expression = parse_expression(statement[self.get_children('children')][0], self) if self.is_compact_ast: expression = statement[self.get_children('expression')] else: expression = statement[self.get_children('expression')][0] new_node = self._new_node(NodeType.EXPRESSION, statement['src']) new_node.add_unparsed_expression(expression) link_nodes(node, new_node) node = new_node else: logger.error('Statement not parsed %s' % name) exit(-1) return node
def _parse_variable_definition(self, statement, node): #assert len(statement['children']) == 1 # if there is, parse default value #assert not 'attributes' in statement try: local_var = LocalVariableSolc(statement) #local_var = LocalVariableSolc(statement['children'][0], statement['children'][1::]) local_var.set_function(self) local_var.set_offset(statement['src'], self.contract.slither) self._variables[local_var.name] = local_var #local_var.analyze(self) new_node = self._new_node(NodeType.VARIABLE) new_node.add_variable_declaration(local_var) link_nodes(node, new_node) return new_node except MultipleVariablesDeclaration: # Custom handling of var (a,b) = .. style declaration count = 0 children = statement['children'] child = children[0] while child['name'] == 'VariableDeclaration': count = count + 1 child = children[count] assert len(children) == (count + 1) tuple_vars = children[count] variables_declaration = children[0:count] i = 0 new_node = node if tuple_vars['name'] == 'TupleExpression': assert len(tuple_vars['children']) == count for variable in variables_declaration: init = tuple_vars['children'][i] src = variable['src'] i = i + 1 # Create a fake statement to be consistent new_statement = { 'name': 'VariableDefinitionStatement', 'src': src, 'children': [variable, init] } new_node = self._parse_variable_definition( new_statement, new_node) else: # If we have # var (a, b) = f() # we can split in multiple declarations, without init # Then we craft one expression that does not assignment assert tuple_vars['name'] in ['FunctionCall', 'Conditional'] variables = [] for variable in variables_declaration: src = variable['src'] i = i + 1 # Create a fake statement to be consistent new_statement = { 'name': 'VariableDefinitionStatement', 'src': src, 'children': [variable] } variables.append(variable) new_node = self._parse_variable_definition_init_tuple( new_statement, i, new_node) var_identifiers = [] # craft of the expression doing the assignement for v in variables: identifier = { 'name': 'Identifier', 'src': v['src'], 'attributes': { 'value': v['attributes']['name'], 'type': v['attributes']['type'] } } var_identifiers.append(identifier) expression = { 'name': 'Assignment', 'src': statement['src'], 'attributes': { 'operator': '=', 'type': 'tuple()' }, 'children': [{ 'name': 'TupleExpression', 'src': statement['src'], 'children': var_identifiers }, tuple_vars] } node = new_node new_node = self._new_node(NodeType.EXPRESSION) new_node.add_unparsed_expression(expression) link_nodes(node, new_node) return new_node
def _parse_variable_definition(self, statement, node): try: local_var = LocalVariableSolc(statement) local_var.set_function(self) local_var.set_offset(statement['src'], self.contract.slither) self._add_local_variable(local_var) #local_var.analyze(self) new_node = self._new_node(NodeType.VARIABLE, statement['src']) new_node.add_variable_declaration(local_var) link_nodes(node, new_node) return new_node except MultipleVariablesDeclaration: # Custom handling of var (a,b) = .. style declaration if self.is_compact_ast: variables = statement['declarations'] count = len(variables) if statement['initialValue']['nodeType'] == 'TupleExpression': inits = statement['initialValue']['components'] i = 0 new_node = node for variable in variables: init = inits[i] src = variable['src'] i = i + 1 new_statement = { 'nodeType': 'VariableDefinitionStatement', 'src': src, 'declarations': [variable], 'initialValue': init } new_node = self._parse_variable_definition( new_statement, new_node) else: # If we have # var (a, b) = f() # we can split in multiple declarations, without init # Then we craft one expression that does the assignment variables = [] i = 0 new_node = node for variable in statement['declarations']: i = i + 1 if variable: src = variable['src'] # Create a fake statement to be consistent new_statement = { 'nodeType': 'VariableDefinitionStatement', 'src': src, 'declarations': [variable] } variables.append(variable) new_node = self._parse_variable_definition_init_tuple( new_statement, i, new_node) var_identifiers = [] # craft of the expression doing the assignement for v in variables: identifier = { 'nodeType': 'Identifier', 'src': v['src'], 'name': v['name'], 'typeDescriptions': { 'typeString': v['typeDescriptions']['typeString'] } } var_identifiers.append(identifier) tuple_expression = { 'nodeType': 'TupleExpression', 'src': statement['src'], 'components': var_identifiers } expression = { 'nodeType': 'Assignment', 'src': statement['src'], 'operator': '=', 'type': 'tuple()', 'leftHandSide': tuple_expression, 'rightHandSide': statement['initialValue'], 'typeDescriptions': { 'typeString': 'tuple()' } } node = new_node new_node = self._new_node(NodeType.EXPRESSION, statement['src']) new_node.add_unparsed_expression(expression) link_nodes(node, new_node) else: count = 0 children = statement[self.get_children('children')] child = children[0] while child[self.get_key()] == 'VariableDeclaration': count = count + 1 child = children[count] assert len(children) == (count + 1) tuple_vars = children[count] variables_declaration = children[0:count] i = 0 new_node = node if tuple_vars[self.get_key()] == 'TupleExpression': assert len( tuple_vars[self.get_children('children')]) == count for variable in variables_declaration: init = tuple_vars[self.get_children('children')][i] src = variable['src'] i = i + 1 # Create a fake statement to be consistent new_statement = { self.get_key(): 'VariableDefinitionStatement', 'src': src, self.get_children('children'): [variable, init] } new_node = self._parse_variable_definition( new_statement, new_node) else: # If we have # var (a, b) = f() # we can split in multiple declarations, without init # Then we craft one expression that does the assignment assert tuple_vars[self.get_key()] in [ 'FunctionCall', 'Conditional' ] variables = [] for variable in variables_declaration: src = variable['src'] i = i + 1 # Create a fake statement to be consistent new_statement = { self.get_key(): 'VariableDefinitionStatement', 'src': src, self.get_children('children'): [variable] } variables.append(variable) new_node = self._parse_variable_definition_init_tuple( new_statement, i, new_node) var_identifiers = [] # craft of the expression doing the assignement for v in variables: identifier = { self.get_key(): 'Identifier', 'src': v['src'], 'attributes': { 'value': v['attributes'][self.get_key()], 'type': v['attributes']['type'] } } var_identifiers.append(identifier) expression = { self.get_key(): 'Assignment', 'src': statement['src'], 'attributes': { 'operator': '=', 'type': 'tuple()' }, self.get_children('children'): [{ self.get_key(): 'TupleExpression', 'src': statement['src'], self.get_children('children'): var_identifiers }, tuple_vars] } node = new_node new_node = self._new_node(NodeType.EXPRESSION, statement['src']) new_node.add_unparsed_expression(expression) link_nodes(node, new_node) return new_node
def _parse_for(self, statement, node): # ForStatement = 'for' '(' (SimpleStatement)? ';' (Expression)? ';' (ExpressionStatement)? ')' Statement # the handling of loop in the legacy ast is too complex # to integrate the comapct ast # its cleaner to do it separately if self.is_compact_ast: return self._parse_for_compact_ast(statement, node) hasInitExession = True hasCondition = True hasLoopExpression = True # Old solc version do not prevent in the attributes # if the loop has a init value /condition or expression # There is no way to determine that for(a;;) and for(;a;) are different with old solc if 'attributes' in statement: attributes = statement['attributes'] if 'initializationExpression' in statement: if not statement['initializationExpression']: hasInitExession = False elif 'initializationExpression' in attributes: if not attributes['initializationExpression']: hasInitExession = False if 'condition' in statement: if not statement['condition']: hasCondition = False elif 'condition' in attributes: if not attributes['condition']: hasCondition = False if 'loopExpression' in statement: if not statement['loopExpression']: hasLoopExpression = False elif 'loopExpression' in attributes: if not attributes['loopExpression']: hasLoopExpression = False node_startLoop = self._new_node(NodeType.STARTLOOP, statement['src']) node_endLoop = self._new_node(NodeType.ENDLOOP, statement['src']) children = statement[self.get_children('children')] if hasInitExession: if len(children) >= 2: if children[0][self.get_key()] in [ 'VariableDefinitionStatement', 'VariableDeclarationStatement', 'ExpressionStatement' ]: node_initExpression = self._parse_statement( children[0], node) link_nodes(node_initExpression, node_startLoop) else: hasInitExession = False else: hasInitExession = False if not hasInitExession: link_nodes(node, node_startLoop) node_condition = node_startLoop if hasCondition: if hasInitExession and len(children) >= 2: candidate = children[1] else: candidate = children[0] if candidate[self.get_key()] not in [ 'VariableDefinitionStatement', 'VariableDeclarationStatement', 'ExpressionStatement' ]: node_condition = self._new_node(NodeType.IFLOOP, statement['src']) #expression = parse_expression(candidate, self) expression = candidate node_condition.add_unparsed_expression(expression) link_nodes(node_startLoop, node_condition) link_nodes(node_condition, node_endLoop) hasCondition = True else: hasCondition = False node_statement = self._parse_statement(children[-1], node_condition) node_LoopExpression = node_statement if hasLoopExpression: if len(children) > 2: if children[-2][self.get_key()] == 'ExpressionStatement': node_LoopExpression = self._parse_statement( children[-2], node_statement) if not hasCondition: link_nodes(node_LoopExpression, node_endLoop) if not hasCondition and not hasLoopExpression: link_nodes(node, node_endLoop) link_nodes(node_LoopExpression, node_condition) return node_endLoop
def _parse_for_compact_ast(self, statement, node): body = statement['body'] init_expression = statement['initializationExpression'] condition = statement['condition'] loop_expression = statement['loopExpression'] node_startLoop = self._new_node(NodeType.STARTLOOP, statement['src']) node_endLoop = self._new_node(NodeType.ENDLOOP, statement['src']) if init_expression: node_init_expression = self._parse_statement(init_expression, node) link_nodes(node_init_expression, node_startLoop) else: link_nodes(node, node_startLoop) if condition: node_condition = self._new_node(NodeType.IFLOOP, statement['src']) node_condition.add_unparsed_expression(condition) link_nodes(node_startLoop, node_condition) link_nodes(node_condition, node_endLoop) else: node_condition = node_startLoop node_body = self._parse_statement(body, node_condition) if loop_expression: node_LoopExpression = self._parse_statement( loop_expression, node_body) link_nodes(node_LoopExpression, node_condition) else: link_nodes(node_body, node_condition) if not condition: if not loop_expression: # TODO: fix case where loop has no expression link_nodes(node_startLoop, node_endLoop) else: link_nodes(node_LoopExpression, node_endLoop) return node_endLoop
def _fix_catch(self, node, end_node): if not node.sons: link_nodes(node, end_node) else: for son in node.sons: self._fix_catch(son, end_node)
def _parse_for(self, statement, node): # ForStatement = 'for' '(' (SimpleStatement)? ';' (Expression)? ';' (ExpressionStatement)? ')' Statement hasInitExession = True hasCondition = True hasLoopExpression = True # Old solc version do not prevent in the attributes # if the loop has a init value /condition or expression # There is no way to determine that for(a;;) and for(;a;) are different with old solc if 'attributes' in statement: if 'initializationExpression' in statement: if not statement['initializationExpression']: hasInitExession = False if 'condition' in statement: if not statement['condition']: hasCondition = False if 'loopExpression' in statement: if not statement['loopExpression']: hasLoopExpression = False node_startLoop = self._new_node(NodeType.STARTLOOP) node_endLoop = self._new_node(NodeType.ENDLOOP) children = statement['children'] if hasInitExession: if len(children) >= 2: if children[0]['name'] in ['VariableDefinitionStatement', 'VariableDeclarationStatement', 'ExpressionStatement']: node_initExpression = self._parse_statement(children[0], node) link_nodes(node_initExpression, node_startLoop) else: hasInitExession = False else: hasInitExession = False if not hasInitExession: link_nodes(node, node_startLoop) node_condition = node_startLoop if hasCondition: if hasInitExession and len(children) >= 2: candidate = children[1] else: candidate = children[0] if candidate['name'] not in ['VariableDefinitionStatement', 'VariableDeclarationStatement', 'ExpressionStatement']: node_condition = self._new_node(NodeType.IFLOOP) #expression = parse_expression(candidate, self) expression = candidate node_condition.add_unparsed_expression(expression) link_nodes(node_startLoop, node_condition) link_nodes(node_condition, node_endLoop) hasCondition = True else: hasCondition = False node_statement = self._parse_statement(children[-1], node_condition) node_LoopExpression = node_statement if hasLoopExpression: if len(children) > 2: if children[-2]['name'] == 'ExpressionStatement': node_LoopExpression = self._parse_statement(children[-2], node_statement) link_nodes(node_LoopExpression, node_startLoop) return node_endLoop
def link_underlying_nodes(node1: YulNode, node2: YulNode): link_nodes(node1.underlying_node, node2.underlying_node)