Skip to content

Commit

Permalink
New StaticMemoryInitializer type (#38)
Browse files Browse the repository at this point in the history
This simplifies initializing EP memory with static data before the program runs.
  • Loading branch information
adamchalmers authored Dec 18, 2023
1 parent aed3aec commit 0c10405
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 101 deletions.
10 changes: 9 additions & 1 deletion execution-plan/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::fmt;
use api_endpoint::ApiEndpoint;
use kittycad_modeling_cmds::{each_cmd, id::ModelingCmdId};
use kittycad_modeling_session::{RunCommandError, Session as ModelingSession};
use memory::Memory;
pub use memory::{Memory, StaticMemoryInitializer};
use serde::{Deserialize, Serialize};

use self::{arithmetic::Arithmetic, primitive::Primitive};
Expand All @@ -28,6 +28,14 @@ mod value;
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct Address(usize);

impl Address {
/// Offset the memory by `size` addresses.
pub fn offset(self, size: usize) -> Self {
let curr = self.0;
Self(curr + size)
}
}

impl fmt::Display for Address {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
Expand Down
33 changes: 33 additions & 0 deletions execution-plan/src/memory.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,38 @@
use super::Result;
use crate::{primitive::Primitive, value::Value, Address};

/// Helper wrapper around Memory. It lets you push static data into memory before the program runs.
pub struct StaticMemoryInitializer {
memory: Memory,
last: Address,
}

impl Default for StaticMemoryInitializer {
fn default() -> Self {
Self {
memory: Default::default(),
last: Address(0),
}
}
}

impl StaticMemoryInitializer {
/// Finish putting static data into memory, get ready to execute the plan.
/// Returns normal execution plan program memory.
pub fn finish(self) -> Memory {
self.memory
}

/// Put the next value into memory.
/// Returns the address that the value was inserted at.
pub fn push<T: Value>(&mut self, val: T) -> Address {
let addr_of_value = self.last;
let len = self.memory.set_composite(self.last, val);
self.last = self.last.offset(len);
addr_of_value
}
}

/// KCEP's program memory. A flat, linear list of values.
#[derive(Debug)]
#[cfg_attr(test, derive(PartialEq))]
Expand Down Expand Up @@ -51,6 +83,7 @@ impl Memory {
T::from_parts(&mut values)
}

/// Iterate over each memory address and its value.
pub fn iter(&self) -> impl Iterator<Item = (usize, &Option<Primitive>)> {
self.addresses.iter().enumerate()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,32 @@ expression: debug_dump_memory(&mem)
indexval_typevalue
├───────┼──────────┼──────────────────────────────────────┤
0Uuid │ 4cd175a3-e313-4c91-b624-368bea3c0483
2Float40
3Booltrue
4Stringpng
1Float40
2Booltrue
3Stringpng
4Float-20
5Float-20
6Float-20
7Float -20
8Float-20
9String line
10Float20
11Float -20
12Float -20
13Bool false
14String line
15Float20
16Float 20
17Float -20
18Bool false
19String line
7String line
8Float20
9Float -20
10Float-20
11Bool false
12String line
13Float 20
14Float 20
15Float-20
16Bool false
17String line
18Float -20
19Float 20
20Float-20
21Float 20
22Float -20
23Bool false
24String line
21Bool false
22String line
23Float -20
24Float -20
25Float-20
26Float-20
27Float-20
28Boolfalse
26Boolfalse
99StringTAKE_SNAPSHOT
100Byteslength 129068
└───────┴──────────┴──────────────────────────────────────┘
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,30 @@ expression: debug_dump_memory(&mem)
indexval_typevalue
├───────┼──────────┼──────────────────────────────────────┤
0Uuid │ 4cd175a3-e313-4c91-b624-368bea3c0483
2Float40
3Booltrue
4Stringpng
1Float40
2Booltrue
3Stringpng
4Float-20
5Float-20
6Float-20
7Float -20
8Float-20
9String line
10Float20
11Float -20
12Float -20
13Bool false
14String line
15Float20
16Float 20
17Float -20
18Bool false
19String line
7String line
8Float20
9Float -20
10Float-20
11Bool false
12String line
13Float 20
14Float 20
15Float-20
16Bool false
17String line
18Float -20
19Float 20
20Float-20
21Float 20
22Float -20
23Bool false
24String line
21Bool false
22String line
23Float -20
24Float -20
25Float-20
26Float-20
27Float-20
28Boolfalse
26Boolfalse
└───────┴──────────┴──────────────────────────────────────┘
82 changes: 28 additions & 54 deletions execution-plan/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,72 +127,46 @@ async fn add_to_composite_value() {

#[tokio::test]
async fn api_call_draw_cube() {
let mut mem = Memory::default();
let client = test_client().await;

const CUBE_WIDTH: f64 = 20.0;

// Define primitives, load them into memory.
let path_id_addr = Address(0);
let mut static_data = StaticMemoryInitializer::default();
let path = ModelingCmdId(Uuid::parse_str("4cd175a3-e313-4c91-b624-368bea3c0483").unwrap());
let cube_height_addr = Address(2);
let cube_height = Primitive::from(CUBE_WIDTH * 2.0);
let cap_addr = Address(3);
let cap = Primitive::Bool(true);
let img_format_addr = Address(4);
let img_format = Primitive::from("png".to_owned());
let path_id_addr = static_data.push(Primitive::from(path.0));
let cube_height_addr = static_data.push(Primitive::from(CUBE_WIDTH * 2.0));
let cap_addr = static_data.push(Primitive::from(true));
let img_format_addr = static_data.push(Primitive::from("png".to_owned()));
let output_addr = Address(99);
mem.set(path_id_addr, Primitive::from(path.0));
mem.set(cube_height_addr, cube_height);
mem.set(cap_addr, cap);
mem.set(img_format_addr, img_format);

// Define composite objects, load them into memory.
let starting_point_addr = Address(6);
let starting_point = Point3d {
x: -CUBE_WIDTH,
y: -CUBE_WIDTH,
z: -CUBE_WIDTH,
};
let point_size = mem.set_composite(starting_point_addr, starting_point);
let next_addr = Address(starting_point_addr.0 + point_size);
let segments =
[
PathSegment::Line {
end: Point3d {
x: CUBE_WIDTH,
y: -CUBE_WIDTH,
z: -CUBE_WIDTH,
},
relative: false,
},
PathSegment::Line {
end: Point3d {
x: CUBE_WIDTH,
y: CUBE_WIDTH,
z: -CUBE_WIDTH,
},
relative: false,
},
PathSegment::Line {
end: Point3d {
x: -CUBE_WIDTH,
y: CUBE_WIDTH,
z: -CUBE_WIDTH,
},
relative: false,
},
PathSegment::Line {
end: starting_point,
relative: false,
},
];
let mut segment_addrs = vec![next_addr];
for segment in segments {
let addr = segment_addrs.last().unwrap();
let size = mem.set_composite(*addr, segment);
segment_addrs.push(Address(addr.0 + size));
}
let starting_point_addr = static_data.push(starting_point);
let line_segment = |end: Point3d<f64>| PathSegment::Line { end, relative: false };
let segments = [
Point3d {
x: CUBE_WIDTH,
y: -CUBE_WIDTH,
z: -CUBE_WIDTH,
},
Point3d {
x: CUBE_WIDTH,
y: CUBE_WIDTH,
z: -CUBE_WIDTH,
},
Point3d {
x: -CUBE_WIDTH,
y: CUBE_WIDTH,
z: -CUBE_WIDTH,
},
starting_point,
]
.map(line_segment);
let segment_addrs = segments.map(|segment| static_data.push(segment));
let mut mem = static_data.finish();
assert_snapshot!("cube_memory_before", debug_dump_memory(&mem));

// Run the plan!
Expand Down

0 comments on commit 0c10405

Please sign in to comment.