@@ -20,7 +20,7 @@ static const char *String(const void *node, const char *prop) {
2020 return o ? PyUnicode_AsUTF8 (o ) : NULL ;
2121}
2222
23- static int Size (const void * node , const char * prop ) {
23+ static size_t Size (const void * node , const char * prop ) {
2424 PyObject * o = Attribute (node , prop );
2525 return o ? PySequence_Size (o ) : 0 ;
2626}
@@ -39,7 +39,7 @@ static const char *Token(const void *node) {
3939 return String (node , "token" );
4040}
4141
42- static int ChildrenSize (const void * node ) {
42+ static size_t ChildrenSize (const void * node ) {
4343 return Size (node , "children" );
4444}
4545
@@ -48,7 +48,7 @@ static void *ChildAt(const void *node, int index) {
4848 return children ? ItemAt (children , index ) : NULL ;
4949}
5050
51- static int RolesSize (const void * node ) {
51+ static size_t RolesSize (const void * node ) {
5252 return Size (node , "roles" );
5353}
5454
@@ -57,7 +57,7 @@ static uint16_t RoleAt(const void *node, int index) {
5757 return roles ? (uint16_t )PyLong_AsUnsignedLong (ItemAt (roles , index )) : 0 ;
5858}
5959
60- static int PropertiesSize (const void * node ) {
60+ static size_t PropertiesSize (const void * node ) {
6161 PyObject * properties = AttributeValue (node , "properties" );
6262 return properties ? PyMapping_Size (properties ) : 0 ;
6363}
@@ -146,10 +146,116 @@ static Uast *ctx;
146146/////////// PYTHON API //////////////
147147/////////////////////////////////////
148148
149+ typedef struct {
150+ PyObject_HEAD
151+ UastIterator * iter ;
152+ } PyUastIter ;
153+
154+ // iterator.__iter__()
155+ static PyObject * PyUastIter_iter (PyObject * self )
156+ {
157+ Py_INCREF (self );
158+ return self ;
159+ }
160+
161+ // iterator.__next__()
162+ static PyObject * PyUastIter_next (PyObject * self )
163+ {
164+
165+ PyUastIter * it = (PyUastIter * )self ;
166+
167+ void * node = UastIteratorNext (it -> iter );
168+ if (!node ) {
169+ PyErr_SetNone (PyExc_StopIteration );
170+ return NULL ;
171+ }
172+
173+ Py_INCREF (node );
174+ return (PyObject * )node ;
175+ }
176+
177+ // Forward declaration for the Type ref
178+ static PyObject * PyUastIter_new (PyObject * self , PyObject * args );
179+ static void PyUastIter_dealloc (PyObject * self );
180+
181+ static PyTypeObject PyUastIterType = {
182+ PyVarObject_HEAD_INIT (NULL , 0 )
183+ "pyuast.UastIterator" , // tp_name
184+ sizeof (PyUastIter ), // tp_basicsize
185+ 0 , // tp_itemsize
186+ PyUastIter_dealloc , // tp_dealloc
187+ 0 , // tp_print
188+ 0 , // tp_getattr
189+ 0 , // tp_setattr
190+ 0 , // tp_reserved
191+ 0 , // tp_repr
192+ 0 , // tp_as_number
193+ 0 , // tp_as_sequence
194+ 0 , // tp_as_mapping
195+ 0 , // tp_hash
196+ 0 , // tp_call
197+ 0 , // tp_str
198+ 0 , // tp_getattro
199+ 0 , // tp_setattro
200+ 0 , // tp_as_buffer
201+ Py_TPFLAGS_DEFAULT , // tp_flags
202+ "Internal UastIterator object" , // tp_doc
203+ 0 , // tp_traverse
204+ 0 , // tp_clear
205+ 0 , // tp_richcompare
206+ 0 , // tp_weaklistoffset
207+ PyUastIter_iter , // tp_iter: __iter()__ method
208+ (iternextfunc )PyUastIter_next , // tp_iternext: next() method
209+ 0 , // tp_methods
210+ 0 , // tp_members
211+ 0 , // tp_getset
212+ 0 , // tp_base
213+ 0 , // tp_dict
214+ 0 , // tp_descr_get
215+ 0 , // tp_descr_set
216+ 0 , // tp_dictoffset
217+ 0 , // tp_init
218+ PyType_GenericAlloc , // tp_alloc
219+ 0 , // tp_new
220+ };
221+
222+ static PyObject * PyUastIter_new (PyObject * self , PyObject * args )
223+ {
224+ void * node = NULL ;
225+ uint8_t order ;
226+
227+ if (!PyArg_ParseTuple (args , "OB" , & node , & order ))
228+ return NULL ;
229+
230+ PyUastIter * pyIt = PyObject_New (PyUastIter , & PyUastIterType );
231+ if (!pyIt )
232+ return NULL ;
233+
234+ if (!PyObject_Init ((PyObject * )pyIt , & PyUastIterType )) {
235+ Py_DECREF (pyIt );
236+ return NULL ;
237+ }
238+
239+ pyIt -> iter = UastIteratorNew (ctx , node , (TreeOrder )order );
240+ if (!pyIt -> iter ) {
241+ Py_DECREF (pyIt );
242+ return NULL ;
243+ }
244+
245+ return (PyObject * )pyIt ;
246+ }
247+
248+
249+ static void PyUastIter_dealloc (PyObject * self )
250+ {
251+ UastIteratorFree (((PyUastIter * )self )-> iter );
252+ }
253+
149254static PyObject * PyFilter (PyObject * self , PyObject * args )
150255{
151256 PyObject * obj = NULL ;
152257 const char * query = NULL ;
258+
153259 if (!PyArg_ParseTuple (args , "Os" , & obj , & query ))
154260 return NULL ;
155261
@@ -160,10 +266,10 @@ static PyObject *PyFilter(PyObject *self, PyObject *args)
160266 free (error );
161267 return NULL ;
162268 }
163- int len = NodesSize (nodes );
269+ size_t len = NodesSize (nodes );
164270 PyObject * list = PyList_New (len );
165271
166- for (int i = 0 ; i < len ; i ++ ) {
272+ for (size_t i = 0 ; i < len ; i ++ ) {
167273 PyObject * node = (PyObject * )NodeAt (nodes , i );
168274 Py_INCREF (node );
169275 PyList_SET_ITEM (list , i , node );
@@ -174,6 +280,7 @@ static PyObject *PyFilter(PyObject *self, PyObject *args)
174280
175281static PyMethodDef extension_methods [] = {
176282 {"filter" , PyFilter , METH_VARARGS , "Filter nodes in the UAST using the given query" },
283+ {"iterator" , PyUastIter_new , METH_VARARGS , "Get an iterator over a node" },
177284 {NULL , NULL , 0 , NULL }
178285};
179286
@@ -189,7 +296,8 @@ static struct PyModuleDef module_def = {
189296 NULL
190297};
191298
192- PyMODINIT_FUNC PyInit_pyuast (void )
299+ PyMODINIT_FUNC
300+ PyInit_pyuast (void )
193301{
194302 NodeIface iface = {
195303 .InternalType = InternalType ,
0 commit comments