-
-
Notifications
You must be signed in to change notification settings - Fork 205
Improvements to tackle wrong expression outputs #605
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
890f315
d5064c6
40c59a7
685313f
50a117f
6f64854
0cd310d
16def7f
338115e
08a1677
32eb3db
d06c963
104fea9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -62,6 +62,15 @@ def system_symbols_dict(d): | |
| return {ensure_context(k): v for k, v in six.iteritems(d)} | ||
|
|
||
|
|
||
| _layout_boxes = system_symbols( | ||
| 'RowBox', | ||
| 'SuperscriptBox', | ||
| 'SubscriptBox', | ||
| 'SubsuperscriptBox', | ||
| 'FractionBox', | ||
| 'SqrtBox') | ||
|
|
||
|
|
||
| class BoxError(Exception): | ||
| def __init__(self, box, form): | ||
| super(BoxError, self).__init__( | ||
|
|
@@ -311,6 +320,9 @@ def format(self, evaluation, form): | |
| 'MakeBoxes', expr, Symbol(form)).evaluate(evaluation) | ||
| return result | ||
|
|
||
| def output_cost(self): | ||
| return 0 | ||
|
|
||
| def is_free(self, form, evaluation): | ||
| from mathics.core.pattern import StopGenerator | ||
|
|
||
|
|
@@ -1155,6 +1167,21 @@ def block(tex, only_subsup=False): | |
| else: | ||
| raise BoxError(self, 'tex') | ||
|
|
||
| def output_cost(self): | ||
| name = self.get_head_name() | ||
|
|
||
| if name in ('System`ImageBox', 'System`GraphicsBox', 'System`Graphics3DBox'): | ||
| return 0 # always display | ||
|
|
||
| cost = sum(leaf.output_cost() for leaf in self.leaves) | ||
|
|
||
| if name == 'System`List': | ||
| return 2 + cost + len(self.leaves) # {a, b, c} | ||
| elif name in _layout_boxes: | ||
| return cost | ||
| else: | ||
| return cost + 2 + self.head.output_cost() + len(self.leaves) # XYZ[a, b, c] | ||
|
||
|
|
||
| def default_format(self, evaluation, form): | ||
| return '%s[%s]' % (self.head.default_format(evaluation, form), | ||
| ', '.join([leaf.default_format(evaluation, form) | ||
|
|
@@ -1435,6 +1462,9 @@ def __str__(self): | |
| def do_copy(self): | ||
| return Symbol(self.name) | ||
|
|
||
| def output_cost(self): | ||
| return len(self.name) | ||
|
|
||
| def boxes_to_text(self, **options): | ||
| return str(self.name) | ||
|
|
||
|
|
@@ -1596,6 +1626,9 @@ def boxes_to_text(self, **options): | |
| def boxes_to_xml(self, **options): | ||
| return self.make_boxes('MathMLForm').boxes_to_xml(**options) | ||
|
|
||
| def output_cost(self): | ||
| return len(str(self.value)) | ||
|
|
||
| def boxes_to_tex(self, **options): | ||
| return str(self.value) | ||
|
|
||
|
|
@@ -1665,6 +1698,9 @@ def __new__(cls, numerator, denominator=None): | |
| self.value = sympy.Rational(numerator, denominator) | ||
| return self | ||
|
|
||
| def output_cost(self): | ||
| return len(str(self.value)) | ||
|
|
||
| def atom_to_boxes(self, f, evaluation): | ||
| return self.format(evaluation, f.get_name()) | ||
|
|
||
|
|
@@ -1771,6 +1807,9 @@ def __new__(cls, value, p=None): | |
| else: | ||
| return PrecisionReal.__new__(PrecisionReal, value) | ||
|
|
||
| def output_cost(self): | ||
| return len(str(self.value)) | ||
|
|
||
| def boxes_to_text(self, **options): | ||
| return self.make_boxes('System`OutputForm').boxes_to_text(**options) | ||
|
|
||
|
|
@@ -2134,6 +2173,9 @@ def __new__(cls, value): | |
| def __str__(self): | ||
| return '"%s"' % self.value | ||
|
|
||
| def output_cost(self): | ||
| return len(self.value) | ||
|
|
||
| def boxes_to_text(self, show_string_characters=False, output_size_limit=None, **options): | ||
| value = self.value | ||
| if (not show_string_characters and # nopep8 | ||
|
|
@@ -2289,7 +2331,8 @@ def boxes_to_text(self, **options): | |
|
|
||
| def boxes_to_xml(self, **options): | ||
| new_options = dict((k, v) for k, v in options.items() if k != 'output_size_limit') | ||
| return super(Omitted, self).boxes_to_xml(**new_options) | ||
| s = super(Omitted, self).boxes_to_xml(**new_options) | ||
| return "<mtext mathcolor='#4040a0'>%s</mtext>" % s | ||
|
|
||
| def boxes_to_tex(self, **options): | ||
| new_options = dict((k, v) for k, v in options.items() if k != 'output_size_limit') | ||
|
|
@@ -2342,9 +2385,25 @@ def make(self, items, form, segment=None): | |
| raise NotImplementedError() | ||
|
|
||
|
|
||
| class Omissions: | ||
| def __init__(self): | ||
| self._omissions = [] | ||
|
|
||
| def add(self, count): | ||
| n = len(self._omissions) | ||
| if n < 3: | ||
| self._omissions.append('<<%d>>' % count) | ||
| if n == 3: | ||
| self._omissions.append('...') | ||
|
|
||
| def warn(self, evaluation): | ||
| if self._omissions: | ||
| evaluation.message('General', 'omit', ', '.join(self._omissions)) | ||
|
|
||
|
|
||
| class _UnlimitedMakeBoxesStrategy(_MakeBoxesStrategy): | ||
| def __init__(self): | ||
| pass | ||
| self.omissions_occured = False | ||
|
|
||
| def capacity(self): | ||
| return None | ||
|
|
@@ -2365,11 +2424,12 @@ def __init__(self, capacity, side, both_sides, depth): | |
|
|
||
|
|
||
| class _LimitedMakeBoxesStrategy(_MakeBoxesStrategy): | ||
| def __init__(self, capacity, evaluation): | ||
| def __init__(self, capacity, omissions, evaluation): | ||
| self._capacity = capacity | ||
| self._evaluation = evaluation | ||
| self._state = _LimitedMakeBoxesState(self._capacity, 1, True, 1) | ||
| self._unlimited = _UnlimitedMakeBoxesStrategy() | ||
| self._omissions = omissions | ||
|
|
||
| def capacity(self): | ||
| return self._capacity | ||
|
|
@@ -2378,8 +2438,8 @@ def make(self, items, form, segment=None): | |
| state = self._state | ||
| capacity = state.capacity | ||
|
|
||
| if capacity is None or len(items) < 1: | ||
| return self._unlimited(items, form, segment) | ||
| if capacity is None or len(items) <= 2: | ||
| return self._unlimited.make(items, form, segment) | ||
|
|
||
| left_leaves = [] | ||
| right_leaves = [] | ||
|
|
@@ -2447,6 +2507,8 @@ def make(self, items, form, segment=None): | |
| break | ||
|
|
||
| ellipsis_size = len(items) - (len(left_leaves) + len(right_leaves)) | ||
| if ellipsis_size > 0 and self._omissions: | ||
| self._omissions.add(ellipsis_size) | ||
| ellipsis = [Omitted('<<%d>>' % ellipsis_size)] if ellipsis_size > 0 else [] | ||
|
|
||
| if segment is not None: | ||
|
|
@@ -2469,16 +2531,16 @@ def _evaluate(self, item, form, **kwargs): | |
| # the simple solution; the problem is that it's redundant, as for {{{a}, b}, c}, we'd | ||
| # call boxes_to_xml first on {a}, then on {{a}, b}, then on {{{a}, b}, c}. a good fix | ||
| # is not simple though, so let's keep it this way for now. | ||
| cost = len(box.boxes_to_xml(evaluation=self._evaluation)) # evaluate len as XML | ||
| cost = box.output_cost() | ||
|
|
||
| return box, cost | ||
| finally: | ||
| self._state = old_state | ||
|
|
||
|
|
||
| def make_boxes_strategy(capacity, evaluation): | ||
| def make_boxes_strategy(capacity, omissions, evaluation): | ||
| if capacity is None: | ||
| return _UnlimitedMakeBoxesStrategy() | ||
| else: | ||
| return _LimitedMakeBoxesStrategy(capacity, evaluation) | ||
| return _LimitedMakeBoxesStrategy(capacity, omissions, evaluation) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it be better to compute the sum cost of leaves? Also, what about the size of ", " between leaves?