diff options
author | Aria <me@aria.rip> | 2023-12-08 18:28:09 +0000 |
---|---|---|
committer | Aria <me@aria.rip> | 2023-12-08 18:28:09 +0000 |
commit | d7817691e2f684b425244de7d28d44f03e900a19 (patch) | |
tree | 3650c1addb57ee17a6e9c8553daf2cc962f96e20 /src/crates/primrose | |
parent | 85c57002b70da3a99ae23e6a0502c0b3130e02e4 (diff) |
fix(primrose): fix code generation using opaque types
this requires an unstable feature unfortunately, but is still
preferable to Box<dyn> for now.
Diffstat (limited to 'src/crates/primrose')
-rw-r--r-- | src/crates/primrose/src/codegen.rs | 37 |
1 files changed, 16 insertions, 21 deletions
diff --git a/src/crates/primrose/src/codegen.rs b/src/crates/primrose/src/codegen.rs index d56c2b3..206f034 100644 --- a/src/crates/primrose/src/codegen.rs +++ b/src/crates/primrose/src/codegen.rs @@ -9,7 +9,6 @@ use crate::{ const CODEGEN: &str = "/*CODEGEN*/\n"; const CODEGENEND: &str = "/*ENDCODEGEN*/\n"; const TRAITCRATE: &str = "primrose_library::traits::"; -const IMPORT: &str = "use primrose_library::traits::ContainerConstructor;\n"; impl ContainerSelector { /// Generate replacement code for the whole file, with the given `(tag_id, selection)` pairs. @@ -20,6 +19,11 @@ impl ContainerSelector { selections: T, ) -> String { let mut result = String::new(); + + result += CODEGEN; + result += &self.bounds_decl; + result += CODEGENEND; + for (tag_id, selection) in selections { result += &self.gen_replacement_code(tag_id, selection); } @@ -41,16 +45,14 @@ impl ContainerSelector { pub fn gen_replacement_code(&self, tag_id: &String, selection: &str) -> String { let tag = self.analyser.ctx().get(tag_id).expect("invalid tag_id"); - let Tag::Con(elem_ty, i_name, _tags) = tag else { + let Tag::Con(elem_ty, _, _) = tag else { panic!("tag_id was not Tag::Con"); }; // generated code at top let mut result = String::new(); result += CODEGEN; - result += IMPORT; - result += &self.bounds_decl; - result += &gen_output_code(tag_id, elem_ty, selection, i_name); + result += &gen_output_code(tag_id, elem_ty, selection); result += CODEGENEND; result @@ -58,18 +60,12 @@ impl ContainerSelector { } // TODO: Constructing a box like this is inefficient, and might affect performance of some programs -fn gen_output_code(s: &str, elem_type: &str, chosen: &str, trait_name: &str) -> String { +fn gen_output_code(s: &str, elem_type: &str, chosen: &str) -> String { format!( - r#"struct {s}<{elem_type}> {{ - elem_t: core::marker::PhantomData<{elem_type}>, -}} - -impl<{elem_type}: 'static + Ord + std::hash::Hash> ContainerConstructor for {s}<{elem_type}> {{ - type Impl = {chosen}<{elem_type}>; - type Bound = dyn {trait_name}<{elem_type}>; - fn new() -> Box<Self::Bound> {{ - Box::new(Self::Impl::new()) - }} + r#" +#[allow(non_snake_case)] +fn _{s}<{elem_type}: PartialEq>() -> {s}<{elem_type}> {{ + {chosen}::<{elem_type}>::default() }} "# ) @@ -77,7 +73,7 @@ impl<{elem_type}: 'static + Ord + std::hash::Hash> ContainerConstructor for {s}< pub fn process_bound_decl(ctx: &InforMap) -> String { let mut code = String::new(); - for (id, tag) in ctx.iter() { + for (_, tag) in ctx.iter() { match tag { Tag::Bound((c, t), decs) => { let traits = decs @@ -85,7 +81,7 @@ pub fn process_bound_decl(ctx: &InforMap) -> String { .map(|name| process_bound_elem_ty(name, t)) .collect::<Vec<String>>() .join(" + "); - code = code + &gen_trait_code(id, c, t, &traits); + code = code + &gen_trait_code(c, t, &traits); } _ => continue, } @@ -94,11 +90,10 @@ pub fn process_bound_decl(ctx: &InforMap) -> String { code } -fn gen_trait_code(trait_name: &str, s: &str, elem_type: &str, traits: &str) -> String { +fn gen_trait_code(typ_name: &str, elem_type: &str, traits: &str) -> String { format!( r#" -trait {trait_name}<{elem_type}> : {traits} {{}} -impl<{elem_type}: 'static + Ord + std::hash::Hash> {trait_name}<{elem_type}> for <{s}<{elem_type}> as ContainerConstructor>::Impl {{}} +pub type {typ_name}<{elem_type}: PartialEq> = impl {traits} + Default; "# ) } |