Skip to main content

shape_ext_python/
lib.rs

1//! Shape Python language runtime extension.
2//!
3//! Provides a `shape.language_runtime` capability that embeds CPython
4//! for executing `foreign "python" { ... }` blocks in Shape programs.
5//!
6//! # ABI Exports
7//!
8//! - `shape_plugin_info()` -- plugin metadata
9//! - `shape_abi_version()` -- ABI version tag
10//! - `shape_capability_manifest()` -- declares LanguageRuntime capability
11//! - `shape_capability_vtable(contract, len)` -- generic vtable dispatch
12//! - `shape_language_runtime_vtable()` -- direct vtable accessor
13
14pub mod arrow_bridge;
15pub mod error_mapping;
16pub mod marshaling;
17pub mod runtime;
18
19use shape_abi_v1::{
20    ABI_VERSION, CAPABILITY_LANGUAGE_RUNTIME, CapabilityDescriptor, CapabilityKind,
21    CapabilityManifest, ErrorModel, LanguageRuntimeVTable, PluginInfo, PluginType,
22};
23use std::ffi::c_void;
24
25// ============================================================================
26// Plugin Metadata
27// ============================================================================
28
29#[unsafe(no_mangle)]
30pub extern "C" fn shape_plugin_info() -> *const PluginInfo {
31    static INFO: PluginInfo = PluginInfo {
32        name: c"python".as_ptr(),
33        version: c"0.1.0".as_ptr(),
34        plugin_type: PluginType::DataSource, // closest existing variant
35        description: c"Python language runtime for foreign function blocks".as_ptr(),
36    };
37    &INFO
38}
39
40#[unsafe(no_mangle)]
41pub extern "C" fn shape_abi_version() -> u32 {
42    ABI_VERSION
43}
44
45// ============================================================================
46// Capability Manifest
47// ============================================================================
48
49#[unsafe(no_mangle)]
50pub extern "C" fn shape_capability_manifest() -> *const CapabilityManifest {
51    static CAPABILITIES: [CapabilityDescriptor; 1] = [CapabilityDescriptor {
52        kind: CapabilityKind::LanguageRuntime,
53        contract: c"shape.language_runtime".as_ptr(),
54        version: c"1".as_ptr(),
55        flags: 0,
56    }];
57    static MANIFEST: CapabilityManifest = CapabilityManifest {
58        capabilities: CAPABILITIES.as_ptr(),
59        capabilities_len: CAPABILITIES.len(),
60    };
61    &MANIFEST
62}
63
64// ============================================================================
65// VTable
66// ============================================================================
67
68#[unsafe(no_mangle)]
69pub extern "C" fn shape_language_runtime_vtable() -> *const LanguageRuntimeVTable {
70    static VTABLE: LanguageRuntimeVTable = LanguageRuntimeVTable {
71        init: Some(runtime::python_init),
72        register_types: Some(runtime::python_register_types),
73        compile: Some(runtime::python_compile),
74        invoke: Some(runtime::python_invoke),
75        dispose_function: Some(runtime::python_dispose_function),
76        language_id: Some(runtime::python_language_id),
77        get_lsp_config: Some(runtime::python_get_lsp_config),
78        free_buffer: Some(runtime::python_free_buffer),
79        drop: Some(runtime::python_drop),
80        error_model: ErrorModel::Dynamic,
81    };
82    &VTABLE
83}
84
85#[unsafe(no_mangle)]
86pub extern "C" fn shape_capability_vtable(
87    contract: *const u8,
88    contract_len: usize,
89) -> *const c_void {
90    if contract.is_null() {
91        return std::ptr::null();
92    }
93    let contract = unsafe { std::slice::from_raw_parts(contract, contract_len) };
94    if contract == CAPABILITY_LANGUAGE_RUNTIME.as_bytes() {
95        shape_language_runtime_vtable() as *const c_void
96    } else {
97        std::ptr::null()
98    }
99}