diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index 6d9b007..7ca04a5 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -3,7 +3,7 @@ pub mod expr; pub mod statement; pub mod top_level; -use std::path::PathBuf; +use std::{collections::HashMap, path::PathBuf}; use mist_parser::{ ast::*, @@ -26,9 +26,15 @@ pub trait GetRust { } } +pub enum Include { + Glob(Path), + Use(Visibility, Path), +} + pub struct RustCodegen { output: String, indent: usize, + pub crates: HashMap>, pub mapping: Mapping, position: RustMap, } @@ -38,6 +44,7 @@ impl RustCodegen { Self { output: String::new(), indent: 0, + crates: HashMap::new(), mapping: Mapping::new(mist_path), position: RustMap(1, 0), } @@ -84,6 +91,39 @@ impl RustCodegen { tl.gen_rust(&mut ctx, self); } + let mut crates = HashMap::new(); + std::mem::swap(&mut self.crates, &mut crates); + + for (c, items) in crates { + self.add("mod "); + c.gen_rust(&mut ctx, self); + self.addln(" {"); + self.indent += 1; + + self.add_indented("extern crate "); + c.gen_rust(&mut ctx, self); + self.addln(";"); + + for item in items { + self.add_indentedln("#[doc(inline)]"); + self.add_indented("pub use "); + match item { + Include::Glob(item) => { + item.gen_rust(&mut ctx, self); + self.add("::*"); + } + Include::Use(vis, item) => { + vis.gen_rust(&mut ctx, self); + item.gen_rust(&mut ctx, self); + } + } + self.addln(";"); + } + + self.indent -= 1; + self.addln("}"); + } + self.output.clone() } diff --git a/crates/codegen/src/top_level.rs b/crates/codegen/src/top_level.rs index 004a42b..bbe1490 100644 --- a/crates/codegen/src/top_level.rs +++ b/crates/codegen/src/top_level.rs @@ -326,6 +326,23 @@ impl GenRust for TopLevelKind { constructor, items, ), + Self::IncludeGlobal(incl) => { + cg.crates + .entry(incl.0[0].clone()) + .or_insert(Vec::new()) + .push(crate::Include::Glob(incl.clone())); + } + Self::IncludeUse(vis, incl) => { + cg.crates + .entry(incl.0[0].clone()) + .or_insert(Vec::new()) + .push(crate::Include::Use(vis.clone(), incl.clone())); + } + Self::IncludeLocal(path) => { + cg.add("include!(\""); + cg.add(&path.replace(".mist", ".rs")); + cg.add("\");"); + } } } } diff --git a/crates/parser/src/ast/top_level.rs b/crates/parser/src/ast/top_level.rs index 1762de9..2e95aed 100644 --- a/crates/parser/src/ast/top_level.rs +++ b/crates/parser/src/ast/top_level.rs @@ -28,6 +28,9 @@ pub struct TopLevel(pub Spanned, pub Vec); pub enum TopLevelKind { ModAttribute, Import(Visibility, Path), + IncludeGlobal(Path), + IncludeUse(Visibility, Path), + IncludeLocal(String), DeclareModule(Visibility, Identifier), ImplDecl(ImplDecl), StaticDecl(VarDeclStmt), diff --git a/crates/parser/src/grammar.pest b/crates/parser/src/grammar.pest index 8ed88cb..24b188b 100644 --- a/crates/parser/src/grammar.pest +++ b/crates/parser/src/grammar.pest @@ -258,6 +258,18 @@ param_list = { // IMPORTS / MODULES // ====================================================== +include_global = { + "#" ~ "include" ~ "<" ~ identifier ~ ("/" ~ identifier)* ~ ">" +} + +include_use_global = { + visibility? ~ "#" ~ "use" ~ static_path ~ semicolon +} + +include_local = { + "#" ~ "include" ~ string_lit +} + import = { visibility? ~ "use" ~ static_path ~ semicolon } @@ -384,7 +396,7 @@ type_alias = { "type" ~ identifier ~ generics_decl? ~ "=" ~ type_expr ~ ";" } top_level = { mod_attribute - | (attributes ~ (import | impl_for_decl | impl_decl | trait_decl | struct_decl | enum_decl | class_decl | declare_module | function_decl | const_decl | static_decl | type_alias)) + | (attributes ~ (include_global | include_local | include_use_global | import | impl_for_decl | impl_decl | trait_decl | struct_decl | enum_decl | class_decl | declare_module | function_decl | const_decl | static_decl | type_alias)) } // ====================================================== diff --git a/crates/parser/src/parser/items/mod.rs b/crates/parser/src/parser/items/mod.rs index 57e8bee..4022024 100644 --- a/crates/parser/src/parser/items/mod.rs +++ b/crates/parser/src/parser/items/mod.rs @@ -129,6 +129,25 @@ impl<'a> TryFrom> for TopLevelKind { ty: inner.next().unwrap().try_into()?, }), + Rule::include_global => Ok(TopLevelKind::IncludeGlobal(Path(collect_recovered( + &mut inner, + )?))), + + Rule::include_use_global => Ok(TopLevelKind::IncludeUse( + Visibility::try_from(&mut inner)?, + Path::try_from(inner.next().unwrap())?, + )), + + Rule::include_local => Ok(TopLevelKind::IncludeLocal( + inner + .next() + .unwrap() + .into_inner() + .next() + .unwrap() + .to_string(), + )), + _ => AstError::bug_unimplemented(pair), } }