diff --git a/src/PYTHON/python_impl.cpp b/src/PYTHON/python_impl.cpp index 556a79261a..483038cc1c 100644 --- a/src/PYTHON/python_impl.cpp +++ b/src/PYTHON/python_impl.cpp @@ -451,16 +451,23 @@ int PythonImpl::find(const char *name) ensure a string is returned only if retrieve() is the caller --------------------------------------------------------------------- */ -int PythonImpl::function_match(const char *name, const char *varname, int numeric) +int PythonImpl::function_match(const char *name, const char *varname, int numeric, Error *error) { - // NOTE to Richard - any reason not to put error messages here instead of in Variable class ? - // error messages appear 3x in Variable - int ifunc = find(name); - if (ifunc < 0) return -1; - if (pfuncs[ifunc].noutput == 0) return -2; - if (strcmp(pfuncs[ifunc].ovarname, varname) != 0) return -3; - if (numeric && pfuncs[ifunc].otype == STRING) return -4; + + if (ifunc < 0) + error->all(FLERR, Error::NOLASTLINE, "Python function {} specified by variable {} not found", + name, varname); + if (pfuncs[ifunc].noutput == 0) + error->all(FLERR, Error::NOLASTLINE, + "Python function {} for variable {} does not return a value", name, varname); + if (strcmp(pfuncs[ifunc].ovarname, varname) != 0) + error->all(FLERR, Error::NOLASTLINE, + "Python function {} and variable {} do not not link to each other", name, varname); + if (numeric && pfuncs[ifunc].otype == STRING) + error->all(FLERR, Error::NOLASTLINE, "Python function {} for variable {} returns a string", + name, varname); + return ifunc; } @@ -477,18 +484,18 @@ int PythonImpl::function_match(const char *name, const char *varname, int numeri other classes avoid this issue by setting variable indices in their init() method --------------------------------------------------------------------- */ -int PythonImpl::wrapper_match(const char *name, const char *varname, int narg, int *argvars) +int PythonImpl::wrapper_match(const char *name, const char *varname, int narg, int *argvars, + Error *error) { - // NOTE to Richard - any reason not to put 2 extra error messages here instead of in Variable class ? - // only this class knows the name of the missing internal var, so can generate better error message - - int ifunc = function_match(name, varname, 1); + int ifunc = function_match(name, varname, 1, error); if (ifunc < 0) return ifunc; int internal_count = 0; for (int i = 0; i < pfuncs[ifunc].ninput; i++) if (pfuncs[ifunc].ivarflag[i] == INTERNALVAR) internal_count++; - if (internal_count != narg) return -5; + if (internal_count != narg) + error->all(FLERR, Error::NOLASTLINE, + "Python function {} does not use {} internal variable args", name, narg); // set argvars of internal-style variables for use by Variable class // in Python wrapper functions @@ -496,13 +503,15 @@ int PythonImpl::wrapper_match(const char *name, const char *varname, int narg, i // so that invoke_function() is as fast as possible for args which are internal-style vars int j = 0; - for (int i = 0; i < pfuncs[ifunc].ninput; i++) + for (int i = 0; i < pfuncs[ifunc].ninput; i++) { if (pfuncs[ifunc].ivarflag[i] == INTERNALVAR) { int ivar = input->variable->find(pfuncs[ifunc].svalue[i]); - if (ivar < 0) return -6; + error->all(FLERR, Error::NOLASTLINE, "Python function {} cannot find internal variable {}", + name, pfuncs[ifunc].svalue[i]); pfuncs[ifunc].internal_var[i] = ivar; argvars[j++] = ivar; } + } return ifunc; } diff --git a/src/PYTHON/python_impl.h b/src/PYTHON/python_impl.h index 3ead92f6f2..5c3955afc6 100644 --- a/src/PYTHON/python_impl.h +++ b/src/PYTHON/python_impl.h @@ -27,8 +27,8 @@ class PythonImpl : protected Pointers, public PythonInterface { void command(int, char **) override; void invoke_function(int, char *, double *) override; int find(const char *) override; - int function_match(const char *, const char *, int) override; - int wrapper_match(const char *, const char *, int, int *) override; + int function_match(const char *, const char *, int, Error *) override; + int wrapper_match(const char *, const char *, int, int *, Error *) override; char *long_string(int) override; int execute_string(char *) override; int execute_file(char *) override; diff --git a/src/lmppython.cpp b/src/lmppython.cpp index 6a8bc1f5a2..f7a213302a 100644 --- a/src/lmppython.cpp +++ b/src/lmppython.cpp @@ -14,9 +14,8 @@ #include "lmppython.h" #if defined(LMP_PYTHON) #include "python_impl.h" -#else -#include "error.h" #endif +#include "error.h" using namespace LAMMPS_NS; @@ -43,7 +42,7 @@ void Python::init() #if defined(LMP_PYTHON) if (!impl) impl = new PythonImpl(lmp); #else - error->all(FLERR, "Python support missing! Compile with PYTHON package installed!"); + error->all(FLERR, Error::NOLASTLINE, "Python support missing! Compile with PYTHON package installed!"); #endif } @@ -83,19 +82,19 @@ int Python::find(const char *name) /* ------------------------------------------------------------------ */ -int Python::function_match(const char *name, const char *varname, int numeric) +int Python::function_match(const char *name, const char *varname, int numeric, Error *errptr) { init(); - return impl->function_match(name, varname, numeric); + return impl->function_match(name, varname, numeric, errptr); } /* ------------------------------------------------------------------ */ -int Python::wrapper_match(const char *name, const char *varname, - int narg, int *argvars) +int Python::wrapper_match(const char *name, const char *varname, int narg, int *argvars, + Error *errptr) { init(); - return impl->wrapper_match(name, varname, narg, argvars); + return impl->wrapper_match(name, varname, narg, argvars, errptr); } /* ------------------------------------------------------------------ */ diff --git a/src/lmppython.h b/src/lmppython.h index 23137b7ecb..f7db8a4c06 100644 --- a/src/lmppython.h +++ b/src/lmppython.h @@ -24,8 +24,8 @@ class PythonInterface { virtual void command(int, char **) = 0; virtual void invoke_function(int, char *, double *) = 0; virtual int find(const char *) = 0; - virtual int function_match(const char *, const char *, int) = 0; - virtual int wrapper_match(const char *, const char *, int, int *) = 0; + virtual int function_match(const char *, const char *, int, Error *) = 0; + virtual int wrapper_match(const char *, const char *, int, int *, Error *) = 0; virtual char *long_string(int ifunc) = 0; virtual int execute_string(char *) = 0; virtual int execute_file(char *) = 0; @@ -40,8 +40,8 @@ class Python : protected Pointers { void command(int, char **); void invoke_function(int, char *, double *); int find(const char *); - int function_match(const char *, const char *, int); - int wrapper_match(const char *, const char *, int, int *); + int function_match(const char *, const char *, int, Error *); + int wrapper_match(const char *, const char *, int, int *, Error *); char *long_string(int ifunc); int execute_string(char *); int execute_file(char *); diff --git a/src/variable.cpp b/src/variable.cpp index 07f331c72a..5f848913c8 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -959,31 +959,10 @@ void Variable::python_command(int narg, char **arg) int Variable::equalstyle(int ivar) { - if (style[ivar] == EQUAL || style[ivar] == TIMER || - style[ivar] == INTERNAL) return 1; - if (style[ivar] == PYTHON) { - pyindex[ivar] = python->function_match(data[ivar][0],names[ivar],1); - if (pyindex[ivar] < 0) { - int ierror = pyindex[ivar]; - if (ierror == -1) { - error->all(FLERR, "Python function {} specified by variable {} not found", - data[ivar][0], names[ivar]); - } else if (ierror == -2) { - error->all(FLERR, "Python function {} for variable {} does not return a value", - data[ivar][0], names[ivar]); - } else if (ierror == -3) { - error->all(FLERR, "Python function {} and variable {} do not not link to each other", - data[ivar][0], names[ivar]); - } else if (ierror == -4) { - error->all(FLERR, "Python function {} for variable {} returns a string", - data[ivar][0], names[ivar]); - } else { - error->all(FLERR, "Unknown error linking Python function {} to variable {}", - data[ivar][0],names[ivar]); - } - return 0; - } else return 1; - } + if (style[ivar] == EQUAL || style[ivar] == TIMER || style[ivar] == INTERNAL) return 1; + if ((style[ivar] == PYTHON) && (python->function_match(data[ivar][0], names[ivar], 1, error) >= 0)) + return 1; + return 0; } @@ -1103,22 +1082,7 @@ char *Variable::retrieve(const char *name) str = data[ivar][1] = utils::strdup(result); } else if (style[ivar] == PYTHON) { - int ifunc = python->function_match(data[ivar][0],name,0); - if (ifunc < 0) { - if (ifunc == -1) { - error->all(FLERR, "Python function {} specified by variable {} not found", - data[ivar][0], name); - } else if (ifunc == -2) { - error->all(FLERR, "Python function {} for variable {} does not return a value", - data[ivar][0], name); - } else if (ifunc == -3) { - error->all(FLERR, "Python function {} and variable {} do not not link to each other", - data[ivar][0], name); - } else { - error->all(FLERR, "Unknown error linking Python function {} to variable {}", - data[ivar][0],name); - } - } + int ifunc = python->function_match(data[ivar][0],name,0,error); python->invoke_function(ifunc,data[ivar][1],nullptr); str = data[ivar][1]; @@ -4208,32 +4172,7 @@ int Variable::math_function(char *word, char *contents, Tree **tree, Tree **tree // jvars = returned indices of narg internal variables used by Python function int *jvars = new int[narg]; - pyindex[pyvar] = python->wrapper_match(data[pyvar][0],names[pyvar],narg,jvars); - if (pyindex[pyvar] < 0) { - int ierror = pyindex[pyvar]; - if (ierror == -1) { - error->all(FLERR, "Python function {} specified by variable {} not found", - data[ivar][0], names[ivar]); - } else if (ierror == -2) { - error->all(FLERR, "Python function {} for variable {} does not return a value", - data[ivar][0], names[ivar]); - } else if (ierror == -3) { - error->all(FLERR, "Python function {} and variable {} do not not link to each other", - data[ivar][0], names[ivar]); - } else if (ierror == -4) { - error->all(FLERR, "Python function {} for variable {} returns a string", - data[ivar][0], names[ivar]); - } else if (ierror == -5) { - error->all(FLERR, "Python function {} does not use {} internal variable args", - data[ivar][0], narg); - } else if (ierror == -6) { - error->all(FLERR,"Python function {} cannot find an internal variable", - data[ivar][0]); - } else { - error->all(FLERR, "Unknown error linking Python function {} to variable {}", - data[ivar][0],names[ivar]); - } - } + pyindex[pyvar] = python->wrapper_match(data[pyvar][0],names[pyvar],narg,jvars,error); // if tree: store python variable and arg info in tree for later eval // else: one-time eval of python-coded function now via python variable