Skip to main content

ShapeEngine

Struct ShapeEngine 

Source
pub struct ShapeEngine {
    pub runtime: Runtime,
    pub default_data: DataFrame,
    /* private fields */
}
Expand description

The unified Shape execution engine

Fields§

§runtime: Runtime

The runtime environment

§default_data: DataFrame

Default data for expressions/assignments

Implementations§

Source§

impl ShapeEngine

Source

pub fn execute( &mut self, executor: &mut impl ProgramExecutor, source: &str, ) -> Result<ExecutionResult>

Execute a Shape program from source code (sync mode)

This method allows blocking data loads (REPL mode). For scripts/backtests, use execute_async() instead.

Source

pub async fn execute_async( &mut self, executor: &mut impl ProgramExecutor, source: &str, ) -> Result<ExecutionResult>

Execute a Shape program with async prefetching (Phase 6/8)

This method:

  1. Sets Async data mode (runtime data requests use cache, not blocking)
  2. Parses and analyzes the program
  3. Determines required data (symbols/timeframes)
  4. Prefetches data concurrently
  5. Executes synchronously using cached data
§Example
ⓘ
let provider = DataFrameAdapter::new(...);
let mut engine = ShapeEngine::with_async_provider(provider)?;
let result = engine.execute_async(&interpreter, "let sma = close.sma(20)").await?;
Source

pub async fn execute_repl( &mut self, executor: &mut impl ProgramExecutor, source: &str, ) -> Result<ExecutionResult>

Execute a REPL command with persistent state

Unlike execute_async, this uses incremental analysis where variables and functions persist across commands. Call init_repl() once before the first call to this method.

Source

pub fn parse_and_analyze(&mut self, source: &str) -> Result<Program>

Parse and analyze source code without executing it.

Returns the analyzed AST Program, ready for compilation. Used by the recompile-and-resume flow.

Source

pub fn execute_repl_command( &mut self, executor: &mut impl ProgramExecutor, command: &str, ) -> Result<ExecutionResult>

Execute a REPL command

Source

pub fn repl_definitions(&self) -> &[Item]

Definition items accumulated from prior REPL cells (WS-11).

The ProgramExecutor re-prepends these to each new cell’s program before bytecode compilation so that fn / type / enum / trait / impl / type-alias / annotation declarations from earlier lines remain resolvable. Empty unless [init_repl] enabled cross-cell persistence.

Source

pub fn has_repl_definitions(&self) -> bool

Whether cross-cell persistence is active AND there is at least one accumulated definition to inject.

Source

pub fn absorb_repl_cell_definitions(&mut self, program: &Program)

Harvest a successfully-executed cell’s definition items into the cross-cell accumulator (WS-11).

Call this only after the cell ran without error, so a failed cell does not poison the accumulated state. No-op when cross-cell persistence is disabled.

Source

pub fn repl_user_schemas(&self) -> &HashMap<String, TypeSchema>

User type schemas persisted across REPL cells, keyed by name (WS-11). The ProgramExecutor seeds each cell’s compiler with these so a type keeps a stable SchemaId for the whole session.

Source

pub fn remember_repl_user_schema(&mut self, schema: TypeSchema)

Record a user type schema under its first-assigned id (WS-11).

Idempotent and first-write-wins: once a type has a session id, later cells must not overwrite it — that id is what every already persisted instance of the type carries.

Source

pub fn repl_user_type_names(program: &Program) -> Vec<String>

Names of the struct / enum types this cell’s definition items introduce — used to pull the matching schemas out of the compiled program’s registry for cross-cell id stabilization.

Source§

impl ShapeEngine

Source

pub fn load_stdlib(&mut self) -> Result<()>

Load stdlib core modules only. Domain-specific modules (finance, iot, etc.) require explicit import.

Source§

impl ShapeEngine

Source

pub fn new() -> Result<Self>

Create a new Shape engine

Source

pub fn with_data(data: DataFrame) -> Result<Self>

Create engine with data

Source

pub fn with_async_provider(provider: SharedAsyncProvider) -> Result<Self>

Create engine with async data provider (Phase 6)

This constructor sets up the engine with an async data provider. Call execute_async() instead of execute() to use async prefetching.

Source

pub fn init_repl(&mut self)

Initialize REPL mode

