Rename Value to Primitive and Composite to Value
This commit is contained in:
		| @ -1,4 +1,4 @@ | ||||
| use crate::value::{NumericValue, Value}; | ||||
| use crate::primitive::{NumericPrimitive, Primitive}; | ||||
| use crate::{ExecutionError, Memory, Operand, Operation}; | ||||
| use serde::{Deserialize, Serialize}; | ||||
|  | ||||
| @ -20,14 +20,20 @@ macro_rules! arithmetic_body { | ||||
|             $arith.operand1.eval(&$mem)?.clone(), | ||||
|         ) { | ||||
|             // If both operands are numeric, then do the arithmetic operation. | ||||
|             (Value::NumericValue(x), Value::NumericValue(y)) => { | ||||
|             (Primitive::NumericValue(x), Primitive::NumericValue(y)) => { | ||||
|                 let num = match (x, y) { | ||||
|                     (NumericValue::Integer(x), NumericValue::Integer(y)) => NumericValue::Integer(x.$method(y)), | ||||
|                     (NumericValue::Integer(x), NumericValue::Float(y)) => NumericValue::Float((x as f64).$method(y)), | ||||
|                     (NumericValue::Float(x), NumericValue::Integer(y)) => NumericValue::Float(x.$method(y as f64)), | ||||
|                     (NumericValue::Float(x), NumericValue::Float(y)) => NumericValue::Float(x.$method(y)), | ||||
|                     (NumericPrimitive::Integer(x), NumericPrimitive::Integer(y)) => { | ||||
|                         NumericPrimitive::Integer(x.$method(y)) | ||||
|                     } | ||||
|                     (NumericPrimitive::Integer(x), NumericPrimitive::Float(y)) => { | ||||
|                         NumericPrimitive::Float((x as f64).$method(y)) | ||||
|                     } | ||||
|                     (NumericPrimitive::Float(x), NumericPrimitive::Integer(y)) => { | ||||
|                         NumericPrimitive::Float(x.$method(y as f64)) | ||||
|                     } | ||||
|                     (NumericPrimitive::Float(x), NumericPrimitive::Float(y)) => NumericPrimitive::Float(x.$method(y)), | ||||
|                 }; | ||||
|                 Ok(Value::NumericValue(num)) | ||||
|                 Ok(Primitive::NumericValue(num)) | ||||
|             } | ||||
|             // This operation can only be done on numeric types. | ||||
|             _ => Err(ExecutionError::CannotApplyOperation { | ||||
| @ -43,7 +49,7 @@ macro_rules! arithmetic_body { | ||||
| impl Arithmetic { | ||||
|     /// Calculate the the arithmetic equation. | ||||
|     /// May read values from the given memory. | ||||
|     pub fn calculate(self, mem: &Memory) -> Result<Value, ExecutionError> { | ||||
|     pub fn calculate(self, mem: &Memory) -> Result<Primitive, ExecutionError> { | ||||
|         use std::ops::{Add, Div, Mul, Sub}; | ||||
|         match self.operation { | ||||
|             Operation::Add => { | ||||
|  | ||||
| @ -1,13 +0,0 @@ | ||||
| use crate::{ExecutionError, Value}; | ||||
|  | ||||
| mod impls; | ||||
|  | ||||
| /// Types that can be written to or read from KCEP program memory, | ||||
| /// but require multiple values to store. | ||||
| /// They get laid out into multiple consecutive memory addresses. | ||||
| pub trait Composite: Sized { | ||||
|     /// Store the value in memory. | ||||
|     fn into_parts(self) -> Vec<Value>; | ||||
|     /// Read the value from memory. | ||||
|     fn from_parts(values: &[Option<Value>]) -> Result<Self, ExecutionError>; | ||||
| } | ||||
| @ -7,13 +7,13 @@ | ||||
| //! the results to make other API calls. | ||||
|  | ||||
| use self::arithmetic::Arithmetic; | ||||
| use self::value::Value; | ||||
| use composite::Composite; | ||||
| use self::primitive::Primitive; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| use std::fmt; | ||||
| use value::Value; | ||||
|  | ||||
| mod arithmetic; | ||||
| mod composite; | ||||
| mod primitive; | ||||
| #[cfg(test)] | ||||
| mod tests; | ||||
| mod value; | ||||
| @ -21,7 +21,7 @@ mod value; | ||||
| /// KCEP's program memory. A flat, linear list of values. | ||||
| #[derive(Debug)] | ||||
| #[cfg_attr(test, derive(PartialEq))] | ||||
| pub struct Memory(Vec<Option<Value>>); | ||||
| pub struct Memory(Vec<Option<Primitive>>); | ||||
|  | ||||
| impl Default for Memory { | ||||
|     fn default() -> Self { | ||||
| @ -47,12 +47,12 @@ impl From<usize> for Address { | ||||
|  | ||||
| impl Memory { | ||||
|     /// Get a value from KCEP's program memory. | ||||
|     pub fn get(&self, Address(addr): &Address) -> Option<&Value> { | ||||
|     pub fn get(&self, Address(addr): &Address) -> Option<&Primitive> { | ||||
|         self.0[*addr].as_ref() | ||||
|     } | ||||
|  | ||||
|     /// Store a value in KCEP's program memory. | ||||
|     pub fn set(&mut self, Address(addr): Address, value: Value) { | ||||
|     pub fn set(&mut self, Address(addr): Address, value: Primitive) { | ||||
|         // If isn't big enough for this value, double the size of memory until it is. | ||||
|         while addr > self.0.len() { | ||||
|             self.0.extend(vec![None; self.0.len()]); | ||||
| @ -60,18 +60,18 @@ impl Memory { | ||||
|         self.0[addr] = Some(value); | ||||
|     } | ||||
|  | ||||
|     /// Store a composite value (i.e. a value which takes up multiple addresses in memory). | ||||
|     /// Store a value value (i.e. a value which takes up multiple addresses in memory). | ||||
|     /// Store its parts in consecutive memory addresses starting at `start`. | ||||
|     pub fn set_composite<T: Composite>(&mut self, composite_value: T, start: Address) { | ||||
|     pub fn set_composite<T: Value>(&mut self, composite_value: T, start: Address) { | ||||
|         let parts = composite_value.into_parts().into_iter(); | ||||
|         for (value, addr) in parts.zip(start.0..) { | ||||
|             self.0[addr] = Some(value); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Get a composite value (i.e. a value which takes up multiple addresses in memory). | ||||
|     /// Get a value value (i.e. a value which takes up multiple addresses in memory). | ||||
|     /// Its parts are stored in consecutive memory addresses starting at `start`. | ||||
|     pub fn get_composite<T: Composite>(&self, start: Address) -> Result<T, ExecutionError> { | ||||
|     pub fn get_composite<T: Value>(&self, start: Address) -> Result<T, ExecutionError> { | ||||
|         let values = &self.0[start.0..]; | ||||
|         T::from_parts(values) | ||||
|     } | ||||
| @ -83,7 +83,7 @@ pub enum Instruction { | ||||
|     /// Call the KittyCAD API. | ||||
|     ApiRequest { | ||||
|         /// Which ModelingCmd to call. | ||||
|         /// It's a composite value starting at the given address. | ||||
|         /// It's a value value starting at the given address. | ||||
|         endpoint: Address, | ||||
|         /// Which address should the response be stored in? | ||||
|         store_response: Option<usize>, | ||||
| @ -95,7 +95,7 @@ pub enum Instruction { | ||||
|         /// Which memory address to set. | ||||
|         address: Address, | ||||
|         /// What value to set the memory address to. | ||||
|         value: Value, | ||||
|         value: Primitive, | ||||
|     }, | ||||
|     /// Perform arithmetic on values in memory. | ||||
|     Arithmetic { | ||||
| @ -130,13 +130,13 @@ impl fmt::Display for Operation { | ||||
| /// Argument to an operation. | ||||
| #[derive(Deserialize, Serialize)] | ||||
| pub enum Operand { | ||||
|     Literal(Value), | ||||
|     Literal(Primitive), | ||||
|     Reference(Address), | ||||
| } | ||||
|  | ||||
| impl Operand { | ||||
|     /// Evaluate the operand, getting its value. | ||||
|     fn eval(&self, mem: &Memory) -> Result<Value, ExecutionError> { | ||||
|     fn eval(&self, mem: &Memory) -> Result<Primitive, ExecutionError> { | ||||
|         match self { | ||||
|             Operand::Literal(v) => Ok(v.to_owned()), | ||||
|             Operand::Reference(addr) => match mem.get(addr) { | ||||
| @ -173,7 +173,7 @@ pub enum ExecutionError { | ||||
|     #[error("Memory address {addr} was not set")] | ||||
|     MemoryEmpty { addr: Address }, | ||||
|     #[error("Cannot apply operation {op} to operands {operands:?}")] | ||||
|     CannotApplyOperation { op: Operation, operands: Vec<Value> }, | ||||
|     CannotApplyOperation { op: Operation, operands: Vec<Primitive> }, | ||||
|     #[error("Tried to read a '{expected}' from KCEP program memory, found an '{actual}' instead")] | ||||
|     MemoryWrongType { expected: &'static str, actual: String }, | ||||
|     #[error("Wanted {expected} values but did not get enough")] | ||||
|  | ||||
							
								
								
									
										87
									
								
								src/wasm-lib/execution-plan/src/primitive.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/wasm-lib/execution-plan/src/primitive.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,87 @@ | ||||
| use crate::ExecutionError; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| use uuid::Uuid; | ||||
|  | ||||
| /// A value stored in KCEP program memory. | ||||
| #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] | ||||
| pub enum Primitive { | ||||
|     String(String), | ||||
|     NumericValue(NumericPrimitive), | ||||
|     Uuid(Uuid), | ||||
| } | ||||
|  | ||||
| impl From<Uuid> for Primitive { | ||||
|     fn from(u: Uuid) -> Self { | ||||
|         Self::Uuid(u) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<String> for Primitive { | ||||
|     fn from(value: String) -> Self { | ||||
|         Self::String(value) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<f64> for Primitive { | ||||
|     fn from(value: f64) -> Self { | ||||
|         Self::NumericValue(NumericPrimitive::Float(value)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl TryFrom<Primitive> for String { | ||||
|     type Error = ExecutionError; | ||||
|  | ||||
|     fn try_from(value: Primitive) -> Result<Self, Self::Error> { | ||||
|         if let Primitive::String(s) = value { | ||||
|             Ok(s) | ||||
|         } else { | ||||
|             Err(ExecutionError::MemoryWrongType { | ||||
|                 expected: "string", | ||||
|                 actual: format!("{value:?}"), | ||||
|             }) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl TryFrom<Primitive> for Uuid { | ||||
|     type Error = ExecutionError; | ||||
|  | ||||
|     fn try_from(value: Primitive) -> Result<Self, Self::Error> { | ||||
|         if let Primitive::Uuid(u) = value { | ||||
|             Ok(u) | ||||
|         } else { | ||||
|             Err(ExecutionError::MemoryWrongType { | ||||
|                 expected: "uuid", | ||||
|                 actual: format!("{value:?}"), | ||||
|             }) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl TryFrom<Primitive> for f64 { | ||||
|     type Error = ExecutionError; | ||||
|  | ||||
|     fn try_from(value: Primitive) -> Result<Self, Self::Error> { | ||||
|         if let Primitive::NumericValue(NumericPrimitive::Float(x)) = value { | ||||
|             Ok(x) | ||||
|         } else { | ||||
|             Err(ExecutionError::MemoryWrongType { | ||||
|                 expected: "float", | ||||
|                 actual: format!("{value:?}"), | ||||
|             }) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(test)] | ||||
| impl From<usize> for Primitive { | ||||
|     fn from(value: usize) -> Self { | ||||
|         Self::NumericValue(NumericPrimitive::Integer(value)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] | ||||
| pub enum NumericPrimitive { | ||||
|     Integer(usize), | ||||
|     Float(f64), | ||||
| } | ||||
| @ -1,87 +1,13 @@ | ||||
| use crate::ExecutionError; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| use uuid::Uuid; | ||||
| use crate::{ExecutionError, Primitive}; | ||||
|  | ||||
| /// A value stored in KCEP program memory. | ||||
| #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] | ||||
| pub enum Value { | ||||
|     String(String), | ||||
|     NumericValue(NumericValue), | ||||
|     Uuid(Uuid), | ||||
| } | ||||
|  | ||||
| impl From<Uuid> for Value { | ||||
|     fn from(u: Uuid) -> Self { | ||||
|         Self::Uuid(u) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<String> for Value { | ||||
|     fn from(value: String) -> Self { | ||||
|         Self::String(value) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<f64> for Value { | ||||
|     fn from(value: f64) -> Self { | ||||
|         Self::NumericValue(NumericValue::Float(value)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl TryFrom<Value> for String { | ||||
|     type Error = ExecutionError; | ||||
|  | ||||
|     fn try_from(value: Value) -> Result<Self, Self::Error> { | ||||
|         if let Value::String(s) = value { | ||||
|             Ok(s) | ||||
|         } else { | ||||
|             Err(ExecutionError::MemoryWrongType { | ||||
|                 expected: "string", | ||||
|                 actual: format!("{value:?}"), | ||||
|             }) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl TryFrom<Value> for Uuid { | ||||
|     type Error = ExecutionError; | ||||
|  | ||||
|     fn try_from(value: Value) -> Result<Self, Self::Error> { | ||||
|         if let Value::Uuid(u) = value { | ||||
|             Ok(u) | ||||
|         } else { | ||||
|             Err(ExecutionError::MemoryWrongType { | ||||
|                 expected: "uuid", | ||||
|                 actual: format!("{value:?}"), | ||||
|             }) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl TryFrom<Value> for f64 { | ||||
|     type Error = ExecutionError; | ||||
|  | ||||
|     fn try_from(value: Value) -> Result<Self, Self::Error> { | ||||
|         if let Value::NumericValue(NumericValue::Float(x)) = value { | ||||
|             Ok(x) | ||||
|         } else { | ||||
|             Err(ExecutionError::MemoryWrongType { | ||||
|                 expected: "float", | ||||
|                 actual: format!("{value:?}"), | ||||
|             }) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(test)] | ||||
| impl From<usize> for Value { | ||||
|     fn from(value: usize) -> Self { | ||||
|         Self::NumericValue(NumericValue::Integer(value)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] | ||||
| pub enum NumericValue { | ||||
|     Integer(usize), | ||||
|     Float(f64), | ||||
| mod impls; | ||||
|  | ||||
| /// Types that can be written to or read from KCEP program memory. | ||||
| /// If they require multiple memory addresses, they will be laid out | ||||
| /// into multiple consecutive memory addresses. | ||||
| pub trait Value: Sized { | ||||
|     /// Store the value in memory. | ||||
|     fn into_parts(self) -> Vec<Primitive>; | ||||
|     /// Read the value from memory. | ||||
|     fn from_parts(values: &[Option<Primitive>]) -> Result<Self, ExecutionError>; | ||||
| } | ||||
|  | ||||
| @ -1,21 +1,21 @@ | ||||
| use kittycad_modeling_cmds::{id::ModelingCmdId, shared::Point3d, MovePathPen}; | ||||
| use uuid::Uuid; | ||||
| 
 | ||||
| use crate::{Address, ExecutionError, Value}; | ||||
| use crate::{Address, ExecutionError, Primitive}; | ||||
| 
 | ||||
| use super::Composite; | ||||
| use super::Value; | ||||
| 
 | ||||
| impl<T> Composite for kittycad_modeling_cmds::shared::Point3d<T> | ||||
| impl<T> Value for kittycad_modeling_cmds::shared::Point3d<T> | ||||
| where | ||||
|     Value: From<T>, | ||||
|     T: TryFrom<Value, Error = ExecutionError>, | ||||
|     Primitive: From<T>, | ||||
|     T: TryFrom<Primitive, Error = ExecutionError>, | ||||
| { | ||||
|     fn into_parts(self) -> Vec<Value> { | ||||
|     fn into_parts(self) -> Vec<Primitive> { | ||||
|         let points = [self.x, self.y, self.z]; | ||||
|         points.into_iter().map(|component| component.into()).collect() | ||||
|     } | ||||
| 
 | ||||
|     fn from_parts(values: &[Option<Value>]) -> Result<Self, ExecutionError> { | ||||
|     fn from_parts(values: &[Option<Primitive>]) -> Result<Self, ExecutionError> { | ||||
|         let err = ExecutionError::MemoryWrongSize { expected: 3 }; | ||||
|         let [x, y, z] = [0, 1, 2].map(|n| values.get(n).ok_or(err.clone())); | ||||
|         let x = x?.to_owned().ok_or(err.clone())?.try_into()?; | ||||
| @ -28,17 +28,17 @@ where | ||||
| const START_PATH: &str = "StartPath"; | ||||
| const MOVE_PATH_PEN: &str = "MovePathPen"; | ||||
| 
 | ||||
| impl Composite for MovePathPen { | ||||
|     fn into_parts(self) -> Vec<Value> { | ||||
| impl Value for MovePathPen { | ||||
|     fn into_parts(self) -> Vec<Primitive> { | ||||
|         let MovePathPen { path, to } = self; | ||||
|         let to = to.into_parts(); | ||||
|         let mut vals = Vec::with_capacity(1 + to.len()); | ||||
|         vals.push(Value::Uuid(path.into())); | ||||
|         vals.push(Primitive::Uuid(path.into())); | ||||
|         vals.extend(to); | ||||
|         vals | ||||
|     } | ||||
| 
 | ||||
|     fn from_parts(values: &[Option<Value>]) -> Result<Self, ExecutionError> { | ||||
|     fn from_parts(values: &[Option<Primitive>]) -> Result<Self, ExecutionError> { | ||||
|         let path = get_some(values, 0)?; | ||||
|         let path = Uuid::try_from(path)?; | ||||
|         let path = ModelingCmdId::from(path); | ||||
| @ -51,14 +51,14 @@ impl Composite for MovePathPen { | ||||
| /// Memory layout for modeling commands:
 | ||||
| /// Field 0 is the command's name.
 | ||||
| /// Fields 1 onwards are the command's fields.
 | ||||
| impl Composite for kittycad_modeling_cmds::ModelingCmd { | ||||
|     fn into_parts(self) -> Vec<Value> { | ||||
| impl Value for kittycad_modeling_cmds::ModelingCmd { | ||||
|     fn into_parts(self) -> Vec<Primitive> { | ||||
|         let (endpoint_name, params) = match self { | ||||
|             kittycad_modeling_cmds::ModelingCmd::StartPath => (START_PATH, vec![]), | ||||
|             kittycad_modeling_cmds::ModelingCmd::MovePathPen(MovePathPen { path, to }) => { | ||||
|                 let to = to.into_parts(); | ||||
|                 let mut vals = Vec::with_capacity(1 + to.len()); | ||||
|                 vals.push(Value::Uuid(path.into())); | ||||
|                 vals.push(Primitive::Uuid(path.into())); | ||||
|                 vals.extend(to); | ||||
|                 (MOVE_PATH_PEN, vals) | ||||
|             } | ||||
| @ -70,7 +70,7 @@ impl Composite for kittycad_modeling_cmds::ModelingCmd { | ||||
|         out | ||||
|     } | ||||
| 
 | ||||
|     fn from_parts(values: &[Option<Value>]) -> Result<Self, ExecutionError> { | ||||
|     fn from_parts(values: &[Option<Primitive>]) -> Result<Self, ExecutionError> { | ||||
|         // Check the array has an element at index 0
 | ||||
|         let first_memory = values | ||||
|             .get(0) | ||||
| @ -90,7 +90,7 @@ impl Composite for kittycad_modeling_cmds::ModelingCmd { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn get_some(values: &[Option<Value>], i: usize) -> Result<Value, ExecutionError> { | ||||
| fn get_some(values: &[Option<Primitive>], i: usize) -> Result<Primitive, ExecutionError> { | ||||
|     let addr = Address(0); // TODO: pass the `start` addr in
 | ||||
|     let v = values.get(i).ok_or(ExecutionError::MemoryEmpty { addr })?.to_owned(); | ||||
|     let v = v.ok_or(ExecutionError::MemoryEmpty { addr })?.to_owned(); | ||||
		Reference in New Issue
	
	Block a user