def deep_find_match_Name(self, ins_node, std_node, check_meta=True): name_id = ins_node.astNode.id match = _name_regex(name_id) mapping = AstMap() matched = False meta_matched = self.metas_match(ins_node, std_node, check_meta) if match[_VAR] and meta_matched: # if variable # This if body is probably unnecessary. if type(std_node.astNode).__name__ == "Name": return self.deep_find_match_generic(ins_node, std_node, check_meta) # could else return False, but shallow_match_generic should do this as well elif match[_EXP]: # and meta_matched: # if expression # terminate recursion, the whole subtree should match since expression nodes match to anything mapping.add_exp_to_sym_table(ins_node, std_node) matched = True elif match[_WILD] and meta_matched: # if wild card, don't care # terminate the recursion, the whole subtree should match since wild cards match to anything matched = True if matched: mapping.add_node_pairing(ins_node, std_node) return [mapping] # else return self.deep_find_match_generic(ins_node, std_node, check_meta)
def deep_find_match_Expr(self, ins_node, std_node, check_meta=True): """ An Expression node (not to be confused with expressions denoted by the instructor nodes in Name ast nodes) checks whether it should be generic, or not Args: ins_node: Instructor ast to find in the student ast std_node: Student AST to search for the instructor ast in check_meta: flag to check whether the fields of the instructor node and the student node should match Returns: AstMap: a mapping between the instructor and student asts, or False if such a mapping doesn't exist """ # if check_meta and ins_node.field != std_node.field: if not self.metas_match(ins_node, std_node, check_meta): return [] mapping = AstMap() value = ins_node.value ast_type = type(value.astNode).__name__ if ast_type == "Name": name_id = value.astNode.id exp_match = re.compile('^__.*__$') # /regex wild_card = re.compile('^___$') # /regex matched = False meta_matched = self.metas_match(ins_node, std_node, check_meta) if exp_match.match(name_id): # and meta_matched: # if expression # terminate recursion, the whole subtree should match since expression nodes match to anything mapping.add_exp_to_sym_table(value, std_node) matched = True elif wild_card.match(name_id) and meta_matched: # if wild card, don't care # terminate the recursion, the whole subtree should match since wild cards match to anything matched = True if matched: mapping.add_node_pairing(ins_node, std_node) return [mapping] return self.deep_find_match_generic(ins_node, std_node, check_meta)
def shallow_symbol_handler(self, ins_node, std_node, id_val, check_meta=True): """ TODO: Make this handle the func field to handle functions Matches ins_node to std_node for different cases of encountering a name node in ins_node case 1: _var_ matches if std_node is a name node and automatically returns a mapping and symbol table case 2: __exp__ matches to any subtree and automatically returns a mapping and symbol table case 3: ___ matches to any subtree and automatically returns a mapping case 4: matches only if the exact names are the same (falls through to shallow_match_generic) Args: ins_node: std_node: id_val: check_meta: Returns: list of AstMap: a mapping of ins_node to std_node and possibly a symbol_table, or False if it doesn't match """ name_id = ins_node.astNode.__getattribute__(id_val) match = _name_regex(name_id) mapping = AstMap() matched = False # TODO: add functionality to add function references to func_table? meta_matched = self.metas_match(ins_node, std_node, check_meta) if match[_VAR] and meta_matched: # variable if type(std_node.astNode).__name__ == "Name" or id_val == "attr": if id_val == "attr": std_node.astNode.id = std_node.astNode.attr if std_node.field == "func" and ins_node.field != "none": # TODO: This 'ins_node.field != "none"' code is for an obscure edge case where the instructor code # is only _var_ mapping.add_func_to_sym_table(ins_node, std_node) else: mapping.add_var_to_sym_table( ins_node, std_node) # TODO: Capture result? matched = True # could else return False, but shallow_match_generic should do this as well elif match[ _EXP] and meta_matched: # expression TODO: In theory this won't run? mapping.add_exp_to_sym_table(ins_node, std_node) matched = True elif match[ _WILD] and meta_matched: # don't care TODO: In theory this won't run? matched = True if matched: mapping.add_node_pairing(ins_node, std_node) return [mapping] # else return self.shallow_match_generic(ins_node, std_node, check_meta)
def shallow_symbol_handler(self, ins_node, std_node, id_val, check_meta=True): """ TODO: Make this handle the func field to handle functions Matches ins_node to std_node for different cases of encountering a name node in ins_node case 1: _var_ matches if std_node is a name node and automatically returns a mapping and symbol table case 2: __exp__ matches to any subtree and automatically returns a mapping and symbol table case 3: ___ matches to any subtree and automatically returns a mapping case 4: matches only if the exact names are the same (falls through to shallow_match_generic) Args: ins_node: std_node: id_val: check_meta: Returns: list of AstMap: a mapping of ins_node to std_node and possibly a symbol_table, or False if it doesn't match """ name_id = ins_node.astNode.__getattribute__(id_val) match = _name_regex(name_id) mapping = AstMap() matched = False # TODO: add functionality to add function references to func_table? meta_matched = self.metas_match(ins_node, std_node, check_meta) if match[_VAR] and meta_matched: # variable if type(std_node.astNode).__name__ == "Name" or id_val in ["attr", "arg"]: if id_val in ["attr", "arg"]: std_node.astNode._id = std_node.astNode.__getattribute__(id_val) if std_node.field == "func" and ins_node.field != _NONE_FIELD: # TODO: This 'ins_node.field != _NONE_FIELD' code is for an obscure edge case where the # instructor code is only _var_ std_node.astNode._id = std_node.astNode.__getattribute__(id_val) mapping.add_func_to_sym_table(ins_node, std_node) else: std_node.astNode._id = std_node.astNode.__getattribute__(id_val) mapping.add_var_to_sym_table(ins_node, std_node) # TODO: Capture result? matched = True # could else return False, but shallow_match_generic should do this as well elif match[_EXP] and meta_matched: mapping.add_exp_to_sym_table(ins_node, std_node) matched = True elif match[_WILD] and meta_matched: matched = True if matched: mapping.add_node_pairing(ins_node, std_node) return [mapping] # else return self.shallow_match_main(ins_node, std_node, check_meta=check_meta, ignores=["ctx"])
def deep_find_match_Name(self, ins_node, std_node, check_meta=True, use_previous=None): """ Args: ins_node: std_node: check_meta: use_previous: Returns: """ name_id = ins_node.astNode.id match = _name_regex(name_id) mapping = AstMap() matched = False meta_matched = self.metas_match(ins_node, std_node, check_meta) if match[_VAR] and meta_matched: # if variable if type(std_node.astNode).__name__ == "Name": return self.deep_find_match_generic(ins_node, std_node, check_meta=check_meta, ignores=["ctx"], use_previous=use_previous) # could else return False, but shallow_match_generic should do this as well elif match[_EXP] and meta_matched: # and meta_matched: # if expression # terminate recursion, the whole subtree should match since expression nodes match to anything mapping.merge_map_with(use_previous) mapping.add_exp_to_sym_table(ins_node, std_node) matched = True elif match[_WILD] and meta_matched: # if wild card, don't care # terminate the recursion, the whole subtree should match since wild cards match to anything matched = True if matched: mapping.add_node_pairing(ins_node, std_node) return [mapping] # else return self.deep_find_match_generic(ins_node, std_node, check_meta=check_meta, ignores=["ctx"], use_previous=use_previous)
def deep_find_match_Expr(self, ins_node, std_node, check_meta=True, use_previous=None): """ An Expression node (not to be confused with expressions denoted by the instructor nodes in Name ast nodes) checks whether it should be generic, or not Args: ins_node: Instructor ast to find in the student ast std_node: Student AST to search for the instructor ast in check_meta: flag to check whether the fields of the instructor node and the student node should match use_previous: An AstMap from a previous matching run Returns: AstMap: a mapping between the instructor and student asts, or False if such a mapping doesn't exist """ # if check_meta and ins_node.field != std_node.field: if not self.metas_match(ins_node, std_node, check_meta): return [] mapping = AstMap() if use_previous is None else use_previous value = ins_node.value ast_type = type(value.astNode).__name__ if ast_type == "Name": name_id = value.astNode.id exp_match = re.compile('^__.*__$') # /regex wild_card = re.compile('^___$') # /regex matched = False meta_matched = self.metas_match(ins_node, std_node, check_meta) if exp_match.match( name_id ) and meta_matched: # and meta_matched: # if expression # terminate recursion, the whole subtree should match since expression nodes match to anything mapping.add_exp_to_sym_table(value, std_node) matched = True elif wild_card.match( name_id) and meta_matched: # if wild card, don't care # terminate the recursion, the whole subtree should match since wild cards match to anything matched = True if matched: mapping.add_node_pairing(ins_node, std_node) return [mapping] return self.deep_find_match_generic(ins_node, std_node, check_meta)
def deep_find_match_Name(self, ins_node, std_node, check_meta=True): name_id = ins_node.astNode.id match = _name_regex(name_id) mapping = AstMap() matched = False meta_matched = self.metas_match(ins_node, std_node, check_meta) if match[_VAR] and meta_matched: # if variable # This if body is probably unnecessary. if type(std_node.astNode).__name__ == "Name": return self.deep_find_match_generic(ins_node, std_node, check_meta=check_meta, ignores=["ctx"]) # could else return False, but shallow_match_generic should do this as well elif match[_EXP]: # and meta_matched: # if expression # terminate recursion, the whole subtree should match since expression nodes match to anything mapping.add_exp_to_sym_table(ins_node, std_node) matched = True elif match[_WILD] and meta_matched: # if wild card, don't care # terminate the recursion, the whole subtree should match since wild cards match to anything matched = True if matched: mapping.add_node_pairing(ins_node, std_node) return [mapping] # else return self.deep_find_match_generic(ins_node, std_node, check_meta=check_meta, ignores=["ctx"])