Path: blob/develop/src/sage_setup/autogen/interpreters/internal/specs/element.py
7403 views
#*****************************************************************************1# Copyright (C) 2009 Carl Witty <[email protected]>2# Copyright (C) 2015 Jeroen Demeyer <[email protected]>3#4# This program is free software: you can redistribute it and/or modify5# it under the terms of the GNU General Public License as published by6# the Free Software Foundation, either version 2 of the License, or7# (at your option) any later version.8# http://www.gnu.org/licenses/9#*****************************************************************************101112from ..storage import ty_python13from ..utils import reindent_lines as ri14from .base import StackInterpreter15from .python import MemoryChunkPyConstant, MemoryChunkPythonArguments, PythonInterpreter161718class MemoryChunkElementArguments(MemoryChunkPythonArguments):19r"""20A special-purpose memory chunk, for the Python-object based21interpreters that want to process (and perhaps modify) the data.2223We allocate a new list on every call to hold the modified arguments.24That's not strictly necessary -- we could pre-allocate a list and map into25it -- but this lets us use simpler code for a very-likely-negligible26efficiency cost. (The Element interpreter is going to allocate lots of27objects as it runs, anyway.)28"""2930def setup_args(self):31r"""32Handle the arguments of __call__. Note: This hardcodes33"self._domain".3435EXAMPLES::3637sage: from sage_setup.autogen.interpreters.internal import *38sage: from sage_setup.autogen.interpreters.internal.specs.element import *39sage: mc = MemoryChunkElementArguments('args', ty_python)40sage: mc.setup_args()41'mapped_args = [self._domain(a) for a in args]\n'42"""43return "mapped_args = [self._domain(a) for a in args]\n"4445def pass_argument(self):46r"""47Pass the innards of the argument tuple to the interpreter.4849EXAMPLES::5051sage: from sage_setup.autogen.interpreters.internal import *52sage: from sage_setup.autogen.interpreters.internal.specs.element import *53sage: mc = MemoryChunkElementArguments('args', ty_python)54sage: mc.pass_argument()55'(<PyListObject*>mapped_args).ob_item'56"""57return "(<PyListObject*>mapped_args).ob_item"585960class ElementInterpreter(PythonInterpreter):61r"""62A subclass of PythonInterpreter, specifying an interpreter over63Sage elements with a particular parent.6465This is very similar to the PythonInterpreter, but after every66instruction, the result is checked to make sure it actually an67element with the correct parent; if not, we attempt to convert it.6869Uses the same instructions (with the same implementation) as70PythonInterpreter.71"""7273name = 'el'7475def __init__(self):76r"""77Initialize an ElementInterpreter.7879EXAMPLES::8081sage: from sage_setup.autogen.interpreters.internal import *82sage: from sage_setup.autogen.interpreters.internal.specs.element import *83sage: interp = ElementInterpreter()84sage: interp.name85'el'86sage: interp.mc_args87{MC:args}88sage: interp.chunks89[{MC:args}, {MC:constants}, {MC:stack}, {MC:domain}, {MC:code}]90sage: instrs = dict([(ins.name, ins) for ins in interp.instr_descs])91sage: instrs['add']92add: SS->S = 'o0 = PyNumber_Add(i0, i1);'93sage: instrs['py_call']94py_call: *->S = '\nPyObject *py_args...CREF(py_args);\n'95"""9697super().__init__()98# PythonInterpreter.__init__ gave us a MemoryChunkPythonArguments.99# Override with MemoryChunkElementArguments.100self.mc_args = MemoryChunkElementArguments('args', ty_python)101self.mc_domain_info = MemoryChunkPyConstant('domain')102self.chunks = [self.mc_args, self.mc_constants, self.mc_stack,103self.mc_domain_info, self.mc_code]104self.c_header = ri(0, """105#define CHECK(x) do_check(&(x), domain)106107static inline int do_check(PyObject **x, PyObject *domain) {108if (*x == NULL) return 0;109PyObject *new_x = el_check_element(*x, domain);110Py_DECREF(*x);111*x = new_x;112if (*x == NULL) return 0;113return 1;114}115""")116117self.pyx_header += ri(0, """118from sage.structure.element cimport Element119120cdef public object el_check_element(object v, parent):121cdef Element v_el122123if isinstance(v, Element):124v_el = <Element>v125if v_el._parent is parent:126return v_el127128return parent(v)129"""[1:])130131132