The goal is to design a very small and clean ASR design. As few functions and ASR nodes as possible, the S type does not have methods, we have global ASR nodes (as few as possible) and IntrinsicFunctions (can be many) to operate on it. We want to keep this Symbolic API surface to be minimal and clean (no duplication).
Let's write a pure Python implementation of this Symbolic API, initially we'll just ship it with LPython. It will implement exactly this API in pure CPython, so we will ensure 100% compatibility (thus satisfying the LPython contract that if it works in LPython, it gives exactly the same result in CPython). SymPy itself will be about 95% compatible, so most tests will work in both and we will continue testing both, but in some corner cases (such as exp(x).func, and sin(pi/8) etc.) it will differ, so those tests will only test in our pure Python implementation (we will ensure that majority of tests work in SymPy). And then much later, we'll ensure that the symengine.py (Python wrappers to SymEngine) are a strict superset of our "lean Symbolic API", so that one can use symengine.py interchangeably with our pure Python implementation (and it will be faster, while still being in CPython). And we will carefully document all differences to SymPy. The contract will eventually be that if a symbolic code compiles and works with LPython, it will automatically work with our pure Python implementation as well as with symengine.py 100% of the time, and with SymPy only about 95%. And we'll offer our pure Python implementation (which will be slower than symengine.py, but faster than current SymPy) to SymPy itself, and using LPython SymPy can gradually move to this new core, we can start with limits.
gruntz2branch)e.has(x)(ASR:SymbolicHasQ)e.func == Mul,e.func == Add,e.func == Powe.func == log(e.func == expwill not be supported, since SymEngine doesn't have anexptype, onlyPow: Design question: shouldexp(x)be its own type/function? symengine/symengine#1984)e.func == siny.args[0]andy.args[1](ASR:SymbolicGetArguments, Design of getargs() #2393), whereyis any expressionexponent = int(e.args[1])as_two_terms(e),as_independent(e, x)(ASR:SymbolicAsTwoTermsandSymbolicAsIndependent){exp(x)}), make sure printing and comparison worksmrvusing LPythonThe goal is to design a very small and clean ASR design. As few functions and ASR nodes as possible, the
Stype does not have methods, we have global ASR nodes (as few as possible) and IntrinsicFunctions (can be many) to operate on it. We want to keep this Symbolic API surface to be minimal and clean (no duplication).Let's write a pure Python implementation of this Symbolic API, initially we'll just ship it with LPython. It will implement exactly this API in pure CPython, so we will ensure 100% compatibility (thus satisfying the LPython contract that if it works in LPython, it gives exactly the same result in CPython). SymPy itself will be about 95% compatible, so most tests will work in both and we will continue testing both, but in some corner cases (such as
exp(x).func, andsin(pi/8)etc.) it will differ, so those tests will only test in our pure Python implementation (we will ensure that majority of tests work in SymPy). And then much later, we'll ensure that thesymengine.py(Python wrappers to SymEngine) are a strict superset of our "lean Symbolic API", so that one can usesymengine.pyinterchangeably with our pure Python implementation (and it will be faster, while still being in CPython). And we will carefully document all differences to SymPy. The contract will eventually be that if a symbolic code compiles and works with LPython, it will automatically work with our pure Python implementation as well as withsymengine.py100% of the time, and with SymPy only about 95%. And we'll offer our pure Python implementation (which will be slower thansymengine.py, but faster than current SymPy) to SymPy itself, and using LPython SymPy can gradually move to this new core, we can start with limits.