Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor to extract early_generator between high-level intermediate representation and mid-level intermediate representation #2049

Merged
merged 23 commits into from
Jun 8, 2024
Merged
74 changes: 43 additions & 31 deletions frb_codegen/src/library/codegen/dumper/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,56 @@ use strum::IntoEnumIterator;

pub(super) mod internal_config;

pub(crate) struct Dumper<'a>(pub &'a DumperInternalConfig);
#[derive(Clone)]
pub(crate) struct Dumper<'a> {
config: &'a DumperInternalConfig,
content: Option<ConfigDumpContent>,
name_prefix: String,
}

impl Dumper<'_> {
pub(crate) fn dump<T: Serialize>(
&self,
content: ConfigDumpContent,
name: &str,
data: &T,
) -> anyhow::Result<()> {
if !self.is_enabled(content) {
impl<'a> Dumper<'a> {
pub(crate) fn new(config: &'a DumperInternalConfig) -> Self {
Self {
config,
content: None,
name_prefix: "".to_string(),
}
}

pub(crate) fn with_content(&self, content: ConfigDumpContent) -> Self {
Self {
content: Some(content),
..self.clone()
}
}

pub(crate) fn with_add_name_prefix(&self, add_name_prefix: &str) -> Self {
Self {
name_prefix: format!("{}{}", self.name_prefix, add_name_prefix),
..self.clone()
}
}

pub(crate) fn dump<T: Serialize>(&self, name: &str, data: &T) -> anyhow::Result<()> {
if !self.is_enabled() {
return Ok(());
}

self.dump_str(content, name, &serde_json::to_string_pretty(data)?)
self.dump_str(name, &serde_json::to_string_pretty(data)?)
}

pub(crate) fn dump_path_texts(
&self,
content: ConfigDumpContent,
partial_name: &str,
path_texts: &PathTexts,
base_dir: &Path,
) -> anyhow::Result<()> {
if !self.is_enabled(content) {
if !self.is_enabled() {
return Ok(());
}

for path_text in path_texts.0.iter() {
self.dump_str(
content,
&format!(
"{partial_name}/{}",
path_to_string(
Expand All @@ -59,18 +79,16 @@ impl Dumper<'_> {

pub(crate) fn dump_acc(
&self,
content: ConfigDumpContent,
partial_name: &str,
extension: &str,
acc: &Acc<Option<String>>,
) -> anyhow::Result<()> {
if !self.is_enabled(content) {
if !self.is_enabled() {
return Ok(());
}

for target in TargetOrCommon::iter() {
self.dump_str(
content,
&format!("{partial_name}/{target}.{extension}"),
&acc[target].clone().unwrap_or_default(),
)?;
Expand All @@ -79,27 +97,21 @@ impl Dumper<'_> {
Ok(())
}

pub(crate) fn dump_str(
&self,
content: ConfigDumpContent,
name: &str,
str: &str,
) -> anyhow::Result<()> {
if !self.is_enabled(content) {
pub(crate) fn dump_str(&self, partial_name: &str, text: &str) -> anyhow::Result<()> {
if !self.is_enabled() {
return Ok(());
}

let path = self
.0
.dump_directory
.join(content.to_string().to_case(Case::Snake))
.join(name);
let name = format!("{}{}", self.name_prefix, partial_name);
let path = (self.config.dump_directory)
.join(self.content.unwrap().to_string().to_case(Case::Snake))
.join(&name);
debug!("Dumping {name} into {path:?}");

create_dir_all_and_write(path, str)
create_dir_all_and_write(path, text)
}

fn is_enabled(&self, content: ConfigDumpContent) -> bool {
self.0.dump_contents.contains(&content)
fn is_enabled(&self) -> bool {
self.config.dump_contents.contains(&self.content.unwrap())
}
}
10 changes: 5 additions & 5 deletions frb_codegen/src/library/codegen/generator/api_dart/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ pub(crate) fn generate(
dumper: &Dumper,
) -> Result<GeneratorApiDartOutput> {
let spec = spec_generator::generate(mir_pack, config, dumper)?;
dumper.dump(ConfigDumpContent::GeneratorSpec, "api_dart.json", &spec)?;

(dumper.with_content(ConfigDumpContent::GeneratorSpec)).dump("api_dart.json", &spec)?;

let text = text_generator::generate(&spec, config)?;
dumper.dump_path_texts(
ConfigDumpContent::GeneratorText,
(dumper.with_content(ConfigDumpContent::GeneratorText)).dump_path_texts(
"api_dart",
&text.output_texts,
&config.dart_decl_base_output_path,
Expand Down Expand Up @@ -85,13 +85,13 @@ mod tests {
let internal_config = InternalConfig::parse(&config, &MetaConfig { watch: false })?;
let mir_pack = crate::codegen::parser::parse(
&internal_config.parser,
&Dumper(&Default::default()),
&Dumper::new(&Default::default()),
&GeneratorProgressBarPack::new(),
)?;
let actual = generate(
&mir_pack,
&internal_config.generator.api_dart,
&Dumper(&Default::default()),
&Dumper::new(&Default::default()),
)?;

let output_texts = actual.output_texts;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,8 @@ pub(crate) fn generate(
let cache = MirPackComputedCache::compute(mir_pack);
let context = ApiDartGeneratorContext { mir_pack, config };

dumper.dump(
GeneratorInfo,
"api_dart.json",
&generate_dump_info(&cache, context),
)?;
(dumper.with_content(GeneratorInfo))
.dump("api_dart.json", &generate_dump_info(&cache, context))?;

let funcs_with_impl = mir_pack.funcs_with_impl();
let grouped_funcs = (funcs_with_impl.iter()).into_group_map_by(|x| x.name.namespace.clone());
Expand Down
4 changes: 2 additions & 2 deletions frb_codegen/src/library/codegen/generator/wire/c/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ pub(crate) fn generate(
rust_output_texts,
progress_bar_pack,
)?;
dumper.dump(ConfigDumpContent::GeneratorSpec, "wire_c.json", &spec)?;
(dumper.with_content(ConfigDumpContent::GeneratorSpec)).dump("wire_c.json", &spec)?;

let text = text_generator::generate(spec)?;
dumper.dump_str(ConfigDumpContent::GeneratorText, "wire_c/content.h", &text)?;
(dumper.with_content(ConfigDumpContent::GeneratorText)).dump_str("wire_c/content.h", &text)?;

Ok(GeneratorWireCOutput {
output_texts: PathTexts({
Expand Down
5 changes: 2 additions & 3 deletions frb_codegen/src/library/codegen/generator/wire/dart/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,10 @@ pub(crate) fn generate(
dumper,
progress_bar_pack,
)?;
dumper.dump(ConfigDumpContent::GeneratorSpec, "wire_dart.json", &spec)?;
(dumper.with_content(ConfigDumpContent::GeneratorSpec)).dump("wire_dart.json", &spec)?;

let text = text_generator::generate(&spec, context.config)?;
dumper.dump_acc(
ConfigDumpContent::GeneratorText,
(dumper.with_content(ConfigDumpContent::GeneratorText)).dump_acc(
"wire_dart",
"dart",
&text.text.clone().map(|x, _| x.map(|x| x.all_code())),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,8 @@ pub(crate) fn generate(
) -> anyhow::Result<WireDartOutputSpec> {
let cache = MirPackComputedCache::compute(context.mir_pack);

dumper.dump(
GeneratorInfo,
"wire_dart.json",
&generate_dump_info(&cache, context),
)?;
(dumper.with_content(GeneratorInfo))
.dump("wire_dart.json", &generate_dump_info(&cache, context))?;

Ok(WireDartOutputSpec {
misc: misc::generate(
Expand Down
5 changes: 2 additions & 3 deletions frb_codegen/src/library/codegen/generator/wire/rust/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@ pub(crate) fn generate(
dumper: &Dumper,
) -> anyhow::Result<GeneratorWireRustOutput> {
let spec = spec_generator::generate(context, dumper)?;
dumper.dump(ConfigDumpContent::GeneratorSpec, "wire_rust.json", &spec)?;
(dumper.with_content(ConfigDumpContent::GeneratorSpec)).dump("wire_rust.json", &spec)?;

let text = text_generator::generate(&spec, context.config)?;
dumper.dump_acc(
ConfigDumpContent::GeneratorText,
(dumper.with_content(ConfigDumpContent::GeneratorText)).dump_acc(
"wire_rust",
"rs",
&text.text,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,8 @@ pub(super) fn generate(
) -> anyhow::Result<WireRustOutputSpec> {
let cache = MirPackComputedCache::compute(context.mir_pack);

dumper.dump(
GeneratorInfo,
"wire_rust.json",
&generate_dump_info(&cache, context),
)?;
(dumper.with_content(GeneratorInfo))
.dump("wire_rust.json", &generate_dump_info(&cache, context))?;

let dart2rust = WireRustCodecEntrypoint::generate_all(context, &cache, Decode);
let rust2dart = WireRustCodecEntrypoint::generate_all(context, &cache, Encode);
Expand Down
10 changes: 7 additions & 3 deletions frb_codegen/src/library/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ pub fn generate(config: Config, meta_config: MetaConfig) -> anyhow::Result<()> {
let internal_config = InternalConfig::parse(&config, &meta_config)?;
debug!("internal_config={internal_config:?}");

let dumper = Dumper(&internal_config.dumper);
dumper.dump(ContentConfig, "config.json", &config)?;
let dumper = Dumper::new(&internal_config.dumper);
dumper
.with_content(ContentConfig)
.dump("config.json", &config)?;

controller::run(&internal_config.controller, &|| {
generate_once(&internal_config, &dumper)
Expand All @@ -38,7 +40,9 @@ pub fn generate(config: Config, meta_config: MetaConfig) -> anyhow::Result<()> {
fn generate_once(internal_config: &InternalConfig, dumper: &Dumper) -> anyhow::Result<()> {
let progress_bar_pack = GeneratorProgressBarPack::new();

dumper.dump(ContentConfig, "internal_config.json", &internal_config)?;
dumper
.with_content(ContentConfig)
.dump("internal_config.json", &internal_config)?;

preparer::prepare(&internal_config.preparer)?;

Expand Down
27 changes: 27 additions & 0 deletions frb_codegen/src/library/codegen/parser/early_generator/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
pub(crate) mod trait_impl_enum;

use crate::codegen::dumper::Dumper;
use crate::codegen::ir::hir::flat::pack::HirFlatPack;
use crate::codegen::parser::hir::flat::extra_code_injector::inject_extra_code;
use crate::codegen::parser::hir::internal_config::ParserHirInternalConfig;
use crate::codegen::parser::mir;
use crate::codegen::parser::mir::internal_config::ParserMirInternalConfig;

pub(crate) fn execute(
mut pack: HirFlatPack,
config_mir: &ParserMirInternalConfig,
dumper: &Dumper,
) -> anyhow::Result<HirFlatPack> {
let dumper_tentative_mir = dumper.with_add_name_prefix("tentative_mir/");
let tentative_mir_pack = mir::parse(config_mir, &pack, &dumper_tentative_mir)?;

let extra_code = trait_impl_enum::generate(&pack, &tentative_mir_pack)?;

inject_extra_code(
&mut pack,
&extra_code,
&(config_mir.rust_input_namespace_pack).rust_output_path_namespace,
)?;

Ok(pack)
}
Original file line number Diff line number Diff line change
@@ -1,40 +1,32 @@
use crate::codegen::ir::hir::flat::pack::HirFlatPack;
use crate::codegen::ir::hir::flat::traits::HirFlatTrait;
use crate::codegen::ir::mir::pack::MirPack;
use crate::codegen::ir::mir::trait_impl::MirTraitImpl;
use crate::codegen::ir::mir::ty::MirType;
use crate::codegen::parser::hir::flat::extra_code_injector::inject_extra_code;
use crate::codegen::parser::hir::internal_config::ParserHirInternalConfig;
use crate::codegen::parser::mir::parser::attribute::FrbAttributes;
use crate::codegen::parser::mir::parser::function::real::FUNC_PREFIX_FRB_INTERNAL_NO_IMPL;
use crate::codegen::parser::mir::parser::tentative_parse_trait_impls;
use crate::library::codegen::ir::mir::ty::MirTypeTrait;
use convert_case::{Case, Casing};
use itertools::Itertools;
use strum_macros::Display;

pub(crate) fn transform(
mut pack: HirFlatPack,
config: &ParserHirInternalConfig,
) -> anyhow::Result<HirFlatPack> {
let trait_impls = tentative_parse_trait_impls(&pack)?;

let extra_code = (pack.traits.iter())
pub(crate) fn generate(
pack: &HirFlatPack,
tentative_mir_pack: &MirPack,
) -> anyhow::Result<String> {
Ok((pack.traits.iter())
.filter(|x| {
FrbAttributes::parse(&x.attrs)
.unwrap()
.generate_implementor_enum()
})
.sorted_by_key(|x| x.name.clone())
.map(|x| generate_trait_impl_enum(x, &trait_impls))
.map(|x| generate_trait_impl_enum(x, &tentative_mir_pack.trait_impls))
.collect::<anyhow::Result<Vec<_>>>()?
.into_iter()
.join("");

let namespace = &config.rust_input_namespace_pack.rust_output_path_namespace;

inject_extra_code(&mut pack, &extra_code, namespace)?;

Ok(pack)
.join(""))
}

fn generate_trait_impl_enum(
Expand Down
24 changes: 8 additions & 16 deletions frb_codegen/src/library/codegen/parser/hir/flat/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,35 @@ use crate::codegen::dumper::Dumper;
use crate::codegen::ir::hir::flat::pack::HirFlatPack;
use crate::codegen::ir::hir::naive_flat::pack::HirNaiveFlatPack;
use crate::codegen::parser::hir::internal_config::ParserHirInternalConfig;
use crate::codegen::ConfigDumpContent::Hir;

pub(crate) fn parse(
config: &ParserHirInternalConfig,
hir_naive_flat: HirNaiveFlatPack,
dumper: &Dumper,
) -> anyhow::Result<HirFlatPack> {
let pack = parser::pack::parse_pack(config, hir_naive_flat)?;
dump(dumper, "1_parse_pack", &pack)?;
dumper.dump("1_parse_pack", &pack)?;

let pack = transformer::filter_transformer::transform(pack, config)?;
dump(dumper, "2_filter_transformer", &pack)?;
dumper.dump("2_filter_transformer", &pack)?;

let pack = transformer::remove_not_defined_trait_transformer::transform(pack)?;
dump(dumper, "3_remove_not_defined_trait_transformer", &pack)?;
dumper.dump("3_remove_not_defined_trait_transformer", &pack)?;

let pack = transformer::copy_trait_def_to_impl_transformer::transform(pack)?;
dump(dumper, "4_copy_trait_def_to_impl_transformer", &pack)?;
dumper.dump("4_copy_trait_def_to_impl_transformer", &pack)?;

let pack = transformer::function_frb_override_transformer::transform(pack)?;
dump(dumper, "5_function_frb_override_transformer", &pack)?;
dumper.dump("5_function_frb_override_transformer", &pack)?;

let pack = transformer::merge_duplicate_transformer::transform(pack)?;
dump(dumper, "6_merge_duplicate_transformer", &pack)?;
dumper.dump("6_merge_duplicate_transformer", &pack)?;

let pack = transformer::resolve_type_alias_transformer::transform(pack)?;
dump(dumper, "7_resolve_type_alias_transformer", &pack)?;

let pack = transformer::generate_trait_impl_enum_transformer::transform(pack, config)?;
dump(dumper, "8_generate_trait_impl_enum_transformer", &pack)?;
dumper.dump("7_resolve_type_alias_transformer", &pack)?;

let pack = transformer::sort_transformer::transform(pack)?;
dump(dumper, "9_sort_transformer", &pack)?;
dumper.dump("8_sort_transformer", &pack)?;

Ok(pack)
}

fn dump(dumper: &Dumper, name: &str, pack: &HirFlatPack) -> anyhow::Result<()> {
dumper.dump(Hir, &format!("hir_flat/{name}.json"), pack)
}
Loading
Loading