diff --git a/ast_generator/ast_generator.py b/ast_generator/ast_generator.py index 21eae7f..3490121 100644 --- a/ast_generator/ast_generator.py +++ b/ast_generator/ast_generator.py @@ -186,7 +186,10 @@ class AstGenerator: i = 0 for i in range(len(cutoffs) - 1): if cutoffs[i] < a < cutoffs[i + 1]: - options[i]() + try: + options[i]() + except ValueError: + break break def generate_int_real_expr(self): @@ -229,7 +232,7 @@ class AstGenerator: 7: "or", 8: "xor", 9: "not", - } # FIXME sometimes this will return a "" op, need to figure out why + } unary = ["not"] @@ -268,7 +271,7 @@ class AstGenerator: self.current_nesting_depth -= 1 self.current_ast_element = parent - def generate_declaration(self): + def generate_declaration(self, mut=None): parent = self.current_ast_element decl_type = self.get_type(GAZ_VAR_TAG) decl_args = [ @@ -278,7 +281,7 @@ class AstGenerator: self.current_ast_element.append(element) self.current_ast_element = element - variable = self.generate_variable(decl_type) + variable = self.generate_variable(decl_type, mut=mut) self.current_ast_element.append(variable.xml) self.current_scope.append(variable.name, variable) @@ -374,6 +377,10 @@ class AstGenerator: def generate_assignment(self): + possible_vars = self.current_scope.get_all_defined_mutable_vars() + if len(possible_vars) == 0: + raise ValueError("No possible variables to assign to!") + # same structure as a declaration parent = self.current_ast_element @@ -381,12 +388,7 @@ class AstGenerator: self.current_ast_element.append(element) self.current_ast_element = element - possible_vars = self.current_scope.get_all_defined_mutable_vars() - if len(possible_vars) == 0: - self.generate_global() - possible_vars = self.current_scope.get_all_defined_mutable_vars() - assert len(possible_vars) > 0 variable = random.choice(possible_vars) self.current_ast_element.append(variable.xml) @@ -413,8 +415,12 @@ class AstGenerator: self.current_ast_element = parent - def generate_variable(self, var_type: str): - return Variable(self.get_name(GAZ_VAR_TAG), var_type, self.get_qualifier()) + def generate_variable(self, var_type: str, mut=None): + if mut is None: + return Variable(self.get_name(GAZ_VAR_TAG), var_type, self.get_qualifier()) + else: + return Variable(self.get_name(GAZ_VAR_TAG), var_type, mut) + def generate_literal(self, var_type: str): args = [ diff --git a/ast_generator/test/test_ast_generator.py b/ast_generator/test/test_ast_generator.py index ca85630..ed20b2d 100644 --- a/ast_generator/test/test_ast_generator.py +++ b/ast_generator/test/test_ast_generator.py @@ -232,10 +232,49 @@ class TestGeneration(unittest.TestCase): # self.write_ast() if self.ast_gen.ast.find("operator") is None: + l -= 1 continue operator = self.ast_gen.ast.find("operator") self.assertFalse(self.is_no_op(operator)) + def test_create_global(self): + self.ast_gen.ast = ET.Element("block") + self.ast_gen.current_ast_element = self.ast_gen.ast + self.ast_gen.generate_main() + + global_block = self.ast_gen.current_ast_element + global_scope = self.ast_gen.current_scope + + self.assertIsNotNone(self.ast_gen.ast.find("procedure")) + self.ast_gen.current_ast_element = self.ast_gen.ast.find("procedure") + self.ast_gen.generate_global() + + self.assertGreater(len(global_scope.symbols), 0) + self.assertIsNotNone(global_block.find("declaration")) + + def test_generate_assignment_no_declaration(self): + for l in range(1000): + self.ast_gen.ast = ET.Element("block") + self.ast_gen.current_ast_element = self.ast_gen.ast + self.ast_gen.generate_declaration(mut='var') + self.ast_gen.generate_assignment() + + self.assertIsNotNone(self.ast_gen.ast.find("assignment")) + + decl = self.ast_gen.ast.find("assignment") + self.assertIsNone(decl.find("declaration")) + + def test_failing_assignment(self): + self.ast_gen.ast = ET.Element("block") + self.ast_gen.current_ast_element = self.ast_gen.ast + self.ast_gen.generate_main() + with self.assertRaises(ValueError): + self.ast_gen.generate_assignment() + + self.assertIsNone(self.ast_gen.ast.find("assignment")) + + + def is_no_op(self, operator): """ diff --git a/ast_parser/general_unparser.py b/ast_parser/general_unparser.py index 0fb59e7..64ea586 100644 --- a/ast_parser/general_unparser.py +++ b/ast_parser/general_unparser.py @@ -126,6 +126,8 @@ class GeneralUnparser: self.source += self.endline def unparse_variable(self, node, is_declaration: bool = False): + if node is None: + raise ValueError("Node is None") mut = node.get(GAZ_QUALIFIER_KEY) type = node.get(GAZ_TY_KEY) name = node.get(GAZ_NAME_KEY) diff --git a/gazprea_fuzzer.py b/gazprea_fuzzer.py index 4160e58..981e886 100644 --- a/gazprea_fuzzer.py +++ b/gazprea_fuzzer.py @@ -32,7 +32,7 @@ class Fuzzer(): self.fuzzer.fuzz() dom = xml.dom.minidom.parseString(ET.tostring(self.fuzzer.ast).decode('utf-8')) pretty: str = dom.toprettyxml() - with open("fuzzer/source/{}_{}.in".format(self.file_name, i), 'w') as f: + with open("fuzzer/input/{}_{}.in".format(self.file_name, i), 'w') as f: f.write(self.fuzzer.source) with open("fuzzer/debug/{}_{}.out".format(self.file_name, i), 'w') as f: f.write(pretty)