11#include "types.h"
22
3+ extern void wasm_engine_delete (TSWasmEngine * engine );
4+ extern TSWasmEngine * wasmtime_engine_clone (TSWasmEngine * engine );
5+
36int language_init (Language * self , PyObject * args , PyObject * Py_UNUSED (kwargs )) {
47 PyObject * language ;
58 if (!PyArg_ParseTuple (args , "O:__init__" , & language )) {
@@ -25,10 +28,119 @@ int language_init(Language *self, PyObject *args, PyObject *Py_UNUSED(kwargs)) {
2528}
2629
2730void language_dealloc (Language * self ) {
31+ if (self -> wasm_engine != NULL ) {
32+ wasm_engine_delete (self -> wasm_engine );
33+ }
2834 ts_language_delete (self -> language );
2935 Py_TYPE (self )-> tp_free (self );
3036}
3137
38+ // ctypes.cast(managed_pointer.ptr(), ctypes.c_void_p).value
39+ static void * get_managed_pointer (PyObject * cast , PyObject * c_void_p , PyObject * managed_pointer ) {
40+ void * ptr = NULL ;
41+ PyObject * ptr_method = NULL ;
42+ PyObject * ptr_result = NULL ;
43+ PyObject * cast_result = NULL ;
44+ PyObject * value_attr = NULL ;
45+
46+ // Call .ptr() method on the managed pointer
47+ ptr_method = PyObject_GetAttrString (managed_pointer , "ptr" );
48+ if (ptr_method == NULL ) {
49+ goto cleanup ;
50+ }
51+ ptr_result = PyObject_CallObject (ptr_method , NULL );
52+ if (ptr_result == NULL ) {
53+ goto cleanup ;
54+ }
55+
56+ // Call cast function
57+ cast_result = PyObject_CallFunctionObjArgs (cast , ptr_result , c_void_p , NULL );
58+ if (cast_result == NULL ) {
59+ goto cleanup ;
60+ }
61+
62+ // Get the 'value' attribute from the cast result
63+ value_attr = PyObject_GetAttrString (cast_result , "value" );
64+ if (value_attr == NULL ) {
65+ goto cleanup ;
66+ }
67+
68+ // Convert the value attribute to a C void pointer
69+ ptr = PyLong_AsVoidPtr (value_attr );
70+
71+ cleanup :
72+ Py_XDECREF (value_attr );
73+ Py_XDECREF (cast_result );
74+ Py_XDECREF (ptr_result );
75+ Py_XDECREF (ptr_method );
76+
77+ if (PyErr_Occurred ()) {
78+ return NULL ;
79+ }
80+
81+ return ptr ;
82+ }
83+
84+ PyObject * language_from_wasm (PyTypeObject * cls , PyObject * args ) {
85+ ModuleState * state = (ModuleState * )PyType_GetModuleState (cls );
86+ TSWasmError error ;
87+ TSWasmStore * wasm_store = NULL ;
88+ TSLanguage * language = NULL ;
89+ Language * self = NULL ;
90+ char * name ;
91+ PyObject * py_engine = NULL ;
92+ char * wasm ;
93+ Py_ssize_t wasm_length ;
94+ if (state -> wasmtime_engine_type == NULL ) {
95+ PyErr_SetString (PyExc_RuntimeError , "wasmtime module is not loaded" );
96+ return NULL ;
97+ }
98+ if (!PyArg_ParseTuple (args , "sO!y#:from_wasm" , & name , state -> wasmtime_engine_type , & py_engine , & wasm , & wasm_length )) {
99+ return NULL ;
100+ }
101+
102+ TSWasmEngine * engine = (TSWasmEngine * )get_managed_pointer (state -> ctypes_cast , state -> c_void_p , py_engine );
103+ if (engine == NULL ) {
104+ goto fail ;
105+ }
106+ engine = wasmtime_engine_clone (engine );
107+ if (engine == NULL ) {
108+ goto fail ;
109+ }
110+
111+ wasm_store = ts_wasm_store_new (engine , & error );
112+ if (wasm_store == NULL ) {
113+ PyErr_Format (PyExc_RuntimeError , "Failed to create TSWasmStore: %s" , error .message );
114+ goto fail ;
115+ }
116+
117+ language = (TSLanguage * )ts_wasm_store_load_language (wasm_store , name , wasm , wasm_length , & error );
118+ if (language == NULL ) {
119+ PyErr_Format (PyExc_RuntimeError , "Failed to load language: %s" , error .message );
120+ goto fail ;
121+ }
122+
123+ self = (Language * )cls -> tp_alloc (cls , 0 );
124+ if (self == NULL ) {
125+ goto fail ;
126+ }
127+
128+ self -> language = language ;
129+ self -> wasm_engine = engine ;
130+ self -> version = ts_language_version (self -> language );
131+ #if HAS_LANGUAGE_NAMES
132+ self -> name = ts_language_name (self -> language );
133+ #endif
134+ return (PyObject * )self ;
135+
136+ fail :
137+ if (engine != NULL ) {
138+ wasm_engine_delete (engine );
139+ }
140+ ts_language_delete (language );
141+ return NULL ;
142+ }
143+
32144PyObject * language_repr (Language * self ) {
33145#if HAS_LANGUAGE_NAMES
34146 if (self -> name == NULL ) {
@@ -77,6 +189,10 @@ PyObject *language_get_field_count(Language *self, void *Py_UNUSED(payload)) {
77189 return PyLong_FromUnsignedLong (ts_language_field_count (self -> language ));
78190}
79191
192+ PyObject * language_is_wasm (Language * self , void * Py_UNUSED (payload )) {
193+ return PyBool_FromLong (ts_language_is_wasm (self -> language ));
194+ }
195+
80196PyObject * language_node_kind_for_id (Language * self , PyObject * args ) {
81197 TSSymbol symbol ;
82198 if (!PyArg_ParseTuple (args , "H:node_kind_for_id" , & symbol )) {
@@ -185,6 +301,9 @@ PyObject *language_query(Language *self, PyObject *args) {
185301 return PyObject_CallFunction ((PyObject * )state -> query_type , "Os#" , self , source , length );
186302}
187303
304+ PyDoc_STRVAR (language_from_wasm_doc ,
305+ "from_wasm(self, name, engine, wasm, /)\n--\n\n"
306+ "Load a language compiled as wasm." );
188307PyDoc_STRVAR (language_node_kind_for_id_doc ,
189308 "node_kind_for_id(self, id, /)\n--\n\n"
190309 "Get the name of the node kind for the given numerical id." );
@@ -215,6 +334,12 @@ PyDoc_STRVAR(
215334 "Create a new :class:`Query` from a string containing one or more S-expression patterns." );
216335
217336static PyMethodDef language_methods [] = {
337+ {
338+ .ml_name = "from_wasm" ,
339+ .ml_meth = (PyCFunction )language_from_wasm ,
340+ .ml_flags = METH_CLASS | METH_VARARGS ,
341+ .ml_doc = language_from_wasm_doc ,
342+ },
218343 {
219344 .ml_name = "node_kind_for_id" ,
220345 .ml_meth = (PyCFunction )language_node_kind_for_id ,
@@ -286,6 +411,8 @@ static PyGetSetDef language_accessors[] = {
286411 PyDoc_STR ("The number of valid states in this language." ), NULL },
287412 {"field_count" , (getter )language_get_field_count , NULL ,
288413 PyDoc_STR ("The number of distinct field names in this language." ), NULL },
414+ {"is_wasm" , (getter )language_is_wasm , NULL ,
415+ PyDoc_STR ("Check if the language came from a wasm module." ), NULL },
289416 {NULL },
290417};
291418
0 commit comments