Skip to content

Commit

Permalink
Start using FromMemory macro
Browse files Browse the repository at this point in the history
  • Loading branch information
adamchalmers committed Dec 22, 2023
1 parent 7f83129 commit c08f7ff
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 120 deletions.
50 changes: 37 additions & 13 deletions execution-plan-macros/src/derive_from_memory.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::{quote, quote_spanned};
use syn::{spanned::Spanned, DeriveInput, Fields};
use quote::quote_spanned;
use syn::{spanned::Spanned, DeriveInput, Fields, FieldsNamed};

use crate::helpers::remove_generics_defaults;

Expand All @@ -12,25 +12,49 @@ pub(crate) fn impl_derive_from_memory(input: DeriveInput) -> TokenStream2 {
// Any generics defined on the type deriving Value.
let generics = input.generics;
match input.data {
syn::Data::Struct(data) => impl_on_struct(span, name, data, generics),
syn::Data::Struct(data) => match data.fields {
Fields::Named(expr) => impl_on_struct_named_fields(span, name, expr, generics),
Fields::Unnamed(_) => todo!(),
Fields::Unit => impl_on_struct_no_fields(span, name, generics),
},
_ => quote_spanned! {span =>
compile_error!("Value cannot be implemented on an enum or union type")
},
}
}

fn impl_on_struct(
fn impl_on_struct_no_fields(span: Span, name: proc_macro2::Ident, generics: syn::Generics) -> TokenStream2 {
// Handle generics in the original struct.
// Firstly, if the original struct has defaults on its generics, e.g. Point2d<T = f32>,
// don't include those defaults in this macro's output, because the compiler
// complains it's unnecessary and will soon be a compile error.
let generics_without_defaults = remove_generics_defaults(generics.clone());
let where_clause = generics.where_clause;

// Final return value: the generated Rust code to implement the trait.
// This uses the fragments above, interpolating them into the final outputted code.
quote_spanned! {span=>
impl #generics_without_defaults kittycad_execution_plan_traits::FromMemory for #name #generics_without_defaults
#where_clause
{
fn from_memory<I, M>(_fields: &mut I, _mem: &M) -> Result<Self, kittycad_execution_plan_traits::MemoryError>
where
M: kittycad_execution_plan_traits::ReadMemory,
I: Iterator<Item = M::Address>
{

Ok(Self {})
}
}
}
}

fn impl_on_struct_named_fields(
span: Span,
name: proc_macro2::Ident,
data: syn::DataStruct,
fields: FieldsNamed,
generics: syn::Generics,
) -> proc_macro2::TokenStream {
let Fields::Named(ref fields) = data.fields else {
return quote_spanned! {span =>
compile_error!("Value cannot be implemented on a struct with unnamed fields")
};
};

) -> TokenStream2 {
// We're going to construct some fragments of Rust source code, which will get used in the
// final generated code this function returns.

Expand Down Expand Up @@ -71,7 +95,7 @@ fn impl_on_struct(

// Final return value: the generated Rust code to implement the trait.
// This uses the fragments above, interpolating them into the final outputted code.
quote! {
quote_spanned! {span=>
impl #generics_without_defaults kittycad_execution_plan_traits::FromMemory for #name #generics_without_defaults
#where_clause
{
Expand Down
88 changes: 0 additions & 88 deletions execution-plan/src/api_endpoint.rs

This file was deleted.

4 changes: 1 addition & 3 deletions execution-plan/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@
use std::fmt;

use api_endpoint::ApiEndpoint;
use kittycad_execution_plan_traits::{MemoryError, Primitive};
use kittycad_execution_plan_traits::{FromMemory, MemoryError, Primitive, ReadMemory};
use kittycad_modeling_cmds::{each_cmd, id::ModelingCmdId};
use kittycad_modeling_session::{RunCommandError, Session as ModelingSession};
pub use memory::{Memory, StaticMemoryInitializer};
use serde::{Deserialize, Serialize};

use self::arithmetic::Arithmetic;

mod api_endpoint;
mod arithmetic;
mod memory;
#[cfg(test)]
Expand Down
22 changes: 13 additions & 9 deletions execution-plan/src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,23 @@ impl Default for Memory {
}
}

impl Memory {
impl kittycad_execution_plan_traits::ReadMemory for Memory {
type Address = crate::Address;

/// Get a value from KCEP's program memory.
pub fn get(&self, Address(addr): &Address) -> Option<&Primitive> {
fn get(&self, Address(addr): &Address) -> Option<&Primitive> {
self.addresses[*addr].as_ref()
}

/// 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`.
fn get_composite<T: Value>(&self, start: Address) -> std::result::Result<T, MemoryError> {
let mut values = self.addresses.iter().skip(start.0).cloned();
T::from_parts(&mut values)
}
}

impl Memory {
/// Store a value in KCEP's program memory.
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.
Expand All @@ -77,13 +88,6 @@ impl Memory {
total_addrs
}

/// 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: Value>(&self, start: Address) -> std::result::Result<T, MemoryError> {
let mut values = self.addresses.iter().skip(start.0).cloned();
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
14 changes: 7 additions & 7 deletions modeling-cmds/src/each_cmd.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::HashSet;

use kittycad_execution_plan_macros::ExecutionPlanValue;
use kittycad_execution_plan_macros::{ExecutionPlanFromMemory, ExecutionPlanValue};
use parse_display_derive::{Display, FromStr};
// //! Types for parameters to Modeling API commands.
use schemars::JsonSchema;
Expand All @@ -19,11 +19,11 @@ use crate::{
};

/// Start a new path.
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ExecutionPlanFromMemory)]
pub struct StartPath;

/// Move the path's "pen".
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ExecutionPlanFromMemory)]
pub struct MovePathPen {
/// The ID of the command which created the path.
pub path: ModelingCmdId,
Expand All @@ -33,7 +33,7 @@ pub struct MovePathPen {

/// Extend a path by adding a new segment which starts at the path's "pen".
/// If no "pen" location has been set before (via `MovePen`), then the pen is at the origin.
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ExecutionPlanFromMemory)]
pub struct ExtendPath {
/// The ID of the command which created the path.
pub path: ModelingCmdId,
Expand All @@ -43,7 +43,7 @@ pub struct ExtendPath {
}

/// Command for extruding a solid.
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ExecutionPlanFromMemory)]
pub struct Extrude {
/// Which sketch to extrude.
/// Must be a closed 2D solid.
Expand All @@ -57,7 +57,7 @@ pub struct Extrude {
}

/// Closes a path, converting it to a 2D solid.
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ExecutionPlanFromMemory)]
pub struct ClosePath {
/// Which path to close.
pub path_id: Uuid,
Expand Down Expand Up @@ -538,7 +538,7 @@ pub enum ImageFormat {
}

/// Take a snapshot of the current view.
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ExecutionPlanFromMemory)]
pub struct TakeSnapshot {
/// What image format to return.
pub format: ImageFormat,
Expand Down

0 comments on commit c08f7ff

Please sign in to comment.