harn_vm/stdlib/macros.rs
1//! Support module referenced by `#[harn_builtin]`-emitted code.
2//!
3//! The proc-macro emits paths like `crate::stdlib::macros::VmBuiltinDef`,
4//! `crate::stdlib::macros::BuiltinSignature`, etc. This module re-exports
5//! everything those expansions need so any `harn-vm/src/stdlib/*.rs` file
6//! can apply `#[harn_builtin]` to a fn without extra imports.
7
8use std::future::Future;
9use std::pin::Pin;
10
11pub use crate::value::{VmError, VmValue};
12
13pub use harn_builtin_macros::{harn_builtin, harn_capability_method};
14pub use harn_builtin_meta::{
15 BuiltinContract, BuiltinExposure, BuiltinSignature, CapabilityId, EffectAccess,
16 EffectAuthorization, EffectKind, EffectSpec, Param, ResourceSelector, ShapeFieldDescriptor, Ty,
17 TY_ANY, TY_BOOL, TY_BYTES, TY_BYTES_OR_NIL, TY_CLOSURE, TY_DICT, TY_DICT_OR_NIL, TY_DURATION,
18 TY_FLOAT, TY_INT, TY_INT_OR_NIL, TY_LIST, TY_NEVER, TY_NIL, TY_NUMBER, TY_RESOURCE, TY_STRING,
19 TY_STRING_OR_NIL,
20};
21pub use harn_builtin_registry::BuiltinDef;
22// Re-export the shared shape vocabulary so `#[harn_builtin]` sig strings can
23// reference a named structural shape via the `@NAME` injection form, which
24// the macro expands to `crate::stdlib::macros::shapes::NAME`.
25pub use harn_builtin_meta::shapes;
26// Re-export so the `#[harn_builtin]` proc-macro can name the
27// distributed-slice attribute without each call-site importing linkme.
28pub use linkme::distributed_slice;
29
30/// Workspace-global registry of `#[harn_builtin]`-emitted definitions.
31/// Each annotated fn contributes one entry via
32/// `#[linkme::distributed_slice(ALL_BUILTIN_DEFS)]`, so there is no
33/// per-module `MODULE_BUILTINS` slice to maintain. The CLI / LSP / lint /
34/// serve / dap binaries force-link `harn-vm` to defeat rlib dead-code
35/// stripping (linkme issue #36) so every static lands in this slice at
36/// link time.
37#[linkme::distributed_slice]
38pub static ALL_BUILTIN_DEFS: [&'static VmBuiltinDef];
39
40/// Pinned future returned by async builtin handlers.
41pub type AsyncBuiltinFuture = Pin<Box<dyn Future<Output = Result<VmValue, VmError>> + Send>>;
42
43/// Sync builtin handler signature (matches `crate::vm::dispatch`'s register_builtin shape).
44pub type SyncHandler = fn(&[VmValue], &mut String) -> Result<VmValue, VmError>;
45/// Async builtin handler signature. Receives an explicit
46/// [`crate::vm::AsyncBuiltinCtx`] handle so handlers thread the context they
47/// were given through async helper calls.
48pub type AsyncHandler = fn(crate::vm::AsyncBuiltinCtx, Vec<VmValue>) -> AsyncBuiltinFuture;
49
50/// Runtime handler attached to a `VmBuiltinDef`. `None` covers parser-only
51/// builtins (method-dispatched at runtime, but the parser still wants a
52/// signature for typo suggestion + return-type inference).
53#[derive(Debug, Clone, Copy)]
54pub enum VmBuiltinHandler {
55 Sync(SyncHandler),
56 Async(AsyncHandler),
57 /// No runtime impl — registered with the parser only (e.g. `len`,
58 /// `split`, method-dispatch builtins).
59 None,
60}
61
62/// `BuiltinDef` specialized to the VM's handler type.
63pub type VmBuiltinDef = BuiltinDef<VmBuiltinHandler>;
64
65/// Eager-registration helper: install every entry (name + aliases) on `vm`
66/// using the macro-emitted handler. Each module's `register_*_builtins(vm)`
67/// calls this with its `MODULE_BUILTINS` slice so the call ordering between
68/// modules stays deterministic (e.g. `clock` overrides `process::timestamp`).
69pub fn register_builtin_defs(vm: &mut crate::vm::Vm, defs: &'static [&'static VmBuiltinDef]) {
70 for def in defs {
71 vm.register_builtin_def(def);
72 }
73}