Call this once after creating the engine and loading stdlib, but before executing any REPL commands. This configures output adapters for REPL-friendly display and enables cross-cell persistence: let/ var bindings round-trip through the persistent ExecutionContext and fn/type/enum/trait/impl/type-alias/annotation definitions accumulate across cells.

Source

pub fn repl_persistence(&self) -> bool

Whether REPL cross-cell persistence is active (set by [init_repl]).

Source

pub fn capture_bootstrap_state(&self) -> Result<EngineBootstrapState>

Capture semantic/runtime state after stdlib bootstrap.

Call this on an engine that has already loaded stdlib.

Source

pub fn apply_bootstrap_state(&mut self, state: &EngineBootstrapState)

Apply a previously captured stdlib bootstrap state.

Source

pub fn set_script_path(&mut self, path: impl Into<String>)

Set the script path for snapshot metadata.

Source

pub fn script_path(&self) -> Option<&str>

Get the current script path, if set.

Source

pub fn enable_snapshot_store(&mut self, store: SnapshotStore)

Enable snapshotting with a content-addressed store.

Source

pub fn last_snapshot(&self) -> Option<&HashDigest>

Get last snapshot ID, if any.

Source

pub fn snapshot_store(&self) -> Option<&SnapshotStore>

Access the snapshot store (if configured).

Source

pub fn store_snapshot_blob<T: Serialize>(&self, value: &T) -> Result<HashDigest>

Store a serializable blob in the snapshot store and return its hash.

Source

pub fn snapshot_with_hashes( &mut self, vm_hash: Option<HashDigest>, bytecode_hash: Option<HashDigest>, ) -> Result<HashDigest>

Create a snapshot of semantic/runtime state, with optional VM/bytecode hashes supplied by the executor.

Source

pub fn load_snapshot( &self, snapshot_id: &HashDigest, ) -> Result<(SemanticSnapshot, ContextSnapshot, Option<HashDigest>, Option<HashDigest>)>

Load a snapshot and return its components (semantic/context + optional vm/bytecode hashes).

Source

pub fn apply_snapshot( &mut self, semantic: SemanticSnapshot, context: ContextSnapshot, ) -> Result<()>

Apply a semantic/context snapshot to the current engine.

Source

pub fn register_extension_modules(&mut self, modules: &[ParsedModuleSchema])

Register extension module namespaces with the runtime. Must be called before execute() so the module loader recognizes modules like duckdb.

Source

pub fn register_language_runtime_artifacts(&mut self)

Register Shape source artifacts bundled by loaded language runtime extensions.

Each language runtime extension (e.g. Python, TypeScript) may bundle a .shape module source that defines the extension’s own namespace. The namespace is the language identifier itself (e.g. "python", "typescript") – NOT "std::core::*".

Call this after loading extensions but before execute().

Source

pub fn set_source(&mut self, source: &str)

Set the current source text for error messages

Call this before execute() to enable source-contextualized error messages. The source is used during bytecode compilation to populate debug info.

Source

pub fn current_source(&self) -> Option<&str>

Get the current source text (if set)

Source

pub fn register_provider(&mut self, name: &str, provider: SharedAsyncProvider)

Register a data provider (Phase 8)

Registers a named provider for runtime data access.

§Example
ⓘ
let adapter = Arc::new(DataFrameAdapter::new(...));
engine.register_provider("data", adapter);
Source

pub fn set_default_provider(&mut self, name: &str) -> Result<()>

Set default data provider (Phase 8)

Sets which provider to use for runtime data access when no provider is specified.

Source

pub fn register_type_mapping(&mut self, type_name: &str, mapping: TypeMapping)

Register a type mapping (Phase 8)

Registers a type mapping that defines the expected DataFrame structure for a given type name. Type mappings enable validation and JIT optimization.

§Example
ⓘ
use shape_core::runtime::type_mapping::TypeMapping;

// Register the Candle type (from stdlib)
let candle_mapping = TypeMapping::new("Candle".to_string())
    .add_field("timestamp", "timestamp")
    .add_field("open", "open")
    .add_field("high", "high")
    .add_field("low", "low")
    .add_field("close", "close")
    .add_field("volume", "volume")
    .add_required("timestamp")
    .add_required("open")
    .add_required("high")
    .add_required("low")
    .add_required("close");

engine.register_type_mapping("Candle", candle_mapping);
Source

