Skip to content

Commit

Permalink
tags are globals (#2795)
Browse files Browse the repository at this point in the history
* tags are globals

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* A snapshot a day keeps the bugs away! πŸ“·πŸ› (OS: ubuntu)

* empty

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
jessfraz and github-actions[bot] authored Jun 25, 2024
1 parent d7e36ee commit 8fe2d33
Show file tree
Hide file tree
Showing 17 changed files with 216 additions and 25 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/wasm-lib/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/wasm-lib/kcl/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "kcl-lib"
description = "KittyCAD Language implementation and tools"
version = "0.1.66"
version = "0.1.67"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"
Expand Down
28 changes: 17 additions & 11 deletions src/wasm-lib/kcl/src/ast/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1232,28 +1232,34 @@ impl CallExpression {
source_ranges: vec![self.into()],
})
})?;
let result = result.get_value()?;

let result = result.get_value()?;
Ok(result)
}
FunctionKind::UserDefined => {
let func = memory.get(&fn_name, self.into())?;
let result = func
.call_fn(fn_args, memory.clone(), ctx.clone())
.await
.map_err(|e| {
let (result, global_memory_items) =
func.call_fn(fn_args, memory.clone(), ctx.clone()).await.map_err(|e| {
// Add the call expression to the source ranges.
e.add_source_ranges(vec![self.into()])
})?
.ok_or_else(|| {
KclError::UndefinedValue(KclErrorDetails {
message: format!("Result of user-defined function {} is undefined", fn_name),
source_ranges: vec![self.into()],
})
})?;

let result = result.ok_or_else(|| {
KclError::UndefinedValue(KclErrorDetails {
message: format!("Result of user-defined function {} is undefined", fn_name),
source_ranges: vec![self.into()],
})
})?;
let result = result.get_value()?;

// Add the global memory items to the memory.
for (key, item) in global_memory_items {
// We don't care about errors here because any collisions
// would happened in the function call itself and already
// errored out.
memory.add(&key, item, self.into()).unwrap_or_default();
}

Ok(result)
}
}
Expand Down
53 changes: 41 additions & 12 deletions src/wasm-lib/kcl/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,18 @@ impl ProgramMemory {
})
.collect()
}

/// Get all TagDeclarators and TagIdentifiers in the memory.
pub fn get_tags(&self) -> HashMap<String, MemoryItem> {
self.root
.values()
.filter_map(|item| match item {
MemoryItem::TagDeclarator(t) => Some((t.name.to_string(), item.clone())),
MemoryItem::TagIdentifier(t) => Some((t.value.to_string(), item.clone())),
_ => None,
})
.collect::<HashMap<String, MemoryItem>>()
}
}

impl Default for ProgramMemory {
Expand Down Expand Up @@ -525,14 +537,17 @@ impl std::hash::Hash for TagIdentifier {
}
}

