passagemath-repl 10.5.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_repl-10.5.1.data/scripts/sage-cachegrind +25 -0
- passagemath_repl-10.5.1.data/scripts/sage-callgrind +16 -0
- passagemath_repl-10.5.1.data/scripts/sage-cleaner +230 -0
- passagemath_repl-10.5.1.data/scripts/sage-coverage +327 -0
- passagemath_repl-10.5.1.data/scripts/sage-eval +14 -0
- passagemath_repl-10.5.1.data/scripts/sage-fixdoctests +710 -0
- passagemath_repl-10.5.1.data/scripts/sage-inline-fortran +12 -0
- passagemath_repl-10.5.1.data/scripts/sage-ipynb2rst +50 -0
- passagemath_repl-10.5.1.data/scripts/sage-ipython +16 -0
- passagemath_repl-10.5.1.data/scripts/sage-massif +25 -0
- passagemath_repl-10.5.1.data/scripts/sage-notebook +267 -0
- passagemath_repl-10.5.1.data/scripts/sage-omega +25 -0
- passagemath_repl-10.5.1.data/scripts/sage-preparse +302 -0
- passagemath_repl-10.5.1.data/scripts/sage-run +27 -0
- passagemath_repl-10.5.1.data/scripts/sage-run-cython +10 -0
- passagemath_repl-10.5.1.data/scripts/sage-runtests +9 -0
- passagemath_repl-10.5.1.data/scripts/sage-startuptime.py +163 -0
- passagemath_repl-10.5.1.data/scripts/sage-valgrind +34 -0
- passagemath_repl-10.5.1.dist-info/METADATA +77 -0
- passagemath_repl-10.5.1.dist-info/RECORD +162 -0
- passagemath_repl-10.5.1.dist-info/WHEEL +5 -0
- passagemath_repl-10.5.1.dist-info/top_level.txt +1 -0
- sage/all__sagemath_repl.py +119 -0
- sage/doctest/__init__.py +4 -0
- sage/doctest/__main__.py +236 -0
- sage/doctest/all.py +4 -0
- sage/doctest/check_tolerance.py +261 -0
- sage/doctest/control.py +1727 -0
- sage/doctest/external.py +534 -0
- sage/doctest/fixtures.py +383 -0
- sage/doctest/forker.py +2665 -0
- sage/doctest/marked_output.py +102 -0
- sage/doctest/parsing.py +1708 -0
- sage/doctest/parsing_test.py +79 -0
- sage/doctest/reporting.py +733 -0
- sage/doctest/rif_tol.py +124 -0
- sage/doctest/sources.py +1657 -0
- sage/doctest/test.py +584 -0
- sage/doctest/tests/1second.rst +4 -0
- sage/doctest/tests/99seconds.rst +4 -0
- sage/doctest/tests/abort.rst +5 -0
- sage/doctest/tests/atexit.rst +7 -0
- sage/doctest/tests/fail_and_die.rst +6 -0
- sage/doctest/tests/initial.rst +15 -0
- sage/doctest/tests/interrupt.rst +7 -0
- sage/doctest/tests/interrupt_diehard.rst +14 -0
- sage/doctest/tests/keyboardinterrupt.rst +11 -0
- sage/doctest/tests/longtime.rst +5 -0
- sage/doctest/tests/nodoctest +5 -0
- sage/doctest/tests/random_seed.rst +4 -0
- sage/doctest/tests/show_skipped.rst +18 -0
- sage/doctest/tests/sig_on.rst +9 -0
- sage/doctest/tests/simple_failure.rst +8 -0
- sage/doctest/tests/sleep_and_raise.rst +106 -0
- sage/doctest/tests/tolerance.rst +31 -0
- sage/doctest/util.py +750 -0
- sage/interfaces/cleaner.py +48 -0
- sage/interfaces/quit.py +163 -0
- sage/misc/all__sagemath_repl.py +51 -0
- sage/misc/banner.py +235 -0
- sage/misc/benchmark.py +221 -0
- sage/misc/classgraph.py +134 -0
- sage/misc/copying.py +22 -0
- sage/misc/cython.py +694 -0
- sage/misc/dev_tools.py +745 -0
- sage/misc/edit_module.py +304 -0
- sage/misc/explain_pickle.py +3079 -0
- sage/misc/gperftools.py +361 -0
- sage/misc/inline_fortran.py +212 -0
- sage/misc/messaging.py +86 -0
- sage/misc/pager.py +21 -0
- sage/misc/profiler.py +179 -0
- sage/misc/python.py +70 -0
- sage/misc/remote_file.py +53 -0
- sage/misc/sage_eval.py +249 -0
- sage/misc/sage_input.py +3621 -0
- sage/misc/sagedoc.py +1742 -0
- sage/misc/sh.py +38 -0
- sage/misc/trace.py +90 -0
- sage/repl/__init__.py +16 -0
- sage/repl/all.py +15 -0
- sage/repl/attach.py +625 -0
- sage/repl/configuration.py +186 -0
- sage/repl/display/__init__.py +1 -0
- sage/repl/display/fancy_repr.py +354 -0
- sage/repl/display/formatter.py +318 -0
- sage/repl/display/jsmol_iframe.py +290 -0
- sage/repl/display/pretty_print.py +153 -0
- sage/repl/display/util.py +163 -0
- sage/repl/image.py +302 -0
- sage/repl/inputhook.py +91 -0
- sage/repl/interface_magic.py +298 -0
- sage/repl/interpreter.py +854 -0
- sage/repl/ipython_extension.py +593 -0
- sage/repl/ipython_kernel/__init__.py +1 -0
- sage/repl/ipython_kernel/__main__.py +4 -0
- sage/repl/ipython_kernel/all_jupyter.py +10 -0
- sage/repl/ipython_kernel/install.py +301 -0
- sage/repl/ipython_kernel/interact.py +278 -0
- sage/repl/ipython_kernel/kernel.py +217 -0
- sage/repl/ipython_kernel/widgets.py +466 -0
- sage/repl/ipython_kernel/widgets_sagenb.py +587 -0
- sage/repl/ipython_tests.py +163 -0
- sage/repl/load.py +326 -0
- sage/repl/preparse.py +2218 -0
- sage/repl/prompts.py +90 -0
- sage/repl/rich_output/__init__.py +4 -0
- sage/repl/rich_output/backend_base.py +648 -0
- sage/repl/rich_output/backend_doctest.py +316 -0
- sage/repl/rich_output/backend_emacs.py +151 -0
- sage/repl/rich_output/backend_ipython.py +596 -0
- sage/repl/rich_output/buffer.py +311 -0
- sage/repl/rich_output/display_manager.py +829 -0
- sage/repl/rich_output/example.avi +0 -0
- sage/repl/rich_output/example.canvas3d +1 -0
- sage/repl/rich_output/example.dvi +0 -0
- sage/repl/rich_output/example.flv +0 -0
- sage/repl/rich_output/example.gif +0 -0
- sage/repl/rich_output/example.jpg +0 -0
- sage/repl/rich_output/example.mkv +0 -0
- sage/repl/rich_output/example.mov +0 -0
- sage/repl/rich_output/example.mp4 +0 -0
- sage/repl/rich_output/example.ogv +0 -0
- sage/repl/rich_output/example.pdf +0 -0
- sage/repl/rich_output/example.png +0 -0
- sage/repl/rich_output/example.svg +54 -0
- sage/repl/rich_output/example.webm +0 -0
- sage/repl/rich_output/example.wmv +0 -0
- sage/repl/rich_output/example_jmol.spt.zip +0 -0
- sage/repl/rich_output/example_wavefront_scene.mtl +7 -0
- sage/repl/rich_output/example_wavefront_scene.obj +17 -0
- sage/repl/rich_output/output_basic.py +391 -0
- sage/repl/rich_output/output_browser.py +103 -0
- sage/repl/rich_output/output_catalog.py +54 -0
- sage/repl/rich_output/output_graphics.py +320 -0
- sage/repl/rich_output/output_graphics3d.py +345 -0
- sage/repl/rich_output/output_video.py +231 -0
- sage/repl/rich_output/preferences.py +432 -0
- sage/repl/rich_output/pretty_print.py +339 -0
- sage/repl/rich_output/test_backend.py +201 -0
- sage/repl/user_globals.py +214 -0
- sage/tests/all.py +0 -0
- sage/tests/all__sagemath_repl.py +3 -0
- sage/tests/article_heuberger_krenn_kropf_fsm-in-sage.py +630 -0
- sage/tests/arxiv_0812_2725.py +351 -0
- sage/tests/benchmark.py +1925 -0
- sage/tests/book_schilling_zabrocki_kschur_primer.py +795 -0
- sage/tests/book_stein_ent.py +651 -0
- sage/tests/book_stein_modform.py +558 -0
- sage/tests/cmdline.py +796 -0
- sage/tests/combinatorial_hopf_algebras.py +52 -0
- sage/tests/finite_poset.py +623 -0
- sage/tests/functools_partial_src.py +27 -0
- sage/tests/gosper-sum.py +218 -0
- sage/tests/lazy_imports.py +28 -0
- sage/tests/modular_group_cohomology.py +80 -0
- sage/tests/numpy.py +21 -0
- sage/tests/parigp.py +76 -0
- sage/tests/startup.py +27 -0
- sage/tests/symbolic-series.py +76 -0
- sage/tests/sympy.py +16 -0
- sage/tests/test_deprecation.py +31 -0
sage/misc/sage_input.py
ADDED
@@ -0,0 +1,3621 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-repl
|
2
|
+
r"""
|
3
|
+
Sage Input Formatting
|
4
|
+
|
5
|
+
This module provides the function :func:`sage_input` that takes an
|
6
|
+
arbitrary sage value and produces a sequence of commands that, if typed
|
7
|
+
at the ``sage:`` prompt, will recreate the value. If this is not
|
8
|
+
implemented for a particular value, then an exception is raised instead.
|
9
|
+
This might be useful in understanding a part of Sage, or for debugging.
|
10
|
+
For instance, if you have a value produced in a complicated way in the
|
11
|
+
middle of a debugging session, you could use :func:`sage_input` to find
|
12
|
+
a simple way to produce the same value. We attempt to produce commands
|
13
|
+
that are readable and idiomatic.::
|
14
|
+
|
15
|
+
sage: sage_input(3)
|
16
|
+
3
|
17
|
+
sage: sage_input((polygen(RR) + RR(pi))^2, verify=True) # needs sage.symbolic
|
18
|
+
# Verified
|
19
|
+
R.<x> = RR[]
|
20
|
+
x^2 + 6.2831853071795862*x + 9.869604401089358
|
21
|
+
|
22
|
+
With ``verify=True``, :func:`sage_input` also verifies the results, by
|
23
|
+
calling :func:`~sage.misc.sage_eval.sage_eval` on the result and
|
24
|
+
verifying that it is equal to the input.::
|
25
|
+
|
26
|
+
sage: sage_input(GF(2)(1), verify=True)
|
27
|
+
# Verified
|
28
|
+
GF(2)(1)
|
29
|
+
|
30
|
+
We can generate code that works without the preparser, with
|
31
|
+
``preparse=False``; or we can generate code that will work whether or
|
32
|
+
not the preparser is enabled, with ``preparse=None``. Generating code
|
33
|
+
with ``preparse=False`` may be useful to see how to create a certain
|
34
|
+
value in a Python or Cython source file.::
|
35
|
+
|
36
|
+
sage: sage_input(5, verify=True)
|
37
|
+
# Verified
|
38
|
+
5
|
39
|
+
sage: sage_input(5, preparse=False)
|
40
|
+
ZZ(5)
|
41
|
+
sage: sage_input(5, preparse=None)
|
42
|
+
ZZ(5)
|
43
|
+
sage: sage_input(5r, verify=True)
|
44
|
+
# Verified
|
45
|
+
5r
|
46
|
+
sage: sage_input(5r, preparse=False)
|
47
|
+
5
|
48
|
+
sage: sage_input(5r, preparse=None)
|
49
|
+
int(5)
|
50
|
+
|
51
|
+
Adding :func:`sage_input` support to your own classes is
|
52
|
+
straightforward. You need to add a :func:`_sage_input_` method which
|
53
|
+
returns a :class:`SageInputExpression` (henceforth abbreviated as SIE)
|
54
|
+
which will reconstruct this instance of your class.
|
55
|
+
|
56
|
+
A ``_sage_input_`` method takes two parameters, conventionally named
|
57
|
+
``sib`` and ``coerced``. The first argument is a
|
58
|
+
:class:`SageInputBuilder`; it has methods to build SIEs. The second
|
59
|
+
argument, ``coerced``, is a boolean. This is only useful if your class
|
60
|
+
is a subclass of :class:`Element` (although it is always present). If
|
61
|
+
``coerced`` is ``False``, then your method must generate an expression
|
62
|
+
which will evaluate to a value of the correct type with the correct
|
63
|
+
parent. If ``coerced`` is ``True``, then your method may generate an
|
64
|
+
expression of a type that has a canonical coercion to your type; and if
|
65
|
+
``coerced`` is 2, then your method may generate an expression of a type
|
66
|
+
that has a conversion to your type.
|
67
|
+
|
68
|
+
Let's work through some examples. We'll build a sequence of functions
|
69
|
+
that would be acceptable as ``_sage_input_`` methods for the
|
70
|
+
:class:`~sage.rings.rational.Rational` class.
|
71
|
+
|
72
|
+
Here's the first and simplest version.::
|
73
|
+
|
74
|
+
sage: def qq_sage_input_v1(self, sib, coerced):
|
75
|
+
....: return sib(self.numerator())/sib(self.denominator())
|
76
|
+
|
77
|
+
We see that given a :class:`SageInputBuilder` ``sib``, you can construct
|
78
|
+
a SIE for a value ``v`` simply with ``sib(v)``, and you can construct a
|
79
|
+
SIE for a quotient with the division operator. Of course, the other
|
80
|
+
operators also work, and so do function calls, method calls, subscripts,
|
81
|
+
etc.
|
82
|
+
|
83
|
+
We'll test with the following code, which you don't need to understand.
|
84
|
+
(It produces a list of 8 results, showing the formatted versions of -5/7
|
85
|
+
and 3, with the preparser either enabled or disabled and either with or
|
86
|
+
without an automatic coercion to QQ.)::
|
87
|
+
|
88
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
89
|
+
sage: def test_qq_formatter(fmt):
|
90
|
+
....: results = []
|
91
|
+
....: for v in [-5/7, QQ(3)]:
|
92
|
+
....: for pp in [False, True]:
|
93
|
+
....: for coerced in [False, True]:
|
94
|
+
....: sib = SageInputBuilder(preparse=pp)
|
95
|
+
....: results.append(sib.result(fmt(v, sib, coerced)))
|
96
|
+
....: return results
|
97
|
+
|
98
|
+
sage: test_qq_formatter(qq_sage_input_v1)
|
99
|
+
[-ZZ(5)/ZZ(7), -ZZ(5)/ZZ(7), -5/7, -5/7, ZZ(3)/ZZ(1), ZZ(3)/ZZ(1), 3/1, 3/1]
|
100
|
+
|
101
|
+
Let's try for some shorter, perhaps nicer-looking output. We'll start
|
102
|
+
by getting rid of the ``ZZ`` in the denominators; even without the
|
103
|
+
preparser, ``-ZZ(5)/7 == -ZZ(5)/ZZ(7)``.::
|
104
|
+
|
105
|
+
sage: def qq_sage_input_v2(self, sib, coerced):
|
106
|
+
....: return sib(self.numerator())/sib.int(self.denominator())
|
107
|
+
|
108
|
+
The ``int`` method on :class:`SageInputBuilder` returns a SIE for an
|
109
|
+
integer that is always represented in the simple way, without coercions.
|
110
|
+
(So, depending on the preparser mode, it might read in as an
|
111
|
+
:class:`~sage.rings.integer.Integer` or an ``int``.)::
|
112
|
+
|
113
|
+
sage: test_qq_formatter(qq_sage_input_v2)
|
114
|
+
[-ZZ(5)/7, -ZZ(5)/7, -5/7, -5/7, ZZ(3)/1, ZZ(3)/1, 3/1, 3/1]
|
115
|
+
|
116
|
+
Next let us get rid of the divisions by 1. These are more complicated,
|
117
|
+
since if we are not careful we will get results in `\ZZ` instead of `\QQ`::
|
118
|
+
|
119
|
+
sage: def qq_sage_input_v3(self, sib, coerced):
|
120
|
+
....: if self.denominator() == 1:
|
121
|
+
....: if coerced:
|
122
|
+
....: return sib.int(self.numerator())
|
123
|
+
....: else:
|
124
|
+
....: return sib.name('QQ')(sib.int(self.numerator()))
|
125
|
+
....: return sib(self.numerator())/sib.int(self.denominator())
|
126
|
+
|
127
|
+
We see that the \method{name} method gives an SIE representing a \sage
|
128
|
+
constant or function.::
|
129
|
+
|
130
|
+
sage: test_qq_formatter(qq_sage_input_v3)
|
131
|
+
[-ZZ(5)/7, -ZZ(5)/7, -5/7, -5/7, QQ(3), 3, QQ(3), 3]
|
132
|
+
|
133
|
+
This is the prettiest output we're going to get, but let's make one
|
134
|
+
further refinement. Other :class:`_sage_input_` methods, like the one
|
135
|
+
for polynomials, analyze the structure of SIEs; they work better (give
|
136
|
+
prettier output) if negations are at the outside. If the above code
|
137
|
+
were used for rationals, then ``sage_input(polygen(QQ) - 2/3)`` would
|
138
|
+
produce ``x + (-2/3)``; if we change to the following code, then we
|
139
|
+
would get ``x - 2/3`` instead.::
|
140
|
+
|
141
|
+
sage: def qq_sage_input_v4(self, sib, coerced):
|
142
|
+
....: num = self.numerator()
|
143
|
+
....: neg = (num < 0)
|
144
|
+
....: if neg: num = -num
|
145
|
+
....: if self.denominator() == 1:
|
146
|
+
....: if coerced:
|
147
|
+
....: v = sib.int(num)
|
148
|
+
....: else:
|
149
|
+
....: v = sib.name('QQ')(sib.int(num))
|
150
|
+
....: else:
|
151
|
+
....: v = sib(num)/sib.int(self.denominator())
|
152
|
+
....: if neg: v = -v
|
153
|
+
....: return v
|
154
|
+
|
155
|
+
sage: test_qq_formatter(qq_sage_input_v4)
|
156
|
+
[-ZZ(5)/7, -ZZ(5)/7, -5/7, -5/7, QQ(3), 3, QQ(3), 3]
|
157
|
+
|
158
|
+
AUTHORS:
|
159
|
+
|
160
|
+
- Carl Witty (2008-04): new file
|
161
|
+
|
162
|
+
- Vincent Delecroix (2015-02): documentation formatting
|
163
|
+
"""
|
164
|
+
|
165
|
+
# ****************************************************************************
|
166
|
+
# Copyright (C) 2008 Carl Witty <Carl.Witty@gmail.com>
|
167
|
+
# 2015 Vincent Delecroix <20100.delecroix@gmail.com>
|
168
|
+
#
|
169
|
+
# This program is free software: you can redistribute it and/or modify
|
170
|
+
# it under the terms of the GNU General Public License as published by
|
171
|
+
# the Free Software Foundation, either version 2 of the License, or
|
172
|
+
# (at your option) any later version.
|
173
|
+
# https://www.gnu.org/licenses/
|
174
|
+
# ****************************************************************************
|
175
|
+
|
176
|
+
from sage.misc.lazy_import import lazy_import
|
177
|
+
|
178
|
+
lazy_import('sage.rings.real_mpfi', 'RealIntervalFieldElement')
|
179
|
+
lazy_import('sage.rings.complex_interval', 'ComplexIntervalFieldElement')
|
180
|
+
|
181
|
+
|
182
|
+
def sage_input(x, preparse=True, verify=False, allow_locals=False):
|
183
|
+
r"""
|
184
|
+
Return a sequence of commands that can be used to rebuild the object ``x``.
|
185
|
+
|
186
|
+
INPUT:
|
187
|
+
|
188
|
+
- ``x`` -- the value we want to find an input form for
|
189
|
+
|
190
|
+
- ``preparse`` -- (default: ``True``) whether to generate code that requires
|
191
|
+
the preparser. With ``True``, generated code requires the preparser.
|
192
|
+
With ``False``, generated code requires that the preparser not be used.
|
193
|
+
With ``None``, generated code will work whether or not the preparser is
|
194
|
+
used.
|
195
|
+
|
196
|
+
- ``verify`` -- (default: ``False``) if ``True``, then the answer will be
|
197
|
+
evaluated with :func:`sage_eval`, and an exception will be raised if the
|
198
|
+
result is not equal to the original value. (In fact, for ``verify=True``,
|
199
|
+
:func:`sage_input` is effectively run three times, with ``preparse`` set
|
200
|
+
to ``True``, ``False``, and ``None``, and all three results are checked.)
|
201
|
+
This is particularly useful for doctests.
|
202
|
+
|
203
|
+
- ``allow_locals`` -- (default: ``False``) if ``True``, then values that
|
204
|
+
:func:`sage_input` cannot handle are returned in a dictionary, and the
|
205
|
+
returned code assumes that this dictionary is passed as the ``locals``
|
206
|
+
parameter of :func:`sage_eval`. (Otherwise, if :func:`sage_input` cannot
|
207
|
+
handle a value, an exception is raised.)
|
208
|
+
|
209
|
+
EXAMPLES::
|
210
|
+
|
211
|
+
sage: sage_input(GF(2)(1))
|
212
|
+
GF(2)(1)
|
213
|
+
sage: sage_input((GF(2)(0), GF(2)(1)), verify=True)
|
214
|
+
# Verified
|
215
|
+
GF_2 = GF(2)
|
216
|
+
(GF_2(0), GF_2(1))
|
217
|
+
|
218
|
+
When the preparser is enabled, we use the \sage generator syntax.::
|
219
|
+
|
220
|
+
sage: K.<x> = GF(5)[]
|
221
|
+
sage: sage_input(x^3 + 2*x, verify=True)
|
222
|
+
# Verified
|
223
|
+
R.<x> = GF(5)[]
|
224
|
+
x^3 + 2*x
|
225
|
+
sage: sage_input(x^3 + 2*x, preparse=False)
|
226
|
+
R = GF(5)['x']
|
227
|
+
x = R.gen()
|
228
|
+
x**3 + 2*x
|
229
|
+
|
230
|
+
The result of :func:`sage_input` is actually a pair of strings with a
|
231
|
+
special ``__repr__`` method to print nicely.::
|
232
|
+
|
233
|
+
sage: # needs sage.rings.real_mpfr sage.symbolic
|
234
|
+
sage: r = sage_input(RealField(20)(pi), verify=True)
|
235
|
+
sage: r
|
236
|
+
# Verified
|
237
|
+
RealField(20)(3.1415939)
|
238
|
+
sage: isinstance(r, tuple)
|
239
|
+
True
|
240
|
+
sage: len(r)
|
241
|
+
2
|
242
|
+
sage: tuple(r)
|
243
|
+
('# Verified\n', 'RealField(20)(3.1415939)')
|
244
|
+
|
245
|
+
We cannot find an input form for a function.::
|
246
|
+
|
247
|
+
sage: sage_input((3, lambda x: x))
|
248
|
+
Traceback (most recent call last):
|
249
|
+
...
|
250
|
+
ValueError: cannot convert <function <lambda> at 0x...> to sage_input form
|
251
|
+
|
252
|
+
But we can have :func:`sage_input` continue anyway, and return an input form
|
253
|
+
for the rest of the expression, with ``allow_locals=True``.::
|
254
|
+
|
255
|
+
sage: r = sage_input((3, lambda x: x), verify=True, allow_locals=True)
|
256
|
+
sage: r
|
257
|
+
LOCALS:
|
258
|
+
_sil1: <function <lambda> at 0x...>
|
259
|
+
# Verified
|
260
|
+
(3, _sil1)
|
261
|
+
sage: tuple(r)
|
262
|
+
('# Verified\n', '(3, _sil1)', {'_sil1': <function <lambda> at 0x...>})
|
263
|
+
"""
|
264
|
+
if not verify:
|
265
|
+
sib = SageInputBuilder(allow_locals=allow_locals, preparse=preparse)
|
266
|
+
return sib.result(sib(x))
|
267
|
+
|
268
|
+
# In verify mode, we actually compute and verify the answer with
|
269
|
+
# all three settings of preparse.
|
270
|
+
|
271
|
+
for pp in (True, False, None):
|
272
|
+
sib = SageInputBuilder(allow_locals=allow_locals, preparse=pp)
|
273
|
+
ans = sib.result(sib(x))
|
274
|
+
verify_si_answer(x, ans, pp)
|
275
|
+
if pp == preparse:
|
276
|
+
ans_l = list(ans)
|
277
|
+
ans_l[0] = '# Verified\n' + ans_l[0]
|
278
|
+
final_answer = SageInputAnswer(*ans_l)
|
279
|
+
|
280
|
+
return final_answer
|
281
|
+
|
282
|
+
|
283
|
+
class SageInputBuilder:
|
284
|
+
r"""
|
285
|
+
An instance of this class is passed to ``_sage_input_`` methods.
|
286
|
+
It keeps track of the current state of the ``_sage_input_`` process,
|
287
|
+
and contains many utility methods for building :class:`SageInputExpression`
|
288
|
+
objects.
|
289
|
+
|
290
|
+
In normal use, instances of :class:`SageInputBuilder` are created
|
291
|
+
internally by :func:`sage_input`, but it may be useful to create
|
292
|
+
an instance directly for testing or doctesting.
|
293
|
+
|
294
|
+
EXAMPLES::
|
295
|
+
|
296
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
297
|
+
|
298
|
+
We can create a :class:`SageInputBuilder`, use it to create some
|
299
|
+
:class:`SageInputExpression` s, and get a result. (As mentioned
|
300
|
+
above, this is only useful for testing or doctesting; normally
|
301
|
+
you would just use :func:`sage_input`.)::
|
302
|
+
|
303
|
+
sage: sib = SageInputBuilder()
|
304
|
+
sage: sib.result((sib(3) + sib(4)) * (sib(5) + sib(6)))
|
305
|
+
(3 + 4)*(5 + 6)
|
306
|
+
"""
|
307
|
+
|
308
|
+
def __init__(self, allow_locals=False, preparse=True):
|
309
|
+
r"""
|
310
|
+
Initialize an instance of :class:`SageInputBuilder`.
|
311
|
+
|
312
|
+
In normal use, instances of :class:`SageInputBuilder` are created
|
313
|
+
internally by :func:`sage_input`, but it may be useful to create
|
314
|
+
an instance directly for testing or doctesting.
|
315
|
+
|
316
|
+
INPUT:
|
317
|
+
|
318
|
+
- ``allow_locals`` -- (default: ``False``) if true, then values
|
319
|
+
that cannot be converted to input form will be stored in
|
320
|
+
a dictionary, which must be passed as the ``locals``
|
321
|
+
when evaluating the result.
|
322
|
+
|
323
|
+
- ``preparse`` -- (default: ``True``) if true, then the result
|
324
|
+
will assume that the preparser is enabled. If false, then
|
325
|
+
the result will assume that the preparser is disabled.
|
326
|
+
If ``None``, then the result will work whether or
|
327
|
+
not the preparser is enabled.
|
328
|
+
|
329
|
+
EXAMPLES::
|
330
|
+
|
331
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
332
|
+
sage: SageInputBuilder().preparse()
|
333
|
+
True
|
334
|
+
sage: SageInputBuilder(preparse=False).preparse()
|
335
|
+
False
|
336
|
+
"""
|
337
|
+
self._allow_locals = allow_locals
|
338
|
+
self._preparse = preparse
|
339
|
+
self._cached_types = set()
|
340
|
+
self._cache = {}
|
341
|
+
self._id_cache = {}
|
342
|
+
self._parent_gens = {}
|
343
|
+
self._next_local = 1
|
344
|
+
self._locals = {}
|
345
|
+
|
346
|
+
def __call__(self, x, coerced=False):
|
347
|
+
r"""
|
348
|
+
Try to convert an arbitrary value ``x`` into a
|
349
|
+
:class:`SageInputExpression` (an SIE).
|
350
|
+
|
351
|
+
We first check to see if an SIE has been cached for ``x``;
|
352
|
+
if so, we return it. If ``x`` is already an SIE, we return
|
353
|
+
it unchanged.
|
354
|
+
|
355
|
+
If ``x`` has a \method{_sage_input_} method, we call that
|
356
|
+
method.
|
357
|
+
|
358
|
+
Otherwise, if ``x`` is a value of some Python type that
|
359
|
+
we know how to deal with, we convert it directly.
|
360
|
+
|
361
|
+
Finally, for values we don't know how to convert, if
|
362
|
+
``self._allow_locals`` is true, we add it to a
|
363
|
+
``locals`` dictionary.
|
364
|
+
|
365
|
+
EXAMPLES::
|
366
|
+
|
367
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
368
|
+
|
369
|
+
sage: sib = SageInputBuilder()
|
370
|
+
sage: sib.result(sib(sib(3)))
|
371
|
+
3
|
372
|
+
|
373
|
+
sage: sib = SageInputBuilder()
|
374
|
+
sage: sib.result(sib(GF(17)(5)))
|
375
|
+
GF(17)(5)
|
376
|
+
|
377
|
+
The argument ``coerced=True`` or ``coerced=2`` will get
|
378
|
+
passed to the \method{_sage_input_} method of the argument.::
|
379
|
+
|
380
|
+
sage: sib = SageInputBuilder()
|
381
|
+
sage: sib.result(sib(GF(17)(5), True))
|
382
|
+
5
|
383
|
+
sage: sib.result(sib(RealField(200)(1.5), True)) # needs sage.rings.real_mpfr
|
384
|
+
1.5000000000000000000000000000000000000000000000000000000000000
|
385
|
+
sage: sib.result(sib(RealField(200)(1.5), 2)) # needs sage.rings.real_mpfr
|
386
|
+
1.5
|
387
|
+
|
388
|
+
Since :func:`sage_input` directly calls this method, all
|
389
|
+
of the following are indirect doctests.::
|
390
|
+
|
391
|
+
sage: sage_input(True)
|
392
|
+
True
|
393
|
+
sage: sage_input(-5r, verify=True)
|
394
|
+
# Verified
|
395
|
+
-5r
|
396
|
+
sage: sage_input(7r, preparse=False, verify=True)
|
397
|
+
# Verified
|
398
|
+
7
|
399
|
+
sage: sage_input(-11r, preparse=None, verify=True)
|
400
|
+
# Verified
|
401
|
+
-int(11)
|
402
|
+
sage: sage_input(float(-infinity), preparse=True, verify=True)
|
403
|
+
# Verified
|
404
|
+
-float(infinity)
|
405
|
+
sage: sage_input(float(NaN), preparse=True, verify=True) # needs sage.symbolic
|
406
|
+
# Verified
|
407
|
+
float(NaN)
|
408
|
+
sage: sage_input(float(-pi), preparse=True, verify=True) # needs sage.symbolic
|
409
|
+
# Verified
|
410
|
+
float(-RR(3.1415926535897931))
|
411
|
+
sage: sage_input(float(42), preparse=True, verify=True) # needs sage.rings.real_mpfr
|
412
|
+
# Verified
|
413
|
+
float(42)
|
414
|
+
sage: sage_input("Hello, world\n", verify=True)
|
415
|
+
# Verified
|
416
|
+
'Hello, world\n'
|
417
|
+
sage: sage_input("'", verify=True)
|
418
|
+
# Verified
|
419
|
+
"'"
|
420
|
+
sage: sage_input('"', verify=True)
|
421
|
+
# Verified
|
422
|
+
'"'
|
423
|
+
sage: sage_input(''' "'Hi,' she said." ''', verify=True)
|
424
|
+
# Verified
|
425
|
+
' "\'Hi,\' she said." '
|
426
|
+
sage: sage_input('Icky chars: \0\n\t\b\'\"\200\300\234', verify=True)
|
427
|
+
# Verified
|
428
|
+
'Icky chars: \x00\n\t\x08\'"\x80\xc0\x9c'
|
429
|
+
sage: sage_input('unicode with spectral: \u1234\U00012345', verify=True)
|
430
|
+
# Verified
|
431
|
+
'unicode with spectral: \u1234\U00012345'
|
432
|
+
sage: sage_input((2, 3.5, 'Hi'), verify=True) # needs sage.rings.real_mpfr
|
433
|
+
# Verified
|
434
|
+
(2, 3.5, 'Hi')
|
435
|
+
sage: sage_input(lambda x: x)
|
436
|
+
Traceback (most recent call last):
|
437
|
+
...
|
438
|
+
ValueError: cannot convert <function <lambda> at 0x...> to sage_input form
|
439
|
+
sage: sage_input(lambda x: x, allow_locals=True, verify=True)
|
440
|
+
LOCALS:
|
441
|
+
_sil1: <function <lambda> at 0x...>
|
442
|
+
# Verified
|
443
|
+
_sil1
|
444
|
+
"""
|
445
|
+
# We want to look up x in our cache, to see if we've seen it before.
|
446
|
+
# However, we don't want to assume that hashing x is always
|
447
|
+
# efficient, so we only try the lookup if some value of the same
|
448
|
+
# type as x has been cached.
|
449
|
+
from sage.structure.all import parent
|
450
|
+
|
451
|
+
if type(x) in self._cached_types:
|
452
|
+
v = self._cache.get((parent(x), x))
|
453
|
+
if v is not None:
|
454
|
+
return v
|
455
|
+
|
456
|
+
v = self._id_cache.get(id(x))
|
457
|
+
if v is not None:
|
458
|
+
return v[1]
|
459
|
+
|
460
|
+
if isinstance(x, SageInputExpression):
|
461
|
+
return x
|
462
|
+
|
463
|
+
if hasattr(x, '_sage_input_'):
|
464
|
+
return x._sage_input_(self, coerced)
|
465
|
+
|
466
|
+
if x is None:
|
467
|
+
return SIE_literal_stringrep(self, 'None')
|
468
|
+
|
469
|
+
if isinstance(x, bool):
|
470
|
+
return SIE_literal_stringrep(self, str(x))
|
471
|
+
|
472
|
+
if isinstance(x, int):
|
473
|
+
if self._preparse is True:
|
474
|
+
if x < 0:
|
475
|
+
return -SIE_literal_stringrep(self, str(-x) + 'r')
|
476
|
+
else:
|
477
|
+
return SIE_literal_stringrep(self, str(x) + 'r')
|
478
|
+
elif self._preparse is False:
|
479
|
+
return self.int(x)
|
480
|
+
else:
|
481
|
+
if x < 0:
|
482
|
+
return -self.name('int')(self.int(-x))
|
483
|
+
else:
|
484
|
+
return self.name('int')(self.int(x))
|
485
|
+
|
486
|
+
if isinstance(x, float):
|
487
|
+
# floats could often have prettier output,
|
488
|
+
# but I think they're rare enough in Sage that it's not
|
489
|
+
# worth the effort.
|
490
|
+
from math import inf
|
491
|
+
if x == inf:
|
492
|
+
return self.name('float')(self.name('infinity'))
|
493
|
+
if x != x:
|
494
|
+
return self.name('float')(self.name('NaN'))
|
495
|
+
if x == -inf:
|
496
|
+
return -self.name('float')(self.name('infinity'))
|
497
|
+
if self._preparse is False and float(str(x)) == x:
|
498
|
+
if x < 0:
|
499
|
+
return -SIE_literal_stringrep(self, str(-x))
|
500
|
+
else:
|
501
|
+
return SIE_literal_stringrep(self, str(x))
|
502
|
+
from sage.rings.real_mpfr import RR
|
503
|
+
from sage.rings.integer_ring import ZZ
|
504
|
+
rrx = RR(x)
|
505
|
+
if rrx in ZZ and abs(rrx) < (1 << 53):
|
506
|
+
return self.name('float')(self.int(ZZ(rrx)))
|
507
|
+
return self.name('float')(RR(x))
|
508
|
+
|
509
|
+
if isinstance(x, str):
|
510
|
+
return SIE_literal_stringrep(self, repr(x))
|
511
|
+
|
512
|
+
if isinstance(x, tuple):
|
513
|
+
return SIE_tuple(self, [self(_) for _ in x], False)
|
514
|
+
|
515
|
+
if isinstance(x, list):
|
516
|
+
return SIE_tuple(self, [self(_) for _ in x], True)
|
517
|
+
|
518
|
+
if isinstance(x, dict):
|
519
|
+
return self.dict(x)
|
520
|
+
|
521
|
+
if self._allow_locals:
|
522
|
+
loc = self._next_local
|
523
|
+
self._next_local += 1
|
524
|
+
loc_name = '_sil%d' % loc
|
525
|
+
self._locals[loc_name] = x
|
526
|
+
return SIE_literal_stringrep(self, loc_name)
|
527
|
+
else:
|
528
|
+
raise ValueError("cannot convert {} to sage_input form".format(x))
|
529
|
+
|
530
|
+
def preparse(self):
|
531
|
+
r"""
|
532
|
+
Check the preparse status.
|
533
|
+
|
534
|
+
It returns ``True`` if the preparser will be enabled, ``False`` if it
|
535
|
+
will be disabled, and ``None`` if the result must work whether or not
|
536
|
+
the preparser is enabled.
|
537
|
+
|
538
|
+
For example, this is useful in the \method{_sage_input_}
|
539
|
+
methods of :class:`~sage.rings.integer.Integer` and :class:`RealNumber`; but most
|
540
|
+
\method{_sage_input_} methods will not need to examine this.
|
541
|
+
|
542
|
+
EXAMPLES::
|
543
|
+
|
544
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
545
|
+
sage: SageInputBuilder().preparse()
|
546
|
+
True
|
547
|
+
sage: SageInputBuilder(preparse=False).preparse()
|
548
|
+
False
|
549
|
+
"""
|
550
|
+
return self._preparse
|
551
|
+
|
552
|
+
def int(self, n):
|
553
|
+
r"""
|
554
|
+
Return a raw SIE from the integer ``n``.
|
555
|
+
|
556
|
+
As it is raw, it may read back as a Sage Integer or a Python int,
|
557
|
+
depending on its size and whether the preparser is enabled.
|
558
|
+
|
559
|
+
INPUT:
|
560
|
+
|
561
|
+
- ``n`` -- a Sage Integer or a Python int
|
562
|
+
|
563
|
+
EXAMPLES::
|
564
|
+
|
565
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
566
|
+
|
567
|
+
sage: sib = SageInputBuilder()
|
568
|
+
sage: sib.result(sib.int(-3^50))
|
569
|
+
-717897987691852588770249
|
570
|
+
|
571
|
+
sage: sib = SageInputBuilder()
|
572
|
+
sage: sib.result(sib.int(-42r))
|
573
|
+
-42
|
574
|
+
"""
|
575
|
+
if n < 0:
|
576
|
+
return -SIE_literal_stringrep(self, -n)
|
577
|
+
else:
|
578
|
+
return SIE_literal_stringrep(self, n)
|
579
|
+
|
580
|
+
def float_str(self, n):
|
581
|
+
r"""
|
582
|
+
Given a string representing a floating-point number,
|
583
|
+
produces a :class:`SageInputExpression` that formats as that
|
584
|
+
string.
|
585
|
+
|
586
|
+
EXAMPLES::
|
587
|
+
|
588
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
589
|
+
|
590
|
+
sage: sib = SageInputBuilder()
|
591
|
+
sage: sib.result(sib.float_str(repr(RR(e)))) # needs sage.symbolic
|
592
|
+
2.71828182845905
|
593
|
+
"""
|
594
|
+
return SIE_literal_stringrep(self, n)
|
595
|
+
|
596
|
+
def name(self, n):
|
597
|
+
r"""
|
598
|
+
Given a string representing a Python name,
|
599
|
+
produces a :class:`SageInputExpression` for that name.
|
600
|
+
|
601
|
+
EXAMPLES::
|
602
|
+
|
603
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
604
|
+
|
605
|
+
sage: sib = SageInputBuilder()
|
606
|
+
sage: sib.result(sib.name('pi') + sib.name('e'))
|
607
|
+
pi + e
|
608
|
+
"""
|
609
|
+
return SIE_literal_stringrep(self, n)
|
610
|
+
|
611
|
+
def cache(self, x, sie, name):
|
612
|
+
r"""
|
613
|
+
INPUT:
|
614
|
+
|
615
|
+
- ``x`` -- an arbitrary value
|
616
|
+
|
617
|
+
- ``sie`` -- a :class:`SageInputExpression`
|
618
|
+
|
619
|
+
- ``name`` -- a requested variable name
|
620
|
+
|
621
|
+
Enters ``x`` and ``sie`` in a cache, so that subsequent calls
|
622
|
+
``self(x)`` will directly return ``sie``. Also, marks the
|
623
|
+
requested name of this ``sie`` to be ``name``.
|
624
|
+
|
625
|
+
This should almost always be called as part of the
|
626
|
+
\method{_sage_input_} method of a parent. It may also be called
|
627
|
+
on values of an arbitrary type, which may be useful if the values
|
628
|
+
are both large and likely to be used multiple times in a single
|
629
|
+
expression.
|
630
|
+
|
631
|
+
EXAMPLES::
|
632
|
+
|
633
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
634
|
+
|
635
|
+
sage: sib = SageInputBuilder()
|
636
|
+
sage: sie42 = sib(GF(101)(42))
|
637
|
+
sage: sib.cache(GF(101)(42), sie42, 'the_ultimate_answer')
|
638
|
+
sage: sib.result(sib(GF(101)(42)) + sib(GF(101)(42)))
|
639
|
+
the_ultimate_answer = GF(101)(42)
|
640
|
+
the_ultimate_answer + the_ultimate_answer
|
641
|
+
|
642
|
+
Note that we don't assign the result to a variable if the value
|
643
|
+
is only used once.::
|
644
|
+
|
645
|
+
sage: sib = SageInputBuilder()
|
646
|
+
sage: sie42 = sib(GF(101)(42))
|
647
|
+
sage: sib.cache(GF(101)(42), sie42, 'the_ultimate_answer')
|
648
|
+
sage: sib.result(sib(GF(101)(42)) + sib(GF(101)(43)))
|
649
|
+
GF_101 = GF(101)
|
650
|
+
GF_101(42) + GF_101(43)
|
651
|
+
"""
|
652
|
+
from sage.structure.all import parent
|
653
|
+
|
654
|
+
self._cached_types.add(type(x))
|
655
|
+
self._cache[(parent(x), x)] = sie
|
656
|
+
sie._sie_preferred_varname = name
|
657
|
+
|
658
|
+
def id_cache(self, x, sie, name):
|
659
|
+
r"""
|
660
|
+
INPUT:
|
661
|
+
|
662
|
+
- ``x`` -- an arbitrary value
|
663
|
+
|
664
|
+
- ``sie`` -- a :class:`SageInputExpression`
|
665
|
+
|
666
|
+
- ``name`` -- a requested variable name
|
667
|
+
|
668
|
+
Enters ``x`` and ``sie`` in a cache, so that subsequent calls
|
669
|
+
``self(x)`` will directly return ``sie``. Also, marks the
|
670
|
+
requested name of this ``sie`` to be ``name``. Differs from
|
671
|
+
the \method{cache} method in that the cache is keyed by
|
672
|
+
``id(x)`` instead of by ``x``.
|
673
|
+
|
674
|
+
This may be called on values of an arbitrary type, which may
|
675
|
+
be useful if the values are both large and likely to be used
|
676
|
+
multiple times in a single expression; it should be preferred to
|
677
|
+
\method{cache} if equality on the values is difficult or impossible
|
678
|
+
to compute.
|
679
|
+
|
680
|
+
EXAMPLES::
|
681
|
+
|
682
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
683
|
+
|
684
|
+
sage: x = polygen(ZZ)
|
685
|
+
sage: sib = SageInputBuilder()
|
686
|
+
sage: my_42 = 42*x
|
687
|
+
sage: sie42 = sib(my_42)
|
688
|
+
sage: sib.id_cache(my_42, sie42, 'the_ultimate_answer')
|
689
|
+
sage: sib.result(sib(my_42) + sib(my_42))
|
690
|
+
R.<x> = ZZ[]
|
691
|
+
the_ultimate_answer = 42*x
|
692
|
+
the_ultimate_answer + the_ultimate_answer
|
693
|
+
|
694
|
+
Since id_cache keys off of object identity ("is"), the
|
695
|
+
following does not trigger the cache.::
|
696
|
+
|
697
|
+
sage: sib.result(sib(42*x) + sib(42*x))
|
698
|
+
42*x + 42*x
|
699
|
+
|
700
|
+
Note that we don't assign the result to a variable if the value
|
701
|
+
is only used once.::
|
702
|
+
|
703
|
+
sage: sib = SageInputBuilder()
|
704
|
+
sage: my_42 = 42*x
|
705
|
+
sage: sie42 = sib(my_42)
|
706
|
+
sage: sib.id_cache(my_42, sie42, 'the_ultimate_answer')
|
707
|
+
sage: sib.result(sib(my_42) + sib(43*x))
|
708
|
+
R.<x> = ZZ[]
|
709
|
+
42*x + 43*x
|
710
|
+
"""
|
711
|
+
# If we just mapped id(x) -> sie, then it's possible that x could
|
712
|
+
# be freed and another value allocated at the same position,
|
713
|
+
# corrupting the cache. But since we store x, that can't happen;
|
714
|
+
# we don't even have to look at x when we read the cache.
|
715
|
+
self._id_cache[id(x)] = (x, sie)
|
716
|
+
sie._sie_preferred_varname = name
|
717
|
+
|
718
|
+
def import_name(self, module, name, alt_name=None):
|
719
|
+
r"""
|
720
|
+
INPUT:
|
721
|
+
|
722
|
+
- ``module``, ``name``, ``alt_name`` -- strings
|
723
|
+
|
724
|
+
Creates an expression that will import a name from a module and
|
725
|
+
then use that name.
|
726
|
+
|
727
|
+
EXAMPLES::
|
728
|
+
|
729
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
730
|
+
|
731
|
+
sage: sib = SageInputBuilder()
|
732
|
+
sage: v1 = sib.import_name('sage.foo.bar', 'baz')
|
733
|
+
sage: v2 = sib.import_name('sage.foo.bar', 'ZZ', 'not_the_real_ZZ')
|
734
|
+
sage: sib.result(v1+v2)
|
735
|
+
from sage.foo.bar import baz
|
736
|
+
from sage.foo.bar import ZZ as not_the_real_ZZ
|
737
|
+
baz + not_the_real_ZZ
|
738
|
+
|
739
|
+
We adjust the names if there is a conflict.::
|
740
|
+
|
741
|
+
sage: sib = SageInputBuilder()
|
742
|
+
sage: v1 = sib.import_name('sage.foo', 'poly')
|
743
|
+
sage: v2 = sib.import_name('sage.bar', 'poly')
|
744
|
+
sage: sib.result(v1+v2)
|
745
|
+
from sage.foo import poly as poly1
|
746
|
+
from sage.bar import poly as poly2
|
747
|
+
poly1 + poly2
|
748
|
+
"""
|
749
|
+
return SIE_import_name(self, module, name, alt_name)
|
750
|
+
|
751
|
+
def assign(self, e, val):
|
752
|
+
r"""
|
753
|
+
Construct a command that performs the assignment ``e=val``.
|
754
|
+
|
755
|
+
Can only be used as an argument to the ``command`` method.
|
756
|
+
|
757
|
+
INPUT:
|
758
|
+
|
759
|
+
- ``e``, ``val`` -- SageInputExpression
|
760
|
+
|
761
|
+
EXAMPLES::
|
762
|
+
|
763
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
764
|
+
|
765
|
+
sage: sib = SageInputBuilder()
|
766
|
+
sage: circular = sib([None])
|
767
|
+
sage: sib.command(circular, sib.assign(circular[0], circular))
|
768
|
+
sage: sib.result(circular)
|
769
|
+
si = [None]
|
770
|
+
si[0] = si
|
771
|
+
si
|
772
|
+
"""
|
773
|
+
e = self(e)
|
774
|
+
val = self(val)
|
775
|
+
|
776
|
+
return SIE_assign(self, e, val)
|
777
|
+
|
778
|
+
def command(self, v, cmd):
|
779
|
+
r"""
|
780
|
+
INPUT:
|
781
|
+
|
782
|
+
- ``v``, ``cmd`` -- SageInputExpression
|
783
|
+
|
784
|
+
Attaches a command to v, which will be executed before v is used.
|
785
|
+
Multiple commands will be executed in the order added.
|
786
|
+
|
787
|
+
EXAMPLES::
|
788
|
+
|
789
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
790
|
+
|
791
|
+
sage: sib = SageInputBuilder()
|
792
|
+
sage: incr_list = sib([])
|
793
|
+
sage: sib.command(incr_list, incr_list.append(1))
|
794
|
+
sage: sib.command(incr_list, incr_list.extend([2, 3]))
|
795
|
+
sage: sib.result(incr_list)
|
796
|
+
si = []
|
797
|
+
si.append(1)
|
798
|
+
si.extend([2, 3])
|
799
|
+
si
|
800
|
+
"""
|
801
|
+
v = self(v)
|
802
|
+
cmd = self(cmd)
|
803
|
+
|
804
|
+
v._sie_commands.append(cmd)
|
805
|
+
|
806
|
+
def dict(self, entries):
|
807
|
+
r"""
|
808
|
+
Given a dictionary, or a list of (key, value) pairs,
|
809
|
+
produces a :class:`SageInputExpression` representing
|
810
|
+
the dictionary.
|
811
|
+
|
812
|
+
EXAMPLES::
|
813
|
+
|
814
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
815
|
+
|
816
|
+
sage: sib = SageInputBuilder()
|
817
|
+
sage: sib.result(sib.dict({1:1, 2:5/2, 3:100/3}))
|
818
|
+
{1:1, 2:5/2, 3:100/3}
|
819
|
+
sage: sib.result(sib.dict([('hello', 'sunshine'), ('goodbye', 'rain')]))
|
820
|
+
{'hello':'sunshine', 'goodbye':'rain'}
|
821
|
+
"""
|
822
|
+
if isinstance(entries, dict):
|
823
|
+
entries = list(entries.items())
|
824
|
+
entries = [(self(key), self(val)) for (key, val) in entries]
|
825
|
+
return SIE_dict(self, entries)
|
826
|
+
|
827
|
+
def getattr(self, sie, attr):
|
828
|
+
r"""
|
829
|
+
Given a :class:`SageInputExpression` representing ``foo``
|
830
|
+
and an attribute name bar, produce a :class:`SageInputExpression`
|
831
|
+
representing ``foo.bar``. Normally, you could just use
|
832
|
+
attribute-access syntax, but that doesn't work if bar
|
833
|
+
is some attribute that bypasses __getattr__ (such as if
|
834
|
+
bar is '__getattr__' itself).
|
835
|
+
|
836
|
+
EXAMPLES::
|
837
|
+
|
838
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
839
|
+
|
840
|
+
sage: sib = SageInputBuilder()
|
841
|
+
sage: sib.getattr(ZZ, '__getattr__')
|
842
|
+
{getattr: {atomic:ZZ}.__getattr__}
|
843
|
+
sage: sib.getattr(sib.name('foo'), '__new__')
|
844
|
+
{getattr: {atomic:foo}.__new__}
|
845
|
+
"""
|
846
|
+
return SIE_getattr(self, self(sie), attr)
|
847
|
+
|
848
|
+
def empty_subscript(self, parent):
|
849
|
+
r"""
|
850
|
+
Given a :class:`SageInputExpression` representing ``foo``,
|
851
|
+
produces a :class:`SageInputExpression` representing ``foo[]``.
|
852
|
+
Since this is not legal Python syntax, it is useful only for
|
853
|
+
producing the \sage generator syntax for a polynomial ring.
|
854
|
+
|
855
|
+
EXAMPLES::
|
856
|
+
|
857
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
858
|
+
|
859
|
+
sage: sib = SageInputBuilder()
|
860
|
+
sage: sib.result(sib.empty_subscript(sib(2) + sib(3)))
|
861
|
+
(2 + 3)[]
|
862
|
+
|
863
|
+
The following calls this method indirectly.::
|
864
|
+
|
865
|
+
sage: sage_input(polygen(ZZ['y']))
|
866
|
+
R.<x> = ZZ['y'][]
|
867
|
+
x
|
868
|
+
"""
|
869
|
+
return SIE_subscript(self, parent, None)
|
870
|
+
|
871
|
+
def use_variable(self, sie, name):
|
872
|
+
r"""
|
873
|
+
Marks the :class:`SageInputExpression` ``sie`` to use a variable
|
874
|
+
even if it is only referenced once. (If ``sie`` is the final
|
875
|
+
top-level expression, though, it will not use a variable.)
|
876
|
+
|
877
|
+
EXAMPLES::
|
878
|
+
|
879
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
880
|
+
|
881
|
+
sage: sib = SageInputBuilder()
|
882
|
+
sage: e = sib.name('MatrixSpace')(ZZ, 10, 10)
|
883
|
+
sage: sib.use_variable(e, 'MS')
|
884
|
+
sage: sib.result(e.zero_matrix())
|
885
|
+
MS = MatrixSpace(ZZ, 10, 10)
|
886
|
+
MS.zero_matrix()
|
887
|
+
|
888
|
+
Without the call to use_variable, we get this instead::
|
889
|
+
|
890
|
+
sage: sib = SageInputBuilder()
|
891
|
+
sage: e = sib.name('MatrixSpace')(ZZ, 10, 10)
|
892
|
+
sage: sib.result(e.zero_matrix())
|
893
|
+
MatrixSpace(ZZ, 10, 10).zero_matrix()
|
894
|
+
|
895
|
+
And even with the call to use_variable, we don't use a variable here::
|
896
|
+
|
897
|
+
sage: sib = SageInputBuilder()
|
898
|
+
sage: e = sib.name('MatrixSpace')(ZZ, 10, 10)
|
899
|
+
sage: sib.use_variable(e, 'MS')
|
900
|
+
sage: sib.result(e)
|
901
|
+
MatrixSpace(ZZ, 10, 10)
|
902
|
+
"""
|
903
|
+
sie._sie_preferred_varname = name
|
904
|
+
sie._sie_request_use_var = True
|
905
|
+
|
906
|
+
def share(self, sie):
|
907
|
+
r"""
|
908
|
+
Mark the given expression as sharable, so that it will be replaced
|
909
|
+
by a variable if it occurs multiple times in the expression.
|
910
|
+
(Most non-single-token expressions are already sharable.)
|
911
|
+
|
912
|
+
EXAMPLES::
|
913
|
+
|
914
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
915
|
+
|
916
|
+
Without explicitly using .share(), string literals are not shared::
|
917
|
+
|
918
|
+
sage: sib = SageInputBuilder()
|
919
|
+
sage: e = sib('hello')
|
920
|
+
sage: sib.result(sib((e, e)))
|
921
|
+
('hello', 'hello')
|
922
|
+
|
923
|
+
See the difference if we use .share()::
|
924
|
+
|
925
|
+
sage: sib = SageInputBuilder()
|
926
|
+
sage: e = sib('hello')
|
927
|
+
sage: sib.share(e)
|
928
|
+
sage: sib.result(sib((e, e)))
|
929
|
+
si = 'hello'
|
930
|
+
(si, si)
|
931
|
+
"""
|
932
|
+
sie._sie_share = True
|
933
|
+
|
934
|
+
def parent_with_gens(self, parent, sie, gen_names, name, gens_syntax=None):
|
935
|
+
r"""
|
936
|
+
This method is used for parents with generators, to manage the
|
937
|
+
\sage preparser generator syntax (like ``K.<x> = QQ[]``).
|
938
|
+
|
939
|
+
The \method{_sage_input_} method of a parent class with
|
940
|
+
generators should construct a :class:`SageInputExpression` for
|
941
|
+
the parent, and then call this method with the parent itself,
|
942
|
+
the constructed SIE, a sequence containing the names of the
|
943
|
+
generators, and (optionally) another SIE to use if the \sage
|
944
|
+
generator syntax is used; typically this will be the same as
|
945
|
+
the first SIE except omitting a ``names`` parameter.
|
946
|
+
|
947
|
+
EXAMPLES::
|
948
|
+
|
949
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
950
|
+
|
951
|
+
|
952
|
+
sage: def test_setup(use_gens=True, preparse=True):
|
953
|
+
....: sib = SageInputBuilder(preparse=preparse)
|
954
|
+
....: gen_names=('foo', 'bar')
|
955
|
+
....: parent = "some parent"
|
956
|
+
....: normal_sie = sib.name('make_a_parent')(names=gen_names)
|
957
|
+
....: if use_gens:
|
958
|
+
....: gens_sie = sib.name('make_a_parent')()
|
959
|
+
....: else:
|
960
|
+
....: gens_sie = None
|
961
|
+
....: name = 'the_thing'
|
962
|
+
....: result = sib.parent_with_gens(parent, normal_sie,
|
963
|
+
....: gen_names, name,
|
964
|
+
....: gens_syntax=gens_sie)
|
965
|
+
....: return sib, result
|
966
|
+
|
967
|
+
sage: sib, par_sie = test_setup()
|
968
|
+
sage: sib.result(par_sie)
|
969
|
+
make_a_parent(names=('foo', 'bar'))
|
970
|
+
|
971
|
+
sage: sib, par_sie = test_setup()
|
972
|
+
sage: sib.result(sib(3) * sib.gen("some parent", 0))
|
973
|
+
the_thing.<foo,bar> = make_a_parent()
|
974
|
+
3*foo
|
975
|
+
|
976
|
+
sage: sib, par_sie = test_setup(preparse=False)
|
977
|
+
sage: sib.result(par_sie)
|
978
|
+
make_a_parent(names=('foo', 'bar'))
|
979
|
+
|
980
|
+
sage: sib, par_sie = test_setup(preparse=False)
|
981
|
+
sage: sib.result(sib(3) * sib.gen("some parent", 0))
|
982
|
+
the_thing = make_a_parent(names=('foo', 'bar'))
|
983
|
+
foo,bar = the_thing.gens()
|
984
|
+
ZZ(3)*foo
|
985
|
+
|
986
|
+
sage: sib, par_sie = test_setup(use_gens=False)
|
987
|
+
sage: sib.result(par_sie)
|
988
|
+
make_a_parent(names=('foo', 'bar'))
|
989
|
+
|
990
|
+
sage: sib, par_sie = test_setup(use_gens=False)
|
991
|
+
sage: sib.result(sib(3) * sib.gen("some parent", 0))
|
992
|
+
the_thing = make_a_parent(names=('foo', 'bar'))
|
993
|
+
foo,bar = the_thing.gens()
|
994
|
+
3*foo
|
995
|
+
|
996
|
+
sage: sib, par_sie = test_setup()
|
997
|
+
sage: sib.result(par_sie - sib.gen("some parent", 1))
|
998
|
+
the_thing.<foo,bar> = make_a_parent()
|
999
|
+
the_thing - bar
|
1000
|
+
"""
|
1001
|
+
v = SIE_gens_constructor(self, sie, gen_names, gens_syntax=gens_syntax)
|
1002
|
+
self.cache(parent, v, name)
|
1003
|
+
gens = [SIE_gen(self, v, n) for n in gen_names]
|
1004
|
+
self._parent_gens[parent] = gens
|
1005
|
+
v._sie_gens = gens
|
1006
|
+
return v
|
1007
|
+
|
1008
|
+
def gen(self, parent, n=0):
|
1009
|
+
r"""
|
1010
|
+
Given a parent, returns a :class:`SageInputExpression` for
|
1011
|
+
the `n`-th (default: 0) generator of the parent.
|
1012
|
+
|
1013
|
+
EXAMPLES::
|
1014
|
+
|
1015
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1016
|
+
|
1017
|
+
sage: sib = SageInputBuilder()
|
1018
|
+
sage: sib.result(sib.gen(ZZ['y']))
|
1019
|
+
R.<y> = ZZ[]
|
1020
|
+
y
|
1021
|
+
"""
|
1022
|
+
if parent not in self._parent_gens:
|
1023
|
+
self(parent)
|
1024
|
+
if parent not in self._parent_gens:
|
1025
|
+
raise ValueError("{} did not register generators for sage_input".format(parent))
|
1026
|
+
|
1027
|
+
gens = self._parent_gens[parent]
|
1028
|
+
|
1029
|
+
if n > len(gens):
|
1030
|
+
raise ValueError("{} registered only {} generators for sage_input".format(parent, len(gens)))
|
1031
|
+
|
1032
|
+
return gens[n]
|
1033
|
+
|
1034
|
+
def prod(self, factors, simplify=False):
|
1035
|
+
r"""
|
1036
|
+
Given a sequence, returns a :class:`SageInputExpression`
|
1037
|
+
for the product of the elements.
|
1038
|
+
|
1039
|
+
With ``simplify=True``, performs some simplifications
|
1040
|
+
first. If any element is formatted as a string ``'0'``,
|
1041
|
+
then that element is returned directly. If any element is
|
1042
|
+
formatted as a string ``'1'``, then it is removed
|
1043
|
+
from the sequence (unless it is the only element in the sequence).
|
1044
|
+
And any negations are removed from the elements and moved to the
|
1045
|
+
outside of the product.
|
1046
|
+
|
1047
|
+
EXAMPLES::
|
1048
|
+
|
1049
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1050
|
+
|
1051
|
+
sage: sib = SageInputBuilder()
|
1052
|
+
sage: sib.result(sib.prod([-1, 0, 1, -2]))
|
1053
|
+
-1*0*1*-2
|
1054
|
+
|
1055
|
+
sage: sib = SageInputBuilder()
|
1056
|
+
sage: sib.result(sib.prod([-1, 0, 1, 2], simplify=True))
|
1057
|
+
0
|
1058
|
+
|
1059
|
+
sage: sib = SageInputBuilder()
|
1060
|
+
sage: sib.result(sib.prod([-1, 2, -3, -4], simplify=True))
|
1061
|
+
-2*3*4
|
1062
|
+
|
1063
|
+
sage: sib = SageInputBuilder()
|
1064
|
+
sage: sib.result(sib.prod([-1, 1, -1, -1], simplify=True))
|
1065
|
+
-1
|
1066
|
+
|
1067
|
+
sage: sib = SageInputBuilder()
|
1068
|
+
sage: sib.result(sib.prod([1, 1, 1], simplify=True))
|
1069
|
+
1
|
1070
|
+
"""
|
1071
|
+
neg = False
|
1072
|
+
factors = [self(factor) for factor in factors]
|
1073
|
+
if simplify:
|
1074
|
+
i = 0
|
1075
|
+
while i < len(factors):
|
1076
|
+
factor = factors[i]
|
1077
|
+
while isinstance(factor, SIE_unary) and factor._sie_op == '-':
|
1078
|
+
neg = not neg
|
1079
|
+
factor = factor._sie_operand
|
1080
|
+
factors[i] = factor
|
1081
|
+
if isinstance(factor, SIE_literal_stringrep) and factor._sie_value == '0':
|
1082
|
+
factors = [factor]
|
1083
|
+
neg = False
|
1084
|
+
break
|
1085
|
+
if isinstance(factor, SIE_literal_stringrep) and factor._sie_value == '1':
|
1086
|
+
factors[i:i + 1] = []
|
1087
|
+
else:
|
1088
|
+
i += 1
|
1089
|
+
if len(factors) == 0:
|
1090
|
+
factors.append(SIE_literal_stringrep(self, '1'))
|
1091
|
+
|
1092
|
+
prod = factors[0]
|
1093
|
+
for factor in factors[1:]:
|
1094
|
+
prod = prod * factor
|
1095
|
+
if neg:
|
1096
|
+
prod = -prod
|
1097
|
+
return prod
|
1098
|
+
|
1099
|
+
def sum(self, terms, simplify=False):
|
1100
|
+
r"""
|
1101
|
+
Given a sequence, returns a :class:`SageInputExpression`
|
1102
|
+
for the product of the elements.
|
1103
|
+
|
1104
|
+
With ``simplify=True``, performs some simplifications
|
1105
|
+
first. If any element is formatted as a string ``'0'``,
|
1106
|
+
then it is removed from the sequence (unless it is the only
|
1107
|
+
element in the sequence); and any instances of ``a + -b``
|
1108
|
+
are changed to ``a - b``.
|
1109
|
+
|
1110
|
+
EXAMPLES::
|
1111
|
+
|
1112
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1113
|
+
|
1114
|
+
sage: sib = SageInputBuilder()
|
1115
|
+
sage: sib.result(sib.sum([-1, 0, 1, 0, -1]))
|
1116
|
+
-1 + 0 + 1 + 0 + -1
|
1117
|
+
|
1118
|
+
sage: sib = SageInputBuilder()
|
1119
|
+
sage: sib.result(sib.sum([-1, 0, 1, 0, -1], simplify=True))
|
1120
|
+
-1 + 1 - 1
|
1121
|
+
|
1122
|
+
sage: sib = SageInputBuilder()
|
1123
|
+
sage: sib.result(sib.sum([0, 0, 0], simplify=True))
|
1124
|
+
0
|
1125
|
+
"""
|
1126
|
+
terms = [self(term) for term in terms]
|
1127
|
+
if simplify:
|
1128
|
+
i = 0
|
1129
|
+
while i < len(terms):
|
1130
|
+
term = terms[i]
|
1131
|
+
if isinstance(term, SIE_literal_stringrep) and term._sie_value == '0':
|
1132
|
+
terms[i:i + 1] = []
|
1133
|
+
else:
|
1134
|
+
i += 1
|
1135
|
+
if len(terms) == 0:
|
1136
|
+
terms.append(SIE_literal_stringrep(self, '0'))
|
1137
|
+
|
1138
|
+
sum = terms[0]
|
1139
|
+
for term in terms[1:]:
|
1140
|
+
negate = False
|
1141
|
+
while simplify and isinstance(term, SIE_unary) and term._sie_op == '-':
|
1142
|
+
negate = not negate
|
1143
|
+
term = term._sie_operand
|
1144
|
+
if negate:
|
1145
|
+
sum = sum - term
|
1146
|
+
else:
|
1147
|
+
sum = sum + term
|
1148
|
+
return sum
|
1149
|
+
|
1150
|
+
def result(self, e):
|
1151
|
+
r"""
|
1152
|
+
Given a :class:`SageInputExpression` constructed using ``self``,
|
1153
|
+
returns a tuple of a list of commands and an expression
|
1154
|
+
(and possibly a dictionary of local variables) suitable for
|
1155
|
+
:func:`sage_eval`.
|
1156
|
+
|
1157
|
+
EXAMPLES::
|
1158
|
+
|
1159
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1160
|
+
|
1161
|
+
sage: sib = SageInputBuilder()
|
1162
|
+
sage: r = sib.result(sib(6) * sib(7)); r
|
1163
|
+
6*7
|
1164
|
+
sage: tuple(r)
|
1165
|
+
('', '6*7')
|
1166
|
+
"""
|
1167
|
+
sif = SageInputFormatter()
|
1168
|
+
|
1169
|
+
# Even if use_variable was called on e, don't automatically
|
1170
|
+
# use a variable for it.
|
1171
|
+
e._sie_request_use_var = False
|
1172
|
+
|
1173
|
+
e._sie_prepare(sif)
|
1174
|
+
|
1175
|
+
s = sif.format(e, 0)
|
1176
|
+
|
1177
|
+
locals = self._locals
|
1178
|
+
if len(locals):
|
1179
|
+
return SageInputAnswer(sif._commands, sif.format(e, 0), locals)
|
1180
|
+
else:
|
1181
|
+
return SageInputAnswer(sif._commands, sif.format(e, 0))
|
1182
|
+
|
1183
|
+
|
1184
|
+
# Python's precedence levels. Hand-transcribed from section 5.14 of
|
1185
|
+
# the Python 2 reference manual. In the Python 3 reference manual
|
1186
|
+
# this is section 6.16.
|
1187
|
+
# See https://docs.python.org/3/reference/expressions.html
|
1188
|
+
_prec_lambda = 2
|
1189
|
+
_prec_or = 4
|
1190
|
+
_prec_and = 6
|
1191
|
+
_prec_not = 8
|
1192
|
+
_prec_membership = 10
|
1193
|
+
_prec_identity = 12
|
1194
|
+
_prec_comparison = 14
|
1195
|
+
_prec_bitor = 16
|
1196
|
+
_prec_bitxor = 18
|
1197
|
+
_prec_bitand = 20
|
1198
|
+
_prec_shift = 22
|
1199
|
+
_prec_addsub = 24
|
1200
|
+
_prec_muldiv = 26
|
1201
|
+
_prec_negate = 28
|
1202
|
+
_prec_bitnot = 30
|
1203
|
+
_prec_exponent = 32
|
1204
|
+
_prec_attribute = 34
|
1205
|
+
_prec_subscript = 36
|
1206
|
+
_prec_slicing = 38
|
1207
|
+
_prec_funcall = 40
|
1208
|
+
_prec_atomic = 42
|
1209
|
+
|
1210
|
+
|
1211
|
+
class SageInputExpression:
|
1212
|
+
r"""
|
1213
|
+
Subclasses of this class represent expressions for :func:`sage_input`.
|
1214
|
+
\sage classes should define a \method{_sage_input_} method, which
|
1215
|
+
will return an instance of :class:`SageInputExpression`, created using
|
1216
|
+
methods of :class:`SageInputBuilder`.
|
1217
|
+
|
1218
|
+
To the extent possible, operations on :class:`SageInputExpression` objects
|
1219
|
+
construct a new :class:`SageInputExpression` representing that operation.
|
1220
|
+
That is, if ``a`` is a :class:`SageInputExpression`, then ``a + b``
|
1221
|
+
constructs a :class:`SageInputExpression` representing this sum.
|
1222
|
+
This also works for attribute access, function calls, subscripts, etc.
|
1223
|
+
Since arbitrary attribute accesses might be used to construct a new
|
1224
|
+
attribute-access expression, all internal attributes and methods
|
1225
|
+
have names that begin with ``_sie_`` to reduce the chance of
|
1226
|
+
collisions.
|
1227
|
+
|
1228
|
+
It is expected that instances of this class will not be directly
|
1229
|
+
created outside this module; instead, instances will be created
|
1230
|
+
using methods of :class:`SageInputBuilder` and :class:`SageInputExpression`.
|
1231
|
+
|
1232
|
+
Values of type :class:`SageInputExpression` print in a fairly ugly
|
1233
|
+
way, that reveals the internal structure of the expression tree.
|
1234
|
+
"""
|
1235
|
+
|
1236
|
+
def __init__(self, sib):
|
1237
|
+
r"""
|
1238
|
+
Initialize a :class:`SageInputExpression`.
|
1239
|
+
|
1240
|
+
EXAMPLES::
|
1241
|
+
|
1242
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1243
|
+
sage: sib = SageInputBuilder()
|
1244
|
+
sage: sie = sib(3) # indirect doctest
|
1245
|
+
sage: sie
|
1246
|
+
{atomic:3}
|
1247
|
+
sage: sie._sie_builder is sib
|
1248
|
+
True
|
1249
|
+
"""
|
1250
|
+
self._sie_refcount = 0
|
1251
|
+
self._sie_builder = sib
|
1252
|
+
self._sie_context = None
|
1253
|
+
self._sie_preferred_varname = None
|
1254
|
+
self._sie_varname = None
|
1255
|
+
self._sie_request_use_var = False
|
1256
|
+
self._sie_use_var = False
|
1257
|
+
self._sie_requested_varname = False
|
1258
|
+
self._sie_commands = []
|
1259
|
+
|
1260
|
+
def _sie_is_simple(self):
|
1261
|
+
r"""
|
1262
|
+
Return ``True`` if this :class:`SageInputExpression` is simple
|
1263
|
+
enough that duplicate uses are not worth caching. Normally
|
1264
|
+
this will be true if the expression represents a single token.
|
1265
|
+
|
1266
|
+
EXAMPLES::
|
1267
|
+
|
1268
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1269
|
+
sage: sib = SageInputBuilder()
|
1270
|
+
sage: sib.name('QQ')._sie_is_simple()
|
1271
|
+
True
|
1272
|
+
sage: sib(GF(2))._sie_is_simple()
|
1273
|
+
False
|
1274
|
+
"""
|
1275
|
+
return False
|
1276
|
+
|
1277
|
+
def _sie_referenced(self):
|
1278
|
+
r"""
|
1279
|
+
Return a list of the immediate subexpressions of this
|
1280
|
+
:class:`SageInputExpression`.
|
1281
|
+
|
1282
|
+
EXAMPLES::
|
1283
|
+
|
1284
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1285
|
+
sage: sib = SageInputBuilder()
|
1286
|
+
sage: len(sib(GF(2))._sie_referenced())
|
1287
|
+
2
|
1288
|
+
sage: sib(5)._sie_referenced()
|
1289
|
+
[]
|
1290
|
+
"""
|
1291
|
+
return []
|
1292
|
+
|
1293
|
+
def _sie_prepare(self, sif):
|
1294
|
+
r"""
|
1295
|
+
We traverse the entire expression DAG to prepare for printing.
|
1296
|
+
Here, we notice nodes with more than one parent, and mark them
|
1297
|
+
to replace with a variable (rather than generating the value
|
1298
|
+
multiple times).
|
1299
|
+
|
1300
|
+
EXAMPLES::
|
1301
|
+
|
1302
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
1303
|
+
sage: sib = SageInputBuilder()
|
1304
|
+
sage: sif = SageInputFormatter()
|
1305
|
+
sage: pair = sib((GF(2), GF(2)))
|
1306
|
+
sage: single = sib(GF(2))
|
1307
|
+
sage: single._sie_refcount
|
1308
|
+
0
|
1309
|
+
sage: single._sie_use_var
|
1310
|
+
False
|
1311
|
+
sage: sib((GF(2), GF(2)))._sie_prepare(sif)
|
1312
|
+
sage: single._sie_refcount
|
1313
|
+
2
|
1314
|
+
sage: single._sie_use_var
|
1315
|
+
True
|
1316
|
+
"""
|
1317
|
+
if self._sie_context is not sif:
|
1318
|
+
self._sie_context = sif
|
1319
|
+
self._sie_refcount = 0
|
1320
|
+
self._sie_refcount += 1
|
1321
|
+
if self._sie_request_use_var:
|
1322
|
+
self._sie_require_varname(sif)
|
1323
|
+
self._sie_use_var = True
|
1324
|
+
if not self._sie_is_simple():
|
1325
|
+
if self._sie_refcount == 2:
|
1326
|
+
self._sie_require_varname(sif)
|
1327
|
+
self._sie_use_var = True
|
1328
|
+
if self._sie_refcount == 1:
|
1329
|
+
for r in self._sie_referenced():
|
1330
|
+
r._sie_prepare(sif)
|
1331
|
+
for r in self._sie_commands:
|
1332
|
+
r._sie_prepare(sif)
|
1333
|
+
|
1334
|
+
def _sie_require_varname(self, sif):
|
1335
|
+
r"""
|
1336
|
+
Mark this :class:`SageInputExpression` as requiring a variable name,
|
1337
|
+
and register it with a :class:`SageInputFormatter` (which will
|
1338
|
+
allocate a variable name at the end of the preparatory phase).
|
1339
|
+
|
1340
|
+
EXAMPLES::
|
1341
|
+
|
1342
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
1343
|
+
sage: sib = SageInputBuilder()
|
1344
|
+
sage: sif = SageInputFormatter()
|
1345
|
+
sage: sie = sib(3)
|
1346
|
+
sage: sie._sie_require_varname(sif)
|
1347
|
+
sage: sie._sie_requested_varname
|
1348
|
+
True
|
1349
|
+
"""
|
1350
|
+
if not self._sie_requested_varname:
|
1351
|
+
sif.register_name(self._sie_preferred_varname)
|
1352
|
+
self._sie_requested_varname = True
|
1353
|
+
self._sie_generated = False
|
1354
|
+
|
1355
|
+
def _sie_get_varname(self, sif):
|
1356
|
+
r"""
|
1357
|
+
Get the variable name that the :class:`SageInputFormatter` allocated
|
1358
|
+
for this :class:`SageInputExpression`.
|
1359
|
+
|
1360
|
+
EXAMPLES::
|
1361
|
+
|
1362
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
1363
|
+
sage: sib = SageInputBuilder()
|
1364
|
+
sage: sif = SageInputFormatter()
|
1365
|
+
sage: sie = sib(3)
|
1366
|
+
sage: sie._sie_require_varname(sif)
|
1367
|
+
sage: sie._sie_get_varname(sif)
|
1368
|
+
'si'
|
1369
|
+
"""
|
1370
|
+
if self._sie_varname is None:
|
1371
|
+
self._sie_varname = sif.get_name(self._sie_preferred_varname)
|
1372
|
+
|
1373
|
+
return self._sie_varname
|
1374
|
+
|
1375
|
+
def _sie_is_negation(self):
|
1376
|
+
r"""
|
1377
|
+
Test whether a :class:`SageInputExpression` is a negation.
|
1378
|
+
|
1379
|
+
Despite the obscure name, this is intended to be a public method.
|
1380
|
+
|
1381
|
+
See the documentation for \method{SIE_unary._sie_is_negation}
|
1382
|
+
for useful examples.
|
1383
|
+
|
1384
|
+
EXAMPLES::
|
1385
|
+
|
1386
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
1387
|
+
sage: sib = SageInputBuilder()
|
1388
|
+
sage: sie = sib.name('foo')
|
1389
|
+
sage: sie._sie_is_negation()
|
1390
|
+
False
|
1391
|
+
"""
|
1392
|
+
return False
|
1393
|
+
|
1394
|
+
def __call__(self, *args, **kwargs):
|
1395
|
+
r"""
|
1396
|
+
Given a :class:`SageInputExpression`, build a new
|
1397
|
+
:class:`SageInputExpression` representing a function call node
|
1398
|
+
(with ``self`` as the function).
|
1399
|
+
|
1400
|
+
EXAMPLES::
|
1401
|
+
|
1402
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1403
|
+
sage: sib = SageInputBuilder()
|
1404
|
+
sage: sie = sib(3)
|
1405
|
+
sage: sie(4)
|
1406
|
+
{call: {atomic:3}({atomic:4})}
|
1407
|
+
"""
|
1408
|
+
args = [self._sie_builder(_) for _ in args]
|
1409
|
+
for k in kwargs:
|
1410
|
+
kwargs[k] = self._sie_builder(kwargs[k])
|
1411
|
+
return SIE_call(self._sie_builder, self, args, kwargs)
|
1412
|
+
|
1413
|
+
def __getitem__(self, key):
|
1414
|
+
r"""
|
1415
|
+
Given a :class:`SageInputExpression`, build a new
|
1416
|
+
:class:`SageInputExpression` representing a subscript expression
|
1417
|
+
(with ``self`` as the value being subscripted).
|
1418
|
+
|
1419
|
+
Currently, slices are not supported.
|
1420
|
+
|
1421
|
+
EXAMPLES::
|
1422
|
+
|
1423
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1424
|
+
sage: sib = SageInputBuilder()
|
1425
|
+
sage: sie = sib(3)
|
1426
|
+
sage: sie[4]
|
1427
|
+
{subscr: {atomic:3}[{atomic:4}]}
|
1428
|
+
sage: sie[sib.name('x'), sib.name('y')]
|
1429
|
+
{subscr: {atomic:3}[{tuple: ({atomic:x}, {atomic:y})}]}
|
1430
|
+
"""
|
1431
|
+
skey = self._sie_builder(key)
|
1432
|
+
return SIE_subscript(self._sie_builder, self, skey)
|
1433
|
+
|
1434
|
+
def __getattr__(self, attr):
|
1435
|
+
r"""
|
1436
|
+
Given a :class:`SageInputExpression`, build a new
|
1437
|
+
:class:`SageInputExpression` representing an attribute access.
|
1438
|
+
|
1439
|
+
EXAMPLES::
|
1440
|
+
|
1441
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1442
|
+
sage: sib = SageInputBuilder()
|
1443
|
+
sage: sie = sib.name('x')
|
1444
|
+
sage: sie.foo
|
1445
|
+
{getattr: {atomic:x}.foo}
|
1446
|
+
sage: sie.foo()
|
1447
|
+
{call: {getattr: {atomic:x}.foo}()}
|
1448
|
+
"""
|
1449
|
+
return SIE_getattr(self._sie_builder, self, attr)
|
1450
|
+
|
1451
|
+
def _rich_repr_(self, display_manager, **kwds):
|
1452
|
+
"""
|
1453
|
+
Disable rich output.
|
1454
|
+
|
1455
|
+
This is necessary because otherwise our :meth:`__getattr__`
|
1456
|
+
would be called.
|
1457
|
+
|
1458
|
+
EXAMPLES::
|
1459
|
+
|
1460
|
+
sage: from sage.repl.rich_output import get_display_manager
|
1461
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1462
|
+
sage: sib = SageInputBuilder()
|
1463
|
+
sage: sie = sib.name('x')
|
1464
|
+
sage: sie._rich_repr_(get_display_manager()) is None
|
1465
|
+
True
|
1466
|
+
"""
|
1467
|
+
return None
|
1468
|
+
|
1469
|
+
def __pow__(self, other):
|
1470
|
+
r"""
|
1471
|
+
Compute an expression tree for ``self ** other``.
|
1472
|
+
|
1473
|
+
EXAMPLES::
|
1474
|
+
|
1475
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1476
|
+
sage: sib = SageInputBuilder()
|
1477
|
+
sage: sie = sib(3)
|
1478
|
+
sage: sie ^ 4
|
1479
|
+
{binop:** {atomic:3} {atomic:4}}
|
1480
|
+
"""
|
1481
|
+
return self._sie_binop('**', other)
|
1482
|
+
|
1483
|
+
def __mul__(self, other):
|
1484
|
+
r"""
|
1485
|
+
Compute an expression tree for ``self * other``.
|
1486
|
+
|
1487
|
+
EXAMPLES::
|
1488
|
+
|
1489
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1490
|
+
sage: sib = SageInputBuilder()
|
1491
|
+
sage: sie = sib(3)
|
1492
|
+
sage: sie * 4
|
1493
|
+
{binop:* {atomic:3} {atomic:4}}
|
1494
|
+
"""
|
1495
|
+
return self._sie_binop('*', other)
|
1496
|
+
|
1497
|
+
def __truediv__(self, other):
|
1498
|
+
r"""
|
1499
|
+
Compute an expression tree for ``self / other``.
|
1500
|
+
|
1501
|
+
EXAMPLES::
|
1502
|
+
|
1503
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1504
|
+
sage: sib = SageInputBuilder()
|
1505
|
+
sage: sie = sib(3)
|
1506
|
+
sage: sie / 4
|
1507
|
+
{binop:/ {atomic:3} {atomic:4}}
|
1508
|
+
"""
|
1509
|
+
return self._sie_binop('/', other)
|
1510
|
+
|
1511
|
+
def __add__(self, other):
|
1512
|
+
r"""
|
1513
|
+
Compute an expression tree for ``self + other``.
|
1514
|
+
|
1515
|
+
EXAMPLES::
|
1516
|
+
|
1517
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1518
|
+
sage: sib = SageInputBuilder()
|
1519
|
+
sage: sie = sib(3)
|
1520
|
+
sage: sie + 4
|
1521
|
+
{binop:+ {atomic:3} {atomic:4}}
|
1522
|
+
"""
|
1523
|
+
return self._sie_binop('+', other)
|
1524
|
+
|
1525
|
+
def __sub__(self, other):
|
1526
|
+
r"""
|
1527
|
+
Compute an expression tree for ``self - other``.
|
1528
|
+
|
1529
|
+
EXAMPLES::
|
1530
|
+
|
1531
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1532
|
+
sage: sib = SageInputBuilder()
|
1533
|
+
sage: sie = sib(3)
|
1534
|
+
sage: sie - 4
|
1535
|
+
{binop:- {atomic:3} {atomic:4}}
|
1536
|
+
"""
|
1537
|
+
return self._sie_binop('-', other)
|
1538
|
+
|
1539
|
+
def _sie_binop(self, op, other):
|
1540
|
+
r"""
|
1541
|
+
Compute an expression tree for ``self OP other``,
|
1542
|
+
where OP is a string representing a binary operator (such as
|
1543
|
+
'+' or '**').
|
1544
|
+
|
1545
|
+
EXAMPLES::
|
1546
|
+
|
1547
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1548
|
+
sage: sib = SageInputBuilder()
|
1549
|
+
sage: v = sib.name('x')._sie_binop('%', sib.name('y'))
|
1550
|
+
sage: type(v)
|
1551
|
+
<class 'sage.misc.sage_input.SIE_binary'>
|
1552
|
+
sage: (v)._sie_op
|
1553
|
+
'%'
|
1554
|
+
sage: v
|
1555
|
+
{binop:% {atomic:x} {atomic:y}}
|
1556
|
+
"""
|
1557
|
+
return SIE_binary(self._sie_builder, op, self, self._sie_builder(other))
|
1558
|
+
|
1559
|
+
def __neg__(self):
|
1560
|
+
r"""
|
1561
|
+
Compute an expression tree for ``-self``.
|
1562
|
+
|
1563
|
+
EXAMPLES::
|
1564
|
+
|
1565
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1566
|
+
sage: sib = SageInputBuilder()
|
1567
|
+
sage: sie = sib(3)
|
1568
|
+
sage: -sie
|
1569
|
+
{unop:- {atomic:3}}
|
1570
|
+
"""
|
1571
|
+
return self._sie_unop('-')
|
1572
|
+
|
1573
|
+
def __pos__(self):
|
1574
|
+
r"""
|
1575
|
+
Compute an expression tree for ``+self``.
|
1576
|
+
|
1577
|
+
EXAMPLES::
|
1578
|
+
|
1579
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1580
|
+
sage: sib = SageInputBuilder()
|
1581
|
+
sage: sie = sib(3)
|
1582
|
+
sage: +sie
|
1583
|
+
{unop:+ {atomic:3}}
|
1584
|
+
"""
|
1585
|
+
return self._sie_unop('+')
|
1586
|
+
|
1587
|
+
def __invert__(self):
|
1588
|
+
r"""
|
1589
|
+
Compute an expression tree for ``~self``.
|
1590
|
+
|
1591
|
+
EXAMPLES::
|
1592
|
+
|
1593
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1594
|
+
sage: sib = SageInputBuilder()
|
1595
|
+
sage: sie = sib(3)
|
1596
|
+
sage: ~sie
|
1597
|
+
{unop:~ {atomic:3}}
|
1598
|
+
"""
|
1599
|
+
return self._sie_unop('~')
|
1600
|
+
|
1601
|
+
def __abs__(self):
|
1602
|
+
r"""
|
1603
|
+
Compute an expression tree for ``abs(self)``.
|
1604
|
+
|
1605
|
+
EXAMPLES::
|
1606
|
+
|
1607
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1608
|
+
sage: sib = SageInputBuilder()
|
1609
|
+
sage: sie = sib(3)
|
1610
|
+
sage: abs(sie)
|
1611
|
+
{call: {atomic:abs}({atomic:3})}
|
1612
|
+
"""
|
1613
|
+
return self._sie_builder.name('abs')(self)
|
1614
|
+
|
1615
|
+
def _sie_unop(self, op):
|
1616
|
+
r"""
|
1617
|
+
Compute an expression tree for ``OP self``,
|
1618
|
+
where OP is a string representing a unary operator (such as
|
1619
|
+
'-' or '~').
|
1620
|
+
|
1621
|
+
EXAMPLES::
|
1622
|
+
|
1623
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1624
|
+
sage: sib = SageInputBuilder()
|
1625
|
+
sage: sie = sib(3)
|
1626
|
+
sage: v = sie._sie_unop('~')
|
1627
|
+
sage: type(v)
|
1628
|
+
<class 'sage.misc.sage_input.SIE_unary'>
|
1629
|
+
sage: (v)._sie_op
|
1630
|
+
'~'
|
1631
|
+
sage: v
|
1632
|
+
{unop:~ {atomic:3}}
|
1633
|
+
"""
|
1634
|
+
return SIE_unary(self._sie_builder, op, self)
|
1635
|
+
|
1636
|
+
def _sie_format(self, sif):
|
1637
|
+
r"""
|
1638
|
+
Return the formatted string value of this expression, and the
|
1639
|
+
precedence of the top-level operator in the expression.
|
1640
|
+
|
1641
|
+
EXAMPLES:
|
1642
|
+
|
1643
|
+
Actually, all of these are examples of the \method{_sie_format}
|
1644
|
+
method on subclasses of :class:`SageInputExpression`;
|
1645
|
+
:class:`SageInputExpression` itself is an abstract base class
|
1646
|
+
(that cannot be instantiated).::
|
1647
|
+
|
1648
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
1649
|
+
sage: sib = SageInputBuilder()
|
1650
|
+
sage: sif = SageInputFormatter()
|
1651
|
+
sage: sie = sib(3)
|
1652
|
+
|
1653
|
+
sage: for v in (sie, sie+7, sie/5):
|
1654
|
+
....: v._sie_prepare(sif)
|
1655
|
+
....: v._sie_format(sif)
|
1656
|
+
('3', 42)
|
1657
|
+
('3 + 7', 24)
|
1658
|
+
('3/5', 26)
|
1659
|
+
sage: v = sib.assign(sib.name('foo').x, 3)
|
1660
|
+
sage: v._sie_prepare(sif)
|
1661
|
+
sage: v._sie_format(sif)
|
1662
|
+
Traceback (most recent call last):
|
1663
|
+
...
|
1664
|
+
ValueError: Cannot format SIE_assign as expression
|
1665
|
+
"""
|
1666
|
+
raise NotImplementedError
|
1667
|
+
|
1668
|
+
def _sie_format_statement(self, sif):
|
1669
|
+
r"""
|
1670
|
+
Return the formatted string value of this expression, when
|
1671
|
+
used as a statement.
|
1672
|
+
|
1673
|
+
On most :class:`SageInputExpression`s, this forwards directly
|
1674
|
+
to the \method{_sie_format} method. However, on
|
1675
|
+
:class:`SageInputExpression`s that actually represent
|
1676
|
+
statements (such as :class:`SIE_assign`), this method
|
1677
|
+
has an implementation and \method{_sie_format} raises
|
1678
|
+
an error. (This is to prevent accidental use of
|
1679
|
+
:class:`SIE_assign` as a value.)
|
1680
|
+
|
1681
|
+
EXAMPLES::
|
1682
|
+
|
1683
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
1684
|
+
sage: sib = SageInputBuilder()
|
1685
|
+
sage: sif = SageInputFormatter()
|
1686
|
+
sage: v = sib(3)
|
1687
|
+
sage: v._sie_prepare(sif)
|
1688
|
+
sage: v._sie_format_statement(sif)
|
1689
|
+
'3'
|
1690
|
+
sage: v = sib.assign(sib.name('foo').x, 3)
|
1691
|
+
sage: v._sie_prepare(sif)
|
1692
|
+
sage: v._sie_format_statement(sif)
|
1693
|
+
'foo.x = 3'
|
1694
|
+
"""
|
1695
|
+
result, prec = self._sie_format(sif)
|
1696
|
+
return result
|
1697
|
+
|
1698
|
+
|
1699
|
+
class SIE_literal(SageInputExpression):
|
1700
|
+
r"""
|
1701
|
+
An abstract base class for ``literals`` (basically, values which
|
1702
|
+
consist of a single token).
|
1703
|
+
|
1704
|
+
EXAMPLES::
|
1705
|
+
|
1706
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SIE_literal
|
1707
|
+
|
1708
|
+
sage: sib = SageInputBuilder()
|
1709
|
+
sage: sie = sib(3)
|
1710
|
+
sage: sie
|
1711
|
+
{atomic:3}
|
1712
|
+
sage: isinstance(sie, SIE_literal)
|
1713
|
+
True
|
1714
|
+
"""
|
1715
|
+
|
1716
|
+
def _sie_is_simple(self):
|
1717
|
+
r"""
|
1718
|
+
Report that :class:`SIE_literal` values are not worth replacing by
|
1719
|
+
variables (for ``common subexpression elimination``) even if they
|
1720
|
+
occur multiple times in an expression.
|
1721
|
+
|
1722
|
+
EXAMPLES::
|
1723
|
+
|
1724
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1725
|
+
|
1726
|
+
sage: sib = SageInputBuilder()
|
1727
|
+
sage: sie = sib(3)
|
1728
|
+
sage: sie._sie_is_simple()
|
1729
|
+
True
|
1730
|
+
|
1731
|
+
sage: sib.share(sie)
|
1732
|
+
sage: sie._sie_is_simple()
|
1733
|
+
False
|
1734
|
+
sage: sie._sie_share
|
1735
|
+
True
|
1736
|
+
"""
|
1737
|
+
# Perhaps this should actually look at the formatted length of self,
|
1738
|
+
# and sometimes return false? If some 50-digit integer occurs multiple
|
1739
|
+
# times in an expression, it might be better to do the replacement.
|
1740
|
+
return not self._sie_share
|
1741
|
+
|
1742
|
+
|
1743
|
+
class SIE_literal_stringrep(SIE_literal):
|
1744
|
+
r"""
|
1745
|
+
Values in this class are leaves in a :func:`sage_input` expression
|
1746
|
+
tree. Typically they represent a single token, and consist of the
|
1747
|
+
string representation of that token. They are used for integer,
|
1748
|
+
floating-point, and string literals, and for name expressions.
|
1749
|
+
|
1750
|
+
EXAMPLES::
|
1751
|
+
|
1752
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SIE_literal_stringrep
|
1753
|
+
|
1754
|
+
sage: sib = SageInputBuilder()
|
1755
|
+
sage: isinstance(sib(3), SIE_literal_stringrep)
|
1756
|
+
True
|
1757
|
+
sage: isinstance(sib(3.14159, True), SIE_literal_stringrep) # needs sage.rings.real_mpfr
|
1758
|
+
True
|
1759
|
+
sage: isinstance(sib.name('pi'), SIE_literal_stringrep)
|
1760
|
+
True
|
1761
|
+
sage: isinstance(sib(False), SIE_literal_stringrep)
|
1762
|
+
True
|
1763
|
+
sage: sib(False)
|
1764
|
+
{atomic:False}
|
1765
|
+
"""
|
1766
|
+
|
1767
|
+
def __init__(self, sib, n):
|
1768
|
+
r"""
|
1769
|
+
Initialize a :class:`SIE_literal_stringrep` value.
|
1770
|
+
|
1771
|
+
INPUT:
|
1772
|
+
|
1773
|
+
- ``sib`` -- a :class:`SageInputBuilder`
|
1774
|
+
|
1775
|
+
- ``n`` -- string; the value to be printed for this expression
|
1776
|
+
|
1777
|
+
EXAMPLES::
|
1778
|
+
|
1779
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1780
|
+
|
1781
|
+
sage: sib = SageInputBuilder()
|
1782
|
+
sage: sib(3)
|
1783
|
+
{atomic:3}
|
1784
|
+
sage: sib(3)._sie_value
|
1785
|
+
'3'
|
1786
|
+
"""
|
1787
|
+
super().__init__(sib)
|
1788
|
+
self._sie_value = str(n)
|
1789
|
+
self._sie_share = False
|
1790
|
+
|
1791
|
+
def __repr__(self):
|
1792
|
+
r"""
|
1793
|
+
Return a string representing this :class:`SIE_literal_stringrep`
|
1794
|
+
value.
|
1795
|
+
|
1796
|
+
EXAMPLES::
|
1797
|
+
|
1798
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1799
|
+
|
1800
|
+
sage: sib = SageInputBuilder()
|
1801
|
+
sage: sib(3)
|
1802
|
+
{atomic:3}
|
1803
|
+
sage: sib("\n")
|
1804
|
+
{atomic:'\n'}
|
1805
|
+
"""
|
1806
|
+
return "{atomic:%s}" % self._sie_value
|
1807
|
+
|
1808
|
+
def _sie_format(self, sif):
|
1809
|
+
r"""
|
1810
|
+
Return the formatted string value of this expression, and an indication
|
1811
|
+
that it is ``atomic`` (never needs to be parenthesized).
|
1812
|
+
|
1813
|
+
EXAMPLES::
|
1814
|
+
|
1815
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
1816
|
+
|
1817
|
+
sage: sib = SageInputBuilder()
|
1818
|
+
sage: sif = SageInputFormatter()
|
1819
|
+
sage: sie = sib(True)
|
1820
|
+
sage: sie._sie_prepare(sif)
|
1821
|
+
sage: sie._sie_format(sif)
|
1822
|
+
('True', 42)
|
1823
|
+
"""
|
1824
|
+
return self._sie_value, _prec_atomic
|
1825
|
+
|
1826
|
+
|
1827
|
+
class SIE_call(SageInputExpression):
|
1828
|
+
r"""
|
1829
|
+
This class represents a function-call node in a :func:`sage_input`
|
1830
|
+
expression tree.
|
1831
|
+
|
1832
|
+
EXAMPLES::
|
1833
|
+
|
1834
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1835
|
+
|
1836
|
+
sage: sib = SageInputBuilder()
|
1837
|
+
sage: sie = sib.name('GF')
|
1838
|
+
sage: sie(49)
|
1839
|
+
{call: {atomic:GF}({atomic:49})}
|
1840
|
+
"""
|
1841
|
+
|
1842
|
+
def __init__(self, sib, func, args, kwargs):
|
1843
|
+
r"""
|
1844
|
+
Initialize an instance of :class:`SIE_call`.
|
1845
|
+
|
1846
|
+
INPUT:
|
1847
|
+
|
1848
|
+
- ``sib`` -- a :class:`SageInputBuilder`
|
1849
|
+
|
1850
|
+
- ``func`` -- a :class:`SageInputExpression` representing a function
|
1851
|
+
|
1852
|
+
- ``args`` -- list of instances of :class:`SageInputExpression`
|
1853
|
+
representing the positional arguments
|
1854
|
+
|
1855
|
+
- ``kwargs`` -- dictionary mapping strings to instances of
|
1856
|
+
:class:`SageInputExpression` representing the keyword arguments
|
1857
|
+
|
1858
|
+
EXAMPLES::
|
1859
|
+
|
1860
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1861
|
+
|
1862
|
+
sage: sib = SageInputBuilder()
|
1863
|
+
sage: sie = sib('RealField')(53, rnd='RNDZ')
|
1864
|
+
"""
|
1865
|
+
super().__init__(sib)
|
1866
|
+
self._sie_func = func
|
1867
|
+
self._sie_args = args
|
1868
|
+
self._sie_kwargs = kwargs
|
1869
|
+
|
1870
|
+
def __repr__(self):
|
1871
|
+
r"""
|
1872
|
+
Return a string representing this :class:`SIE_call` value.
|
1873
|
+
|
1874
|
+
EXAMPLES::
|
1875
|
+
|
1876
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1877
|
+
|
1878
|
+
sage: sib = SageInputBuilder()
|
1879
|
+
sage: sie = sib('RealField')(53, rnd='RNDZ')
|
1880
|
+
"""
|
1881
|
+
func = repr(self._sie_func)
|
1882
|
+
args = [repr(arg) for arg in self._sie_args]
|
1883
|
+
kwargs = sorted(k + '=' + repr(v)
|
1884
|
+
for k, v in self._sie_kwargs.items())
|
1885
|
+
all_args = ', '.join(args + kwargs)
|
1886
|
+
return "{call: %s(%s)}" % (func, all_args)
|
1887
|
+
|
1888
|
+
def _sie_referenced(self):
|
1889
|
+
r"""
|
1890
|
+
Return a list of the immediate subexpressions of this :class:`SIE_call`.
|
1891
|
+
|
1892
|
+
EXAMPLES::
|
1893
|
+
|
1894
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1895
|
+
|
1896
|
+
sage: sib = SageInputBuilder()
|
1897
|
+
sage: sie = sib('RealField')(53, rnd='RNDZ')
|
1898
|
+
sage: sie._sie_referenced()
|
1899
|
+
[{atomic:53}, {atomic:'RealField'}, {atomic:'RNDZ'}]
|
1900
|
+
"""
|
1901
|
+
refs = self._sie_args[:]
|
1902
|
+
refs.append(self._sie_func)
|
1903
|
+
refs.extend(self._sie_kwargs.values())
|
1904
|
+
return refs
|
1905
|
+
|
1906
|
+
def _sie_format(self, sif):
|
1907
|
+
r"""
|
1908
|
+
Return the formatted string value of this expression, and an indication
|
1909
|
+
that it is a function call.
|
1910
|
+
|
1911
|
+
EXAMPLES::
|
1912
|
+
|
1913
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
1914
|
+
|
1915
|
+
sage: sib = SageInputBuilder()
|
1916
|
+
sage: sif = SageInputFormatter()
|
1917
|
+
sage: sie = sib.name('RealField')(53, rnd='RNDZ')
|
1918
|
+
sage: sie._sie_prepare(sif)
|
1919
|
+
sage: sie._sie_format(sif)
|
1920
|
+
("RealField(53, rnd='RNDZ')", 40)
|
1921
|
+
"""
|
1922
|
+
func = sif.format(self._sie_func, _prec_attribute)
|
1923
|
+
args = [sif.format(arg, 0) for arg in self._sie_args]
|
1924
|
+
kwargs = sorted(k + '=' + sif.format(v, 0)
|
1925
|
+
for k, v in self._sie_kwargs.items())
|
1926
|
+
all_args = ', '.join(args + kwargs)
|
1927
|
+
return ('%s(%s)' % (func, all_args), _prec_funcall)
|
1928
|
+
|
1929
|
+
|
1930
|
+
class SIE_subscript(SageInputExpression):
|
1931
|
+
r"""
|
1932
|
+
This class represents a subscript node in a :func:`sage_input`
|
1933
|
+
expression tree.
|
1934
|
+
|
1935
|
+
EXAMPLES::
|
1936
|
+
|
1937
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1938
|
+
|
1939
|
+
sage: sib = SageInputBuilder()
|
1940
|
+
sage: sie = sib.name('QQ')['x,y']
|
1941
|
+
sage: sie
|
1942
|
+
{subscr: {atomic:QQ}[{atomic:'x,y'}]}
|
1943
|
+
"""
|
1944
|
+
|
1945
|
+
def __init__(self, sib, coll, key):
|
1946
|
+
r"""
|
1947
|
+
Initialize an instance of :class:`SIE_subscript`.
|
1948
|
+
|
1949
|
+
INPUT:
|
1950
|
+
|
1951
|
+
- ``sib`` -- a :class:`SageInputBuilder`
|
1952
|
+
|
1953
|
+
- ``coll`` -- a :class:`SageInputExpression` representing a collection
|
1954
|
+
|
1955
|
+
- ``key`` -- a :class:`SageInputExpression` representing the subscript/key
|
1956
|
+
|
1957
|
+
As a special case, ``key`` may be ``None``; this represents an
|
1958
|
+
empty subscript. This is not legal Python syntax, but it is legal
|
1959
|
+
in the \sage preparser in examples like ``K.<x> = QQ[]``.
|
1960
|
+
|
1961
|
+
EXAMPLES::
|
1962
|
+
|
1963
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1964
|
+
|
1965
|
+
sage: sib = SageInputBuilder()
|
1966
|
+
sage: sib.name('QQ')['x']
|
1967
|
+
{subscr: {atomic:QQ}[{atomic:'x'}]}
|
1968
|
+
sage: sib.name('x')[1,2,3]
|
1969
|
+
{subscr: {atomic:x}[{tuple: ({atomic:1}, {atomic:2}, {atomic:3})}]}
|
1970
|
+
sage: sib.empty_subscript(sib.name('QQ'))
|
1971
|
+
{subscr: {atomic:QQ}[]}
|
1972
|
+
"""
|
1973
|
+
super().__init__(sib)
|
1974
|
+
self._sie_coll = coll
|
1975
|
+
self._sie_key = key
|
1976
|
+
|
1977
|
+
def __repr__(self):
|
1978
|
+
r"""
|
1979
|
+
Return a string representing this :class:`SIE_subscript` value.
|
1980
|
+
|
1981
|
+
EXAMPLES::
|
1982
|
+
|
1983
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
1984
|
+
|
1985
|
+
sage: sib = SageInputBuilder()
|
1986
|
+
sage: sib.name('ZZ')['x,y']
|
1987
|
+
{subscr: {atomic:ZZ}[{atomic:'x,y'}]}
|
1988
|
+
"""
|
1989
|
+
coll = repr(self._sie_coll)
|
1990
|
+
if self._sie_key is None:
|
1991
|
+
key = ''
|
1992
|
+
else:
|
1993
|
+
key = repr(self._sie_key)
|
1994
|
+
return "{subscr: %s[%s]}" % (coll, key)
|
1995
|
+
|
1996
|
+
def _sie_referenced(self):
|
1997
|
+
r"""
|
1998
|
+
Return a list of the immediate subexpressions of this
|
1999
|
+
:class:`SIE_subscript`.
|
2000
|
+
|
2001
|
+
EXAMPLES::
|
2002
|
+
|
2003
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2004
|
+
|
2005
|
+
sage: sib = SageInputBuilder()
|
2006
|
+
sage: sie = sib.name('GF')(5)['x,y']
|
2007
|
+
sage: sie._sie_referenced()
|
2008
|
+
[{call: {atomic:GF}({atomic:5})}, {atomic:'x,y'}]
|
2009
|
+
"""
|
2010
|
+
refs = [self._sie_coll]
|
2011
|
+
if self._sie_key is not None:
|
2012
|
+
refs.append(self._sie_key)
|
2013
|
+
return refs
|
2014
|
+
|
2015
|
+
def _sie_format(self, sif):
|
2016
|
+
r"""
|
2017
|
+
Return the formatted string value of this expression, and an
|
2018
|
+
indication that it is a subscript.
|
2019
|
+
|
2020
|
+
EXAMPLES::
|
2021
|
+
|
2022
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
2023
|
+
|
2024
|
+
sage: sib = SageInputBuilder()
|
2025
|
+
sage: sif = SageInputFormatter()
|
2026
|
+
sage: sie = sib.name('QQ')['x']
|
2027
|
+
sage: sie._sie_prepare(sif)
|
2028
|
+
sage: sie._sie_format(sif)
|
2029
|
+
("QQ['x']", 36)
|
2030
|
+
"""
|
2031
|
+
coll = sif.format(self._sie_coll, _prec_attribute)
|
2032
|
+
if self._sie_key is None:
|
2033
|
+
key = ''
|
2034
|
+
else:
|
2035
|
+
key = sif.format(self._sie_key, 0)
|
2036
|
+
return '%s[%s]' % (coll, key), _prec_subscript
|
2037
|
+
|
2038
|
+
|
2039
|
+
class SIE_getattr(SageInputExpression):
|
2040
|
+
r"""
|
2041
|
+
This class represents a getattr node in a :func:`sage_input`
|
2042
|
+
expression tree.
|
2043
|
+
|
2044
|
+
EXAMPLES::
|
2045
|
+
|
2046
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2047
|
+
|
2048
|
+
sage: sib = SageInputBuilder()
|
2049
|
+
sage: sie = sib.name('CC').gen()
|
2050
|
+
sage: sie
|
2051
|
+
{call: {getattr: {atomic:CC}.gen}()}
|
2052
|
+
"""
|
2053
|
+
def __init__(self, sib, obj, attr):
|
2054
|
+
r"""
|
2055
|
+
Initialize an instance of :class:`SIE_getattr`.
|
2056
|
+
|
2057
|
+
INPUT:
|
2058
|
+
|
2059
|
+
- ``sib`` -- a :class:`SageInputBuilder`
|
2060
|
+
|
2061
|
+
- ``obj`` -- a :class:`SageInputExpression` representing an object
|
2062
|
+
|
2063
|
+
- ``attr`` -- string; the attribute name
|
2064
|
+
|
2065
|
+
EXAMPLES::
|
2066
|
+
|
2067
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2068
|
+
|
2069
|
+
sage: sib = SageInputBuilder()
|
2070
|
+
sage: sib.name('QQbar').zeta(5)
|
2071
|
+
{call: {getattr: {atomic:QQbar}.zeta}({atomic:5})}
|
2072
|
+
"""
|
2073
|
+
super().__init__(sib)
|
2074
|
+
self._sie_obj = obj
|
2075
|
+
self._sie_attr = attr
|
2076
|
+
|
2077
|
+
def __repr__(self):
|
2078
|
+
r"""
|
2079
|
+
Return a string representing this :class:`SIE_getattr` value.
|
2080
|
+
|
2081
|
+
EXAMPLES::
|
2082
|
+
|
2083
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2084
|
+
|
2085
|
+
sage: sib = SageInputBuilder()
|
2086
|
+
sage: sib.name('AA')(3).sqrt()
|
2087
|
+
{call: {getattr: {call: {atomic:AA}({atomic:3})}.sqrt}()}
|
2088
|
+
"""
|
2089
|
+
obj = repr(self._sie_obj)
|
2090
|
+
return "{getattr: %s.%s}" % (obj, self._sie_attr)
|
2091
|
+
|
2092
|
+
def _sie_referenced(self):
|
2093
|
+
r"""
|
2094
|
+
Return a list of the immediate subexpressions of this
|
2095
|
+
:class:`SIE_subscript`.
|
2096
|
+
|
2097
|
+
EXAMPLES::
|
2098
|
+
|
2099
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2100
|
+
|
2101
|
+
sage: sib = SageInputBuilder()
|
2102
|
+
sage: sie = sib.name('CDF').gen
|
2103
|
+
sage: sie._sie_referenced()
|
2104
|
+
[{atomic:CDF}]
|
2105
|
+
"""
|
2106
|
+
return [self._sie_obj]
|
2107
|
+
|
2108
|
+
def _sie_format(self, sif):
|
2109
|
+
r"""
|
2110
|
+
Return the formatted string value of this expression, and an
|
2111
|
+
indication that it is an attribute reference.
|
2112
|
+
|
2113
|
+
EXAMPLES::
|
2114
|
+
|
2115
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
2116
|
+
|
2117
|
+
sage: sib = SageInputBuilder()
|
2118
|
+
sage: sif = SageInputFormatter()
|
2119
|
+
sage: sie = sib.name('AA').common_polynomial
|
2120
|
+
sage: sie._sie_prepare(sif)
|
2121
|
+
sage: sie._sie_format(sif)
|
2122
|
+
('AA.common_polynomial', 34)
|
2123
|
+
"""
|
2124
|
+
obj = sif.format(self._sie_obj, _prec_exponent)
|
2125
|
+
return '%s.%s' % (obj, self._sie_attr), _prec_attribute
|
2126
|
+
|
2127
|
+
|
2128
|
+
class SIE_tuple(SageInputExpression):
|
2129
|
+
r"""
|
2130
|
+
This class represents a tuple or list node in a :func:`sage_input`
|
2131
|
+
expression tree.
|
2132
|
+
|
2133
|
+
EXAMPLES::
|
2134
|
+
|
2135
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2136
|
+
|
2137
|
+
sage: sib = SageInputBuilder()
|
2138
|
+
sage: sib((1, 'howdy'))
|
2139
|
+
{tuple: ({atomic:1}, {atomic:'howdy'})}
|
2140
|
+
sage: sib(["lists"])
|
2141
|
+
{list: ({atomic:'lists'})}
|
2142
|
+
"""
|
2143
|
+
|
2144
|
+
def __init__(self, sib, values, is_list):
|
2145
|
+
r"""
|
2146
|
+
Initialize an instance of :class:`SIE_tuple`.
|
2147
|
+
|
2148
|
+
INPUT:
|
2149
|
+
|
2150
|
+
- ``sib`` -- a :class:`SageInputBuilder`
|
2151
|
+
|
2152
|
+
- ``values`` -- list of instances of :class:`SageInputExpression`
|
2153
|
+
representing the elements of this tuple
|
2154
|
+
|
2155
|
+
- ``is_list`` -- is ``True`` if this class represents a list, False for a
|
2156
|
+
tuple
|
2157
|
+
|
2158
|
+
EXAMPLES::
|
2159
|
+
|
2160
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2161
|
+
|
2162
|
+
sage: sib = SageInputBuilder()
|
2163
|
+
sage: sib((3.5, -2)) # needs sage.rings.real_mpfr
|
2164
|
+
{tuple: ({atomic:3.5}, {unop:- {atomic:2}})}
|
2165
|
+
sage: sib(["Hello", "world"])
|
2166
|
+
{list: ({atomic:'Hello'}, {atomic:'world'})}
|
2167
|
+
"""
|
2168
|
+
super().__init__(sib)
|
2169
|
+
self._sie_values = values
|
2170
|
+
self._sie_is_list = is_list
|
2171
|
+
|
2172
|
+
def __repr__(self):
|
2173
|
+
r"""
|
2174
|
+
Return a string representing this :class:`SIE_tuple` value.
|
2175
|
+
|
2176
|
+
EXAMPLES::
|
2177
|
+
|
2178
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2179
|
+
|
2180
|
+
sage: sib = SageInputBuilder()
|
2181
|
+
sage: sib((2,3,5))
|
2182
|
+
{tuple: ({atomic:2}, {atomic:3}, {atomic:5})}
|
2183
|
+
sage: sib(["Hello", "world"])
|
2184
|
+
{list: ({atomic:'Hello'}, {atomic:'world'})}
|
2185
|
+
"""
|
2186
|
+
kind = "list" if self._sie_is_list else "tuple"
|
2187
|
+
return "{%s: (%s)}" % \
|
2188
|
+
(kind, ', '.join(repr(v) for v in self._sie_values))
|
2189
|
+
|
2190
|
+
def _sie_referenced(self):
|
2191
|
+
r"""
|
2192
|
+
Return a list of the immediate subexpressions of this
|
2193
|
+
:class:`SIE_tuple`.
|
2194
|
+
|
2195
|
+
EXAMPLES::
|
2196
|
+
|
2197
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2198
|
+
|
2199
|
+
sage: sib = SageInputBuilder()
|
2200
|
+
sage: sie = sib((ZZ, GF(5)))
|
2201
|
+
sage: sie._sie_referenced()
|
2202
|
+
[{atomic:ZZ}, {call: {atomic:GF}({atomic:5})}]
|
2203
|
+
"""
|
2204
|
+
return self._sie_values
|
2205
|
+
|
2206
|
+
def _sie_format(self, sif):
|
2207
|
+
r"""
|
2208
|
+
Return the formatted string value of this tuple or list, and an
|
2209
|
+
indication that it is atomic (never needs to be parenthesized).
|
2210
|
+
|
2211
|
+
EXAMPLES::
|
2212
|
+
|
2213
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
2214
|
+
|
2215
|
+
sage: sib = SageInputBuilder()
|
2216
|
+
sage: sif = SageInputFormatter()
|
2217
|
+
sage: for v in ((), (1,), (1,2), [], [1], [1,2]):
|
2218
|
+
....: sie = sib(v)
|
2219
|
+
....: sie._sie_prepare(sif)
|
2220
|
+
....: sie._sie_format(sif)
|
2221
|
+
('()', 42)
|
2222
|
+
('(1,)', 42)
|
2223
|
+
('(1, 2)', 42)
|
2224
|
+
('[]', 42)
|
2225
|
+
('[1]', 42)
|
2226
|
+
('[1, 2]', 42)
|
2227
|
+
"""
|
2228
|
+
values = [sif.format(val, 0) for val in self._sie_values]
|
2229
|
+
if self._sie_is_list:
|
2230
|
+
return '[%s]' % ', '.join(values), _prec_atomic
|
2231
|
+
else:
|
2232
|
+
if len(values) == 1:
|
2233
|
+
return '(%s,)' % values[0], _prec_atomic
|
2234
|
+
else:
|
2235
|
+
return '(%s)' % ', '.join(values), _prec_atomic
|
2236
|
+
|
2237
|
+
|
2238
|
+
class SIE_dict(SageInputExpression):
|
2239
|
+
r"""
|
2240
|
+
This class represents a dict node in a :func:`sage_input`
|
2241
|
+
expression tree.
|
2242
|
+
|
2243
|
+
EXAMPLES::
|
2244
|
+
|
2245
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2246
|
+
|
2247
|
+
sage: sib = SageInputBuilder()
|
2248
|
+
sage: sib.dict([('TeX', RR(pi)), ('Metafont', RR(e))]) # needs sage.symbolic
|
2249
|
+
{dict: {{atomic:'TeX'}:{call: {atomic:RR}({atomic:3.1415926535897931})},
|
2250
|
+
{atomic:'Metafont'}:{call: {atomic:RR}({atomic:2.7182818284590451})}}}
|
2251
|
+
sage: sib.dict({-40:-40, 0:32, 100:212})
|
2252
|
+
{dict: {{unop:- {atomic:40}}:{unop:- {atomic:40}},
|
2253
|
+
{atomic:0}:{atomic:32}, {atomic:100}:{atomic:212}}}
|
2254
|
+
"""
|
2255
|
+
|
2256
|
+
def __init__(self, sib, entries):
|
2257
|
+
r"""
|
2258
|
+
Initialize an instance of :class:`SIE_dict`.
|
2259
|
+
|
2260
|
+
INPUT:
|
2261
|
+
|
2262
|
+
- ``sib`` -- a :class:`SageInputBuilder`
|
2263
|
+
|
2264
|
+
- ``entries`` -- list of pairs of :class:`SageInputExpression`
|
2265
|
+
representing the entries of this dict
|
2266
|
+
|
2267
|
+
EXAMPLES::
|
2268
|
+
|
2269
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2270
|
+
|
2271
|
+
sage: sib = SageInputBuilder()
|
2272
|
+
sage: sib.dict({'me':'good', 'you':'bad'})
|
2273
|
+
{dict: {{atomic:'me'}:{atomic:'good'}, {atomic:'you'}:{atomic:'bad'}}}
|
2274
|
+
sage: sib.dict([(10, 'PS2'), (12, 'PS2'), (13, 'PS3')])
|
2275
|
+
{dict: {{atomic:10}:{atomic:'PS2'}, {atomic:12}:{atomic:'PS2'}, {atomic:13}:{atomic:'PS3'}}}
|
2276
|
+
"""
|
2277
|
+
super().__init__(sib)
|
2278
|
+
self._sie_entries = entries
|
2279
|
+
|
2280
|
+
def __repr__(self):
|
2281
|
+
r"""
|
2282
|
+
Return a string representing this :class:`SIE_dict` value.
|
2283
|
+
|
2284
|
+
EXAMPLES::
|
2285
|
+
|
2286
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2287
|
+
|
2288
|
+
sage: sib = SageInputBuilder()
|
2289
|
+
sage: sib.dict({'keaton':'general', 'chan':'master'})
|
2290
|
+
{dict: {{atomic:'keaton'}:{atomic:'general'}, {atomic:'chan'}:{atomic:'master'}}}
|
2291
|
+
"""
|
2292
|
+
return "{dict: {%s}}" % \
|
2293
|
+
', '.join(repr(key) + ':' + repr(val)
|
2294
|
+
for key, val in self._sie_entries)
|
2295
|
+
|
2296
|
+
def _sie_referenced(self):
|
2297
|
+
r"""
|
2298
|
+
Return a list of the immediate subexpressions of this
|
2299
|
+
:class:`SIE_dict`.
|
2300
|
+
|
2301
|
+
EXAMPLES::
|
2302
|
+
|
2303
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2304
|
+
|
2305
|
+
sage: sib = SageInputBuilder()
|
2306
|
+
sage: sie = sib.dict({1:'beguilement', 2:'legacy', 3:'passage'})
|
2307
|
+
sage: sie._sie_referenced()
|
2308
|
+
[{atomic:1}, {atomic:2}, {atomic:3}, {atomic:'beguilement'}, {atomic:'legacy'}, {atomic:'passage'}]
|
2309
|
+
"""
|
2310
|
+
return [k for k, v in self._sie_entries] + [v for k, v in self._sie_entries]
|
2311
|
+
|
2312
|
+
def _sie_format(self, sif):
|
2313
|
+
r"""
|
2314
|
+
Return the formatted string value of this dict, and an
|
2315
|
+
indication that it is atomic (never needs to be parenthesized).
|
2316
|
+
|
2317
|
+
EXAMPLES::
|
2318
|
+
|
2319
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
2320
|
+
|
2321
|
+
sage: sib = SageInputBuilder()
|
2322
|
+
sage: sif = SageInputFormatter()
|
2323
|
+
sage: sie = sib.dict({'carnivores':1, 'thinking':2, 'triumph':3})
|
2324
|
+
sage: sie._sie_prepare(sif)
|
2325
|
+
sage: sie._sie_format(sif)
|
2326
|
+
("{'carnivores':1, 'thinking':2, 'triumph':3}", 42)
|
2327
|
+
"""
|
2328
|
+
return "{%s}" % ', '.join(sif.format(k, 0) + ':' + sif.format(v, 0)
|
2329
|
+
for k, v in self._sie_entries), _prec_atomic
|
2330
|
+
|
2331
|
+
|
2332
|
+
class SIE_binary(SageInputExpression):
|
2333
|
+
r"""
|
2334
|
+
This class represents an arithmetic expression with a binary operator
|
2335
|
+
and its two arguments, in a :func:`sage_input` expression tree.
|
2336
|
+
|
2337
|
+
EXAMPLES::
|
2338
|
+
|
2339
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2340
|
+
|
2341
|
+
sage: sib = SageInputBuilder()
|
2342
|
+
sage: sib(3)+5
|
2343
|
+
{binop:+ {atomic:3} {atomic:5}}
|
2344
|
+
"""
|
2345
|
+
|
2346
|
+
def __init__(self, sib, op, lhs, rhs):
|
2347
|
+
r"""
|
2348
|
+
Initialize an instance of :class:`SIE_binary`.
|
2349
|
+
|
2350
|
+
INPUT:
|
2351
|
+
|
2352
|
+
- ``sib`` -- a :class:`SageInputBuilder`
|
2353
|
+
|
2354
|
+
- ``op`` -- string representing a binary operator, such as '*' or '%'
|
2355
|
+
|
2356
|
+
- ``lhs`` -- a :class:`SageInputExpression`
|
2357
|
+
|
2358
|
+
- ``rhs`` -- a :class:`SageInputExpression`
|
2359
|
+
|
2360
|
+
EXAMPLES::
|
2361
|
+
|
2362
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2363
|
+
|
2364
|
+
sage: sib = SageInputBuilder()
|
2365
|
+
sage: sib(3)*5
|
2366
|
+
{binop:* {atomic:3} {atomic:5}}
|
2367
|
+
"""
|
2368
|
+
super().__init__(sib)
|
2369
|
+
self._sie_op = op
|
2370
|
+
self._sie_operands = (lhs, rhs)
|
2371
|
+
|
2372
|
+
def __repr__(self):
|
2373
|
+
r"""
|
2374
|
+
Return a string representing this :class:`SIE_binary` value.
|
2375
|
+
|
2376
|
+
EXAMPLES::
|
2377
|
+
|
2378
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2379
|
+
|
2380
|
+
sage: sib = SageInputBuilder()
|
2381
|
+
sage: sib(7)/9
|
2382
|
+
{binop:/ {atomic:7} {atomic:9}}
|
2383
|
+
"""
|
2384
|
+
return "{binop:%s %s %s}" % (self._sie_op, repr(self._sie_operands[0]), repr(self._sie_operands[1]))
|
2385
|
+
|
2386
|
+
def _sie_referenced(self):
|
2387
|
+
r"""
|
2388
|
+
Return a tuple of the immediate subexpressions of this
|
2389
|
+
:class:`SIE_binary`.
|
2390
|
+
|
2391
|
+
EXAMPLES::
|
2392
|
+
|
2393
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2394
|
+
|
2395
|
+
sage: sib = SageInputBuilder()
|
2396
|
+
sage: sie = sib.name('x') + 5
|
2397
|
+
sage: sie._sie_referenced()
|
2398
|
+
({atomic:x}, {atomic:5})
|
2399
|
+
"""
|
2400
|
+
return self._sie_operands
|
2401
|
+
|
2402
|
+
def _sie_format(self, sif):
|
2403
|
+
r"""
|
2404
|
+
Return the formatted string value of this expression,
|
2405
|
+
and the precedence of the top-level operator in the expression.
|
2406
|
+
|
2407
|
+
EXAMPLES::
|
2408
|
+
|
2409
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
2410
|
+
|
2411
|
+
sage: sib = SageInputBuilder()
|
2412
|
+
sage: sif = SageInputFormatter()
|
2413
|
+
sage: x = sib.name('x')
|
2414
|
+
sage: y = sib.name('y')
|
2415
|
+
sage: for v in (x+y, x*y, x**y):
|
2416
|
+
....: v._sie_prepare(sif)
|
2417
|
+
....: v._sie_format(sif)
|
2418
|
+
('x + y', 24)
|
2419
|
+
('x*y', 26)
|
2420
|
+
('x^y', 32)
|
2421
|
+
|
2422
|
+
Note that the printing for $x^y$ varies depending on whether the
|
2423
|
+
preparser is enabled.::
|
2424
|
+
|
2425
|
+
sage: sibnp = SageInputBuilder(preparse=False)
|
2426
|
+
sage: sif = SageInputFormatter()
|
2427
|
+
sage: v = x**y
|
2428
|
+
sage: v._sie_prepare(sif)
|
2429
|
+
sage: v._sie_format(sif)
|
2430
|
+
('x^y', 32)
|
2431
|
+
|
2432
|
+
TESTS::
|
2433
|
+
|
2434
|
+
sage: x = sib.name('x')
|
2435
|
+
sage: y = sib.name('y')
|
2436
|
+
sage: z = sib.name('z')
|
2437
|
+
sage: sib.result((x+y)+z)
|
2438
|
+
x + y + z
|
2439
|
+
sage: sib.result(x+(y+z))
|
2440
|
+
x + (y + z)
|
2441
|
+
sage: sib.result((x*y)*z)
|
2442
|
+
x*y*z
|
2443
|
+
sage: sib.result(x*(y*z))
|
2444
|
+
x*(y*z)
|
2445
|
+
sage: sib.result(x+(y*z))
|
2446
|
+
x + y*z
|
2447
|
+
sage: sib.result((x+y)*z)
|
2448
|
+
(x + y)*z
|
2449
|
+
sage: sib.result((x^y)^z)
|
2450
|
+
(x^y)^z
|
2451
|
+
sage: sib.result(x^(y^z))
|
2452
|
+
x^y^z
|
2453
|
+
"""
|
2454
|
+
op = self._sie_op
|
2455
|
+
fop = op
|
2456
|
+
if op == '**':
|
2457
|
+
lhs = sif.format(self._sie_operands[0], _prec_exponent + 1)
|
2458
|
+
rhs = sif.format(self._sie_operands[1], _prec_exponent)
|
2459
|
+
if self._sie_builder.preparse():
|
2460
|
+
return '%s^%s' % (lhs, rhs), _prec_exponent
|
2461
|
+
else:
|
2462
|
+
return '%s**%s' % (lhs, rhs), _prec_exponent
|
2463
|
+
|
2464
|
+
if op == '*':
|
2465
|
+
prec = _prec_muldiv
|
2466
|
+
elif op == '/':
|
2467
|
+
prec = _prec_muldiv
|
2468
|
+
elif op == '+':
|
2469
|
+
fop = ' + '
|
2470
|
+
prec = _prec_addsub
|
2471
|
+
elif op == '-':
|
2472
|
+
fop = ' - '
|
2473
|
+
prec = _prec_addsub
|
2474
|
+
else:
|
2475
|
+
raise ValueError('Unhandled op {} in SIE_binary'.format(op))
|
2476
|
+
|
2477
|
+
lhs = sif.format(self._sie_operands[0], prec)
|
2478
|
+
rhs = sif.format(self._sie_operands[1], prec + 1)
|
2479
|
+
return '%s%s%s' % (lhs, fop, rhs), prec
|
2480
|
+
|
2481
|
+
|
2482
|
+
class SIE_unary(SageInputExpression):
|
2483
|
+
r"""
|
2484
|
+
This class represents an arithmetic expression with a unary operator
|
2485
|
+
and its argument, in a :func:`sage_input` expression tree.
|
2486
|
+
|
2487
|
+
EXAMPLES::
|
2488
|
+
|
2489
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2490
|
+
|
2491
|
+
sage: sib = SageInputBuilder()
|
2492
|
+
sage: -sib(256)
|
2493
|
+
{unop:- {atomic:256}}
|
2494
|
+
"""
|
2495
|
+
|
2496
|
+
def __init__(self, sib, op, operand):
|
2497
|
+
r"""
|
2498
|
+
Initialize an instance of :class:`SIE_unary`.
|
2499
|
+
|
2500
|
+
INPUT:
|
2501
|
+
|
2502
|
+
- ``sib`` -- a :class:`SageInputBuilder`
|
2503
|
+
|
2504
|
+
- ``op`` -- string representing a unary operator, such as '-'
|
2505
|
+
|
2506
|
+
- ``operand`` -- a :class:`SageInputExpression`
|
2507
|
+
|
2508
|
+
EXAMPLES::
|
2509
|
+
|
2510
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2511
|
+
|
2512
|
+
sage: sib = SageInputBuilder()
|
2513
|
+
sage: -sib(3)
|
2514
|
+
{unop:- {atomic:3}}
|
2515
|
+
"""
|
2516
|
+
super().__init__(sib)
|
2517
|
+
self._sie_op = op
|
2518
|
+
self._sie_operand = operand
|
2519
|
+
|
2520
|
+
def __repr__(self):
|
2521
|
+
r"""
|
2522
|
+
Return a string representing this :class:`SIE_unary` value.
|
2523
|
+
|
2524
|
+
EXAMPLES::
|
2525
|
+
|
2526
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2527
|
+
|
2528
|
+
sage: sib = SageInputBuilder()
|
2529
|
+
sage: -sib(15)
|
2530
|
+
{unop:- {atomic:15}}
|
2531
|
+
"""
|
2532
|
+
return "{unop:%s %s}" % (self._sie_op, repr(self._sie_operand))
|
2533
|
+
|
2534
|
+
def _sie_referenced(self):
|
2535
|
+
r"""
|
2536
|
+
Return a list of the immediate subexpressions of this
|
2537
|
+
:class:`SIE_unary`.
|
2538
|
+
|
2539
|
+
EXAMPLES::
|
2540
|
+
|
2541
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2542
|
+
|
2543
|
+
sage: sib = SageInputBuilder()
|
2544
|
+
sage: sie = -sib.name('x')
|
2545
|
+
sage: sie._sie_referenced()
|
2546
|
+
[{atomic:x}]
|
2547
|
+
"""
|
2548
|
+
return [self._sie_operand]
|
2549
|
+
|
2550
|
+
def _sie_format(self, sif):
|
2551
|
+
r"""
|
2552
|
+
Return the formatted string value of this expression,
|
2553
|
+
and the precedence of the top-level operator in the expression.
|
2554
|
+
|
2555
|
+
EXAMPLES::
|
2556
|
+
|
2557
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
2558
|
+
|
2559
|
+
sage: sib = SageInputBuilder()
|
2560
|
+
sage: sif = SageInputFormatter()
|
2561
|
+
sage: x = sib.name('x')
|
2562
|
+
sage: v = -x
|
2563
|
+
sage: v._sie_prepare(sif)
|
2564
|
+
sage: v._sie_format(sif)
|
2565
|
+
('-x', 28)
|
2566
|
+
sage: v = ~x
|
2567
|
+
sage: v._sie_prepare(sif)
|
2568
|
+
sage: v._sie_format(sif)
|
2569
|
+
('~x', 30)
|
2570
|
+
|
2571
|
+
TESTS::
|
2572
|
+
|
2573
|
+
sage: x = sib.name('x')
|
2574
|
+
sage: y = sib.name('y')
|
2575
|
+
sage: sib.result((-x)+y)
|
2576
|
+
-x + y
|
2577
|
+
sage: sib.result(x+(-y))
|
2578
|
+
x + -y
|
2579
|
+
sage: sib.result(-(x+y))
|
2580
|
+
-(x + y)
|
2581
|
+
sage: sib.result(-(-x))
|
2582
|
+
--x
|
2583
|
+
sage: sib.result(x-(-y))
|
2584
|
+
x - -y
|
2585
|
+
sage: sib.result((+x)+y)
|
2586
|
+
+x + y
|
2587
|
+
sage: sib.result(x+(+y))
|
2588
|
+
x + +y
|
2589
|
+
sage: sib.result(+(x+y))
|
2590
|
+
+(x + y)
|
2591
|
+
sage: sib.result(+(+x))
|
2592
|
+
++x
|
2593
|
+
sage: sib.result(x+(+y))
|
2594
|
+
x + +y
|
2595
|
+
|
2596
|
+
We assume that -(x*y) is always equal to (-x)*y. Using this
|
2597
|
+
assumption, we print -(x*y) as -x*y, which parses as (-x)*y.::
|
2598
|
+
|
2599
|
+
sage: sib.result(-(x*y))
|
2600
|
+
-x*y
|
2601
|
+
sage: sib.result((-x)*y)
|
2602
|
+
-x*y
|
2603
|
+
sage: sib.result(x*(-y))
|
2604
|
+
x*-y
|
2605
|
+
|
2606
|
+
We do not do that for unary +, assuming that the user really
|
2607
|
+
means to express something by using unary +::
|
2608
|
+
|
2609
|
+
sage: sib.result(+(x*y))
|
2610
|
+
+(x*y)
|
2611
|
+
"""
|
2612
|
+
op = self._sie_op
|
2613
|
+
fop = op
|
2614
|
+
rprec = None
|
2615
|
+
if op == '-':
|
2616
|
+
# We print -(a*b) as -a*b, even though that will parse as
|
2617
|
+
# (-a)*b.
|
2618
|
+
prec = _prec_muldiv
|
2619
|
+
rprec = _prec_negate
|
2620
|
+
elif op == '+':
|
2621
|
+
prec = _prec_negate
|
2622
|
+
elif op == '~':
|
2623
|
+
prec = _prec_bitnot
|
2624
|
+
else:
|
2625
|
+
raise ValueError('Unhandled op {} in SIE_unary'.format(op))
|
2626
|
+
|
2627
|
+
if rprec is None:
|
2628
|
+
rprec = prec
|
2629
|
+
|
2630
|
+
return '%s%s' % (fop, sif.format(self._sie_operand, prec)), rprec
|
2631
|
+
|
2632
|
+
def _sie_is_negation(self):
|
2633
|
+
r"""
|
2634
|
+
Test whether a :class:`SageInputExpression` is a negation.
|
2635
|
+
|
2636
|
+
Despite the obscure name, this is intended to be a public method.
|
2637
|
+
|
2638
|
+
This is used in the \method{_sage_input_} method for
|
2639
|
+
:class:`ComplexNumber`, so that ``sage_input(CC(-3))`` will
|
2640
|
+
produce ``-CC(3)`` instead of ``CC(-3)``. (This is preferred
|
2641
|
+
so that you get ``x - CC(3)`` instead of ``x + CC(-3)``.)
|
2642
|
+
|
2643
|
+
EXAMPLES::
|
2644
|
+
|
2645
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
2646
|
+
|
2647
|
+
sage: sib = SageInputBuilder()
|
2648
|
+
sage: x = sib.name('x')
|
2649
|
+
sage: v = -x
|
2650
|
+
|
2651
|
+
sage: def mk_CC(b):
|
2652
|
+
....: if b._sie_is_negation():
|
2653
|
+
....: return -sib.name('CC')(b._sie_operand)
|
2654
|
+
....: else:
|
2655
|
+
....: return sib.name('CC')(b)
|
2656
|
+
|
2657
|
+
sage: mk_CC(x)
|
2658
|
+
{call: {atomic:CC}({atomic:x})}
|
2659
|
+
sage: mk_CC(v)
|
2660
|
+
{unop:- {call: {atomic:CC}({atomic:x})}}
|
2661
|
+
"""
|
2662
|
+
return self._sie_op == '-'
|
2663
|
+
|
2664
|
+
|
2665
|
+
class SIE_gens_constructor(SageInputExpression):
|
2666
|
+
r"""
|
2667
|
+
This class represents an expression that can create a \sage parent
|
2668
|
+
with named generators, optionally using the \sage preparser
|
2669
|
+
generators syntax (like ``K.<x> = QQ[]``).
|
2670
|
+
|
2671
|
+
EXAMPLES::
|
2672
|
+
|
2673
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2674
|
+
|
2675
|
+
sage: sib = SageInputBuilder()
|
2676
|
+
sage: qq = sib.name('QQ')
|
2677
|
+
sage: sib.parent_with_gens("some parent", qq['x'],
|
2678
|
+
....: ('x',), 'QQx',
|
2679
|
+
....: gens_syntax=sib.empty_subscript(qq))
|
2680
|
+
{constr_parent: {subscr: {atomic:QQ}[{atomic:'x'}]} with gens: ('x',)}
|
2681
|
+
"""
|
2682
|
+
|
2683
|
+
def __init__(self, sib, constr, gen_names, gens_syntax=None):
|
2684
|
+
r"""
|
2685
|
+
Initialize an instance of :class:`SIE_gens_constructor`.
|
2686
|
+
|
2687
|
+
INPUT:
|
2688
|
+
|
2689
|
+
- ``sib`` -- a :class:`SageInputBuilder`
|
2690
|
+
|
2691
|
+
- ``constr`` -- a :class:`SageInputExpression` for constructing this
|
2692
|
+
parent ``normally``
|
2693
|
+
|
2694
|
+
- ``gen_names`` -- tuple of generator names
|
2695
|
+
|
2696
|
+
- ``gens_syntax`` -- an optional :class:`SageInputExpression` for
|
2697
|
+
constructing this parent using the \sage preparser generators syntax
|
2698
|
+
|
2699
|
+
EXAMPLES::
|
2700
|
+
|
2701
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2702
|
+
|
2703
|
+
sage: sib = SageInputBuilder()
|
2704
|
+
sage: qq = sib.name('QQ')
|
2705
|
+
sage: sib.parent_with_gens("some parent", qq['x'],
|
2706
|
+
....: ('x',), 'QQx',
|
2707
|
+
....: gens_syntax=sib.empty_subscript(qq))
|
2708
|
+
{constr_parent: {subscr: {atomic:QQ}[{atomic:'x'}]} with gens: ('x',)}
|
2709
|
+
"""
|
2710
|
+
super().__init__(sib)
|
2711
|
+
self._sie_constr = constr
|
2712
|
+
self._sie_gen_names = gen_names
|
2713
|
+
self._sie_gens = None # will be overwritten from .parent_with_gens()
|
2714
|
+
self._sie_gens_constr = gens_syntax
|
2715
|
+
self._sie_assign_gens = False
|
2716
|
+
self._sie_generated = False
|
2717
|
+
|
2718
|
+
def __repr__(self):
|
2719
|
+
r"""
|
2720
|
+
Return a string representing this :class:`SIE_gens_constructor` value.
|
2721
|
+
|
2722
|
+
EXAMPLES::
|
2723
|
+
|
2724
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2725
|
+
|
2726
|
+
sage: sib = SageInputBuilder()
|
2727
|
+
sage: qq = sib.name('QQ')
|
2728
|
+
sage: sib.parent_with_gens("some parent", qq['x'],
|
2729
|
+
....: ('x',), 'QQx',
|
2730
|
+
....: gens_syntax=sib.empty_subscript(qq))
|
2731
|
+
{constr_parent: {subscr: {atomic:QQ}[{atomic:'x'}]} with gens: ('x',)}
|
2732
|
+
"""
|
2733
|
+
return "{constr_parent: %s with gens: %s}" % (repr(self._sie_constr), self._sie_gen_names)
|
2734
|
+
|
2735
|
+
def _sie_referenced(self):
|
2736
|
+
r"""
|
2737
|
+
Return a list of the immediate subexpressions of this
|
2738
|
+
:class:`SIE_gens_constructor`.
|
2739
|
+
|
2740
|
+
EXAMPLES::
|
2741
|
+
|
2742
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2743
|
+
|
2744
|
+
sage: sib = SageInputBuilder()
|
2745
|
+
sage: qq = sib.name('QQ')
|
2746
|
+
sage: gc = sib.parent_with_gens("some parent", qq['x'],
|
2747
|
+
....: ('x',), 'QQx',
|
2748
|
+
....: gens_syntax=sib.empty_subscript(qq))
|
2749
|
+
sage: gc._sie_referenced()
|
2750
|
+
[{subscr: {atomic:QQ}[{atomic:'x'}]}]
|
2751
|
+
"""
|
2752
|
+
# This is used to determine if some expressions should be replaced
|
2753
|
+
# by variables (if the expression has more than one parent in
|
2754
|
+
# the expression DAG). We assume that all expressions in
|
2755
|
+
# self._sie_gens_constr also occur in self._sie_constr.
|
2756
|
+
return [self._sie_constr]
|
2757
|
+
|
2758
|
+
def _sie_gens_referenced(self, sif):
|
2759
|
+
r"""
|
2760
|
+
Mark that at least one of the generators in this
|
2761
|
+
:class:`SIE_gens_constructor` is used. (This means we will actually
|
2762
|
+
construct all of the generators.)
|
2763
|
+
|
2764
|
+
EXAMPLES::
|
2765
|
+
|
2766
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
2767
|
+
|
2768
|
+
sage: sib = SageInputBuilder()
|
2769
|
+
sage: sif = SageInputFormatter()
|
2770
|
+
sage: qq = sib.name('QQ')
|
2771
|
+
sage: gc = sib.parent_with_gens("some parent", qq['x'],
|
2772
|
+
....: ('x',), 'QQx',
|
2773
|
+
....: gens_syntax=sib.empty_subscript(qq))
|
2774
|
+
sage: gc._sie_assign_gens
|
2775
|
+
False
|
2776
|
+
sage: gc._sie_gens_referenced(sif)
|
2777
|
+
sage: gc._sie_assign_gens
|
2778
|
+
True
|
2779
|
+
"""
|
2780
|
+
self._sie_assign_gens = True
|
2781
|
+
self._sie_require_varname(sif)
|
2782
|
+
for gen in self._sie_gens:
|
2783
|
+
gen._sie_require_varname(sif)
|
2784
|
+
|
2785
|
+
def _sie_add_command(self, sif):
|
2786
|
+
r"""
|
2787
|
+
Build commands to construct this parent and (if necessary)
|
2788
|
+
its associated generators.
|
2789
|
+
|
2790
|
+
EXAMPLES::
|
2791
|
+
|
2792
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
2793
|
+
|
2794
|
+
sage: sib = SageInputBuilder()
|
2795
|
+
sage: sif = SageInputFormatter()
|
2796
|
+
sage: qq = sib.name('QQ')
|
2797
|
+
sage: gc = sib.parent_with_gens("some parent", qq['x'],
|
2798
|
+
....: ('x',), 'QQx',
|
2799
|
+
....: gens_syntax=sib.empty_subscript(qq))
|
2800
|
+
sage: gc._sie_gens_referenced(sif)
|
2801
|
+
sage: gc._sie_prepare(sif)
|
2802
|
+
sage: gc._sie_add_command(sif)
|
2803
|
+
sage: sif._commands
|
2804
|
+
'QQx.<x> = QQ[]\n'
|
2805
|
+
|
2806
|
+
TESTS:
|
2807
|
+
|
2808
|
+
There are several tricky cases here.
|
2809
|
+
|
2810
|
+
We prefer the \sage preparser generators syntax::
|
2811
|
+
|
2812
|
+
sage: sage_input(polygen(ZZ))
|
2813
|
+
R.<x> = ZZ[]
|
2814
|
+
x
|
2815
|
+
|
2816
|
+
But of course we can't use that without the preparser::
|
2817
|
+
|
2818
|
+
sage: sage_input(polygen(ZZ), preparse=False)
|
2819
|
+
R = ZZ['x']
|
2820
|
+
x = R.gen()
|
2821
|
+
x
|
2822
|
+
|
2823
|
+
We also can't use the preparser syntax if there is a conflict
|
2824
|
+
between generator names. For example, this works::
|
2825
|
+
|
2826
|
+
sage: sage_input((polygen(ZZ), polygen(GF(17), 'y')))
|
2827
|
+
R1.<x> = ZZ[]
|
2828
|
+
R2.<y> = GF(17)[]
|
2829
|
+
(x, y)
|
2830
|
+
|
2831
|
+
but this can't use the preparser syntax.::
|
2832
|
+
|
2833
|
+
sage: sage_input((polygen(ZZ), polygen(GF(17))))
|
2834
|
+
R1 = ZZ['x']
|
2835
|
+
x1 = R1.gen()
|
2836
|
+
R2 = GF(17)['x']
|
2837
|
+
x2 = R2.gen()
|
2838
|
+
(x1, x2)
|
2839
|
+
|
2840
|
+
If we never use the generators, then we don't bother with the
|
2841
|
+
preparser syntax.::
|
2842
|
+
|
2843
|
+
sage: sage_input((ZZ['x'], ZZ['x'], GF(17)['y']))
|
2844
|
+
R = ZZ['x']
|
2845
|
+
(R, R, GF(17)['y'])
|
2846
|
+
"""
|
2847
|
+
if not self._sie_generated:
|
2848
|
+
if self._sie_builder.preparse() and \
|
2849
|
+
self._sie_gens_constr is not None and \
|
2850
|
+
all(g._sie_got_preferred(sif) for g in self._sie_gens):
|
2851
|
+
s, _ = self._sie_gens_constr._sie_format(sif)
|
2852
|
+
sif._commands += '%s.<%s> = %s\n' % (self._sie_get_varname(sif), ','.join(self._sie_gen_names), s)
|
2853
|
+
else:
|
2854
|
+
s, _ = self._sie_constr._sie_format(sif)
|
2855
|
+
sif._commands += '%s = %s\n' % (self._sie_get_varname(sif), s)
|
2856
|
+
if self._sie_assign_gens:
|
2857
|
+
if len(self._sie_gens) == 1:
|
2858
|
+
sif._commands += '%s = %s.gen()\n' % (self._sie_gens[0]._sie_get_varname(sif), self._sie_get_varname(sif))
|
2859
|
+
else:
|
2860
|
+
sif._commands += '%s = %s.gens()\n' % (','.join(g._sie_get_varname(sif) for g in self._sie_gens), self._sie_get_varname(sif))
|
2861
|
+
self._sie_generated = True
|
2862
|
+
|
2863
|
+
def _sie_format(self, sif):
|
2864
|
+
r"""
|
2865
|
+
Return the formatted string value of this parent-construction
|
2866
|
+
expression, and its precedence.
|
2867
|
+
|
2868
|
+
As a side effect, if the generators of this parent are used,
|
2869
|
+
this adds commands to assign the generators to names.
|
2870
|
+
|
2871
|
+
EXAMPLES::
|
2872
|
+
|
2873
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
2874
|
+
|
2875
|
+
sage: sib = SageInputBuilder()
|
2876
|
+
sage: sif = SageInputFormatter()
|
2877
|
+
sage: qq = sib.name('QQ')
|
2878
|
+
sage: gc = sib.parent_with_gens("some parent", qq['x'],
|
2879
|
+
....: ('x',), 'QQx',
|
2880
|
+
....: gens_syntax=sib.empty_subscript(qq))
|
2881
|
+
sage: gc._sie_gens_referenced(sif)
|
2882
|
+
sage: gc._sie_prepare(sif)
|
2883
|
+
sage: gc._sie_format(sif)
|
2884
|
+
('QQx', 42)
|
2885
|
+
sage: sif._commands
|
2886
|
+
'QQx.<x> = QQ[]\n'
|
2887
|
+
"""
|
2888
|
+
if self._sie_assign_gens:
|
2889
|
+
self._sie_add_command(sif)
|
2890
|
+
return self._sie_get_varname(sif), _prec_atomic
|
2891
|
+
|
2892
|
+
return self._sie_constr._sie_format(sif)
|
2893
|
+
|
2894
|
+
|
2895
|
+
class SIE_gen(SageInputExpression):
|
2896
|
+
r"""
|
2897
|
+
This class represents a named generator of a parent with named
|
2898
|
+
generators.
|
2899
|
+
|
2900
|
+
EXAMPLES::
|
2901
|
+
|
2902
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2903
|
+
|
2904
|
+
sage: sib = SageInputBuilder()
|
2905
|
+
sage: sib.gen(ZZ['x'])
|
2906
|
+
{gen:x {constr_parent: {subscr: {atomic:ZZ}[{atomic:'x'}]} with gens: ('x',)}}
|
2907
|
+
"""
|
2908
|
+
|
2909
|
+
def __init__(self, sib, parent, name):
|
2910
|
+
r"""
|
2911
|
+
Initialize an instance of :class:`SIE_gen`.
|
2912
|
+
|
2913
|
+
INPUT:
|
2914
|
+
|
2915
|
+
- ``sib`` -- a :class:`SageInputBuilder`
|
2916
|
+
|
2917
|
+
- ``parent`` -- a :class:`SIE_gens_constructor`
|
2918
|
+
|
2919
|
+
- ``name`` -- string with the name of this generator
|
2920
|
+
|
2921
|
+
EXAMPLES::
|
2922
|
+
|
2923
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2924
|
+
|
2925
|
+
sage: sib = SageInputBuilder()
|
2926
|
+
sage: sib.gen(ZZ['x']) # indirect doctest
|
2927
|
+
{gen:x {constr_parent: {subscr: {atomic:ZZ}[{atomic:'x'}]} with gens: ('x',)}}
|
2928
|
+
"""
|
2929
|
+
super().__init__(sib)
|
2930
|
+
self._sie_parent = parent
|
2931
|
+
self._sie_preferred_varname = name
|
2932
|
+
|
2933
|
+
def __repr__(self):
|
2934
|
+
r"""
|
2935
|
+
Return a string representing this :class:`SIE_gen` value.
|
2936
|
+
|
2937
|
+
EXAMPLES::
|
2938
|
+
|
2939
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2940
|
+
|
2941
|
+
sage: sib = SageInputBuilder()
|
2942
|
+
sage: sib.gen(ZZ['x']) # indirect doctest
|
2943
|
+
{gen:x {constr_parent: {subscr: {atomic:ZZ}[{atomic:'x'}]} with gens: ('x',)}}
|
2944
|
+
"""
|
2945
|
+
return "{gen:%s %s}" % (self._sie_preferred_varname, repr(self._sie_parent))
|
2946
|
+
|
2947
|
+
def _sie_is_simple(self):
|
2948
|
+
r"""
|
2949
|
+
Report that :class:`SIE_gen` values are single tokens.
|
2950
|
+
|
2951
|
+
EXAMPLES::
|
2952
|
+
|
2953
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
2954
|
+
|
2955
|
+
sage: sib = SageInputBuilder()
|
2956
|
+
sage: sib.gen(ZZ['x'])._sie_is_simple()
|
2957
|
+
True
|
2958
|
+
"""
|
2959
|
+
return True
|
2960
|
+
|
2961
|
+
def _sie_prepare(self, sif):
|
2962
|
+
r"""
|
2963
|
+
We override the \method{_sie_prepare} method from
|
2964
|
+
:class:`SageInputExpression` to additionally mark the parent of this
|
2965
|
+
generator that the generator names must be assigned.
|
2966
|
+
|
2967
|
+
EXAMPLES::
|
2968
|
+
|
2969
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
2970
|
+
|
2971
|
+
sage: sib = SageInputBuilder()
|
2972
|
+
sage: sif = SageInputFormatter()
|
2973
|
+
sage: sie = sib.gen(GF(13)['z'])
|
2974
|
+
sage: sie._sie_parent._sie_assign_gens
|
2975
|
+
False
|
2976
|
+
sage: sie._sie_prepare(sif)
|
2977
|
+
sage: sie._sie_parent._sie_assign_gens
|
2978
|
+
True
|
2979
|
+
"""
|
2980
|
+
super()._sie_prepare(sif)
|
2981
|
+
self._sie_parent._sie_gens_referenced(sif)
|
2982
|
+
|
2983
|
+
def _sie_format(self, sif):
|
2984
|
+
r"""
|
2985
|
+
Return the formatted string value of this named generator,
|
2986
|
+
and an indication that it is atomic.
|
2987
|
+
|
2988
|
+
As a side effect, this generates commands to assign the generators
|
2989
|
+
of the parent to variables.
|
2990
|
+
|
2991
|
+
EXAMPLES::
|
2992
|
+
|
2993
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
2994
|
+
|
2995
|
+
sage: sib = SageInputBuilder()
|
2996
|
+
sage: sif = SageInputFormatter()
|
2997
|
+
sage: sie = sib.gen(GF(41)['x'])
|
2998
|
+
sage: sie._sie_prepare(sif)
|
2999
|
+
sage: sie._sie_format(sif)
|
3000
|
+
('x', 42)
|
3001
|
+
sage: sif._commands
|
3002
|
+
'R.<x> = GF(41)[]\n'
|
3003
|
+
"""
|
3004
|
+
self._sie_parent._sie_add_command(sif)
|
3005
|
+
return self._sie_get_varname(sif), _prec_atomic
|
3006
|
+
|
3007
|
+
def _sie_got_preferred(self, sif):
|
3008
|
+
r"""
|
3009
|
+
Check whether the :class:`SageInputFormatter` assigned us a
|
3010
|
+
variable name which is the same as the name of the generator
|
3011
|
+
name.
|
3012
|
+
|
3013
|
+
EXAMPLES::
|
3014
|
+
|
3015
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
3016
|
+
|
3017
|
+
First we verify that if we use two generators with different
|
3018
|
+
names, then they get their preferred names.::
|
3019
|
+
|
3020
|
+
sage: sib = SageInputBuilder()
|
3021
|
+
sage: sif = SageInputFormatter()
|
3022
|
+
sage: v = sib.gen(GF(2)['x']); w = sib.gen(GF(3)['y'])
|
3023
|
+
sage: v._sie_prepare(sif); w._sie_prepare(sif)
|
3024
|
+
sage: v._sie_got_preferred(sif)
|
3025
|
+
True
|
3026
|
+
sage: w._sie_got_preferred(sif)
|
3027
|
+
True
|
3028
|
+
|
3029
|
+
Now, we repeat the experiment, except that the generators now
|
3030
|
+
have the same names. In this case, the :class:`SageInputFormatter`
|
3031
|
+
will not use the generator name as the variable name, because
|
3032
|
+
of this conflict.::
|
3033
|
+
|
3034
|
+
sage: sib = SageInputBuilder()
|
3035
|
+
sage: sif = SageInputFormatter()
|
3036
|
+
sage: v = sib.gen(GF(2)['x']); w = sib.gen(GF(3)['x'])
|
3037
|
+
sage: v._sie_prepare(sif); w._sie_prepare(sif)
|
3038
|
+
sage: v._sie_got_preferred(sif)
|
3039
|
+
False
|
3040
|
+
sage: w._sie_got_preferred(sif)
|
3041
|
+
False
|
3042
|
+
"""
|
3043
|
+
return self._sie_get_varname(sif) == self._sie_preferred_varname
|
3044
|
+
|
3045
|
+
|
3046
|
+
class SIE_import_name(SageInputExpression):
|
3047
|
+
r"""
|
3048
|
+
This class represents a name which has been imported from a module.
|
3049
|
+
|
3050
|
+
EXAMPLES::
|
3051
|
+
|
3052
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
3053
|
+
|
3054
|
+
sage: sib = SageInputBuilder()
|
3055
|
+
sage: sib.import_name('sage.rings.integer', 'make_integer')
|
3056
|
+
{import:sage.rings.integer/make_integer}
|
3057
|
+
sage: sib.import_name('sage.foo', 'happy', 'sad')
|
3058
|
+
{import:sage.foo/happy as sad}
|
3059
|
+
"""
|
3060
|
+
|
3061
|
+
def __init__(self, sib, module, name, alt_name=None):
|
3062
|
+
r"""
|
3063
|
+
Initialize an instance of :class:`SIE_import_name`.
|
3064
|
+
|
3065
|
+
INPUT:
|
3066
|
+
|
3067
|
+
- ``sib`` -- a :class:`SageInputBuilder`
|
3068
|
+
|
3069
|
+
- ``module`` -- a module name
|
3070
|
+
|
3071
|
+
- ``name`` -- an object name
|
3072
|
+
|
3073
|
+
- ``alt_name`` -- an alternate object name, or None (the default)
|
3074
|
+
to use name
|
3075
|
+
|
3076
|
+
EXAMPLES::
|
3077
|
+
|
3078
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
3079
|
+
|
3080
|
+
sage: sib = SageInputBuilder()
|
3081
|
+
sage: sib.import_name('sage.rings.integer', 'make_integer') # indirect doctest
|
3082
|
+
{import:sage.rings.integer/make_integer}
|
3083
|
+
sage: sib.import_name('sage.foo', 'happy', 'sad')
|
3084
|
+
{import:sage.foo/happy as sad}
|
3085
|
+
"""
|
3086
|
+
super().__init__(sib)
|
3087
|
+
self._sie_formatted = False
|
3088
|
+
self._sie_module_name = module
|
3089
|
+
self._sie_object_name = name
|
3090
|
+
if alt_name is None:
|
3091
|
+
self._sie_preferred_varname = name
|
3092
|
+
else:
|
3093
|
+
self._sie_preferred_varname = alt_name
|
3094
|
+
|
3095
|
+
def __repr__(self):
|
3096
|
+
r"""
|
3097
|
+
Return a string representing this :class:`SIE_import_name` value.
|
3098
|
+
|
3099
|
+
EXAMPLES::
|
3100
|
+
|
3101
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
3102
|
+
|
3103
|
+
sage: sib = SageInputBuilder()
|
3104
|
+
sage: sib.import_name('sage.rings.integer', 'make_integer') # indirect doctest
|
3105
|
+
{import:sage.rings.integer/make_integer}
|
3106
|
+
sage: sib.import_name('sage.foo', 'happy', 'sad')
|
3107
|
+
{import:sage.foo/happy as sad}
|
3108
|
+
"""
|
3109
|
+
return "{import:%s/%s%s}" % (self._sie_module_name, self._sie_object_name,
|
3110
|
+
"" if self._sie_object_name == self._sie_preferred_varname else " as %s" % self._sie_preferred_varname)
|
3111
|
+
|
3112
|
+
def _sie_is_simple(self):
|
3113
|
+
r"""
|
3114
|
+
Report that :class:`SIE_import_name` values are single tokens.
|
3115
|
+
|
3116
|
+
EXAMPLES::
|
3117
|
+
|
3118
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
3119
|
+
|
3120
|
+
sage: sib = SageInputBuilder()
|
3121
|
+
sage: sib.import_name('sage.rings.integer', 'make_integer')._sie_is_simple()
|
3122
|
+
True
|
3123
|
+
"""
|
3124
|
+
return True
|
3125
|
+
|
3126
|
+
def _sie_prepare(self, sif):
|
3127
|
+
r"""
|
3128
|
+
We override the \method{_sie_prepare} method from
|
3129
|
+
:class:`SageInputExpression` to request a variable name.
|
3130
|
+
|
3131
|
+
EXAMPLES::
|
3132
|
+
|
3133
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
3134
|
+
|
3135
|
+
sage: sib = SageInputBuilder()
|
3136
|
+
sage: sif = SageInputFormatter()
|
3137
|
+
sage: sie = sib.import_name('sage.rings.integer', 'make_integer')
|
3138
|
+
sage: sie._sie_requested_varname
|
3139
|
+
False
|
3140
|
+
sage: sie._sie_prepare(sif)
|
3141
|
+
sage: sie._sie_requested_varname
|
3142
|
+
True
|
3143
|
+
"""
|
3144
|
+
super()._sie_prepare(sif)
|
3145
|
+
self._sie_require_varname(sif)
|
3146
|
+
|
3147
|
+
def _sie_format(self, sif):
|
3148
|
+
r"""
|
3149
|
+
Return the formatted string value of this import,
|
3150
|
+
and an indication that it is atomic.
|
3151
|
+
|
3152
|
+
EXAMPLES::
|
3153
|
+
|
3154
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
3155
|
+
|
3156
|
+
sage: sib = SageInputBuilder()
|
3157
|
+
sage: sif = SageInputFormatter()
|
3158
|
+
sage: v1 = sib.import_name('sage.rings.integer', 'make_integer')
|
3159
|
+
sage: v2 = sib.import_name('sage.foo', 'happy', 'sad')
|
3160
|
+
sage: sie = v1(v2)
|
3161
|
+
sage: sie._sie_prepare(sif)
|
3162
|
+
sage: sie._sie_format(sif)
|
3163
|
+
('make_integer(sad)', 40)
|
3164
|
+
sage: print(sif._commands)
|
3165
|
+
from sage.rings.integer import make_integer
|
3166
|
+
from sage.foo import happy as sad
|
3167
|
+
"""
|
3168
|
+
name = self._sie_get_varname(sif)
|
3169
|
+
if self._sie_formatted:
|
3170
|
+
# Only run the import command once
|
3171
|
+
return name, _prec_atomic
|
3172
|
+
self._sie_formatted = True
|
3173
|
+
rename = ''
|
3174
|
+
if name != self._sie_object_name:
|
3175
|
+
rename = ' as ' + name
|
3176
|
+
sif._commands += 'from %s import %s%s\n' % (self._sie_module_name,
|
3177
|
+
self._sie_object_name,
|
3178
|
+
rename)
|
3179
|
+
return name, _prec_atomic
|
3180
|
+
|
3181
|
+
|
3182
|
+
class SIE_assign(SageInputExpression):
|
3183
|
+
r"""
|
3184
|
+
This class represents an assignment command.
|
3185
|
+
|
3186
|
+
EXAMPLES::
|
3187
|
+
|
3188
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
3189
|
+
|
3190
|
+
sage: sib = SageInputBuilder()
|
3191
|
+
sage: sib.assign(sib.name('foo').x, sib.name('pi'))
|
3192
|
+
{assign: {getattr: {atomic:foo}.x} {atomic:pi}}
|
3193
|
+
"""
|
3194
|
+
|
3195
|
+
def __init__(self, sib, lhs, rhs):
|
3196
|
+
r"""
|
3197
|
+
Initialize an instance of :class:`SIE_assign`.
|
3198
|
+
|
3199
|
+
INPUT:
|
3200
|
+
|
3201
|
+
- ``sib`` -- a :class:`SageInputBuilder`
|
3202
|
+
|
3203
|
+
- ``lhs`` -- the left-hand side of the assignment
|
3204
|
+
|
3205
|
+
- ``rhs`` -- the right-hand side of the assignment
|
3206
|
+
|
3207
|
+
EXAMPLES::
|
3208
|
+
|
3209
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
3210
|
+
|
3211
|
+
sage: sib = SageInputBuilder()
|
3212
|
+
sage: sib.assign(sib.name('foo').x, sib.name('pi'))
|
3213
|
+
{assign: {getattr: {atomic:foo}.x} {atomic:pi}}
|
3214
|
+
"""
|
3215
|
+
super().__init__(sib)
|
3216
|
+
self._sie_lhs = lhs
|
3217
|
+
self._sie_rhs = rhs
|
3218
|
+
|
3219
|
+
def __repr__(self):
|
3220
|
+
r"""
|
3221
|
+
Return a string representing this :class:`SIE_assign` command.
|
3222
|
+
|
3223
|
+
EXAMPLES::
|
3224
|
+
|
3225
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
3226
|
+
|
3227
|
+
sage: sib = SageInputBuilder()
|
3228
|
+
sage: sib.assign(sib.name('foo').x, sib.name('pi'))
|
3229
|
+
{assign: {getattr: {atomic:foo}.x} {atomic:pi}}
|
3230
|
+
"""
|
3231
|
+
return "{assign: %s %s}" % (repr(self._sie_lhs), repr(self._sie_rhs))
|
3232
|
+
|
3233
|
+
def _sie_referenced(self):
|
3234
|
+
r"""
|
3235
|
+
Return a list of the immediate subexpressions of this
|
3236
|
+
:class:`SIE_assign`.
|
3237
|
+
|
3238
|
+
EXAMPLES::
|
3239
|
+
|
3240
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
3241
|
+
|
3242
|
+
sage: sib = SageInputBuilder()
|
3243
|
+
sage: sie = sib.assign(sib.name('foo').x, sib.name('pi'))
|
3244
|
+
sage: sie._sie_referenced()
|
3245
|
+
[{getattr: {atomic:foo}.x}, {atomic:pi}]
|
3246
|
+
"""
|
3247
|
+
return [self._sie_lhs, self._sie_rhs]
|
3248
|
+
|
3249
|
+
def _sie_format(self, sif):
|
3250
|
+
r"""
|
3251
|
+
Return the formatted string value of this :class:`SIE_assign`
|
3252
|
+
as an expression. Since an assignment is a statement, not
|
3253
|
+
an expression, always raises an error.
|
3254
|
+
|
3255
|
+
EXAMPLES::
|
3256
|
+
|
3257
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
3258
|
+
|
3259
|
+
sage: sib = SageInputBuilder()
|
3260
|
+
sage: sif = SageInputFormatter()
|
3261
|
+
sage: sie = sib.assign(sib.name('foo').x, sib.name('pi'))
|
3262
|
+
sage: sie._sie_prepare(sif)
|
3263
|
+
sage: sie._sie_format(sif)
|
3264
|
+
Traceback (most recent call last):
|
3265
|
+
...
|
3266
|
+
ValueError: Cannot format SIE_assign as expression
|
3267
|
+
"""
|
3268
|
+
raise ValueError("Cannot format SIE_assign as expression")
|
3269
|
+
|
3270
|
+
def _sie_format_statement(self, sif):
|
3271
|
+
r"""
|
3272
|
+
Return the formatted string of this :class:`SIE_assign`
|
3273
|
+
as a statement.
|
3274
|
+
|
3275
|
+
EXAMPLES::
|
3276
|
+
|
3277
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
3278
|
+
sage: sib = SageInputBuilder()
|
3279
|
+
sage: sif = SageInputFormatter()
|
3280
|
+
sage: sie = sib.assign(sib.name('foo').x, sib.name('pi'))
|
3281
|
+
sage: sie._sie_prepare(sif)
|
3282
|
+
sage: sie._sie_format_statement(sif)
|
3283
|
+
'foo.x = pi'
|
3284
|
+
"""
|
3285
|
+
return '%s = %s' % (sif.format(self._sie_lhs, 0), sif.format(self._sie_rhs, 0))
|
3286
|
+
|
3287
|
+
|
3288
|
+
class SageInputFormatter:
|
3289
|
+
r"""
|
3290
|
+
An instance of this class is used to keep track of variable names
|
3291
|
+
and a sequence of generated commands during the :func:`sage_input`
|
3292
|
+
formatting process.
|
3293
|
+
"""
|
3294
|
+
|
3295
|
+
def __init__(self):
|
3296
|
+
r"""
|
3297
|
+
Initialize an instance of :class:`SageInputFormatter`.
|
3298
|
+
|
3299
|
+
EXAMPLES::
|
3300
|
+
|
3301
|
+
sage: from sage.misc.sage_input import SageInputFormatter
|
3302
|
+
sage: sif = SageInputFormatter()
|
3303
|
+
"""
|
3304
|
+
self._commands = ''
|
3305
|
+
self._names = set()
|
3306
|
+
self._dup_names = {}
|
3307
|
+
|
3308
|
+
def format(self, e, prec):
|
3309
|
+
r"""
|
3310
|
+
Format a Sage input expression into a string.
|
3311
|
+
|
3312
|
+
INPUT:
|
3313
|
+
|
3314
|
+
- ``e`` -- a :class:`SageInputExpression`
|
3315
|
+
|
3316
|
+
- ``prec`` -- integer representing a precedence level
|
3317
|
+
|
3318
|
+
First, we check to see if ``e`` should be replaced by a variable.
|
3319
|
+
If so, we generate the command to assign the variable, and return
|
3320
|
+
the name of the variable.
|
3321
|
+
|
3322
|
+
Otherwise, we format the expression by calling its \method{_sie_format}
|
3323
|
+
method, and add parentheses if necessary.
|
3324
|
+
|
3325
|
+
EXAMPLES::
|
3326
|
+
|
3327
|
+
sage: from sage.misc.sage_input import SageInputBuilder, SageInputFormatter
|
3328
|
+
|
3329
|
+
sage: sib = SageInputBuilder()
|
3330
|
+
sage: sif = SageInputFormatter()
|
3331
|
+
sage: sie = sib(GF(5))
|
3332
|
+
|
3333
|
+
Here we ``cheat`` by calling \method{_sie_prepare} twice, to make it
|
3334
|
+
use a variable.::
|
3335
|
+
|
3336
|
+
sage: sie._sie_prepare(sif)
|
3337
|
+
sage: sie._sie_prepare(sif)
|
3338
|
+
sage: sif._commands
|
3339
|
+
''
|
3340
|
+
sage: sif.format(sie, 0)
|
3341
|
+
'GF_5'
|
3342
|
+
sage: sif._commands
|
3343
|
+
'GF_5 = GF(5)\n'
|
3344
|
+
|
3345
|
+
We demonstrate the use of commands, by showing how to construct
|
3346
|
+
code that will produce a random matrix::
|
3347
|
+
|
3348
|
+
sage: sib = SageInputBuilder()
|
3349
|
+
sage: sif = SageInputFormatter()
|
3350
|
+
sage: sie = sib.name('matrix')(sib.name('ZZ'), 10, 10)
|
3351
|
+
sage: sib.command(sie, sie.randomize())
|
3352
|
+
sage: sie._sie_prepare(sif)
|
3353
|
+
sage: sif._commands
|
3354
|
+
''
|
3355
|
+
sage: sif.format(sie, 0)
|
3356
|
+
'si'
|
3357
|
+
sage: sif._commands
|
3358
|
+
'si = matrix(ZZ, 10, 10)\nsi.randomize()\n'
|
3359
|
+
"""
|
3360
|
+
if e._sie_use_var:
|
3361
|
+
if not e._sie_generated:
|
3362
|
+
s, _ = e._sie_format(self)
|
3363
|
+
# In complicated situations, this can get called
|
3364
|
+
# recursively...
|
3365
|
+
if not e._sie_generated:
|
3366
|
+
self._commands += '%s = %s\n' % (e._sie_get_varname(self), s)
|
3367
|
+
e._sie_generated = True
|
3368
|
+
|
3369
|
+
formatted = e._sie_get_varname(self)
|
3370
|
+
else:
|
3371
|
+
s, iprec = e._sie_format(self)
|
3372
|
+
if iprec < prec:
|
3373
|
+
s = '(' + s + ')'
|
3374
|
+
formatted = s
|
3375
|
+
|
3376
|
+
commands = e._sie_commands
|
3377
|
+
e._sie_commands = []
|
3378
|
+
|
3379
|
+
for cmd in commands:
|
3380
|
+
s_cmd = cmd._sie_format_statement(self)
|
3381
|
+
self._commands += s_cmd + '\n'
|
3382
|
+
|
3383
|
+
return formatted
|
3384
|
+
|
3385
|
+
def register_name(self, name):
|
3386
|
+
r"""
|
3387
|
+
Register that some value would like to use a given name.
|
3388
|
+
If only one request for a name is received, then we will use the
|
3389
|
+
requested name; otherwise, we will add numbers to the end of the
|
3390
|
+
name to make it unique.
|
3391
|
+
|
3392
|
+
If the input name is ``None``, then it is treated as a name of
|
3393
|
+
``'si'``.
|
3394
|
+
|
3395
|
+
EXAMPLES::
|
3396
|
+
|
3397
|
+
sage: from sage.misc.sage_input import SageInputFormatter
|
3398
|
+
|
3399
|
+
sage: sif = SageInputFormatter()
|
3400
|
+
sage: sif._names, sif._dup_names
|
3401
|
+
(set(), {})
|
3402
|
+
sage: sif.register_name('x')
|
3403
|
+
sage: sif.register_name('y')
|
3404
|
+
sage: sif._names, sif._dup_names
|
3405
|
+
({'x', 'y'}, {})
|
3406
|
+
sage: sif.register_name('x')
|
3407
|
+
sage: sif._names, sif._dup_names
|
3408
|
+
({'x', 'y'}, {'x': 0})
|
3409
|
+
"""
|
3410
|
+
if name is None:
|
3411
|
+
name = 'si'
|
3412
|
+
|
3413
|
+
if name in self._names:
|
3414
|
+
self._dup_names[name] = 0
|
3415
|
+
else:
|
3416
|
+
self._names.add(name)
|
3417
|
+
|
3418
|
+
def get_name(self, name):
|
3419
|
+
r"""
|
3420
|
+
Return a name corresponding to a given requested name.
|
3421
|
+
If only one request for a name is received, then we will use the
|
3422
|
+
requested name; otherwise, we will add numbers to the end of the
|
3423
|
+
name to make it unique.
|
3424
|
+
|
3425
|
+
If the input name is ``None``, then it is treated as a name of
|
3426
|
+
``'si'``.
|
3427
|
+
|
3428
|
+
EXAMPLES::
|
3429
|
+
|
3430
|
+
sage: from sage.misc.sage_input import SageInputFormatter
|
3431
|
+
|
3432
|
+
sage: sif = SageInputFormatter()
|
3433
|
+
sage: names = ('x', 'x', 'y', 'z')
|
3434
|
+
sage: for n in names: sif.register_name(n)
|
3435
|
+
sage: for n in names: sif.get_name(n)
|
3436
|
+
'x1'
|
3437
|
+
'x2'
|
3438
|
+
'y'
|
3439
|
+
'z'
|
3440
|
+
"""
|
3441
|
+
if name is None:
|
3442
|
+
name = 'si'
|
3443
|
+
|
3444
|
+
if name in self._dup_names:
|
3445
|
+
next = self._dup_names[name] + 1
|
3446
|
+
self._dup_names[name] = next
|
3447
|
+
return name + str(next)
|
3448
|
+
else:
|
3449
|
+
return name
|
3450
|
+
|
3451
|
+
|
3452
|
+
def verify_same(a, b):
|
3453
|
+
r"""
|
3454
|
+
Verify that two Sage values are the same. This is an extended equality
|
3455
|
+
test; it checks that the values are equal and that their parents are equal.
|
3456
|
+
(For values which are not Elements, the types are checked instead.)
|
3457
|
+
|
3458
|
+
If the values are the same, we return ``None``; otherwise,
|
3459
|
+
we raise an exception.
|
3460
|
+
|
3461
|
+
EXAMPLES::
|
3462
|
+
|
3463
|
+
sage: from sage.misc.sage_input import verify_same
|
3464
|
+
sage: verify_same(1, 1)
|
3465
|
+
sage: verify_same(1, 2)
|
3466
|
+
Traceback (most recent call last):
|
3467
|
+
...
|
3468
|
+
AssertionError: Expected 1 == 2
|
3469
|
+
sage: verify_same(1, 1r)
|
3470
|
+
Traceback (most recent call last):
|
3471
|
+
...
|
3472
|
+
AttributeError: 'int' object has no attribute 'parent'...
|
3473
|
+
sage: verify_same(1r, 1)
|
3474
|
+
Traceback (most recent call last):
|
3475
|
+
...
|
3476
|
+
assert(type(a) == type(b))
|
3477
|
+
AssertionError
|
3478
|
+
sage: verify_same(5, GF(7)(5))
|
3479
|
+
Traceback (most recent call last):
|
3480
|
+
...
|
3481
|
+
assert(a.parent() == b.parent())
|
3482
|
+
AssertionError
|
3483
|
+
"""
|
3484
|
+
from sage.structure.element import Element
|
3485
|
+
if isinstance(a, Element):
|
3486
|
+
assert a.parent() == b.parent()
|
3487
|
+
else:
|
3488
|
+
assert type(a) is type(b)
|
3489
|
+
if isinstance(a, (RealIntervalFieldElement, ComplexIntervalFieldElement)):
|
3490
|
+
assert a.endpoints() == b.endpoints(), "Expected %s == %s" % (a, b)
|
3491
|
+
return
|
3492
|
+
|
3493
|
+
if not (a == b):
|
3494
|
+
# Verification failed => raise an AssertionError.
|
3495
|
+
#
|
3496
|
+
# There is an important exception: the IEEE-754 standard
|
3497
|
+
# recommends that NaN != NaN. So this comparison will fail for
|
3498
|
+
# any object involving NaN.
|
3499
|
+
#
|
3500
|
+
# If this case occurs, then a and b do not compare equal to
|
3501
|
+
# itself. In that case, we compare the string representations of
|
3502
|
+
# a and b.
|
3503
|
+
if not (a == a) and not (b == b):
|
3504
|
+
if repr(a) == repr(b):
|
3505
|
+
return # Good!
|
3506
|
+
raise AssertionError("Expected %r == %r" % (a, b))
|
3507
|
+
|
3508
|
+
|
3509
|
+
def verify_si_answer(x, answer, preparse):
|
3510
|
+
r"""
|
3511
|
+
Verify that evaluating ``answer`` gives a value equal to ``x``
|
3512
|
+
(with the same parent/type). If ``preparse`` is ``True`` or
|
3513
|
+
``False``, then we evaluate ``answer`` with the preparser
|
3514
|
+
enabled or disabled, respectively; if ``preparse`` is ``None``,
|
3515
|
+
then we evaluate ``answer`` both with the preparser enabled and
|
3516
|
+
disabled and check both results.
|
3517
|
+
|
3518
|
+
On success, we return ``None``; on failure, we raise an exception.
|
3519
|
+
|
3520
|
+
INPUT:
|
3521
|
+
|
3522
|
+
- ``x`` -- an arbitrary Sage value
|
3523
|
+
|
3524
|
+
- ``answer`` -- string, or a :class:`SageInputAnswer`
|
3525
|
+
|
3526
|
+
- ``preparse`` -- ``True``, ``False``, or ``None``
|
3527
|
+
|
3528
|
+
EXAMPLES::
|
3529
|
+
|
3530
|
+
sage: from sage.misc.sage_input import verify_si_answer
|
3531
|
+
sage: verify_si_answer(1, '1', True)
|
3532
|
+
sage: verify_si_answer(1, '1', False)
|
3533
|
+
Traceback (most recent call last):
|
3534
|
+
...
|
3535
|
+
AttributeError: 'int' object has no attribute 'parent'...
|
3536
|
+
sage: verify_si_answer(1, 'ZZ(1)', None)
|
3537
|
+
"""
|
3538
|
+
from sage.misc.sage_eval import sage_eval
|
3539
|
+
if preparse is None:
|
3540
|
+
verify_same(x, sage_eval(answer, preparse=True))
|
3541
|
+
verify_same(x, sage_eval(answer, preparse=False))
|
3542
|
+
else:
|
3543
|
+
verify_same(x, sage_eval(answer, preparse=preparse))
|
3544
|
+
|
3545
|
+
|
3546
|
+
class SageInputAnswer(tuple):
|
3547
|
+
r"""
|
3548
|
+
This class inherits from tuple, so it acts like a tuple when passed
|
3549
|
+
to :func:`sage_eval`; but it prints as a sequence of commands.
|
3550
|
+
|
3551
|
+
EXAMPLES::
|
3552
|
+
|
3553
|
+
sage: from sage.misc.sage_input import SageInputAnswer
|
3554
|
+
sage: v = SageInputAnswer('x = 22\n', 'x/7'); v
|
3555
|
+
x = 22
|
3556
|
+
x/7
|
3557
|
+
sage: isinstance(v, tuple)
|
3558
|
+
True
|
3559
|
+
sage: v[0]
|
3560
|
+
'x = 22\n'
|
3561
|
+
sage: v[1]
|
3562
|
+
'x/7'
|
3563
|
+
sage: len(v)
|
3564
|
+
2
|
3565
|
+
sage: v = SageInputAnswer('', 'sin(3.14)', {'sin': math.sin}); v
|
3566
|
+
LOCALS:
|
3567
|
+
sin: <built-in function sin>
|
3568
|
+
sin(3.14)
|
3569
|
+
sage: v[0]
|
3570
|
+
''
|
3571
|
+
sage: v[1]
|
3572
|
+
'sin(3.14)'
|
3573
|
+
sage: v[2]
|
3574
|
+
{'sin': <built-in function sin>}
|
3575
|
+
"""
|
3576
|
+
|
3577
|
+
def __new__(cls, cmds, expr, locals=None):
|
3578
|
+
r"""
|
3579
|
+
Construct an instance of :class:`SageInputAnswer`.
|
3580
|
+
|
3581
|
+
EXAMPLES::
|
3582
|
+
|
3583
|
+
sage: from sage.misc.sage_input import SageInputAnswer
|
3584
|
+
sage: v = SageInputAnswer('', 'sin(3.14)', {'sin': math.sin}); v
|
3585
|
+
LOCALS:
|
3586
|
+
sin: <built-in function sin>
|
3587
|
+
sin(3.14)
|
3588
|
+
sage: v[0]
|
3589
|
+
''
|
3590
|
+
sage: v[1]
|
3591
|
+
'sin(3.14)'
|
3592
|
+
sage: v[2]
|
3593
|
+
{'sin': <built-in function sin>}
|
3594
|
+
"""
|
3595
|
+
if locals:
|
3596
|
+
return tuple.__new__(cls, (cmds, expr, locals))
|
3597
|
+
else:
|
3598
|
+
return tuple.__new__(cls, (cmds, expr))
|
3599
|
+
|
3600
|
+
def __repr__(self):
|
3601
|
+
r"""
|
3602
|
+
Return a string representation for a :class:`SageInputAnswer`,
|
3603
|
+
such that if you evaluate this :class:`SageInputAnswer` at the
|
3604
|
+
\sage command line, you get a result in a nice form ready to
|
3605
|
+
copy-and-paste.
|
3606
|
+
|
3607
|
+
EXAMPLES::
|
3608
|
+
|
3609
|
+
sage: from sage.misc.sage_input import SageInputAnswer
|
3610
|
+
sage: v = SageInputAnswer('', 'sin(3.14)', {'sin': math.sin}); v
|
3611
|
+
LOCALS:
|
3612
|
+
sin: <built-in function sin>
|
3613
|
+
sin(3.14)
|
3614
|
+
"""
|
3615
|
+
if len(self) == 2:
|
3616
|
+
return self[0] + self[1]
|
3617
|
+
|
3618
|
+
locals = self[2]
|
3619
|
+
locals_text = ''.join(' %s: %r\n' % (k, v)
|
3620
|
+
for k, v in locals.items())
|
3621
|
+
return 'LOCALS:\n' + locals_text + self[0] + self[1]
|