def xlat_func2tex(ast, ast2tex): xact = _XLAT_FUNC2TEX.get(ast.func) if xact: args, kw = AST.args2kwargs(ast.args) try: return xact(ast2tex, *args, **kw) except: pass return None
def xlat_attr2tex(ast, ast2tex): if ast.is_attr_func: xact = _XLAT_ATTRFUNC2TEX.get(ast.attr) if xact: args, kw = AST.args2kwargs(ast.args) try: return xact(ast2tex, ast.obj, *args, **kw) except: pass return None
def xlat_funcs2asts( ast, xlat, func_call=None, recurse=True ): # translate eligible functions in tree to other AST representations if not isinstance(ast, AST): return ast if ast.is_func: xact = xlat.get(ast.func) args = ast.args ret = lambda: AST('-func', ast.func, args) elif ast.is_attr_func: xact = xlat.get(f'.{ast.attr}') args = (ast.obj, ) + ast.args ret = lambda: AST('.', args[0], ast.attr, tuple(args[1:])) else: xact = None if xact is not None: if recurse: args = AST(*(xlat_funcs2asts(a, xlat, func_call=func_call) for a in args)) try: if xact is True: # True means execute function and use return value for ast, only happens for -func return func_call( ast.func, args ) # not checking func_call None because that should never happen xargs, xkw = AST.args2kwargs(args) ast2 = xact(*xargs, **xkw) if ast2 is not None: return ast2 except: pass return ret() if recurse: return AST(*(xlat_funcs2asts(a, xlat, func_call=func_call) for a in ast)) #, **ast._kw) return ast
def evalexpr(ast): sym.ast2spt.set_precision(ast) if ast.is_func and ast.func in AST.Func.PLOT: # plotting? args, kw = AST.args2kwargs(AST.apply_vars(ast.args, _VARS), sym.ast2spt) ret = getattr(splot, ast.func)(*args, **kw) return { 'msg': [ 'Plotting not available because matplotlib is not installed.' ] } if ret is None else { 'img': ret } elif ast.op in { '@', '-func' } and ast[1] in AST.Func.ADMIN: # special admin function? asts = globals()[f'_admin_{ast [1]}']( *(ast.args if ast.is_func else ())) if isinstance(asts, str): return {'msg': [asts]} elif isinstance(asts, list) and isinstance(asts[0], str): return {'msg': asts} else: # not admin function, normal evaluation ast, vars = _prepare_ass(ast) if _SYMPAD_DEBUG: print('ast: ', ast, file=sys.stderr) try: spt, xlat = sym.ast2spt(ast, retxlat=True) # , _VARS) if _SYMPAD_DEBUG and xlat: print('xlat: ', xlat, file=sys.stderr) sptast = sym.spt2ast(spt) except: if _SYMPAD_DEBUG: print(file=sys.stderr) raise if _SYMPAD_DEBUG: try: print('spt: ', repr(spt), file=sys.stderr) except: pass print('spt type: ', type(spt), file=sys.stderr) try: print('spt args: ', repr(spt.args), file=sys.stderr) except: pass print('spt latex: ', sp.latex(spt), file=sys.stderr) print('spt ast: ', sptast, file=sys.stderr) print('spt tex: ', sym.ast2tex(sptast), file=sys.stderr) print('spt nat: ', sym.ast2nat(sptast), file=sys.stderr) print('spt py: ', sym.ast2py(sptast), file=sys.stderr) print(file=sys.stderr) asts = _execute_ass(sptast, vars) response = {} if asts and asts[0] != AST.None_: response.update({ 'math': [{ 'tex': sym.ast2tex(ast), 'nat': sym.ast2nat(ast), 'py': sym.ast2py(ast), } for ast in asts] }) return response