Skip to main content

improv_core_model/
extfn_def.rs

1//! Definitions of external-language functions (Phase 6), as plain, serializable
2//! model data. The *runtime* that evaluates these lives in the `improv_extfn`
3//! crate; this module holds only the declaration so a `Model` can persist which
4//! functions a formula may `CALL` and how to type-check them.
5//!
6//! External functions must be **pure**, **typed**, and declare their
7//! dimensionality (arity) so the engine can treat a `CALL` as an ordinary,
8//! deterministic operator (see AGENT_MASTER_STEERING §7 / AGENT_FORMULA_LANGUAGE
9//! §11.3).
10
11use crate::value::ValueType;
12use serde::{Deserialize, Serialize};
13
14/// The runtime language an external function targets. Each variant has a runner
15/// in the `improv_extfn` crate (subprocess for the scripting languages, an
16/// in-process `wasmi` interpreter for `Wasm`).
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
18pub enum Language {
19    Python,
20    R,
21    Julia,
22    Wasm,
23    Pure,
24}
25
26/// A registered external function: everything needed to type-check a call and
27/// (via the `improv_extfn` runtime) invoke it deterministically.
28///
29/// `body` is the function *body* (statements), evaluated with the arguments
30/// bound and expected to produce a result (the runtime defines the exact
31/// contract).
32#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
33pub struct ExternalFn {
34    pub name: String,
35    pub language: Language,
36    pub body: String,
37    /// Declared argument types, in order. `arity() == arg_types.len()`.
38    pub arg_types: Vec<ValueType>,
39    pub return_type: ValueType,
40    /// The author asserts the body is pure (deterministic, no engine-observable
41    /// side effects). Enforcement beyond the runtime's isolated invocation is
42    /// future work.
43    pub pure: bool,
44}
45
46impl ExternalFn {
47    pub fn arity(&self) -> usize {
48        self.arg_types.len()
49    }
50}