Compare commits
33 Commits
more-gears
...
jess/chang
Author | SHA1 | Date | |
---|---|---|---|
495727d617 | |||
e943303434 | |||
8ce175f006 | |||
13aa178734 | |||
de137ff13b | |||
3504b9246f | |||
a035f7879b | |||
d122d7a224 | |||
198e7c4bd2 | |||
14d8903acc | |||
275c23f294 | |||
0ac9ac3896 | |||
0220d0f9de | |||
4523dc209b | |||
ea73eb011c | |||
0aa2824c20 | |||
e66893c5d0 | |||
60274127df | |||
a0d1750829 | |||
00ffa8c0bf | |||
fafdf41093 | |||
a2092e7ed6 | |||
aa103d299c | |||
aaaab495bc | |||
364e38fda2 | |||
b085af139b | |||
ec537cd8dc | |||
8debbc5241 | |||
a590ed99cf | |||
a002bb60a0 | |||
6ba01b8dfa | |||
ca9e6e0944 | |||
e85e54215c |
20
rust/Cargo.lock
generated
20
rust/Cargo.lock
generated
@ -1907,6 +1907,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
"tabled",
|
"tabled",
|
||||||
|
"tempdir",
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.12",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-tungstenite",
|
"tokio-tungstenite",
|
||||||
@ -3084,6 +3085,15 @@ version = "0.8.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "remove_dir_all"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.12.15"
|
version = "0.12.15"
|
||||||
@ -3779,6 +3789,16 @@ version = "0.13.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a"
|
checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tempdir"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
|
||||||
|
dependencies = [
|
||||||
|
"rand 0.4.6",
|
||||||
|
"remove_dir_all",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.19.0"
|
version = "3.19.0"
|
||||||
|
@ -22,7 +22,6 @@ debug = 0
|
|||||||
|
|
||||||
[profile.dev.package]
|
[profile.dev.package]
|
||||||
insta = { opt-level = 3 }
|
insta = { opt-level = 3 }
|
||||||
similar = { opt-level = 3 }
|
|
||||||
|
|
||||||
[profile.test]
|
[profile.test]
|
||||||
debug = "line-tables-only"
|
debug = "line-tables-only"
|
||||||
|
@ -69,6 +69,7 @@ serde = { workspace = true }
|
|||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
sha2 = "0.10.8"
|
sha2 = "0.10.8"
|
||||||
tabled = { version = "0.18.0", optional = true }
|
tabled = { version = "0.18.0", optional = true }
|
||||||
|
tempdir = "0.3.7"
|
||||||
thiserror = "2.0.0"
|
thiserror = "2.0.0"
|
||||||
toml = "0.8.19"
|
toml = "0.8.19"
|
||||||
ts-rs = { version = "10.1.0", features = [
|
ts-rs = { version = "10.1.0", features = [
|
||||||
|
@ -18,7 +18,7 @@ use tokio::sync::{mpsc, oneshot, RwLock};
|
|||||||
use tokio_tungstenite::tungstenite::Message as WsMsg;
|
use tokio_tungstenite::tungstenite::Message as WsMsg;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::{EngineStats, ExecutionKind};
|
use super::EngineStats;
|
||||||
use crate::{
|
use crate::{
|
||||||
engine::EngineManager,
|
engine::EngineManager,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
@ -51,7 +51,6 @@ pub struct EngineConnection {
|
|||||||
/// If the server sends session data, it'll be copied to here.
|
/// If the server sends session data, it'll be copied to here.
|
||||||
session_data: Arc<RwLock<Option<ModelingSessionData>>>,
|
session_data: Arc<RwLock<Option<ModelingSessionData>>>,
|
||||||
|
|
||||||
execution_kind: Arc<RwLock<ExecutionKind>>,
|
|
||||||
stats: EngineStats,
|
stats: EngineStats,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,7 +343,6 @@ impl EngineConnection {
|
|||||||
artifact_commands: Arc::new(RwLock::new(Vec::new())),
|
artifact_commands: Arc::new(RwLock::new(Vec::new())),
|
||||||
default_planes: Default::default(),
|
default_planes: Default::default(),
|
||||||
session_data,
|
session_data,
|
||||||
execution_kind: Default::default(),
|
|
||||||
stats: Default::default(),
|
stats: Default::default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -368,18 +366,6 @@ impl EngineManager for EngineConnection {
|
|||||||
self.artifact_commands.clone()
|
self.artifact_commands.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn execution_kind(&self) -> ExecutionKind {
|
|
||||||
let guard = self.execution_kind.read().await;
|
|
||||||
*guard
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn replace_execution_kind(&self, execution_kind: ExecutionKind) -> ExecutionKind {
|
|
||||||
let mut guard = self.execution_kind.write().await;
|
|
||||||
let original = *guard;
|
|
||||||
*guard = execution_kind;
|
|
||||||
original
|
|
||||||
}
|
|
||||||
|
|
||||||
fn stats(&self) -> &EngineStats {
|
fn stats(&self) -> &EngineStats {
|
||||||
&self.stats
|
&self.stats
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ use kittycad_modeling_cmds::{self as kcmc};
|
|||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::{EngineStats, ExecutionKind};
|
use super::EngineStats;
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::KclError,
|
errors::KclError,
|
||||||
exec::DefaultPlanes,
|
exec::DefaultPlanes,
|
||||||
@ -29,7 +29,6 @@ pub struct EngineConnection {
|
|||||||
batch: Arc<RwLock<Vec<(WebSocketRequest, SourceRange)>>>,
|
batch: Arc<RwLock<Vec<(WebSocketRequest, SourceRange)>>>,
|
||||||
batch_end: Arc<RwLock<IndexMap<uuid::Uuid, (WebSocketRequest, SourceRange)>>>,
|
batch_end: Arc<RwLock<IndexMap<uuid::Uuid, (WebSocketRequest, SourceRange)>>>,
|
||||||
artifact_commands: Arc<RwLock<Vec<ArtifactCommand>>>,
|
artifact_commands: Arc<RwLock<Vec<ArtifactCommand>>>,
|
||||||
execution_kind: Arc<RwLock<ExecutionKind>>,
|
|
||||||
/// The default planes for the scene.
|
/// The default planes for the scene.
|
||||||
default_planes: Arc<RwLock<Option<DefaultPlanes>>>,
|
default_planes: Arc<RwLock<Option<DefaultPlanes>>>,
|
||||||
stats: EngineStats,
|
stats: EngineStats,
|
||||||
@ -41,7 +40,6 @@ impl EngineConnection {
|
|||||||
batch: Arc::new(RwLock::new(Vec::new())),
|
batch: Arc::new(RwLock::new(Vec::new())),
|
||||||
batch_end: Arc::new(RwLock::new(IndexMap::new())),
|
batch_end: Arc::new(RwLock::new(IndexMap::new())),
|
||||||
artifact_commands: Arc::new(RwLock::new(Vec::new())),
|
artifact_commands: Arc::new(RwLock::new(Vec::new())),
|
||||||
execution_kind: Default::default(),
|
|
||||||
default_planes: Default::default(),
|
default_planes: Default::default(),
|
||||||
stats: Default::default(),
|
stats: Default::default(),
|
||||||
})
|
})
|
||||||
@ -70,18 +68,6 @@ impl crate::engine::EngineManager for EngineConnection {
|
|||||||
self.artifact_commands.clone()
|
self.artifact_commands.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn execution_kind(&self) -> ExecutionKind {
|
|
||||||
let guard = self.execution_kind.read().await;
|
|
||||||
*guard
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn replace_execution_kind(&self, execution_kind: ExecutionKind) -> ExecutionKind {
|
|
||||||
let mut guard = self.execution_kind.write().await;
|
|
||||||
let original = *guard;
|
|
||||||
*guard = execution_kind;
|
|
||||||
original
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_default_planes(&self) -> Arc<RwLock<Option<DefaultPlanes>>> {
|
fn get_default_planes(&self) -> Arc<RwLock<Option<DefaultPlanes>>> {
|
||||||
self.default_planes.clone()
|
self.default_planes.clone()
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ use uuid::Uuid;
|
|||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
engine::{EngineStats, ExecutionKind},
|
engine::EngineStats,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{ArtifactCommand, DefaultPlanes, IdGenerator},
|
execution::{ArtifactCommand, DefaultPlanes, IdGenerator},
|
||||||
SourceRange,
|
SourceRange,
|
||||||
@ -42,7 +42,6 @@ pub struct EngineConnection {
|
|||||||
batch_end: Arc<RwLock<IndexMap<uuid::Uuid, (WebSocketRequest, SourceRange)>>>,
|
batch_end: Arc<RwLock<IndexMap<uuid::Uuid, (WebSocketRequest, SourceRange)>>>,
|
||||||
responses: Arc<RwLock<IndexMap<Uuid, WebSocketResponse>>>,
|
responses: Arc<RwLock<IndexMap<Uuid, WebSocketResponse>>>,
|
||||||
artifact_commands: Arc<RwLock<Vec<ArtifactCommand>>>,
|
artifact_commands: Arc<RwLock<Vec<ArtifactCommand>>>,
|
||||||
execution_kind: Arc<RwLock<ExecutionKind>>,
|
|
||||||
/// The default planes for the scene.
|
/// The default planes for the scene.
|
||||||
default_planes: Arc<RwLock<Option<DefaultPlanes>>>,
|
default_planes: Arc<RwLock<Option<DefaultPlanes>>>,
|
||||||
stats: EngineStats,
|
stats: EngineStats,
|
||||||
@ -61,7 +60,6 @@ impl EngineConnection {
|
|||||||
batch_end: Arc::new(RwLock::new(IndexMap::new())),
|
batch_end: Arc::new(RwLock::new(IndexMap::new())),
|
||||||
responses: Arc::new(RwLock::new(IndexMap::new())),
|
responses: Arc::new(RwLock::new(IndexMap::new())),
|
||||||
artifact_commands: Arc::new(RwLock::new(Vec::new())),
|
artifact_commands: Arc::new(RwLock::new(Vec::new())),
|
||||||
execution_kind: Default::default(),
|
|
||||||
default_planes: Default::default(),
|
default_planes: Default::default(),
|
||||||
stats: Default::default(),
|
stats: Default::default(),
|
||||||
})
|
})
|
||||||
@ -164,18 +162,6 @@ impl crate::engine::EngineManager for EngineConnection {
|
|||||||
self.artifact_commands.clone()
|
self.artifact_commands.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn execution_kind(&self) -> ExecutionKind {
|
|
||||||
let guard = self.execution_kind.read().await;
|
|
||||||
*guard
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn replace_execution_kind(&self, execution_kind: ExecutionKind) -> ExecutionKind {
|
|
||||||
let mut guard = self.execution_kind.write().await;
|
|
||||||
let original = *guard;
|
|
||||||
*guard = execution_kind;
|
|
||||||
original
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_default_planes(&self) -> Arc<RwLock<Option<DefaultPlanes>>> {
|
fn get_default_planes(&self) -> Arc<RwLock<Option<DefaultPlanes>>> {
|
||||||
self.default_planes.clone()
|
self.default_planes.clone()
|
||||||
}
|
}
|
||||||
@ -218,11 +204,6 @@ impl crate::engine::EngineManager for EngineConnection {
|
|||||||
.do_send_modeling_cmd(id, source_range, cmd, id_to_source_range)
|
.do_send_modeling_cmd(id, source_range, cmd, id_to_source_range)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// In isolated mode, we don't save the response.
|
|
||||||
if self.execution_kind().await.is_isolated() {
|
|
||||||
return Ok(ws_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut responses = self.responses.write().await;
|
let mut responses = self.responses.write().await;
|
||||||
responses.insert(id, ws_result.clone());
|
responses.insert(id, ws_result.clone());
|
||||||
drop(responses);
|
drop(responses);
|
||||||
|
@ -47,23 +47,6 @@ lazy_static::lazy_static! {
|
|||||||
pub static ref GRID_SCALE_TEXT_OBJECT_ID: uuid::Uuid = uuid::Uuid::parse_str("10782f33-f588-4668-8bcd-040502d26590").unwrap();
|
pub static ref GRID_SCALE_TEXT_OBJECT_ID: uuid::Uuid = uuid::Uuid::parse_str("10782f33-f588-4668-8bcd-040502d26590").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The mode of execution. When isolated, like during an import, attempting to
|
|
||||||
/// send a command results in an error.
|
|
||||||
#[derive(Debug, Default, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, ts_rs::TS, JsonSchema)]
|
|
||||||
#[ts(export)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub enum ExecutionKind {
|
|
||||||
#[default]
|
|
||||||
Normal,
|
|
||||||
Isolated,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ExecutionKind {
|
|
||||||
pub fn is_isolated(&self) -> bool {
|
|
||||||
matches!(self, ExecutionKind::Isolated)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct EngineStats {
|
pub struct EngineStats {
|
||||||
pub commands_batched: AtomicUsize,
|
pub commands_batched: AtomicUsize,
|
||||||
@ -108,13 +91,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
std::mem::take(&mut *self.responses().write().await)
|
std::mem::take(&mut *self.responses().write().await)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current execution kind.
|
|
||||||
async fn execution_kind(&self) -> ExecutionKind;
|
|
||||||
|
|
||||||
/// Replace the current execution kind with a new value and return the
|
|
||||||
/// existing value.
|
|
||||||
async fn replace_execution_kind(&self, execution_kind: ExecutionKind) -> ExecutionKind;
|
|
||||||
|
|
||||||
/// Get the default planes.
|
/// Get the default planes.
|
||||||
fn get_default_planes(&self) -> Arc<RwLock<Option<DefaultPlanes>>>;
|
fn get_default_planes(&self) -> Arc<RwLock<Option<DefaultPlanes>>>;
|
||||||
|
|
||||||
@ -279,11 +255,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
source_range: SourceRange,
|
source_range: SourceRange,
|
||||||
cmd: &ModelingCmd,
|
cmd: &ModelingCmd,
|
||||||
) -> Result<(), crate::errors::KclError> {
|
) -> Result<(), crate::errors::KclError> {
|
||||||
// In isolated mode, we don't send the command to the engine.
|
|
||||||
if self.execution_kind().await.is_isolated() {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let req = WebSocketRequest::ModelingCmdReq(ModelingCmdReq {
|
let req = WebSocketRequest::ModelingCmdReq(ModelingCmdReq {
|
||||||
cmd: cmd.clone(),
|
cmd: cmd.clone(),
|
||||||
cmd_id: id.into(),
|
cmd_id: id.into(),
|
||||||
@ -305,11 +276,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
source_range: SourceRange,
|
source_range: SourceRange,
|
||||||
cmds: &[ModelingCmdReq],
|
cmds: &[ModelingCmdReq],
|
||||||
) -> Result<(), crate::errors::KclError> {
|
) -> Result<(), crate::errors::KclError> {
|
||||||
// In isolated mode, we don't send the command to the engine.
|
|
||||||
if self.execution_kind().await.is_isolated() {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add cmds to the batch.
|
// Add cmds to the batch.
|
||||||
let mut extended_cmds = Vec::with_capacity(cmds.len());
|
let mut extended_cmds = Vec::with_capacity(cmds.len());
|
||||||
for cmd in cmds {
|
for cmd in cmds {
|
||||||
@ -332,11 +298,6 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
source_range: SourceRange,
|
source_range: SourceRange,
|
||||||
cmd: &ModelingCmd,
|
cmd: &ModelingCmd,
|
||||||
) -> Result<(), crate::errors::KclError> {
|
) -> Result<(), crate::errors::KclError> {
|
||||||
// In isolated mode, we don't send the command to the engine.
|
|
||||||
if self.execution_kind().await.is_isolated() {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let req = WebSocketRequest::ModelingCmdReq(ModelingCmdReq {
|
let req = WebSocketRequest::ModelingCmdReq(ModelingCmdReq {
|
||||||
cmd: cmd.clone(),
|
cmd: cmd.clone(),
|
||||||
cmd_id: id.into(),
|
cmd_id: id.into(),
|
||||||
|
@ -5,7 +5,6 @@ use indexmap::IndexMap;
|
|||||||
|
|
||||||
use super::{cad_op::Group, kcl_value::TypeDef, types::PrimitiveType};
|
use super::{cad_op::Group, kcl_value::TypeDef, types::PrimitiveType};
|
||||||
use crate::{
|
use crate::{
|
||||||
engine::ExecutionKind,
|
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
annotations,
|
annotations,
|
||||||
@ -62,7 +61,6 @@ impl ExecutorContext {
|
|||||||
exec_state.mod_local.explicit_length_units = true;
|
exec_state.mod_local.explicit_length_units = true;
|
||||||
}
|
}
|
||||||
let new_units = exec_state.length_unit();
|
let new_units = exec_state.length_unit();
|
||||||
if !self.engine.execution_kind().await.is_isolated() {
|
|
||||||
self.engine
|
self.engine
|
||||||
.set_units(
|
.set_units(
|
||||||
new_units.into(),
|
new_units.into(),
|
||||||
@ -70,7 +68,6 @@ impl ExecutorContext {
|
|||||||
exec_state.id_generator(),
|
exec_state.id_generator(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
exec_state.err(CompilationError::err(
|
exec_state.err(CompilationError::err(
|
||||||
annotation.as_source_range(),
|
annotation.as_source_range(),
|
||||||
@ -100,15 +97,13 @@ impl ExecutorContext {
|
|||||||
&self,
|
&self,
|
||||||
program: &Node<Program>,
|
program: &Node<Program>,
|
||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
exec_kind: ExecutionKind,
|
|
||||||
preserve_mem: bool,
|
preserve_mem: bool,
|
||||||
module_id: ModuleId,
|
module_id: ModuleId,
|
||||||
path: &ModulePath,
|
path: &ModulePath,
|
||||||
) -> Result<(Option<KclValue>, EnvironmentRef, Vec<String>), KclError> {
|
) -> Result<(Option<KclValue>, EnvironmentRef, Vec<String>), KclError> {
|
||||||
crate::log::log(format!("enter module {path} {} {exec_kind:?}", exec_state.stack()));
|
crate::log::log(format!("enter module {path} {}", exec_state.stack()));
|
||||||
|
|
||||||
let old_units = exec_state.length_unit();
|
let old_units = exec_state.length_unit();
|
||||||
let original_execution = self.engine.replace_execution_kind(exec_kind).await;
|
|
||||||
|
|
||||||
let mut local_state = ModuleState::new(path.std_path(), exec_state.stack().memory.clone(), Some(module_id));
|
let mut local_state = ModuleState::new(path.std_path(), exec_state.stack().memory.clone(), Some(module_id));
|
||||||
if !preserve_mem {
|
if !preserve_mem {
|
||||||
@ -141,23 +136,71 @@ impl ExecutorContext {
|
|||||||
// If we reset at the end of the main path, then we just add on an extra
|
// If we reset at the end of the main path, then we just add on an extra
|
||||||
// command and we'd need to flush the batch again.
|
// command and we'd need to flush the batch again.
|
||||||
// This avoids that.
|
// This avoids that.
|
||||||
if !exec_kind.is_isolated() && new_units != old_units && *path != ModulePath::Main {
|
if new_units != old_units && *path != ModulePath::Main {
|
||||||
self.engine
|
self.engine
|
||||||
.set_units(old_units.into(), Default::default(), exec_state.id_generator())
|
.set_units(old_units.into(), Default::default(), exec_state.id_generator())
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
self.engine.replace_execution_kind(original_execution).await;
|
|
||||||
|
|
||||||
crate::log::log(format!("leave {path}"));
|
crate::log::log(format!("leave {path}"));
|
||||||
|
|
||||||
result.map(|result| (result, env_ref, local_state.module_exports))
|
result.map(|result| (result, env_ref, local_state.module_exports))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Execute an AST's program.
|
||||||
|
#[async_recursion]
|
||||||
|
pub(super) async fn preload_all_modules<'a>(
|
||||||
|
&'a self,
|
||||||
|
modules: &mut HashMap<String, Program>,
|
||||||
|
program: NodeRef<'a, Program>,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
|
) -> Result<(), KclError> {
|
||||||
|
for statement in &program.body {
|
||||||
|
if let BodyItem::ImportStatement(import_stmt) = statement {
|
||||||
|
let path_str = import_stmt.path.to_string();
|
||||||
|
|
||||||
|
if modules.contains_key(&path_str) {
|
||||||
|
// don't waste our time if we've already loaded the
|
||||||
|
// module.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let source_range = SourceRange::from(import_stmt);
|
||||||
|
let attrs = &import_stmt.outer_attrs;
|
||||||
|
let module_id = self
|
||||||
|
.open_module(&import_stmt.path, attrs, exec_state, source_range)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let Some(module) = exec_state.get_module(module_id) else {
|
||||||
|
crate::log::log("we got back a module id that doesn't exist");
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
|
||||||
|
let progn = {
|
||||||
|
// this dance is to avoid taking out a mut borrow
|
||||||
|
// below on exec_state after borrowing here. As a
|
||||||
|
// result, we need to clone (ugh) the program for
|
||||||
|
// now.
|
||||||
|
let ModuleRepr::Kcl(ref progn, _) = module.repr else {
|
||||||
|
// not a kcl file, we can skip this
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
progn.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
modules.insert(path_str, progn.clone().inner);
|
||||||
|
|
||||||
|
self.preload_all_modules(modules, &progn, exec_state).await?;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Execute an AST's program.
|
/// Execute an AST's program.
|
||||||
#[async_recursion]
|
#[async_recursion]
|
||||||
pub(super) async fn exec_block<'a>(
|
pub(super) async fn exec_block<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
program: NodeRef<'a, crate::parsing::ast::types::Program>,
|
program: NodeRef<'a, Program>,
|
||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
body_type: BodyType,
|
body_type: BodyType,
|
||||||
) -> Result<Option<KclValue>, KclError> {
|
) -> Result<Option<KclValue>, KclError> {
|
||||||
@ -181,9 +224,9 @@ impl ExecutorContext {
|
|||||||
|
|
||||||
match &import_stmt.selector {
|
match &import_stmt.selector {
|
||||||
ImportSelector::List { items } => {
|
ImportSelector::List { items } => {
|
||||||
let (env_ref, module_exports) = self
|
println!("Importing items from module {}", import_stmt.path,);
|
||||||
.exec_module_for_items(module_id, exec_state, ExecutionKind::Isolated, source_range)
|
let (env_ref, module_exports) =
|
||||||
.await?;
|
self.exec_module_for_items(module_id, exec_state, source_range).await?;
|
||||||
for import_item in items {
|
for import_item in items {
|
||||||
// Extract the item from the module.
|
// Extract the item from the module.
|
||||||
let item = exec_state
|
let item = exec_state
|
||||||
@ -224,9 +267,9 @@ impl ExecutorContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImportSelector::Glob(_) => {
|
ImportSelector::Glob(_) => {
|
||||||
let (env_ref, module_exports) = self
|
println!("Importing all items from module {}", import_stmt.path);
|
||||||
.exec_module_for_items(module_id, exec_state, ExecutionKind::Isolated, source_range)
|
let (env_ref, module_exports) =
|
||||||
.await?;
|
self.exec_module_for_items(module_id, exec_state, source_range).await?;
|
||||||
for name in module_exports.iter() {
|
for name in module_exports.iter() {
|
||||||
let item = exec_state
|
let item = exec_state
|
||||||
.stack()
|
.stack()
|
||||||
@ -417,7 +460,7 @@ impl ExecutorContext {
|
|||||||
Ok(last_expr)
|
Ok(last_expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) async fn open_module(
|
pub async fn open_module(
|
||||||
&self,
|
&self,
|
||||||
path: &ImportPath,
|
path: &ImportPath,
|
||||||
attrs: &[Node<Annotation>],
|
attrs: &[Node<Annotation>],
|
||||||
@ -425,6 +468,7 @@ impl ExecutorContext {
|
|||||||
source_range: SourceRange,
|
source_range: SourceRange,
|
||||||
) -> Result<ModuleId, KclError> {
|
) -> Result<ModuleId, KclError> {
|
||||||
let resolved_path = ModulePath::from_import_path(path, &self.settings.project_directory);
|
let resolved_path = ModulePath::from_import_path(path, &self.settings.project_directory);
|
||||||
|
|
||||||
match path {
|
match path {
|
||||||
ImportPath::Kcl { .. } => {
|
ImportPath::Kcl { .. } => {
|
||||||
exec_state.global.mod_loader.cycle_check(&resolved_path, source_range)?;
|
exec_state.global.mod_loader.cycle_check(&resolved_path, source_range)?;
|
||||||
@ -481,7 +525,6 @@ impl ExecutorContext {
|
|||||||
&self,
|
&self,
|
||||||
module_id: ModuleId,
|
module_id: ModuleId,
|
||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
exec_kind: ExecutionKind,
|
|
||||||
source_range: SourceRange,
|
source_range: SourceRange,
|
||||||
) -> Result<(EnvironmentRef, Vec<String>), KclError> {
|
) -> Result<(EnvironmentRef, Vec<String>), KclError> {
|
||||||
let path = exec_state.global.module_infos[&module_id].path.clone();
|
let path = exec_state.global.module_infos[&module_id].path.clone();
|
||||||
@ -492,7 +535,7 @@ impl ExecutorContext {
|
|||||||
ModuleRepr::Root => Err(exec_state.circular_import_error(&path, source_range)),
|
ModuleRepr::Root => Err(exec_state.circular_import_error(&path, source_range)),
|
||||||
ModuleRepr::Kcl(_, Some((env_ref, items))) => Ok((*env_ref, items.clone())),
|
ModuleRepr::Kcl(_, Some((env_ref, items))) => Ok((*env_ref, items.clone())),
|
||||||
ModuleRepr::Kcl(program, cache) => self
|
ModuleRepr::Kcl(program, cache) => self
|
||||||
.exec_module_from_ast(program, module_id, &path, exec_state, exec_kind, source_range)
|
.exec_module_from_ast(program, module_id, &path, exec_state, source_range)
|
||||||
.await
|
.await
|
||||||
.map(|(_, er, items)| {
|
.map(|(_, er, items)| {
|
||||||
*cache = Some((er, items.clone()));
|
*cache = Some((er, items.clone()));
|
||||||
@ -514,7 +557,6 @@ impl ExecutorContext {
|
|||||||
module_id: ModuleId,
|
module_id: ModuleId,
|
||||||
module_name: &BoxNode<Name>,
|
module_name: &BoxNode<Name>,
|
||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
exec_kind: ExecutionKind,
|
|
||||||
source_range: SourceRange,
|
source_range: SourceRange,
|
||||||
) -> Result<Option<KclValue>, KclError> {
|
) -> Result<Option<KclValue>, KclError> {
|
||||||
exec_state.global.operations.push(Operation::GroupBegin {
|
exec_state.global.operations.push(Operation::GroupBegin {
|
||||||
@ -533,7 +575,7 @@ impl ExecutorContext {
|
|||||||
ModuleRepr::Root => Err(exec_state.circular_import_error(&path, source_range)),
|
ModuleRepr::Root => Err(exec_state.circular_import_error(&path, source_range)),
|
||||||
ModuleRepr::Kcl(program, cached_items) => {
|
ModuleRepr::Kcl(program, cached_items) => {
|
||||||
let result = self
|
let result = self
|
||||||
.exec_module_from_ast(program, module_id, &path, exec_state, exec_kind, source_range)
|
.exec_module_from_ast(program, module_id, &path, exec_state, source_range)
|
||||||
.await;
|
.await;
|
||||||
match result {
|
match result {
|
||||||
Ok((val, env, items)) => {
|
Ok((val, env, items)) => {
|
||||||
@ -556,19 +598,17 @@ impl ExecutorContext {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn exec_module_from_ast(
|
pub async fn exec_module_from_ast(
|
||||||
&self,
|
&self,
|
||||||
program: &Node<Program>,
|
program: &Node<Program>,
|
||||||
module_id: ModuleId,
|
module_id: ModuleId,
|
||||||
path: &ModulePath,
|
path: &ModulePath,
|
||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
exec_kind: ExecutionKind,
|
|
||||||
source_range: SourceRange,
|
source_range: SourceRange,
|
||||||
) -> Result<(Option<KclValue>, EnvironmentRef, Vec<String>), KclError> {
|
) -> Result<(Option<KclValue>, EnvironmentRef, Vec<String>), KclError> {
|
||||||
|
println!("exec_module_from_ast {path}");
|
||||||
exec_state.global.mod_loader.enter_module(path);
|
exec_state.global.mod_loader.enter_module(path);
|
||||||
let result = self
|
let result = self.exec_module_body(program, exec_state, false, module_id, path).await;
|
||||||
.exec_module_body(program, exec_state, exec_kind, false, module_id, path)
|
|
||||||
.await;
|
|
||||||
exec_state.global.mod_loader.leave_module(path);
|
exec_state.global.mod_loader.leave_module(path);
|
||||||
|
|
||||||
result.map_err(|err| {
|
result.map_err(|err| {
|
||||||
@ -604,7 +644,7 @@ impl ExecutorContext {
|
|||||||
Expr::Name(name) => {
|
Expr::Name(name) => {
|
||||||
let value = name.get_result(exec_state, self).await?.clone();
|
let value = name.get_result(exec_state, self).await?.clone();
|
||||||
if let KclValue::Module { value: module_id, meta } = value {
|
if let KclValue::Module { value: module_id, meta } = value {
|
||||||
self.exec_module_for_result(module_id, name, exec_state, ExecutionKind::Normal, metadata.source_range)
|
self.exec_module_for_result(module_id, name, exec_state, metadata.source_range)
|
||||||
.await?
|
.await?
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
exec_state.warn(CompilationError::err(
|
exec_state.warn(CompilationError::err(
|
||||||
@ -792,7 +832,7 @@ impl Node<Name> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
mem_spec = Some(
|
mem_spec = Some(
|
||||||
ctx.exec_module_for_items(*module_id, exec_state, ExecutionKind::Normal, p.as_source_range())
|
ctx.exec_module_for_items(*module_id, exec_state, p.as_source_range())
|
||||||
.await?,
|
.await?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1273,7 +1313,7 @@ impl Node<CallExpressionKw> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let op = if func.feature_tree_operation() && !ctx.is_isolated_execution().await {
|
let op = if func.feature_tree_operation() {
|
||||||
let op_labeled_args = args
|
let op_labeled_args = args
|
||||||
.kw_args
|
.kw_args
|
||||||
.labeled
|
.labeled
|
||||||
@ -1359,7 +1399,7 @@ impl Node<CallExpressionKw> {
|
|||||||
e.add_source_ranges(vec![callsite])
|
e.add_source_ranges(vec![callsite])
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if matches!(fn_src, FunctionSource::User { .. }) && !ctx.is_isolated_execution().await {
|
if matches!(fn_src, FunctionSource::User { .. }) {
|
||||||
// Track return operation.
|
// Track return operation.
|
||||||
exec_state.global.operations.push(Operation::GroupEnd);
|
exec_state.global.operations.push(Operation::GroupEnd);
|
||||||
}
|
}
|
||||||
@ -1411,7 +1451,7 @@ impl Node<CallExpression> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let op = if func.feature_tree_operation() && !ctx.is_isolated_execution().await {
|
let op = if func.feature_tree_operation() {
|
||||||
let op_labeled_args = func
|
let op_labeled_args = func
|
||||||
.args(false)
|
.args(false)
|
||||||
.iter()
|
.iter()
|
||||||
@ -1469,7 +1509,6 @@ impl Node<CallExpression> {
|
|||||||
// exec_state.
|
// exec_state.
|
||||||
let func = fn_name.get_result(exec_state, ctx).await?.clone();
|
let func = fn_name.get_result(exec_state, ctx).await?.clone();
|
||||||
|
|
||||||
if !ctx.is_isolated_execution().await {
|
|
||||||
// Track call operation.
|
// Track call operation.
|
||||||
exec_state.global.operations.push(Operation::GroupBegin {
|
exec_state.global.operations.push(Operation::GroupBegin {
|
||||||
group: Group::FunctionCall {
|
group: Group::FunctionCall {
|
||||||
@ -1481,7 +1520,6 @@ impl Node<CallExpression> {
|
|||||||
},
|
},
|
||||||
source_range: callsite,
|
source_range: callsite,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
let Some(fn_src) = func.as_fn() else {
|
let Some(fn_src) = func.as_fn() else {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
@ -1510,10 +1548,8 @@ impl Node<CallExpression> {
|
|||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if !ctx.is_isolated_execution().await {
|
|
||||||
// Track return operation.
|
// Track return operation.
|
||||||
exec_state.global.operations.push(Operation::GroupEnd);
|
exec_state.global.operations.push(Operation::GroupEnd);
|
||||||
}
|
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
@ -2241,7 +2277,7 @@ impl FunctionSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let op = if props.include_in_feature_tree && !ctx.is_isolated_execution().await {
|
let op = if props.include_in_feature_tree {
|
||||||
let op_labeled_args = args
|
let op_labeled_args = args
|
||||||
.kw_args
|
.kw_args
|
||||||
.labeled
|
.labeled
|
||||||
@ -2285,7 +2321,6 @@ impl FunctionSource {
|
|||||||
Ok(Some(result))
|
Ok(Some(result))
|
||||||
}
|
}
|
||||||
FunctionSource::User { ast, memory, .. } => {
|
FunctionSource::User { ast, memory, .. } => {
|
||||||
if !ctx.is_isolated_execution().await {
|
|
||||||
// Track call operation.
|
// Track call operation.
|
||||||
let op_labeled_args = args
|
let op_labeled_args = args
|
||||||
.kw_args
|
.kw_args
|
||||||
@ -2306,7 +2341,6 @@ impl FunctionSource {
|
|||||||
},
|
},
|
||||||
source_range: callsite,
|
source_range: callsite,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
call_user_defined_function_kw(args.kw_args, *memory, ast, exec_state, ctx).await
|
call_user_defined_function_kw(args.kw_args, *memory, ast, exec_state, ctx).await
|
||||||
}
|
}
|
||||||
@ -2317,13 +2351,14 @@ impl FunctionSource {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
execution::{memory::Stack, parse_execute, ContextType},
|
execution::{memory::Stack, parse_execute, ContextType},
|
||||||
parsing::ast::types::{DefaultParamVal, Identifier, Parameter},
|
parsing::ast::types::{DefaultParamVal, Identifier, Parameter},
|
||||||
|
ExecutorSettings,
|
||||||
};
|
};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tokio::io::AsyncWriteExt;
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_assign_args_to_params() {
|
async fn test_assign_args_to_params() {
|
||||||
@ -2432,7 +2467,7 @@ mod test {
|
|||||||
// Run each test.
|
// Run each test.
|
||||||
let func_expr = &Node::no_src(FunctionExpression {
|
let func_expr = &Node::no_src(FunctionExpression {
|
||||||
params,
|
params,
|
||||||
body: crate::parsing::ast::types::Program::empty(),
|
body: Program::empty(),
|
||||||
return_type: None,
|
return_type: None,
|
||||||
digest: None,
|
digest: None,
|
||||||
});
|
});
|
||||||
@ -2534,4 +2569,100 @@ a = foo()
|
|||||||
let result = parse_execute(program).await;
|
let result = parse_execute(program).await;
|
||||||
assert!(result.unwrap_err().to_string().contains("return"));
|
assert!(result.unwrap_err().to_string().contains("return"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn load_all_modules() {
|
||||||
|
// program a.kcl
|
||||||
|
let programa_kcl = r#"
|
||||||
|
export a = 1
|
||||||
|
"#;
|
||||||
|
// program b.kcl
|
||||||
|
let programb_kcl = r#"
|
||||||
|
import a from 'a.kcl'
|
||||||
|
|
||||||
|
export b = a + 1
|
||||||
|
"#;
|
||||||
|
// program c.kcl
|
||||||
|
let programc_kcl = r#"
|
||||||
|
import a from 'a.kcl'
|
||||||
|
|
||||||
|
export c = a + 2
|
||||||
|
"#;
|
||||||
|
|
||||||
|
// program main.kcl
|
||||||
|
let main_kcl = r#"
|
||||||
|
import b from 'b.kcl'
|
||||||
|
import c from 'c.kcl'
|
||||||
|
|
||||||
|
d = b + c
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let main = crate::parsing::parse_str(main_kcl, ModuleId::default())
|
||||||
|
.parse_errs_as_err()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let tmpdir = tempdir::TempDir::new("zma_kcl_load_all_modules").unwrap();
|
||||||
|
|
||||||
|
tokio::fs::File::create(tmpdir.path().join("main.kcl"))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.write_all(main_kcl.as_bytes())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
tokio::fs::File::create(tmpdir.path().join("a.kcl"))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.write_all(programa_kcl.as_bytes())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
tokio::fs::File::create(tmpdir.path().join("b.kcl"))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.write_all(programb_kcl.as_bytes())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
tokio::fs::File::create(tmpdir.path().join("c.kcl"))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.write_all(programc_kcl.as_bytes())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let exec_ctxt = ExecutorContext {
|
||||||
|
engine: Arc::new(Box::new(
|
||||||
|
crate::engine::conn_mock::EngineConnection::new()
|
||||||
|
.await
|
||||||
|
.map_err(|err| {
|
||||||
|
KclError::Internal(crate::errors::KclErrorDetails {
|
||||||
|
message: format!("Failed to create mock engine connection: {}", err),
|
||||||
|
source_ranges: vec![SourceRange::default()],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
|
)),
|
||||||
|
fs: Arc::new(crate::fs::FileManager::new()),
|
||||||
|
settings: ExecutorSettings {
|
||||||
|
project_directory: Some(tmpdir.path().into()),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
stdlib: Arc::new(crate::std::StdLib::new()),
|
||||||
|
context_type: ContextType::Mock,
|
||||||
|
};
|
||||||
|
let mut exec_state = ExecState::new(&exec_ctxt);
|
||||||
|
|
||||||
|
exec_ctxt
|
||||||
|
.run_concurrent(
|
||||||
|
&crate::Program {
|
||||||
|
ast: main.clone(),
|
||||||
|
original_file_contents: "".to_owned(),
|
||||||
|
},
|
||||||
|
&mut exec_state,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,21 +27,22 @@ pub use memory::EnvironmentRef;
|
|||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
pub use state::{ExecState, MetaSettings};
|
pub use state::{ExecState, MetaSettings};
|
||||||
|
use tokio::task::JoinSet;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
engine::EngineManager,
|
engine::EngineManager,
|
||||||
errors::KclError,
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
artifact::build_artifact_graph,
|
artifact::build_artifact_graph,
|
||||||
cache::{CacheInformation, CacheResult},
|
cache::{CacheInformation, CacheResult},
|
||||||
types::{UnitAngle, UnitLen},
|
types::{UnitAngle, UnitLen},
|
||||||
},
|
},
|
||||||
fs::FileManager,
|
fs::FileManager,
|
||||||
modules::{ModuleId, ModulePath},
|
modules::{ModuleId, ModulePath, ModuleRepr},
|
||||||
parsing::ast::types::{Expr, ImportPath, NodeRef},
|
parsing::ast::types::{Expr, ImportPath, NodeRef},
|
||||||
source_range::SourceRange,
|
source_range::SourceRange,
|
||||||
std::StdLib,
|
std::StdLib,
|
||||||
CompilationError, ExecError, ExecutionKind, KclErrorWithOutputs,
|
CompilationError, ExecError, KclErrorWithOutputs,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) mod annotations;
|
pub(crate) mod annotations;
|
||||||
@ -497,13 +498,9 @@ impl ExecutorContext {
|
|||||||
self.context_type == ContextType::Mock || self.context_type == ContextType::MockCustomForwarded
|
self.context_type == ContextType::Mock || self.context_type == ContextType::MockCustomForwarded
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn is_isolated_execution(&self) -> bool {
|
|
||||||
self.engine.execution_kind().await.is_isolated()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if we should not send engine commands for any reason.
|
/// Returns true if we should not send engine commands for any reason.
|
||||||
pub async fn no_engine_commands(&self) -> bool {
|
pub async fn no_engine_commands(&self) -> bool {
|
||||||
self.is_mock() || self.is_isolated_execution().await
|
self.is_mock()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_clear_scene(
|
pub async fn send_clear_scene(
|
||||||
@ -674,7 +671,7 @@ impl ExecutorContext {
|
|||||||
(program, exec_state, false)
|
(program, exec_state, false)
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = self.inner_run(&program, &mut exec_state, preserve_mem).await;
|
let result = self.run_concurrent(&program, &mut exec_state, preserve_mem).await;
|
||||||
|
|
||||||
if result.is_err() {
|
if result.is_err() {
|
||||||
cache::bust_cache().await;
|
cache::bust_cache().await;
|
||||||
@ -707,7 +704,124 @@ impl ExecutorContext {
|
|||||||
program: &crate::Program,
|
program: &crate::Program,
|
||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
) -> Result<(EnvironmentRef, Option<ModelingSessionData>), KclErrorWithOutputs> {
|
) -> Result<(EnvironmentRef, Option<ModelingSessionData>), KclErrorWithOutputs> {
|
||||||
self.inner_run(program, exec_state, false).await
|
self.run_concurrent(program, exec_state, false).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform the execution of a program using an (experimental!) concurrent
|
||||||
|
/// execution model. This has the same signature as [Self::run].
|
||||||
|
///
|
||||||
|
/// For now -- do not use this unless you're willing to accept some
|
||||||
|
/// breakage.
|
||||||
|
///
|
||||||
|
/// You can optionally pass in some initialization memory for partial
|
||||||
|
/// execution.
|
||||||
|
///
|
||||||
|
/// To access non-fatal errors and warnings, extract them from the `ExecState`.
|
||||||
|
pub async fn run_concurrent(
|
||||||
|
&self,
|
||||||
|
program: &crate::Program,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
|
preserve_mem: bool,
|
||||||
|
) -> Result<(EnvironmentRef, Option<ModelingSessionData>), KclErrorWithOutputs> {
|
||||||
|
self.prepare_mem(exec_state).await.unwrap();
|
||||||
|
|
||||||
|
let mut universe = std::collections::HashMap::new();
|
||||||
|
let mut out_id_map = std::collections::HashMap::new();
|
||||||
|
|
||||||
|
crate::walk::import_universe(self, &program.ast, &mut universe, &mut out_id_map, exec_state)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
for modules in crate::walk::import_graph(&universe).unwrap().into_iter() {
|
||||||
|
println!("Running module {modules:?}");
|
||||||
|
//let mut set = JoinSet::new();
|
||||||
|
println!("AFTER Running module {modules:?}");
|
||||||
|
let (results_tx, mut results_rx): (
|
||||||
|
tokio::sync::mpsc::Sender<(
|
||||||
|
String,
|
||||||
|
Result<(Option<KclValue>, EnvironmentRef, Vec<String>), KclError>,
|
||||||
|
)>,
|
||||||
|
tokio::sync::mpsc::Receiver<_>,
|
||||||
|
) = tokio::sync::mpsc::channel(1);
|
||||||
|
|
||||||
|
for module in modules {
|
||||||
|
let program = universe.get(&module).unwrap().clone();
|
||||||
|
let Some(module_id) = out_id_map.get(&module) else {
|
||||||
|
panic!("Module {module} not found in exec_state");
|
||||||
|
};
|
||||||
|
let module_id = module_id.clone();
|
||||||
|
let module_path = {
|
||||||
|
let module_info = exec_state.get_module(module_id).unwrap();
|
||||||
|
let module_path = module_info.path.clone();
|
||||||
|
module_path
|
||||||
|
};
|
||||||
|
let exec_state = exec_state.clone();
|
||||||
|
let exec_ctxt = self.clone();
|
||||||
|
let results_tx = results_tx.clone();
|
||||||
|
|
||||||
|
println!("before spawn");
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
{
|
||||||
|
wasm_bindgen_futures::spawn_local(async move {
|
||||||
|
//set.spawn(async move {
|
||||||
|
println!("Running module {module} from run_concurrent");
|
||||||
|
let mut exec_state = exec_state;
|
||||||
|
let exec_ctxt = exec_ctxt;
|
||||||
|
let program = program;
|
||||||
|
|
||||||
|
let result = exec_ctxt
|
||||||
|
.exec_module_from_ast(
|
||||||
|
&program,
|
||||||
|
module_id,
|
||||||
|
&module_path,
|
||||||
|
&mut exec_state,
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
results_tx.send((module, result)).await.unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop(results_tx);
|
||||||
|
|
||||||
|
while let Some((module, result)) = results_rx.recv().await {
|
||||||
|
match result {
|
||||||
|
Ok((env_ref, session_data, variables)) => {
|
||||||
|
println!("{module} {:?}", variables);
|
||||||
|
let Some(module_id) = out_id_map.get(&module) else {
|
||||||
|
//let snapshot_png_bytes = self.prepare_snapshot().await.unwrap().contents.0;
|
||||||
|
// Save to a file.
|
||||||
|
//tokio::fs::write("snapshot.png", snapshot_png_bytes).await.unwrap();
|
||||||
|
|
||||||
|
return Err(KclErrorWithOutputs::no_outputs(KclError::Internal(KclErrorDetails {
|
||||||
|
message: format!("Module {module} not found in exec_state"),
|
||||||
|
source_ranges: Default::default(),
|
||||||
|
})));
|
||||||
|
};
|
||||||
|
let path = exec_state.global.module_infos[module_id].path.clone();
|
||||||
|
let mut repr = exec_state.global.module_infos[module_id].take_repr();
|
||||||
|
|
||||||
|
let ModuleRepr::Kcl(program, cache) = &mut repr else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
*cache = Some((session_data, variables.clone()));
|
||||||
|
|
||||||
|
exec_state.global.module_infos[module_id].restore_repr(repr);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
//let snapshot_png_bytes = self.prepare_snapshot().await.unwrap().contents.0;
|
||||||
|
// Save to a file.
|
||||||
|
//tokio::fs::write("snapshot.png", snapshot_png_bytes).await.unwrap();
|
||||||
|
return Err(KclErrorWithOutputs::no_outputs(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.inner_run(program, exec_state, preserve_mem).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform the execution of a program. Accept all possible parameters and
|
/// Perform the execution of a program. Accept all possible parameters and
|
||||||
@ -758,11 +872,11 @@ impl ExecutorContext {
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if !self.is_mock() {
|
/* if !self.is_mock() {
|
||||||
let mut mem = exec_state.stack().deep_clone();
|
let mut mem = exec_state.stack().deep_clone();
|
||||||
mem.restore_env(env_ref);
|
mem.restore_env(env_ref);
|
||||||
cache::write_old_memory((mem, exec_state.global.module_infos.clone())).await;
|
cache::write_old_memory((mem, exec_state.global.module_infos.clone())).await;
|
||||||
}
|
}*/
|
||||||
let session_data = self.engine.get_session_data().await;
|
let session_data = self.engine.get_session_data().await;
|
||||||
Ok((env_ref, session_data))
|
Ok((env_ref, session_data))
|
||||||
}
|
}
|
||||||
@ -785,7 +899,6 @@ impl ExecutorContext {
|
|||||||
.exec_module_body(
|
.exec_module_body(
|
||||||
program,
|
program,
|
||||||
exec_state,
|
exec_state,
|
||||||
ExecutionKind::Normal,
|
|
||||||
preserve_mem,
|
preserve_mem,
|
||||||
ModuleId::default(),
|
ModuleId::default(),
|
||||||
&ModulePath::Main,
|
&ModulePath::Main,
|
||||||
@ -839,9 +952,7 @@ impl ExecutorContext {
|
|||||||
source_range,
|
source_range,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let (module_memory, _) = self
|
let (module_memory, _) = self.exec_module_for_items(id, exec_state, source_range).await?;
|
||||||
.exec_module_for_items(id, exec_state, ExecutionKind::Isolated, source_range)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
exec_state.mut_stack().memory.set_std(module_memory);
|
exec_state.mut_stack().memory.set_std(module_memory);
|
||||||
}
|
}
|
||||||
|
@ -228,6 +228,10 @@ impl ExecState {
|
|||||||
self.global.module_infos.insert(id, module_info);
|
self.global.module_infos.insert(id, module_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_module(&mut self, id: ModuleId) -> Option<&ModuleInfo> {
|
||||||
|
self.global.module_infos.get(&id)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn length_unit(&self) -> UnitLen {
|
pub fn length_unit(&self) -> UnitLen {
|
||||||
self.mod_local.settings.default_length_units
|
self.mod_local.settings.default_length_units
|
||||||
}
|
}
|
||||||
|
@ -76,12 +76,12 @@ pub mod std;
|
|||||||
pub mod test_server;
|
pub mod test_server;
|
||||||
mod thread;
|
mod thread;
|
||||||
mod unparser;
|
mod unparser;
|
||||||
mod walk;
|
pub mod walk;
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
mod wasm;
|
mod wasm;
|
||||||
|
|
||||||
pub use coredump::CoreDump;
|
pub use coredump::CoreDump;
|
||||||
pub use engine::{EngineManager, EngineStats, ExecutionKind};
|
pub use engine::{EngineManager, EngineStats};
|
||||||
pub use errors::{
|
pub use errors::{
|
||||||
CompilationError, ConnectionError, ExecError, KclError, KclErrorWithOutputs, Report, ReportWithOutputs,
|
CompilationError, ConnectionError, ExecError, KclError, KclErrorWithOutputs, Report, ReportWithOutputs,
|
||||||
};
|
};
|
||||||
|
@ -6,8 +6,10 @@ use std::{
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
parsing::ast::types::{ImportPath, NodeRef, Program},
|
modules::ModuleRepr,
|
||||||
|
parsing::ast::types::{ImportPath, Node as AstNode, NodeRef, Program},
|
||||||
walk::{Node, Visitable},
|
walk::{Node, Visitable},
|
||||||
|
ExecState, ExecutorContext, ModuleId,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Specific dependency between two modules. The 0th element of this tuple
|
/// Specific dependency between two modules. The 0th element of this tuple
|
||||||
@ -23,7 +25,7 @@ type Graph = Vec<Dependency>;
|
|||||||
/// run concurrently. Each "stage" is blocking in this model, which will
|
/// run concurrently. Each "stage" is blocking in this model, which will
|
||||||
/// change in the future. Don't use this function widely, yet.
|
/// change in the future. Don't use this function widely, yet.
|
||||||
#[allow(clippy::iter_over_hash_type)]
|
#[allow(clippy::iter_over_hash_type)]
|
||||||
pub fn import_graph(progs: HashMap<String, NodeRef<'_, Program>>) -> Result<Vec<Vec<String>>> {
|
pub fn import_graph(progs: &HashMap<String, AstNode<Program>>) -> Result<Vec<Vec<String>>> {
|
||||||
let mut graph = Graph::new();
|
let mut graph = Graph::new();
|
||||||
|
|
||||||
for (name, program) in progs.iter() {
|
for (name, program) in progs.iter() {
|
||||||
@ -41,6 +43,9 @@ pub fn import_graph(progs: HashMap<String, NodeRef<'_, Program>>) -> Result<Vec<
|
|||||||
|
|
||||||
#[allow(clippy::iter_over_hash_type)]
|
#[allow(clippy::iter_over_hash_type)]
|
||||||
fn topsort(all_modules: &[&str], graph: Graph) -> Result<Vec<Vec<String>>> {
|
fn topsort(all_modules: &[&str], graph: Graph) -> Result<Vec<Vec<String>>> {
|
||||||
|
if all_modules.is_empty() {
|
||||||
|
return Ok(vec![]);
|
||||||
|
}
|
||||||
let mut dep_map = HashMap::<String, Vec<String>>::new();
|
let mut dep_map = HashMap::<String, Vec<String>>::new();
|
||||||
|
|
||||||
for (dependent, dependency) in graph.iter() {
|
for (dependent, dependency) in graph.iter() {
|
||||||
@ -57,6 +62,7 @@ fn topsort(all_modules: &[&str], graph: Graph) -> Result<Vec<Vec<String>>> {
|
|||||||
let mut order = vec![];
|
let mut order = vec![];
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
println!("waiting_modules: {:?}", waiting_modules);
|
||||||
// Each pass through we need to find any modules which have nothing
|
// Each pass through we need to find any modules which have nothing
|
||||||
// "pointing at it" -- so-called reverse dependencies. This is an entry
|
// "pointing at it" -- so-called reverse dependencies. This is an entry
|
||||||
// that is either not in the dep_map OR an empty list.
|
// that is either not in the dep_map OR an empty list.
|
||||||
@ -101,7 +107,7 @@ fn topsort(all_modules: &[&str], graph: Graph) -> Result<Vec<Vec<String>>> {
|
|||||||
Ok(order)
|
Ok(order)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn import_dependencies(prog: NodeRef<'_, Program>) -> Result<Vec<String>> {
|
pub(crate) fn import_dependencies(prog: NodeRef<Program>) -> Result<Vec<String>> {
|
||||||
let ret = Arc::new(Mutex::new(vec![]));
|
let ret = Arc::new(Mutex::new(vec![]));
|
||||||
|
|
||||||
fn walk(ret: Arc<Mutex<Vec<String>>>, node: Node<'_>) {
|
fn walk(ret: Arc<Mutex<Vec<String>>>, node: Node<'_>) {
|
||||||
@ -125,6 +131,51 @@ pub(crate) fn import_dependencies(prog: NodeRef<'_, Program>) -> Result<Vec<Stri
|
|||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn import_universe<'prog>(
|
||||||
|
ctx: &ExecutorContext,
|
||||||
|
prog: NodeRef<'prog, Program>,
|
||||||
|
out: &mut HashMap<String, AstNode<Program>>,
|
||||||
|
out_id_map: &mut HashMap<String, ModuleId>,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
|
) -> Result<()> {
|
||||||
|
let modules = import_dependencies(prog)?;
|
||||||
|
for module in modules {
|
||||||
|
eprintln!("{:?}", module);
|
||||||
|
|
||||||
|
if out.contains_key(&module) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let module_id = ctx
|
||||||
|
.open_module(
|
||||||
|
&ImportPath::Kcl {
|
||||||
|
filename: module.to_string(),
|
||||||
|
},
|
||||||
|
&[],
|
||||||
|
exec_state,
|
||||||
|
Default::default(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
out_id_map.insert(module.clone(), module_id);
|
||||||
|
|
||||||
|
let program = {
|
||||||
|
let Some(module_info) = exec_state.get_module(module_id) else {
|
||||||
|
// We should never get here we just fucking added it.
|
||||||
|
anyhow::bail!("Module {} not found", module);
|
||||||
|
};
|
||||||
|
let ModuleRepr::Kcl(program, _) = &module_info.repr else {
|
||||||
|
anyhow::bail!("Module {} is not a KCL program", module);
|
||||||
|
};
|
||||||
|
program.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
out.insert(module.clone(), program.clone());
|
||||||
|
Box::pin(import_universe(ctx, &program, out, out_id_map, exec_state)).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -140,16 +191,16 @@ mod tests {
|
|||||||
let mut modules = HashMap::new();
|
let mut modules = HashMap::new();
|
||||||
|
|
||||||
let a = kcl!("");
|
let a = kcl!("");
|
||||||
modules.insert("a.kcl".to_owned(), &a);
|
modules.insert("a.kcl".to_owned(), a);
|
||||||
|
|
||||||
let b = kcl!(
|
let b = kcl!(
|
||||||
"
|
"
|
||||||
import \"a.kcl\"
|
import \"a.kcl\"
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
modules.insert("b.kcl".to_owned(), &b);
|
modules.insert("b.kcl".to_owned(), b);
|
||||||
|
|
||||||
let order = import_graph(modules).unwrap();
|
let order = import_graph(&modules).unwrap();
|
||||||
assert_eq!(vec![vec!["a.kcl".to_owned()], vec!["b.kcl".to_owned()]], order);
|
assert_eq!(vec![vec!["a.kcl".to_owned()], vec!["b.kcl".to_owned()]], order);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,16 +213,16 @@ import \"a.kcl\"
|
|||||||
y = 2
|
y = 2
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
modules.insert("a.kcl".to_owned(), &a);
|
modules.insert("a.kcl".to_owned(), a);
|
||||||
|
|
||||||
let b = kcl!(
|
let b = kcl!(
|
||||||
"
|
"
|
||||||
x = 1
|
x = 1
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
modules.insert("b.kcl".to_owned(), &b);
|
modules.insert("b.kcl".to_owned(), b);
|
||||||
|
|
||||||
let order = import_graph(modules).unwrap();
|
let order = import_graph(&modules).unwrap();
|
||||||
assert_eq!(vec![vec!["a.kcl".to_owned(), "b.kcl".to_owned()]], order);
|
assert_eq!(vec![vec!["a.kcl".to_owned(), "b.kcl".to_owned()]], order);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,23 +231,23 @@ x = 1
|
|||||||
let mut modules = HashMap::new();
|
let mut modules = HashMap::new();
|
||||||
|
|
||||||
let a = kcl!("");
|
let a = kcl!("");
|
||||||
modules.insert("a.kcl".to_owned(), &a);
|
modules.insert("a.kcl".to_owned(), a);
|
||||||
|
|
||||||
let b = kcl!(
|
let b = kcl!(
|
||||||
"
|
"
|
||||||
import \"a.kcl\"
|
import \"a.kcl\"
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
modules.insert("b.kcl".to_owned(), &b);
|
modules.insert("b.kcl".to_owned(), b);
|
||||||
|
|
||||||
let c = kcl!(
|
let c = kcl!(
|
||||||
"
|
"
|
||||||
import \"a.kcl\"
|
import \"a.kcl\"
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
modules.insert("c.kcl".to_owned(), &c);
|
modules.insert("c.kcl".to_owned(), c);
|
||||||
|
|
||||||
let order = import_graph(modules).unwrap();
|
let order = import_graph(&modules).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![vec!["a.kcl".to_owned()], vec!["b.kcl".to_owned(), "c.kcl".to_owned()]],
|
vec![vec!["a.kcl".to_owned()], vec!["b.kcl".to_owned(), "c.kcl".to_owned()]],
|
||||||
order
|
order
|
||||||
@ -212,15 +263,15 @@ import \"a.kcl\"
|
|||||||
import \"b.kcl\"
|
import \"b.kcl\"
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
modules.insert("a.kcl".to_owned(), &a);
|
modules.insert("a.kcl".to_owned(), a);
|
||||||
|
|
||||||
let b = kcl!(
|
let b = kcl!(
|
||||||
"
|
"
|
||||||
import \"a.kcl\"
|
import \"a.kcl\"
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
modules.insert("b.kcl".to_owned(), &b);
|
modules.insert("b.kcl".to_owned(), b);
|
||||||
|
|
||||||
import_graph(modules).unwrap_err();
|
import_graph(&modules).unwrap_err();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,3 +8,5 @@ mod import_graph;
|
|||||||
pub use ast_node::Node;
|
pub use ast_node::Node;
|
||||||
pub use ast_visitor::Visitable;
|
pub use ast_visitor::Visitable;
|
||||||
pub use ast_walk::walk;
|
pub use ast_walk::walk;
|
||||||
|
pub use import_graph::import_graph;
|
||||||
|
pub(crate) use import_graph::import_universe;
|
||||||
|
@ -4,7 +4,7 @@ use anyhow::Result;
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use kcl_lib::{
|
use kcl_lib::{
|
||||||
exec::{ArtifactCommand, DefaultPlanes, IdGenerator},
|
exec::{ArtifactCommand, DefaultPlanes, IdGenerator},
|
||||||
EngineStats, ExecutionKind, KclError,
|
EngineStats, KclError,
|
||||||
};
|
};
|
||||||
use kittycad_modeling_cmds::{
|
use kittycad_modeling_cmds::{
|
||||||
self as kcmc,
|
self as kcmc,
|
||||||
@ -23,7 +23,6 @@ pub struct EngineConnection {
|
|||||||
batch: Arc<RwLock<Vec<(WebSocketRequest, kcl_lib::SourceRange)>>>,
|
batch: Arc<RwLock<Vec<(WebSocketRequest, kcl_lib::SourceRange)>>>,
|
||||||
batch_end: Arc<RwLock<IndexMap<uuid::Uuid, (WebSocketRequest, kcl_lib::SourceRange)>>>,
|
batch_end: Arc<RwLock<IndexMap<uuid::Uuid, (WebSocketRequest, kcl_lib::SourceRange)>>>,
|
||||||
core_test: Arc<RwLock<String>>,
|
core_test: Arc<RwLock<String>>,
|
||||||
execution_kind: Arc<RwLock<ExecutionKind>>,
|
|
||||||
/// The default planes for the scene.
|
/// The default planes for the scene.
|
||||||
default_planes: Arc<RwLock<Option<DefaultPlanes>>>,
|
default_planes: Arc<RwLock<Option<DefaultPlanes>>>,
|
||||||
stats: EngineStats,
|
stats: EngineStats,
|
||||||
@ -37,7 +36,6 @@ impl EngineConnection {
|
|||||||
batch: Arc::new(RwLock::new(Vec::new())),
|
batch: Arc::new(RwLock::new(Vec::new())),
|
||||||
batch_end: Arc::new(RwLock::new(IndexMap::new())),
|
batch_end: Arc::new(RwLock::new(IndexMap::new())),
|
||||||
core_test: result,
|
core_test: result,
|
||||||
execution_kind: Default::default(),
|
|
||||||
default_planes: Default::default(),
|
default_planes: Default::default(),
|
||||||
stats: Default::default(),
|
stats: Default::default(),
|
||||||
})
|
})
|
||||||
@ -379,18 +377,6 @@ impl kcl_lib::EngineManager for EngineConnection {
|
|||||||
Arc::new(RwLock::new(Vec::new()))
|
Arc::new(RwLock::new(Vec::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn execution_kind(&self) -> ExecutionKind {
|
|
||||||
let guard = self.execution_kind.read().await;
|
|
||||||
*guard
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn replace_execution_kind(&self, execution_kind: ExecutionKind) -> ExecutionKind {
|
|
||||||
let mut guard = self.execution_kind.write().await;
|
|
||||||
let original = *guard;
|
|
||||||
*guard = execution_kind;
|
|
||||||
original
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_default_planes(&self) -> Arc<RwLock<Option<DefaultPlanes>>> {
|
fn get_default_planes(&self) -> Arc<RwLock<Option<DefaultPlanes>>> {
|
||||||
self.default_planes.clone()
|
self.default_planes.clone()
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ kcl-lib = { path = "../kcl-lib" }
|
|||||||
kittycad = { workspace = true }
|
kittycad = { workspace = true }
|
||||||
kittycad-modeling-cmds = { workspace = true }
|
kittycad-modeling-cmds = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
tokio = { workspace = true, features = ["sync"] }
|
tokio = { workspace = true, features = ["sync", "rt"] }
|
||||||
toml = "0.8.19"
|
toml = "0.8.19"
|
||||||
tower-lsp = { workspace = true, features = ["runtime-agnostic"] }
|
tower-lsp = { workspace = true, features = ["runtime-agnostic"] }
|
||||||
uuid = { workspace = true, features = ["v4", "js", "serde"] }
|
uuid = { workspace = true, features = ["v4", "js", "serde"] }
|
||||||
|
@ -77,7 +77,8 @@ impl Context {
|
|||||||
let program: Program = serde_json::from_str(program_ast_json).map_err(|e| e.to_string())?;
|
let program: Program = serde_json::from_str(program_ast_json).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
let ctx = self.create_executor_ctx(settings, path, false)?;
|
let ctx = self.create_executor_ctx(settings, path, false)?;
|
||||||
match ctx.run_with_caching(program).await {
|
let mut exec_state = kcl_lib::ExecState::new(&ctx);
|
||||||
|
match ctx.run(&program, &mut exec_state).await {
|
||||||
// The serde-wasm-bindgen does not work here because of weird HashMap issues.
|
// The serde-wasm-bindgen does not work here because of weird HashMap issues.
|
||||||
// DO NOT USE serde_wasm_bindgen::to_value it will break the frontend.
|
// DO NOT USE serde_wasm_bindgen::to_value it will break the frontend.
|
||||||
Ok(outcome) => JsValue::from_serde(&outcome).map_err(|e| e.to_string()),
|
Ok(outcome) => JsValue::from_serde(&outcome).map_err(|e| e.to_string()),
|
||||||
|
@ -1965,6 +1965,7 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
range,
|
range,
|
||||||
idToRangeMap,
|
idToRangeMap,
|
||||||
})
|
})
|
||||||
|
console.log("responose to wasm", resp)
|
||||||
return BSON.serialize(resp[0])
|
return BSON.serialize(resp[0])
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user