1use anyhow::Result;
2use runmat_builtins::{self, Type, Value};
3use runmat_gc::{gc_configure, gc_stats, GcConfig};
4use tracing::{debug, info, info_span, warn};
5
6use runmat_hir::{LoweringContext, LoweringResult, SourceId};
7use runmat_lexer::{tokenize_detailed, Token as LexToken};
8use runmat_parser::{parse_with_options, ParserOptions};
9use runmat_runtime::{build_runtime_error, gather_if_needed_async, RuntimeError};
10use runmat_runtime::{
11 runtime_export_workspace_state, runtime_import_workspace_state, WorkspaceReplayMode,
12};
13#[cfg(target_arch = "wasm32")]
14use runmat_snapshot::SnapshotBuilder;
15use runmat_snapshot::{Snapshot, SnapshotConfig, SnapshotLoader};
16use runmat_time::Instant;
17#[cfg(feature = "jit")]
18use runmat_turbine::TurbineEngine;
19use std::collections::{HashMap, HashSet};
20use std::future::Future;
21#[cfg(not(target_arch = "wasm32"))]
22use std::path::Path;
23use std::sync::{
24 atomic::{AtomicBool, Ordering},
25 Arc, Mutex,
26};
27use uuid::Uuid;
28
29use crate::execution::{
30 ExecutionResult, ExecutionStats, ExecutionStreamEntry, ExecutionStreamKind, InputRequest,
31 InputRequestKind, InputResponse, SharedAsyncInputHandler, StdinEvent, StdinEventKind,
32};
33use crate::fusion::{build_fusion_snapshot, FusionPlanSnapshot};
34use crate::profiling::{gather_profiling, reset_provider_telemetry};
35use crate::source_pool::{line_col_from_offset, SourcePool};
36use crate::telemetry::{TelemetryPlatformInfo, TelemetrySink};
37use crate::workspace::{
38 determine_display_label_from_context, format_type_info, gather_gpu_preview_values,
39 gpu_dtype_label, gpu_size_bytes, last_displayable_statement_emit_disposition,
40 last_emit_var_index, last_expr_emits_value, last_unsuppressed_assign_var,
41 slice_value_for_preview, workspace_entry, FinalStmtEmitDisposition, MaterializedVariable,
42 WorkspaceEntry, WorkspaceExportMode, WorkspaceMaterializeOptions, WorkspaceMaterializeTarget,
43 WorkspacePreview, WorkspaceResidency, WorkspaceSnapshot, MATERIALIZE_DEFAULT_LIMIT,
44};
45use crate::{
46 approximate_size_bytes, matlab_class_name, numeric_dtype_label, preview_numeric_values,
47 value_shape, CompatMode, RunError,
48};
49
50mod compile;
51mod config;
52mod run;
53mod snapshot;
54mod workspace;
55
56pub struct RunMatSession {
58 #[cfg(feature = "jit")]
60 jit_engine: Option<TurbineEngine>,
61 verbose: bool,
63 stats: ExecutionStats,
65 variables: HashMap<String, Value>,
67 variable_array: Vec<Value>,
69 variable_names: HashMap<String, usize>,
71 workspace_values: HashMap<String, Value>,
73 function_definitions: HashMap<String, runmat_hir::HirStmt>,
75 source_pool: SourcePool,
77 function_source_ids: HashMap<String, SourceId>,
79 snapshot: Option<Arc<Snapshot>>,
81 interrupt_flag: Arc<AtomicBool>,
83 is_executing: bool,
85 async_input_handler: Option<SharedAsyncInputHandler>,
88 callstack_limit: usize,
90 error_namespace: String,
92 default_source_name: String,
94 source_name_override: Option<String>,
96 pub(crate) telemetry_consent: bool,
97 pub(crate) telemetry_client_id: Option<String>,
98 pub(crate) telemetry_platform: TelemetryPlatformInfo,
99 pub(crate) telemetry_sink: Option<Arc<dyn TelemetrySink>>,
100 workspace_preview_tokens: HashMap<Uuid, WorkspaceMaterializeTicket>,
101 workspace_version: u64,
102 emit_fusion_plan: bool,
103 compat_mode: CompatMode,
104 format_mode: runmat_builtins::FormatMode,
106}
107
108pub(crate) struct PreparedExecution {
109 ast: runmat_parser::Program,
110 lowering: LoweringResult,
111 bytecode: runmat_vm::Bytecode,
112}
113
114#[derive(Debug, Clone)]
115struct WorkspaceMaterializeTicket {
116 name: String,
117}
118
119struct ActiveExecutionGuard {
120 flag: *mut bool,
121}
122
123impl ActiveExecutionGuard {
124 fn new(session: &mut RunMatSession) -> Result<Self> {
125 if session.is_executing {
126 Err(anyhow::anyhow!(
127 "RunMatSession is already executing another script"
128 ))
129 } else {
130 session.is_executing = true;
131 Ok(Self {
132 flag: &mut session.is_executing,
133 })
134 }
135 }
136}
137
138impl Drop for ActiveExecutionGuard {
139 fn drop(&mut self) {
140 unsafe {
141 if let Some(flag) = self.flag.as_mut() {
142 *flag = false;
143 }
144 }
145 }
146}
147
148impl Default for RunMatSession {
149 fn default() -> Self {
150 Self::new().expect("Failed to create default RunMat session")
151 }
152}