pub type MemoryFunction =
fn(
s: Vec<MemoryItem>,
memory: ProgramMemory,
expression: Box<FunctionExpression>,
metadata: Vec<Metadata>,
ctx: ExecutorContext,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Option<ProgramReturn>, KclError>> + Send>>;
pub type MemoryFunction = fn(
s: Vec<MemoryItem>,
memory: ProgramMemory,
expression: Box<FunctionExpression>,
metadata: Vec<Metadata>,
ctx: ExecutorContext,
) -> std::pin::Pin<
Box<
dyn std::future::Future<Output = Result<(Option<ProgramReturn>, HashMap<String, MemoryItem>), KclError>> + Send,
>,
>;

fn force_memory_function<
F: Fn(
Expand All @@ -541,7 +556,12 @@ fn force_memory_function<
Box<FunctionExpression>,
Vec<Metadata>,
ExecutorContext,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Option<ProgramReturn>, KclError>> + Send>>,
) -> std::pin::Pin<
Box<
dyn std::future::Future<Output = Result<(Option<ProgramReturn>, HashMap<String, MemoryItem>), KclError>>
+ Send,
>,
>,
>(
f: F,
) -> F {
Expand Down Expand Up @@ -686,7 +706,7 @@ impl MemoryItem {
args: Vec<MemoryItem>,
memory: ProgramMemory,
ctx: ExecutorContext,
) -> Result<Option<ProgramReturn>, KclError> {
) -> Result<(Option<ProgramReturn>, HashMap<String, MemoryItem>), KclError> {
let MemoryItem::Function { func, expression, meta } = &self else {
return Err(KclError::Semantic(KclErrorDetails {
message: "not a in memory function".to_string(),
Expand Down Expand Up @@ -1500,7 +1520,16 @@ impl ExecutorContext {
}
FunctionKind::UserDefined => {
if let Some(func) = memory.clone().root.get(&fn_name) {
let result = func.call_fn(args.clone(), memory.clone(), self.clone()).await?;
let (result, global_memory_items) =
func.call_fn(args.clone(), memory.clone(), self.clone()).await?;

// Add the global memory items to the memory.
for (key, item) in global_memory_items {
// We don't care about errors here because any collisions
// would happened in the function call itself and already
// errored out.
memory.add(&key, item, call_expr.into()).unwrap_or_default();
}

memory.return_ = result;
} else {
Expand Down Expand Up @@ -1625,7 +1654,7 @@ impl ExecutorContext {
.inner_execute(function_expression.body.clone(), &mut fn_memory, BodyType::Block)
.await?;

Ok(result.return_)
Ok((result.return_, fn_memory.get_tags()))
})
},
);
Expand Down
149 changes: 149 additions & 0 deletions src/wasm-lib/tests/executor/inputs/global-tags.kcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// A mounting bracket for the Focusrite Scarlett Solo audio interface
// This is a bracket that holds an audio device underneath a desk or shelf. The audio device has dimensions of 144mm wide, 80mm length and 45mm depth with fillets of 6mm. This mounting bracket is designed to be 3D printed with PLA material

// define constants in mm
const radius = 6.0
const width = 144.0
const length = 80.0
const depth = 45.0
const thk = 4
const holeDiam = 5
const tabLength = 25
const tabWidth = 12
const tabThk = 4

// define a rectangular shape func
fn rectShape = (pos, w, l) => {
const rr = startSketchOn('xy')
|> startProfileAt([pos[0] - (w / 2), pos[1] - (l / 2)], %)
|> lineTo([pos[0] + w / 2, pos[1] - (l / 2)], %, "edge01")
|> lineTo([pos[0] + w / 2, pos[1] + l / 2], %, "edge02")
|> lineTo([pos[0] - (w / 2), pos[1] + l / 2], %, "edge03")
|> close(%, "edge04")
return rr
}

// define the bracket plane
const bracketPlane = {
plane: {
origin: { x: 0, y: length / 2 + thk, z: 0 },
x_axis: { x: 1, y: 0, z: 0 },
y_axis: { x: 0, y: 0, z: 1 },
z_axis: { x: 0, y: -1, z: 0 }
}
}

// build the bracket sketch around the body
fn bracketSketch = (w, d, t) => {
const s = startSketchOn(bracketPlane)
|> startProfileAt([-w / 2 - t, d + t], %)
|> lineTo([-w / 2 - t, -t], %, "edge1")
|> lineTo([w / 2 + t, -t], %, "edge2")
|> lineTo([w / 2 + t, d + t], %, "edge3")
|> lineTo([w / 2, d + t], %, "edge4")
|> lineTo([w / 2, 0], %, "edge5")
|> lineTo([-w / 2, 0], %, "edge6")
|> lineTo([-w / 2, d + t], %, "edge7")
|> close(%, "edge8")
return s
}

// build the body of the bracket
const bracketBody = bracketSketch(width, depth, thk)
|> extrude(length + 2 * thk, %)
|> fillet({
radius: radius,
tags: [
getNextAdjacentEdge("edge7", %),
getNextAdjacentEdge("edge2", %),
getNextAdjacentEdge("edge3", %),
getNextAdjacentEdge("edge6", %)
]
}, %)

// define the tab plane
const tabPlane = {
plane: {
origin: { x: 0, y: 0, z: depth + thk },
x_axis: { x: 1, y: 0, z: 0 },
y_axis: { x: 0, y: 1, z: 0 },
z_axis: { x: 0, y: 0, z: 1 }
}
}

// build the tabs of the mounting bracket (right side)
const tabsR = startSketchOn(tabPlane)
|> startProfileAt([width / 2 + thk, length / 2 + thk], %)
|> line([tabWidth, -tabLength / 3], %, "edge11")
|> line([0, -tabLength / 3 * 2], %, "edge12")
|> line([-tabWidth, -tabLength / 3], %, "edge13")
|> close(%, "edge14")
|> hole(circle([
width / 2 + thk + tabWidth / 2,
length / 2 + thk - (tabLength / (3 / 2))
], holeDiam / 2, %), %)
|> extrude(-tabThk, %)
|> fillet({
radius: holeDiam / 2,
tags: [
getNextAdjacentEdge("edge12", %),
getNextAdjacentEdge("edge13", %)
]
}, %)
|> patternLinear3d({
axis: [0, -1, 0],
repetitions: 1,
distance: length + 2 * thk - (tabLength * 4 / 3)
}, %)

// build the tabs of the mounting bracket (left side)
const tabsL = startSketchOn(tabPlane)
|> startProfileAt([-width / 2 - thk, length / 2 + thk], %)
|> line([-tabWidth, -tabLength / 3], %, "edge21")
|> line([0, -tabLength / 3 * 2], %, "edge22")
|> line([tabWidth, -tabLength / 3], %, "edge23")
|> close(%, "edge24")
|> hole(circle([
-width / 2 - thk - (tabWidth / 2),
length / 2 + thk - (tabLength / (3 / 2))
], holeDiam / 2, %), %)
|> extrude(-tabThk, %)
|> fillet({
radius: holeDiam / 2,
tags: [
getNextAdjacentEdge("edge21", %),
getNextAdjacentEdge("edge22", %)
]
}, %)
|> patternLinear3d({
axis: [0, -1, 0],
repetitions: 1,
distance: length + 2 * thk - (tabLength * 4 / 3)
}, %)

// define a plane for retention bumps
const retPlane = {
plane: {
origin: { x: -width / 2 + 20, y: 0, z: 0 },
x_axis: { x: 0, y: 1, z: 0 },
y_axis: { x: 0, y: 0, z: 1 },
z_axis: { x: 1, y: 0, z: 0 }
}
}

// build the retention bump in the front
const retFront = startSketchOn(retPlane)
|> startProfileAt([-length / 2 - thk, 0], %)
|> line([0, thk], %)
|> line([thk, -thk], %)
|> close(%)
|> extrude(width - 40, %)

// build the retention bump in the back
const retBack = startSketchOn(retPlane)
|> startProfileAt([length / 2 + thk, 0], %)
|> line([0, thk], %)
|> line([-thk, 0], %)
|> line([0, -thk], %)
|> close(%)
|> extrude(width - 40, %)
7 changes: 7 additions & 0 deletions src/wasm-lib/tests/executor/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2457,3 +2457,10 @@ let p = triangle(200)
r#"value already defined: KclErrorDetails { source_ranges: [SourceRange([317, 319]), SourceRange([332, 345])], message: "Cannot redefine `a`" }"#
);
}

#[tokio::test(flavor = "multi_thread")]
async fn serial_test_global_tags() {
let code = include_str!("inputs/global-tags.kcl");
let result = execute_and_snapshot(code, UnitLength::Mm).await.unwrap();
twenty_twenty::assert_image("tests/executor/outputs/global_tags.png", &result, 0.999);
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 8fe2d33

Please sign in to comment.