Skip to content

Commit

Permalink
split DSL model types into multiple modules (#680)
Browse files Browse the repository at this point in the history
Started working on migrating DSL v0 to v2, and wanted to add common
helpers/utilities to the model.
But faced the limitation is that the existing
`codegen_language_internal_macros` requires defining
all model types in a single module, to allow generating a parallel
`Spanned<>` type tree.
We no longer need to do that, since we are not parsing the DSL using
`serde`.

This PR refactors `codegen_language_internal_macros` to allow splitting
the model types,
at the expense of maintaining an allow-list of type names in
`internal_macros/src/derive/spanned.rs`.
I doubt we will be editing this list frequently, so it I think it should
be fine.
  • Loading branch information
OmarTawfik authored Dec 1, 2023
1 parent 925548b commit b7a0320
Show file tree
Hide file tree
Showing 51 changed files with 1,040 additions and 987 deletions.
2 changes: 0 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions crates/codegen/language/definition/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@ publish = false
codegen_language_internal_macros = { workspace = true }
indexmap = { workspace = true }
Inflector = { workspace = true }
infra_utils = { workspace = true }
itertools = { workspace = true }
proc-macro2 = { workspace = true }
quote = { workspace = true }
semver = { workspace = true }
serde = { workspace = true }
strum = { workspace = true }
strum_macros = { workspace = true }
syn = { workspace = true }
thiserror = { workspace = true }
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
use crate::{
compiler::analysis::{Analysis, ItemMetadata},
internals::Spanned,
model::{
spanned::{Item, VersionSpecifier},
Identifier,
compiler::{
analysis::{Analysis, ItemMetadata},
version_set::VersionSet,
},
utils::VersionSet,
internals::Spanned,
model::{Identifier, SpannedItem, SpannedVersionSpecifier},
};
use std::collections::HashSet;

pub fn analyze_definitions(analysis: &mut Analysis) {
pub(crate) fn analyze_definitions(analysis: &mut Analysis) {
collect_top_level_items(analysis);

check_enum_items(analysis);
Expand All @@ -31,7 +30,7 @@ fn collect_top_level_items(analysis: &mut Analysis) {
(**name).to_owned(),
ItemMetadata {
name: name.clone(),
kind: item.into(),
item: item.clone(),

defined_in,
used_in: VersionSet::new(),
Expand All @@ -45,7 +44,7 @@ fn collect_top_level_items(analysis: &mut Analysis) {

fn check_enum_items(analysis: &mut Analysis) {
for item in analysis.language.clone().items() {
let Item::Enum { item } = item else {
let SpannedItem::Enum { item } = item.as_ref() else {
continue;
};

Expand All @@ -66,7 +65,7 @@ fn check_precedence_items(analysis: &mut Analysis) {
let mut all_expressions = HashSet::new();

for item in analysis.language.clone().items() {
let Item::Precedence { item } = item else {
let SpannedItem::Precedence { item } = item.as_ref() else {
continue;
};

Expand Down Expand Up @@ -99,24 +98,24 @@ fn check_precedence_items(analysis: &mut Analysis) {
}
}

fn get_item_name(item: &Item) -> &Spanned<Identifier> {
fn get_item_name(item: &SpannedItem) -> &Spanned<Identifier> {
match item {
Item::Struct { item } => &item.name,
Item::Enum { item } => &item.name,
Item::Repeated { item } => &item.name,
Item::Separated { item } => &item.name,
Item::Precedence { item } => &item.name,
Item::Trivia { item } => &item.name,
Item::Keyword { item } => &item.name,
Item::Token { item } => &item.name,
Item::Fragment { item } => &item.name,
SpannedItem::Struct { item } => &item.name,
SpannedItem::Enum { item } => &item.name,
SpannedItem::Repeated { item } => &item.name,
SpannedItem::Separated { item } => &item.name,
SpannedItem::Precedence { item } => &item.name,
SpannedItem::Trivia { item } => &item.name,
SpannedItem::Keyword { item } => &item.name,
SpannedItem::Token { item } => &item.name,
SpannedItem::Fragment { item } => &item.name,
}
}

fn calculate_defined_in(analysis: &mut Analysis, item: &Item) -> VersionSet {
fn calculate_defined_in(analysis: &mut Analysis, item: &SpannedItem) -> VersionSet {
let mut defined_in = VersionSet::new();

let mut try_add_specifier = |specifier: &Option<Spanned<VersionSpecifier>>| {
let mut try_add_specifier = |specifier: &Option<Spanned<SpannedVersionSpecifier>>| {
if let Some(specifier) = specifier {
analysis.add_specifier(&mut defined_in, specifier);
} else {
Expand All @@ -125,35 +124,35 @@ fn calculate_defined_in(analysis: &mut Analysis, item: &Item) -> VersionSet {
};

match item {
Item::Struct { item } => {
SpannedItem::Struct { item } => {
try_add_specifier(&item.enabled);
}
Item::Enum { item } => {
SpannedItem::Enum { item } => {
try_add_specifier(&item.enabled);
}
Item::Repeated { item } => {
SpannedItem::Repeated { item } => {
try_add_specifier(&item.enabled);
}
Item::Separated { item } => {
SpannedItem::Separated { item } => {
try_add_specifier(&item.enabled);
}
Item::Precedence { item } => {
SpannedItem::Precedence { item } => {
try_add_specifier(&item.enabled);
}
Item::Trivia { item: _ } => {
SpannedItem::Trivia { item: _ } => {
try_add_specifier(&None);
}
Item::Keyword { item } => {
SpannedItem::Keyword { item } => {
for definition in &item.definitions {
try_add_specifier(&definition.enabled);
}
}
Item::Token { item } => {
SpannedItem::Token { item } => {
for definition in &item.definitions {
try_add_specifier(&definition.enabled)
}
}
Item::Fragment { item } => {
SpannedItem::Fragment { item } => {
try_add_specifier(&item.enabled);
}
};
Expand Down
22 changes: 9 additions & 13 deletions crates/codegen/language/definition/src/compiler/analysis/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,23 @@ use crate::{
definitions::analyze_definitions, reachability::analyze_reachability,
references::analyze_references,
},
compiler::version_set::VersionSet,
internals::{ErrorsCollection, ParseOutput, Spanned},
model::{
spanned::{Item, ItemKind, Language},
Identifier,
},
utils::VersionSet,
model::{Identifier, SpannedItem, SpannedLanguage},
};
use indexmap::IndexMap;
use proc_macro2::Span;
use std::rc::Rc;

pub struct Analysis {
pub(crate) struct Analysis {
pub errors: ErrorsCollection,
pub language: Rc<Language>,
pub language: Rc<SpannedLanguage>,
pub metadata: IndexMap<Identifier, ItemMetadata>,
}

pub struct ItemMetadata {
pub(crate) struct ItemMetadata {
pub name: Spanned<Identifier>,
pub kind: ItemKind,
pub item: Rc<SpannedItem>,

pub defined_in: VersionSet,
pub used_in: VersionSet,
Expand Down Expand Up @@ -71,13 +68,12 @@ impl Analysis {
}
}

impl Language {
fn items(&self) -> impl Iterator<Item = &Item> {
impl SpannedLanguage {
fn items(&self) -> impl Iterator<Item = &Rc<SpannedItem>> {
return self
.sections
.iter()
.flat_map(|section| &section.topics)
.flat_map(|topic| &topic.items)
.map(|item| &***item);
.flat_map(|topic| &topic.items);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use crate::{
compiler::analysis::Analysis,
model::{spanned::TriviaParser, Identifier},
utils::VersionSet,
compiler::{analysis::Analysis, version_set::VersionSet},
model::{Identifier, SpannedTriviaParser},
};
use std::collections::HashSet;

pub fn analyze_reachability(analysis: &mut Analysis) {
pub(crate) fn analyze_reachability(analysis: &mut Analysis) {
check_unreachabable_items(analysis);
check_unused_versions(analysis);
}
Expand Down Expand Up @@ -53,19 +52,19 @@ fn check_unreachabable_items(analysis: &mut Analysis) {
}
}

fn collect_trivia<'l>(parser: &'l TriviaParser, acc: &mut Vec<&'l Identifier>) {
fn collect_trivia<'l>(parser: &'l SpannedTriviaParser, acc: &mut Vec<&'l Identifier>) {
match parser {
TriviaParser::Sequence { parsers } | TriviaParser::Choice { parsers } => {
SpannedTriviaParser::Sequence { parsers } | SpannedTriviaParser::Choice { parsers } => {
for parser in parsers {
collect_trivia(parser, acc);
}
}
TriviaParser::OneOrMore { parser }
| TriviaParser::ZeroOrMore { parser }
| TriviaParser::Optional { parser } => {
SpannedTriviaParser::OneOrMore { parser }
| SpannedTriviaParser::ZeroOrMore { parser }
| SpannedTriviaParser::Optional { parser } => {
collect_trivia(parser, acc);
}
TriviaParser::Trivia { trivia } => {
SpannedTriviaParser::Trivia { trivia } => {
acc.push(trivia);
}
};
Expand Down
Loading

0 comments on commit b7a0320

Please sign in to comment.