def apply(self, items, pattern, ls, evaluation, options): "Cases[items_, pattern_, ls_:{1}, OptionsPattern[]]" if items.is_atom(): return Expression(SymbolList) from mathics.builtin.patterns import Matcher if ls.has_form("Rule", 2): if ls.leaves[0].get_name() == "System`Heads": heads = ls.leaves[1].is_true() ls = Expression("List", 1) else: return evaluation.message("Position", "level", ls) else: heads = self.get_option(options, "Heads", evaluation).is_true() try: start, stop = python_levelspec(ls) except InvalidLevelspecError: return evaluation.message("Position", "level", ls) results = [] if pattern.has_form("Rule", 2) or pattern.has_form("RuleDelayed", 2): match = Matcher(pattern.leaves[0]).match rule = Rule(pattern.leaves[0], pattern.leaves[1]) def callback(level): if match(level, evaluation): result = rule.apply(level, evaluation) result = result.evaluate(evaluation) results.append(result) return level else: match = Matcher(pattern).match def callback(level): if match(level, evaluation): results.append(level) return level walk_levels(items, start, stop, heads=heads, callback=callback) return Expression(SymbolList, *results)
def apply(self, expr, test, level, evaluation): "%(name)s[expr_, test_, level_]" try: start, stop = python_levelspec(level) except InvalidLevelspecError: evaluation.message("Level", "level", level) return def callback(node): self._short_circuit(Expression(test, node).evaluate(evaluation).is_true()) return node try: walk_levels(expr, start, stop, callback=callback) except _ShortCircuit as e: return e.result return self._no_short_circuit()
def apply_level(self, f, expr, ls, evaluation, options={}): 'Map[f_, expr_, ls_?LevelQ:{1}, OptionsPattern[Map]]' try: start, stop = python_levelspec(ls) except InvalidLevelspecError: evaluation.message('Map', 'level', ls) return def callback(level): return Expression(f, level) heads = self.get_option(options, 'Heads', evaluation).is_true() result, depth = walk_levels(expr, start, stop, heads=heads, callback=callback) return result
def apply_level(self, f, expr, ls, evaluation, options={}): 'MapIndexed[f_, expr_, ls_?LevelQ:{1}, OptionsPattern[MapIndexed]]' try: start, stop = python_levelspec(ls) except InvalidLevelspecError: evaluation.message('MapIndexed', 'level', ls) return def callback(level, pos): return Expression(f, level, Expression('List', *(Integer(p) for p in pos))) heads = self.get_option(options, 'Heads', evaluation).is_true() result, depth = walk_levels(expr, start, stop, heads=heads, callback=callback, include_pos=True) return result
def apply_level(self, f, expr, ls, evaluation, options={}): """MapIndexed[f_, expr_, Optional[Pattern[ls, _?LevelQ], {1}], OptionsPattern[MapIndexed]]""" try: start, stop = python_levelspec(ls) except InvalidLevelspecError: evaluation.message("MapIndexed", "level", ls) return def callback(level, pos): return Expression(f, level, Expression("List", *[Integer(p) for p in pos])) heads = self.get_option(options, "Heads", evaluation).is_true() result, depth = walk_levels(expr, start, stop, heads=heads, callback=callback, include_pos=True) return result
def apply_level(self, f, expr, ls, evaluation, options={}): """Map[f_, expr_, Optional[Pattern[ls, _?LevelQ], {1}], OptionsPattern[Map]]""" try: start, stop = python_levelspec(ls) except InvalidLevelspecError: evaluation.message("Map", "level", ls) return def callback(level): return Expression(f, level) heads = self.get_option(options, "Heads", evaluation).is_true() result, depth = walk_levels(expr, start, stop, heads=heads, callback=callback) return result
def apply(self, f, expr, ls, evaluation, options={}): 'Apply[f_, expr_, ls_?LevelQ:{0}, OptionsPattern[Apply]]' try: start, stop = python_levelspec(ls) except InvalidLevelspecError: evaluation.message('Apply', 'level', ls) return def callback(level): if level.is_atom(): return level else: return Expression(f, *level.leaves) heads = self.get_option(options, 'Heads', evaluation).is_true() result, depth = walk_levels(expr, start, stop, heads=heads, callback=callback) return result
def apply_level(self, f, expr, ls, evaluation, options={}): '''Scan[f_, expr_, Optional[Pattern[ls, _?LevelQ], {1}], OptionsPattern[Map]]''' try: start, stop = python_levelspec(ls) except InvalidLevelspecError: evaluation.message('Map', 'level', ls) return def callback(level): Expression(f, level).evaluate(evaluation) return level heads = self.get_option(options, 'Heads', evaluation).is_true() result, depth = walk_levels( expr, start, stop, heads=heads, callback=callback) return Symbol('Null')
def apply_level(self, f, expr, ls, evaluation, options={}): """MapIndexed[f_, expr_, Optional[Pattern[ls, _?LevelQ], {1}], OptionsPattern[MapIndexed]]""" try: start, stop = python_levelspec(ls) except InvalidLevelspecError: evaluation.message("MapIndexed", "level", ls) return def callback(level, pos): return Expression(f, level, Expression("List", *[Integer(p) for p in pos])) heads = self.get_option(options, "Heads", evaluation).is_true() result, depth = walk_levels( expr, start, stop, heads=heads, callback=callback, include_pos=True ) return result
def apply(self, f, expr, ls, evaluation, options={}): """Apply[f_, expr_, Optional[Pattern[ls, _?LevelQ], {0}], OptionsPattern[Apply]]""" try: start, stop = python_levelspec(ls) except InvalidLevelspecError: evaluation.message("Apply", "level", ls) return def callback(level): if level.is_atom(): return level else: return Expression(f, *level.leaves) heads = self.get_option(options, "Heads", evaluation).is_true() result, depth = walk_levels(expr, start, stop, heads=heads, callback=callback) return result
def apply_list(self, expr, n, h, evaluation): "Flatten[expr_, n_List, h_]" # prepare levels # find max depth which matches `h` expr, max_depth = walk_levels(expr) max_depth = { "max_depth": max_depth } # hack to modify max_depth from callback def callback(expr, pos): if len(pos) < max_depth["max_depth"] and (expr.is_atom() or expr.head != h): max_depth["max_depth"] = len(pos) return expr expr, depth = walk_levels(expr, callback=callback, include_pos=True, start=0) max_depth = max_depth["max_depth"] levels = n.to_python() # mappings if isinstance(levels, list) and all( isinstance(level, int) for level in levels): levels = [levels] # verify levels is list of lists of positive ints if not (isinstance(levels, list) and len(levels) > 0): evaluation.message("Flatten", "flpi", n) return seen_levels = [] for level in levels: if not (isinstance(level, list) and len(level) > 0): evaluation.message("Flatten", "flpi", n) return for l in level: if not (isinstance(l, int) and l > 0): evaluation.message("Flatten", "flpi", n) return if l in seen_levels: # level repeated evaluation.message("Flatten", "flrep", l) return seen_levels.append(l) # complete the level spec e.g. {{2}} -> {{2}, {1}, {3}} for l in range(1, max_depth + 1): if l not in seen_levels: levels.append([l]) # verify specified levels are smaller max depth for level in levels: for l in level: if l > max_depth: evaluation.message("Flatten", "fldep", l, n, max_depth, expr) return # assign new indices to each leaf new_indices = {} def callback(expr, pos): if len(pos) == max_depth: new_depth = tuple( tuple(pos[i - 1] for i in level) for level in levels) new_indices[new_depth] = expr return expr expr, depth = walk_levels(expr, callback=callback, include_pos=True) # build new tree inserting nodes as needed result = Expression(h) leaves = sorted(new_indices.items()) def insert_leaf(expr, leaves): # gather leaves into groups with the same leading index # e.g. [((0, 0), a), ((0, 1), b), ((1, 0), c), ((1, 1), d)] # -> [[(0, a), (1, b)], [(0, c), (1, d)]] leading_index = None grouped_leaves = [] for index, leaf in leaves: if index[0] == leading_index: grouped_leaves[-1].append((index[1:], leaf)) else: leading_index = index[0] grouped_leaves.append([(index[1:], leaf)]) # for each group of leaves we either insert them into the current level # or make a new level and recurse for group in grouped_leaves: if len(group[0][0]) == 0: # bottom level leaf assert len(group) == 1 expr.leaves.append(group[0][1]) else: expr.leaves.append(Expression(h)) insert_leaf(expr.leaves[-1], group) insert_leaf(result, leaves) return result
def apply(self, expr, evaluation): "Depth[expr_]" expr, depth = walk_levels(expr) return Integer(depth + 1)
def apply(self, expr, evaluation): 'Depth[expr_]' expr, depth = walk_levels(expr) return Integer(depth + 1)
def apply_list(self, expr, n, h, evaluation): 'Flatten[expr_, n_List, h_]' # prepare levels # find max depth which matches `h` expr, max_depth = walk_levels(expr) max_depth = {'max_depth': max_depth} # hack to modify max_depth from callback def callback(expr, pos): if len(pos) < max_depth['max_depth'] and (expr.is_atom() or expr.head != h): max_depth['max_depth'] = len(pos) return expr expr, depth = walk_levels(expr, callback=callback, include_pos=True, start=0) max_depth = max_depth['max_depth'] levels = n.to_python() # mappings if isinstance(levels, list) and all(isinstance(level, int) for level in levels): levels = [levels] # verify levels is list of lists of positive ints if not (isinstance(levels, list) and len(levels) > 0): evaluation.message('Flatten', 'flpi', n) return seen_levels = [] for level in levels: if not (isinstance(level, list) and len(level) > 0): evaluation.message('Flatten', 'flpi', n) return for l in level: if not (isinstance(l, int) and l > 0): evaluation.message('Flatten', 'flpi', n) return if l in seen_levels: # level repeated evaluation.message('Flatten', 'flrep', l) return seen_levels.append(l) # complete the level spec e.g. {{2}} -> {{2}, {1}, {3}} for l in range(1, max_depth + 1): if l not in seen_levels: levels.append([l]) # verify specified levels are smaller max depth for level in levels: for l in level: if l > max_depth: evaluation.message('Flatten', 'fldep', l, n, max_depth, expr) return # assign new indices to each leaf new_indices = {} def callback(expr, pos): if len(pos) == max_depth: new_depth = tuple(tuple(pos[i - 1] for i in level) for level in levels) new_indices[new_depth] = expr return expr expr, depth = walk_levels(expr, callback=callback, include_pos=True) # build new tree inserting nodes as needed result = Expression(h) leaves = sorted(six.iteritems(new_indices)) def insert_leaf(expr, leaves): # gather leaves into groups with the same leading index # e.g. [((0, 0), a), ((0, 1), b), ((1, 0), c), ((1, 1), d)] # -> [[(0, a), (1, b)], [(0, c), (1, d)]] leading_index = None grouped_leaves = [] for index, leaf in leaves: if index[0] == leading_index: grouped_leaves[-1].append((index[1:], leaf)) else: leading_index = index[0] grouped_leaves.append([(index[1:], leaf)]) # for each group of leaves we either insert them into the current level # or make a new level and recurse for group in grouped_leaves: if len(group[0][0]) == 0: # bottom level leaf assert len(group) == 1 expr.leaves.append(group[0][1]) else: expr.leaves.append(Expression(h)) insert_leaf(expr.leaves[-1], group) insert_leaf(result, leaves) return result