From fb36aef06ef2fda476f465442df8dd164ec2636a Mon Sep 17 00:00:00 2001 From: ayrton Date: Tue, 21 Nov 2023 21:39:04 -0700 Subject: [PATCH] Refactor and bugfix for integer division Took 54 minutes --- ast_generator/ast_generator.py | 97 ++++++++++++++---------- ast_generator/test/test_ast_generator.py | 2 +- ast_parser/gaz_unparser.py | 2 +- ast_parser/general_unparser.py | 5 +- ast_parser/python_unparser.py | 10 ++- config.yaml | 2 +- 6 files changed, 67 insertions(+), 51 deletions(-) diff --git a/ast_generator/ast_generator.py b/ast_generator/ast_generator.py index c2ba44e..b588ff5 100644 --- a/ast_generator/ast_generator.py +++ b/ast_generator/ast_generator.py @@ -55,10 +55,30 @@ class AstGenerator: self.int_op_options, self.int_op_cutoffs, self.int_op_numline = ( self.get_numberlines('expression-weights', ['brackets', 'arithmetic', 'unary'], - [[], [], ['negation']])) + [[], [], ['not']])) self.int_unary = ['negation', 'noop'] - pass + self.bool_op_options, self.bool_op_cutoffs, self.bool_op_numline = ( + self.get_numberlines('expression-weights', + ['comparison', 'logical', 'brackets', 'unary'], + [['less-than-or-equal', 'greater-than-or-equal', 'less-than', 'greater-than'], [], [], ['noop', 'negation']])) + self.bool_unary = ['not'] + + self.float_op_options, self.float_op_cutoffs, self.float_op_numline = ( + self.get_numberlines('expression-weights', + ['brackets', 'arithmetic', 'unary'], + [[], [], ['not']])) + self.float_unary = ['negation', 'noop'] + + self.char_op_options, self.char_op_cutoffs, self.char_op_numline = ( + self.get_numberlines('expression-weights', + ['brackets', 'comparison'], + [[], ['less-than', 'greater-than', 'less-than-or-equal', 'greater-than-or-equal']])) + + self.comp_op_options, self.comp_op_cutoffs, self.comp_op_numline = ( + self.get_numberlines('expression-weights', + ['brackets', 'comparison'], + [[], []])) def get_numberlines(self, settings_section: str, subsettings: list[str], excluded_values: list[list[str or None]]): assert len(subsettings) == len(excluded_values) @@ -242,49 +262,42 @@ class AstGenerator: break break - def generate_int_real_expr(self): - # Number line - number_line = 100 - cutoffs = [10, 30, 50, 80, 100] - options = { #TODO add brackets - 0: "addition", - 1: "subtraction", - 2: "multiplication", - 3: "division", - 4: "modulo", - 5: "power", - 6: "negation", - 7: "noop", - 8: "equality", - 9: "inequality", - 10: "less-than", - 11: "greater-than", - 12: "less-than-or-equal", - 13: "greater-than-or-equal", - } + def generate_int_expr(self): + self._generate_expression([GAZ_INT_KEY], + self.int_op_numline, + self.int_op_cutoffs, + self.int_op_options, + self.int_unary) - unary = ["negation", "noop"] - - self._generate_expression([GAZ_INT_KEY, GAZ_FLOAT_KEY], self.int_op_numline, self.int_op_cutoffs, - self.int_op_options, self.int_unary) + def generate_float_expr(self): + self._generate_expression([GAZ_FLOAT_KEY, GAZ_INT_KEY], + self.float_op_numline, + self.float_op_cutoffs, + self.float_op_options, + self.float_unary) def generate_bool_expr(self): - # Number line - number_line = 100 - cutoffs = [10, 30, 50, 80, 100] - options = { #TODO add brackets # TODO cannot guarantee correctness of comparison since booleans may appear - 0: "equality", - 1: "and", - 2: "or", - 3: "xor", - 4: "not", - } + self._generate_expression([GAZ_BOOL_KEY], + self.bool_op_numline, + self.bool_op_cutoffs, + self.bool_op_options, + self.bool_unary) - unary = ["not"] + def generate_char_expr(self): + self._generate_expression([GAZ_CHAR_KEY], + self.char_op_numline, + self.char_op_cutoffs, + self.char_op_options) - self._generate_expression([GAZ_BOOL_KEY], number_line, cutoffs, options, unary) + def generate_comp_expr(self): + self._generate_expression([GAZ_BOOL_KEY], + self.comp_op_numline, + self.comp_op_cutoffs, + self.comp_op_options, + comparison=True) - def _generate_expression(self, expr_type: list[str], number_line, cutoffs, options, unary=None): + def _generate_expression(self, expr_type: list[str], number_line, + cutoffs, options, unary=None, comparison: bool = False): if unary is None: unary = [] @@ -293,7 +306,7 @@ class AstGenerator: if self.current_nesting_depth > self.settings['generation-options']['max-nesting-depth'] or random.random() < \ self.settings['block-termination-probability']: - self.generate_literal(random.choice(expr_type)) # TODO add the reals + self.generate_literal(random.choice(expr_type)) self.current_nesting_depth -= 1 return @@ -511,11 +524,11 @@ class AstGenerator: def generate_expression(self, expr_type: str): if expr_type == GAZ_INT_KEY or expr_type == GAZ_FLOAT_KEY: - self.generate_int_real_expr() + self.generate_int_expr() elif expr_type == GAZ_BOOL_KEY: self.generate_bool_expr() elif expr_type == ANY_TYPE: # TODO implement the choice of any type - self.generate_int_real_expr() + self.generate_int_expr() else: raise NotImplementedError(f"Expression type {expr_type} not implemented") diff --git a/ast_generator/test/test_ast_generator.py b/ast_generator/test/test_ast_generator.py index 4d0ea51..8009b47 100644 --- a/ast_generator/test/test_ast_generator.py +++ b/ast_generator/test/test_ast_generator.py @@ -228,7 +228,7 @@ class TestGeneration(unittest.TestCase): # print("iteration: " + str(l)) self.ast_gen.ast = ET.Element("block") self.ast_gen.current_ast_element = self.ast_gen.ast - self.ast_gen.generate_int_real_expr() + self.ast_gen.generate_int_expr() # self.write_ast() if self.ast_gen.ast.find("operator") is None: diff --git a/ast_parser/gaz_unparser.py b/ast_parser/gaz_unparser.py index c7afc59..4f129e8 100644 --- a/ast_parser/gaz_unparser.py +++ b/ast_parser/gaz_unparser.py @@ -82,7 +82,7 @@ class GazUnparser(GeneralUnparser): else: return str(val) - def translate_op(self, param): + def translate_op(self, param, ty=None): return to_gaz_op(param) def translate_type(self, ty): diff --git a/ast_parser/general_unparser.py b/ast_parser/general_unparser.py index 751d11d..ddf670a 100644 --- a/ast_parser/general_unparser.py +++ b/ast_parser/general_unparser.py @@ -171,8 +171,9 @@ class GeneralUnparser: self.unparse_node(child) def unparse_operator(self, node): + ty = node.get(GAZ_TY_KEY) self.unparse_xhs(node.find(GAZ_LHS_TAG)) - self.source += " {} ".format(self.translate_op(node.get("op"))) + self.source += " {} ".format(self.translate_op(node.get("op"), ty)) self.unparse_xhs(node.find(GAZ_RHS_TAG)) def unparse_return(self, node): @@ -304,7 +305,7 @@ class GeneralUnparser: def translate_value(self, val): raise NotImplementedError - def translate_op(self, param): + def translate_op(self, param, ty=None): raise NotImplementedError def translate_type(self, ty): diff --git a/ast_parser/python_unparser.py b/ast_parser/python_unparser.py index 69756c6..1109788 100644 --- a/ast_parser/python_unparser.py +++ b/ast_parser/python_unparser.py @@ -21,15 +21,17 @@ def to_python_type(ty): raise Exception("Unknown type: " + ty) -def to_python_op(param): +def to_python_op(param, ty): if param == "negation" or param == "subtraction": return "-" elif param == "addition" or param == "noop": return "+" elif param == "multiplication": return "*" - elif param == "division": + elif param == "division" and ty != GAZ_INT_KEY: return "/" + elif param == "division" and ty == GAZ_INT_KEY: + return "//" elif param == "modulo": return "%" elif param == "power": @@ -79,8 +81,8 @@ class PythonUnparser(GeneralUnparser): def translate_value(self, val): return str(val) - def translate_op(self, param): - return to_python_op(param) + def translate_op(self, param, ty=None): + return to_python_op(param, ty) def translate_type(self, ty): return to_python_type(ty) diff --git a/config.yaml b/config.yaml index 4577154..68329d3 100644 --- a/config.yaml +++ b/config.yaml @@ -17,7 +17,7 @@ properties: number-of-arguments: # number of arguments to a routine min: 1 max: 10 - generate-max-int: True # if False, generate integers between [-1000, 1000] else + generate-max-int: False # if False, generate integers between [-1000, 1000] else expression-weights: # weights for expressions # the higher a weight, the more likely (0, 10000), 0 to exclude, 10000 for only that brackets: 10