forked from KxSystems/embedPy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathp.c
92 lines (83 loc) · 7.19 KB
/
p.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include"k.h"
#define K3(f) K f(K x,K y,K z)
#define K(x...) k(0,"k)"x,0)
#include<stdio.h>
Z K ker(S e,S f,I l,S g){Z C b[99];snprintf(b,98,"%s:%d %s %s",f,l,g,e);K r=krr(b);R r;}
#define F(x) ker((S)x,(S)__FILE__,__LINE__,(S)__func__)
#define E(x) F(#x)
#include<Python.h>
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION // http://docs.scipy.org/doc/numpy/reference/c-api.deprecations.html
#include<numpy/arrayobject.h>
#if PY_MAJOR_VERSION<3
#define PY(x,y) x
#else
#define PY(x,y) y
#endif
#if linux
#include<dlfcn.h>
Z V dyl(S x){V*r=dlopen(x,RTLD_LAZY|RTLD_GLOBAL|RTLD_NODELETE);r?dlclose(r):fprintf(stderr,"'%s: %s\n",dlerror(),x);}
#elif _WIN32
Z V dyl(S x){}
#define typeof decltype
#elif __APPLE__
Z V dyl(S x){}
#else
#error
#endif
#undef O
typedef PyObject*O;typedef PyArrayObject*A;O d,M;K m;
#define A(x) {typeof(x)x_=(x);x_?x_:*(V*)0;}
Z K ko(O);Z O nk(K);Z O ok(K);
Z K pget(O x){K r=PyCapsule_GetPointer(x,0);R r;}Z V destr(O o){r0(pget(o));}Z O pwrap(K x){R PyCapsule_New(r1(x),0,destr);}
Z V p0(K x){Py_DECREF(kK(x)[1]);}Z K ko(O o){P(!o,0);K r=knk(2,p0,o);R r->t=112,r;}ZI pq(K x){R xt==112&&xn==2&&*kK(x)==(K)p0;}Z O kget(K x){P(!pq(x),0)O o=(O)kK(x)[1];Py_INCREF(o);R o;}
Z O ck(O x,O y){K r=K(".",r1(pget(x)),K(".p.py2q",ko(y)));O o=ok(r);R r0(r),o;}
Z PyMethodDef D={"q)",ck,METH_VARARGS,""};Z O ocall(K x){O o=pwrap(x),f=PyCFunction_New(&D,o);Py_DECREF(o);R f;}
Z K at(K x,J i){R !xt?r1(kK(x)[i]):K("@",r1(x),kj(i));}Z J cn(K x){J n;K r=K("#:",r1(x));n=r->j;R r0(r),n;}
#define W sizeof(V*)
ZS ct =" bg xhijefcspmdznuvt";
ZI dh[20]={0,4,2,3,4,5,6,7,8,9,4,2,7,6,6,9,7,6,6,6};
ZI zh[20]={W,1,W,0,1,2,4,8,4,8,0,0,0,0,0,0,0,0,0,0};
C pynt[13]={NPY_OBJECT,NPY_BOOL,0,0,NPY_UINT8,NPY_INT16,NPY_INT32,NPY_INT64,NPY_FLOAT32,NPY_FLOAT64,NPY_INT8,NPY_STRING,-1};I npyt(I c){I i=0;C*t=pynt;while(t[i]+1&&t[i]!=c)i++;R t[i]+1?i:-1;}
#define CK(x) Py##x##_Check
#define Co(x) P(!CK(x)(o),E(pytype))
#define PyC_Check PY(PyString_Check,PyUnicode_Check)
Z K kseq(O o){O f=PySequence_Fast(o,0);K x=ktn(0,PySequence_Fast_GET_SIZE(f));DO(xn,kK(x)[i]=ko(PySequence_Fast_GET_ITEM(f,i)))Py_DECREF(f);R x;}
typedef V*(*T)(S);Z V*PyC_utf8(T f,O o){PY(0,o=PyUnicode_AsUTF8String(o));S s=PY(PyString_AsString,PyBytes_AS_STRING)(o);V*r=f(s);PY(0,Py_DECREF(o));R r;}
#define KO(x) Z K ko##x(O o)
KO(b){Co(Bool)R kb(Py_True==o);} KO(j){Co(Long)R kj(PyLong_AsUnsignedLongLongMask(o));} KO(f){Co(Float)R kf(PyFloat_AsDouble(o));}
KO(C){Co(C)R PyC_utf8((T)kp,o);} KO(G){Co(Bytes)R kpn(PyBytes_AS_STRING(o),PyBytes_Size(o));} KO(none){P(o-Py_None,E(none))R K("::");} KO(buffer){P(!PyObject_CheckBuffer(o),E(buffer))R ks("<buffer>");}
Z C gnull(K x){R xt==101&&!xg;}Z C anull(K x){R !xt&&xn==1&&gnull(xK[0]);}
Z O otup(K x){J n=cn(x);O r=PyTuple_New(n);K y;DO(n,PyTuple_SET_ITEM(r,i,ok(y=at(x,i)));r0(y))R r;}
Z O atup(K x){P(anull(x),PyTuple_New(0));R otup(x);}
Z O odict(K x){O r=PyDict_New(),m,o;K y=kK(x)[1],v,z;x=*kK(x);P(xt<0,Py_None)DO(xn,PyDict_SetItem(r,m=ok(v=at(x,i)),o=ok(z=at(y,i)));r0(v);r0(z);Py_DECREF(m);Py_DECREF(o))R r;}
Z O ok(K x){P(pq(x),kget(x))P(gnull(x),Py_None)P(xt<0,-128==xt?PyErr_Format(PyExc_RuntimeError,"%s",xs):-KB==xt?xg?Py_True:Py_False:-KG>=xt&&-KJ<=xt?PyLong_FromLong(-KG==xt?xg:-KH==xt?xh:-KI==xt?xi:xj):-KE==xt||-KF==xt?PyFloat_FromDouble(xt-KE?xf:xe):-KC==xt?PyUnicode_FromStringAndSize((S)&xg,1):-KS==xt?PyUnicode_FromString(xs):Py_None)P(!xt||xt==XT,otup(x))SW(xt){CS(KG,R PyBytes_FromStringAndSize((S)kG(x),xn))CS(KC,R PyUnicode_FromStringAndSize((S)kC(x),xn))CS(KS,R otup(x))CS(XD,R odict(x))CS(100,R ocall(x))CD:R nk(x);}R Py_None;}
Z O nk(K x){O r;npy_intp n=xn/*q<3?*/;R r=PyArray_SimpleNewFromData(1,&n,pynt[xt],xG),PyArray_SetBaseObject((A)r,pwrap(x)),PyArray_CLEARFLAGS((A)r,NPY_ARRAY_WRITEABLE),r;}
#define Oo O o;P(!(o=kget(x)),E(type))
#define PE (PyErr_Print(),E(pyerr))
#define Ro(o) {PyErr_Clear();R ko(o)?:PE;}
#define X0(a) {typeof(a)r=a;r0(x);R r;}
Z K2(runs){P(xt!=-KJ||y->t!=KC,E(type))J j=x->j;x=y;x=K(",[;10h$0]",r1(x));PyErr_Clear();O o=PyRun_String(xG,j?Py_eval_input:Py_file_input,d,d);r0(x);R ko(o)?:PE;} //evaluate a string, x, returning a foreign. $[y;evaluate;runasfile] TODO check return
Z K2(set){P(xt!=-KS,E(type))PyDict_SetItemString(d,xs,ok(y));R 0;}//set a python variable x (symbol) with value y in the __main__ module TODO - check SIS return
Z K1(import){P(xt!=-KS,E(type))O m=PyImport_ImportModule(xs);P(!m,F(xs))R ko(m);}//import x (symbol) returns a foreign with the contents of module named by x
Z K2(getattr){P(y->t!=-KS,E(type))Oo;O f=PyObject_GetAttrString(o,TX(S,y));P(!f,F(TX(S,y)))Py_DECREF(o);R ko(f);}//for a foreign, x, get the attribute named by y (symbol)
Z K3(call){O f=kget(x),o,s,t;P(!PyCallable_Check(f),E(type))o=PyObject_Call(f,t=pq(y)?kget(y):atup(y),s=pq(z)?kget(z):odict(z));Py_DECREF(t);Py_DECREF(s);P(!o,PE)R ko(o);}//call a foreign, x, with positional args y and keyword args z
Z K1(repr){O o;K r;P(!pq(x),E(type))P(!(o=PyObject_Repr(kget(x))),PE)r=koC(o);Py_DECREF(o);R r;}//return a string like repr(x)
Z K1(getseq){Oo;R kseq(o);}//return an array of foreigns from x. x should be a sequence
#define GX(x) Z K1(get##x){Oo;R ko##x(o);}
GX(b)GX(none)GX(j)GX(f)GX(G)GX(C)GX(buffer)//these functions return a foreign (x) as a bool, none, long, float, G, C or buffer(G)
#define TY(x) {H h=x;r=ja(&r,&h);}
#define CH(x,y) if(CK(x)(o))TY(y);
Z K1(type){Oo;K r=ktn(KH,0);CH(Bool,-1)CH(Long,-7)CH(Float,-9)if(PyArray_CheckScalar(o))TY(-30);if(PyArray_Check(o)){TY(30)TY(npyt(PyArray_TYPE((A)o)))}CH(Bytes,4)CH(Number,-22)CH(Type,-21)
if(Py_None==o)TY(-3);if(PyC_Check(o))TY(10);if(PyObject_CheckBuffer(o))TY(24);
CH(Tuple,41)CH(List,42)CH(Callable,100)CH(Sequence,40)CH(Dict,99)CH(Mapping,101)CH(Iter,45)CH(Set,46)R r;}//for a foreign, x, return a list of shorts indicating the foreign's type
Z K1(q2py){R ko(ok(x));}//take a q value and return an equivalent value as a foreign
Z K1(key){Oo;Co(Mapping)Ro(PyMapping_Keys(o))}//return the keys of a dictionary, x
Z K1(value){Oo;Co(Mapping)Ro(PyMapping_Values(o))}//return the values of a dictionary, x
K dim(O o){A a=(A)o;I n=PyArray_NDIM(a);K x=ktn(KJ,n);DO(n,xJ[i]=PyArray_DIMS(a)[i]);R x;}
Z K1(getarraydims){Oo;Co(Array)R dim(o);}//for an array, return an array of "j" describing the dims (or shape) of x
K arr(O o,J m,J n){A a=(A)o;I t=npyt(PyArray_TYPE(a));P(!t,E(type))I z=zh[t];P(m<0,E(index));P(n<0||PyArray_NBYTES(a)<z*(m+n),E(length))K x=ktn(t,n);memcpy(xG,PyArray_DATA(a)+m*z,n*z);R x;}
Z K3(getarray){Oo;Co(Array)P(y->t!=-KJ||z->t!=-KJ,E(type))R arr(o,y->j,z->j);}//for an array, x, return a q list
Z K1(get){P(xt!=-KS,E(type));O o=PyDict_GetItemString(d,xs);o&&Py_INCREF(o);R ko(o);}//get a python variable named by x (symbol) in the __main__ module
Z K1(init){P(Py_IsInitialized(),0);if(RP)Py_SetPythonHome(PH);Py_Initialize();PySys_SetArgvEx(0,0,0);d=PyModule_GetDict(M=PyImport_AddModule("__main__"));m=ko(M);dyl(DY);import_array1(E(numpy));R 0;}
#define sdl(f,n) (js(&x,ss(#f)),jk(&y,dl(f,n)));
K1(lib){K y=ktn(0,0);init(x);x=ktn(KS,0);sdl(runs,2)sdl(set,2)sdl(import,1)sdl(getattr,2)sdl(call,3)sdl(repr,1)sdl(getseq,1)sdl(getb,1)sdl(getnone,1)sdl(getj,1)sdl(getf,1)sdl(getG,1)sdl(getC,1)sdl(q2py,1)sdl(key,1)sdl(value,1)sdl(type,1)sdl(getarraydims,1)sdl(getarray,3)sdl(getbuffer,1)sdl(get,1)R xD(x,y);}