pub fn get_runtime(&self) -> &Runtime

Get the current runtime state (for REPL)

Source

pub fn get_runtime_mut(&mut self) -> &mut Runtime

Get mutable runtime (for REPL state updates)

Source

pub fn get_variable_format_hint(&self, name: &str) -> Option<String>

Get the format hint for a variable (if any)

Returns the format hint specified in the variable’s type annotation. Example: let rate: Number @ Percent = 0.05 → Some(“Percent”)

Source

pub fn format_value_string( &mut self, value: f64, type_name: &str, format_name: Option<&str>, params: &HashMap<String, Value>, ) -> Result<String>

Format a value using Shape runtime format evaluation

This uses the format definitions from stdlib (e.g., stdlib/core/formats.shape) instead of Rust fallback formatters.

§Arguments
  • value - The value to format (as f64 for numbers)
  • type_name - The Shape type name (“Number”, “String”, etc.)
  • format_name - Optional format name (e.g., “Percent”, “Currency”). Uses default if None.
  • params - Format parameters as JSON (e.g., {“decimals”: 1})
§Returns

Formatted string on success

§Example
ⓘ
let formatted = engine.format_value_string(
    0.1234,
    "Number",
    Some("Percent"),
    &HashMap::new()
)?;
assert_eq!(formatted, "12.34%");
Source

pub fn load_extension( &mut self, path: &Path, config: &Value, ) -> Result<LoadedExtension>

Load a data source extension from a shared library

§Arguments
  • path - Path to the extension shared library (.so, .dll, .dylib)
  • config - Configuration value for the extension
§Returns

Information about the loaded extension

§Safety

Loading extensions executes arbitrary code. Only load from trusted sources.

§Example
ⓘ
let info = engine.load_extension(Path::new("./libshape_ext_csv.so"), &json!({}))?;
println!("Loaded: {} v{}", info.name, info.version);
Source

pub fn unload_extension(&mut self, name: &str) -> bool

Unload an extension by name

§Arguments
  • name - Extension name to unload
§Returns

true if plugin was unloaded, false if not found

Source

pub fn list_extensions(&self) -> Vec<String>

List all loaded extension names

Source

pub fn get_extension_query_schema( &self, name: &str, ) -> Option<ParsedQuerySchema>

Get query schema for an extension (for LSP autocomplete)

§Arguments
  • name - Extension name
§Returns

The query schema if extension exists

Source

pub fn get_extension_output_schema( &self, name: &str, ) -> Option<ParsedOutputSchema>

Get output schema for an extension (for LSP autocomplete)

§Arguments
  • name - Extension name
§Returns

The output schema if extension exists

Source

pub fn get_extension(&self, name: &str) -> Option<Arc<ExtensionDataSource>>

Get an extension data source by name

Source

pub fn get_extension_module_schema( &self, module_name: &str, ) -> Option<ParsedModuleSchema>

Get extension module schema by module namespace.

Source

pub fn module_exports_from_extensions(&self) -> Vec<ModuleExports>

Build VM extension modules from loaded extension module capabilities.

Source

pub fn language_runtimes(&self) -> HashMap<String, Arc<PluginLanguageRuntime>>

Return all loaded language runtimes, keyed by language identifier.

Source

pub fn invoke_extension_module_wire( &self, module_name: &str, function: &str, args: &[WireValue], ) -> Result<WireValue>

Invoke one loaded module export via module namespace.

Source

pub fn enable_progress_tracking(&mut self) -> Arc<ProgressRegistry> ⓘ

Enable progress tracking and return the registry for subscriptions

Call this before executing code that may report progress. The returned registry can be used to subscribe to progress events.

§Example
ⓘ
let registry = engine.enable_progress_tracking();
let mut receiver = registry.subscribe();

// In a separate task
while let Ok(event) = receiver.recv().await {
    println!("Progress: {:?}", event);
}
Source

pub fn progress_registry(&self) -> Option<Arc<ProgressRegistry>>

Get the current progress registry if enabled

Source

pub fn has_pending_progress(&self) -> bool

Check if there are pending progress events

Source

pub fn poll_progress(&self) -> Option<ProgressEvent>

Poll for progress events (non-blocking)

Returns the next progress event if available, or None if queue is empty.

Trait Implementations§

Source§

impl Default for ShapeEngine

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more