From e8400097f2404177adaeab9266f964ef370819d5 Mon Sep 17 00:00:00 2001 From: Bernhard Liebl Date: Thu, 22 Sep 2016 19:53:49 +0200 Subject: [PATCH 1/8] added Expression.flatten_sequence() --- mathics/core/expression.py | 61 +++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/mathics/core/expression.py b/mathics/core/expression.py index d062af44d6..01946c1ecd 100644 --- a/mathics/core/expression.py +++ b/mathics/core/expression.py @@ -142,6 +142,12 @@ def __new__(cls, *args, **kwargs): self.last_evaluated = None return self + def sequences(self): + return None + + def flatten_sequence(self): + return self + def get_attributes(self, definitions): return set() @@ -498,6 +504,12 @@ def __cmp(self, other): return 0 +def _sequences(leaves): + for i, leaf in enumerate(leaves): + if leaf.get_head_name() == 'System`Sequence' or leaf.sequences(): + yield i + + class Expression(BaseExpression): def __new__(cls, head, *leaves): self = super(Expression, cls).__new__(cls) @@ -505,8 +517,55 @@ def __new__(cls, head, *leaves): head = Symbol(head) self.head = head self.leaves = [from_python(leaf) for leaf in leaves] + self.seq = list(_sequences(self.leaves)) return self + def sequences(self): + return self.seq + + def _flatten_sequence(self, sequence): + indices = self.seq + if not indices: + return self + + leaves = self.leaves + + flattened = [] + extend = flattened.extend + + last = 0 + for i in indices: + next = indices[i] + extend(leaves[last:next]) + extend(sequence(next)) + last = next + 1 + + extend(leaves[last:]) + + return Expression(self.head, *flattened) + + def flatten_sequence(self): + def sequence(leaf): + if leaf.get_head_name() == 'System`Sequence': + return leaf.leaves + else: + return [leaf] + + return self._flatten_sequence(sequence) + + def flatten_pattern_sequence(self): + def sequence(leaf): + flattened = leaf.flatten_pattern_sequence() + if leaf.get_head_name() == 'System`Sequence' and leaf.pattern_sequence: + return flattened.leaves + else: + return [flattened] + + expr = self._flatten_sequence(sequence) + if hasattr(self, 'options'): + expr.options = self.options + return expr + def copy(self): result = Expression( self.head.copy(), *[leaf.copy() for leaf in self.leaves]) @@ -808,7 +867,7 @@ def eval_range(indices): if ('System`SequenceHold' not in attributes and # noqa 'System`HoldAllComplete' not in attributes): - new = new.flatten(SEQUENCE) + new = new.flatten_sequence() leaves = new.leaves for leaf in leaves: From 27f9a8f4c00b97f3bca26909e1921f33974e6e13 Mon Sep 17 00:00:00 2001 From: Bernhard Liebl Date: Thu, 22 Sep 2016 20:03:45 +0200 Subject: [PATCH 2/8] enabled usage of flatten_pattern_sequence() --- mathics/core/expression.py | 3 +++ mathics/core/rules.py | 12 +----------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/mathics/core/expression.py b/mathics/core/expression.py index 01946c1ecd..cedc173567 100644 --- a/mathics/core/expression.py +++ b/mathics/core/expression.py @@ -148,6 +148,9 @@ def sequences(self): def flatten_sequence(self): return self + def flatten_pattern_sequence(self): + return self + def get_attributes(self, definitions): return set() diff --git a/mathics/core/rules.py b/mathics/core/rules.py index a1c4115d62..7c239fc661 100644 --- a/mathics/core/rules.py +++ b/mathics/core/rules.py @@ -46,17 +46,7 @@ def yield_match(vars, rest): result = new_expression # Flatten out sequences (important for Rule itself!) - - def flatten(expr): - new_expr = expr.flatten(SEQUENCE, pattern_only=True) - if not new_expr.is_atom(): - for index, leaf in enumerate(new_expr.leaves): - new_expr.leaves[index] = flatten(leaf) - if hasattr(expr, 'options'): - new_expr.options = expr.options - return new_expr - - result = flatten(result) + result = result.flatten_pattern_sequence() if return_list: result_list.append(result) # count += 1 From 0b6695e98f23911c07574197f8e4351ae9dc8c99 Mon Sep 17 00:00:00 2001 From: Bernhard Liebl Date: Thu, 22 Sep 2016 20:18:30 +0200 Subject: [PATCH 3/8] fixes bugs --- mathics/core/expression.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/mathics/core/expression.py b/mathics/core/expression.py index cedc173567..95f6455c55 100644 --- a/mathics/core/expression.py +++ b/mathics/core/expression.py @@ -536,14 +536,12 @@ def _flatten_sequence(self, sequence): flattened = [] extend = flattened.extend - last = 0 + k = 0 for i in indices: - next = indices[i] - extend(leaves[last:next]) - extend(sequence(next)) - last = next + 1 - - extend(leaves[last:]) + extend(leaves[k:i]) + extend(sequence(leaves[i])) + k = i + 1 + extend(leaves[k:]) return Expression(self.head, *flattened) From f6ace4c9b22db82e69fdc8b686e9b35abb92beb3 Mon Sep 17 00:00:00 2001 From: Bernhard Liebl Date: Thu, 22 Sep 2016 20:33:51 +0200 Subject: [PATCH 4/8] lazy initialization for Expression.seq --- mathics/core/expression.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mathics/core/expression.py b/mathics/core/expression.py index 95f6455c55..048c3a912b 100644 --- a/mathics/core/expression.py +++ b/mathics/core/expression.py @@ -520,11 +520,15 @@ def __new__(cls, head, *leaves): head = Symbol(head) self.head = head self.leaves = [from_python(leaf) for leaf in leaves] - self.seq = list(_sequences(self.leaves)) + self.seq = None return self def sequences(self): - return self.seq + seq = self.seq + if seq is None: + seq = list(_sequences(self.leaves)) + self.seq = seq + return seq def _flatten_sequence(self, sequence): indices = self.seq From 7e531e81443b494b7e900def1ce825961add20e9 Mon Sep 17 00:00:00 2001 From: Bernhard Liebl Date: Thu, 22 Sep 2016 20:40:30 +0200 Subject: [PATCH 5/8] access self.seq only through self.sequences() --- mathics/core/expression.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mathics/core/expression.py b/mathics/core/expression.py index 048c3a912b..202bdd5270 100644 --- a/mathics/core/expression.py +++ b/mathics/core/expression.py @@ -531,7 +531,7 @@ def sequences(self): return seq def _flatten_sequence(self, sequence): - indices = self.seq + indices = self.sequences() if not indices: return self From 23f0cbbb6bcfc350aa536a6dcfbfb18841152c49 Mon Sep 17 00:00:00 2001 From: Bernhard Liebl Date: Thu, 22 Sep 2016 21:11:29 +0200 Subject: [PATCH 6/8] copy seq in copy() and shallow_copy() --- mathics/core/expression.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mathics/core/expression.py b/mathics/core/expression.py index 202bdd5270..ebde5e3b80 100644 --- a/mathics/core/expression.py +++ b/mathics/core/expression.py @@ -574,6 +574,7 @@ def sequence(leaf): def copy(self): result = Expression( self.head.copy(), *[leaf.copy() for leaf in self.leaves]) + result.seq = self.seq result.options = self.options result.original = self # result.last_evaluated = self.last_evaluated @@ -584,6 +585,7 @@ def shallow_copy(self): # the original, only the Expression instance is new. expr = Expression(self.head) expr.leaves = self.leaves + expr.seq = self.seq expr.options = self.options expr.last_evaluated = self.last_evaluated return expr From c392b3b049cd23930085fa073dc2c02c2bbee1f8 Mon Sep 17 00:00:00 2001 From: Bernhard Liebl Date: Thu, 22 Sep 2016 21:15:26 +0200 Subject: [PATCH 7/8] cleanup: remove SEQUENCE --- mathics/core/expression.py | 3 --- mathics/core/rules.py | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/mathics/core/expression.py b/mathics/core/expression.py index ebde5e3b80..5444f64440 100644 --- a/mathics/core/expression.py +++ b/mathics/core/expression.py @@ -1527,9 +1527,6 @@ def __getnewargs__(self): return (self.name, self.sympy_dummy) -SEQUENCE = Symbol('Sequence') - - class Number(Atom): def __str__(self): return str(self.value) diff --git a/mathics/core/rules.py b/mathics/core/rules.py index 7c239fc661..1a9f7f6334 100644 --- a/mathics/core/rules.py +++ b/mathics/core/rules.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals from __future__ import absolute_import -from mathics.core.expression import Expression, SEQUENCE, strip_context, KeyComparable +from mathics.core.expression import Expression, strip_context, KeyComparable from mathics.core.pattern import Pattern, StopGenerator From 51e5ff0b124acd2b5ff9f562302f1457fc777b45 Mon Sep 17 00:00:00 2001 From: Bernhard Liebl Date: Fri, 23 Sep 2016 18:31:20 +0200 Subject: [PATCH 8/8] cleanup --- mathics/core/expression.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mathics/core/expression.py b/mathics/core/expression.py index 5444f64440..532c14c565 100644 --- a/mathics/core/expression.py +++ b/mathics/core/expression.py @@ -520,14 +520,14 @@ def __new__(cls, head, *leaves): head = Symbol(head) self.head = head self.leaves = [from_python(leaf) for leaf in leaves] - self.seq = None + self._sequences = None return self def sequences(self): - seq = self.seq + seq = self._sequences if seq is None: seq = list(_sequences(self.leaves)) - self.seq = seq + self._sequences = seq return seq def _flatten_sequence(self, sequence): @@ -574,7 +574,7 @@ def sequence(leaf): def copy(self): result = Expression( self.head.copy(), *[leaf.copy() for leaf in self.leaves]) - result.seq = self.seq + result._sequences = self._sequences result.options = self.options result.original = self # result.last_evaluated = self.last_evaluated @@ -585,7 +585,7 @@ def shallow_copy(self): # the original, only the Expression instance is new. expr = Expression(self.head) expr.leaves = self.leaves - expr.seq = self.seq + expr._sequences = self._sequences expr.options = self.options expr.last_evaluated = self.last_evaluated return expr