aboutsummaryrefslogtreecommitdiff
path: root/src/crates
diff options
context:
space:
mode:
authorAria <me@aria.rip>2023-12-08 18:28:09 +0000
committerAria <me@aria.rip>2023-12-08 18:28:09 +0000
commitd7817691e2f684b425244de7d28d44f03e900a19 (patch)
tree3650c1addb57ee17a6e9c8553daf2cc962f96e20 /src/crates
parent85c57002b70da3a99ae23e6a0502c0b3130e02e4 (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')
-rw-r--r--src/crates/primrose/src/codegen.rs37
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;
"#
)
}