Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sage
Path: blob/develop/src/sage_setup/autogen/interpreters/internal/specs/element.py
7403 views
1
#*****************************************************************************
2
# Copyright (C) 2009 Carl Witty <[email protected]>
3
# Copyright (C) 2015 Jeroen Demeyer <[email protected]>
4
#
5
# This program is free software: you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation, either version 2 of the License, or
8
# (at your option) any later version.
9
# http://www.gnu.org/licenses/
10
#*****************************************************************************
11
12
13
from ..storage import ty_python
14
from ..utils import reindent_lines as ri
15
from .base import StackInterpreter
16
from .python import MemoryChunkPyConstant, MemoryChunkPythonArguments, PythonInterpreter
17
18
19
class MemoryChunkElementArguments(MemoryChunkPythonArguments):
20
r"""
21
A special-purpose memory chunk, for the Python-object based
22
interpreters that want to process (and perhaps modify) the data.
23
24
We allocate a new list on every call to hold the modified arguments.
25
That's not strictly necessary -- we could pre-allocate a list and map into
26
it -- but this lets us use simpler code for a very-likely-negligible
27
efficiency cost. (The Element interpreter is going to allocate lots of
28
objects as it runs, anyway.)
29
"""
30
31
def setup_args(self):
32
r"""
33
Handle the arguments of __call__. Note: This hardcodes
34
"self._domain".
35
36
EXAMPLES::
37
38
sage: from sage_setup.autogen.interpreters.internal import *
39
sage: from sage_setup.autogen.interpreters.internal.specs.element import *
40
sage: mc = MemoryChunkElementArguments('args', ty_python)
41
sage: mc.setup_args()
42
'mapped_args = [self._domain(a) for a in args]\n'
43
"""
44
return "mapped_args = [self._domain(a) for a in args]\n"
45
46
def pass_argument(self):
47
r"""
48
Pass the innards of the argument tuple to the interpreter.
49
50
EXAMPLES::
51
52
sage: from sage_setup.autogen.interpreters.internal import *
53
sage: from sage_setup.autogen.interpreters.internal.specs.element import *
54
sage: mc = MemoryChunkElementArguments('args', ty_python)
55
sage: mc.pass_argument()
56
'(<PyListObject*>mapped_args).ob_item'
57
"""
58
return "(<PyListObject*>mapped_args).ob_item"
59
60
61
class ElementInterpreter(PythonInterpreter):
62
r"""
63
A subclass of PythonInterpreter, specifying an interpreter over
64
Sage elements with a particular parent.
65
66
This is very similar to the PythonInterpreter, but after every
67
instruction, the result is checked to make sure it actually an
68
element with the correct parent; if not, we attempt to convert it.
69
70
Uses the same instructions (with the same implementation) as
71
PythonInterpreter.
72
"""
73
74
name = 'el'
75
76
def __init__(self):
77
r"""
78
Initialize an ElementInterpreter.
79
80
EXAMPLES::
81
82
sage: from sage_setup.autogen.interpreters.internal import *
83
sage: from sage_setup.autogen.interpreters.internal.specs.element import *
84
sage: interp = ElementInterpreter()
85
sage: interp.name
86
'el'
87
sage: interp.mc_args
88
{MC:args}
89
sage: interp.chunks
90
[{MC:args}, {MC:constants}, {MC:stack}, {MC:domain}, {MC:code}]
91
sage: instrs = dict([(ins.name, ins) for ins in interp.instr_descs])
92
sage: instrs['add']
93
add: SS->S = 'o0 = PyNumber_Add(i0, i1);'
94
sage: instrs['py_call']
95
py_call: *->S = '\nPyObject *py_args...CREF(py_args);\n'
96
"""
97
98
super().__init__()
99
# PythonInterpreter.__init__ gave us a MemoryChunkPythonArguments.
100
# Override with MemoryChunkElementArguments.
101
self.mc_args = MemoryChunkElementArguments('args', ty_python)
102
self.mc_domain_info = MemoryChunkPyConstant('domain')
103
self.chunks = [self.mc_args, self.mc_constants, self.mc_stack,
104
self.mc_domain_info, self.mc_code]
105
self.c_header = ri(0, """
106
#define CHECK(x) do_check(&(x), domain)
107
108
static inline int do_check(PyObject **x, PyObject *domain) {
109
if (*x == NULL) return 0;
110
PyObject *new_x = el_check_element(*x, domain);
111
Py_DECREF(*x);
112
*x = new_x;
113
if (*x == NULL) return 0;
114
return 1;
115
}
116
""")
117
118
self.pyx_header += ri(0, """
119
from sage.structure.element cimport Element
120
121
cdef public object el_check_element(object v, parent):
122
cdef Element v_el
123
124
if isinstance(v, Element):
125
v_el = <Element>v
126
if v_el._parent is parent:
127
return v_el
128
129
return parent(v)
130
"""[1:])
131
132