From a318014c2838afa11c116dec9699b731f5ec94e6 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Wed, 5 Jun 2024 13:26:53 +0100 Subject: [PATCH] refactor: Use collect_breaking_versions from v2 directly in PG (#1002) Part of #638 Follow-up to #991 Pretty straightforward: instead of visiting the previously built v1 definition structure, we defer to `Language::collect_breaking_changes` as the definitions overlap - the breaking changes are defined as versions in which the syntax items may be evaluated differently, which means that these are exactly the versions that will be referenced for the conditional syntax item evaluation in the parser/lexer. --- .../language/definition/src/model/manifest.rs | 20 +++-------- .../cargo/src/runtime/language.rs.jinja2 | 7 ++-- crates/codegen/runtime/generator/src/model.rs | 2 ++ .../codegen/runtime/generator/src/parser.rs | 34 ++----------------- .../src/generated/generated/language.rs | 3 ++ .../src/generated/generated/language.rs | 1 + 6 files changed, 18 insertions(+), 49 deletions(-) diff --git a/crates/codegen/language/definition/src/model/manifest.rs b/crates/codegen/language/definition/src/model/manifest.rs index a26e9c2b7f..2455b1ed99 100644 --- a/crates/codegen/language/definition/src/model/manifest.rs +++ b/crates/codegen/language/definition/src/model/manifest.rs @@ -36,27 +36,15 @@ impl Language { } /// Collects all versions that change the language grammar in a breaking way. + /// + /// Includes the first supported version. pub fn collect_breaking_versions(&self) -> BTreeSet { let first = self.versions.first().unwrap().clone(); let mut res = BTreeSet::from_iter([first]); let mut add_spec = |spec: &Option| { - let Some(spec) = spec else { - return; - }; - - match spec.clone() { - VersionSpecifier::Never => (), - VersionSpecifier::From { from } => { - res.insert(from); - } - VersionSpecifier::Till { till } => { - res.insert(till); - } - VersionSpecifier::Range { from, till } => { - res.insert(from); - res.insert(till); - } + if let Some(spec) = spec { + res.extend(spec.versions().cloned()); } }; diff --git a/crates/codegen/runtime/cargo/src/runtime/language.rs.jinja2 b/crates/codegen/runtime/cargo/src/runtime/language.rs.jinja2 index 488add51f2..34d5c64cbf 100644 --- a/crates/codegen/runtime/cargo/src/runtime/language.rs.jinja2 +++ b/crates/codegen/runtime/cargo/src/runtime/language.rs.jinja2 @@ -30,7 +30,10 @@ use crate::parser_support::{ #[cfg_attr(feature = "slang_napi_interfaces", napi(namespace = "language"))] pub struct Language { {%- if not rendering_in_stubs -%} - {%- for version in model.parser.referenced_versions -%} + {%- for version in model.breaking_versions -%} + {% if loop.first %} {# The first supported version may not be referenced by the items #} + #[allow(dead_code)] + {% endif %} pub(crate) version_is_at_least_{{ version | replace(from=".", to="_") }}: bool, {%- endfor -%} {%- endif -%} @@ -68,7 +71,7 @@ impl Language { if Self::SUPPORTED_VERSIONS.binary_search(&version).is_ok() { Ok(Self { {%- if not rendering_in_stubs -%} - {%- for version in model.parser.referenced_versions %} + {%- for version in model.breaking_versions %} version_is_at_least_{{ version | replace(from=".", to="_") }}: Version::new({{ version | split(pat=".") | join(sep=", ") }}) <= version, {%- endfor -%} {%- endif -%} diff --git a/crates/codegen/runtime/generator/src/model.rs b/crates/codegen/runtime/generator/src/model.rs index 308d8e8845..cdc806110a 100644 --- a/crates/codegen/runtime/generator/src/model.rs +++ b/crates/codegen/runtime/generator/src/model.rs @@ -13,6 +13,7 @@ use crate::parser::ParserModel; pub struct RuntimeModel { /// Defines the `Language::SUPPORTED_VERSIONS` field. all_versions: BTreeSet, + breaking_versions: BTreeSet, parser: ParserModel, ast: AstModel, kinds: KindsModel, @@ -22,6 +23,7 @@ impl RuntimeModel { pub fn from_language(language: &Rc) -> Self { Self { all_versions: language.versions.iter().cloned().collect(), + breaking_versions: language.collect_breaking_versions(), ast: AstModel::create(language), parser: ParserModel::from_language(language), kinds: KindsModel::create(language), diff --git a/crates/codegen/runtime/generator/src/parser.rs b/crates/codegen/runtime/generator/src/parser.rs index 8a2c42e847..637480f055 100644 --- a/crates/codegen/runtime/generator/src/parser.rs +++ b/crates/codegen/runtime/generator/src/parser.rs @@ -3,8 +3,7 @@ use std::collections::{BTreeMap, BTreeSet}; use std::rc::Rc; -use codegen_language_definition::model::{Identifier, Language, VersionSpecifier}; -use semver::Version; +use codegen_language_definition::model::{Identifier, Language}; use serde::Serialize; mod codegen; @@ -16,8 +15,8 @@ use codegen::{ }; use grammar::{ Grammar, GrammarVisitor, KeywordScannerAtomic, KeywordScannerDefinitionRef, - ParserDefinitionNode, ParserDefinitionRef, PrecedenceParserDefinitionRef, - ScannerDefinitionNode, ScannerDefinitionRef, TriviaParserDefinitionRef, + ParserDefinitionNode, ParserDefinitionRef, PrecedenceParserDefinitionRef, ScannerDefinitionRef, + TriviaParserDefinitionRef, }; /// Newtype for the already generated Rust code, not to be confused with regular strings. @@ -26,9 +25,6 @@ struct RustCode(String); #[derive(Default, Serialize)] pub struct ParserModel { - /// Constructs inner `Language` the state to evaluate the version-dependent branches. - referenced_versions: BTreeSet, - /// Defines the top-level scanner functions in `Language`. scanner_functions: BTreeMap, // (name of scanner, code) // Defines the `Lexer::next_terminal` method. @@ -61,9 +57,6 @@ struct ScannerContextModel { #[derive(Default)] struct ParserAccumulatorState { - /// Constructs inner `Language` the state to evaluate the version-dependent branches. - referenced_versions: BTreeSet, - // Defines the `Lexer::next_terminal` method. scanner_contexts: BTreeMap, @@ -192,7 +185,6 @@ impl ParserAccumulatorState { .collect(); ParserModel { - referenced_versions: self.referenced_versions, parser_functions: self.parser_functions, trivia_parser_functions: self.trivia_parser_functions, // These are derived from the accumulated state @@ -209,15 +201,6 @@ impl GrammarVisitor for ParserAccumulatorState { .insert(scanner.name().clone(), Rc::clone(scanner)); } - fn keyword_scanner_definition_enter(&mut self, scanner: &KeywordScannerDefinitionRef) { - for def in scanner.definitions() { - let specifiers = def.enabled.iter().chain(def.reserved.iter()); - - self.referenced_versions - .extend(specifiers.flat_map(VersionSpecifier::versions).cloned()); - } - } - fn trivia_parser_definition_enter(&mut self, parser: &TriviaParserDefinitionRef) { self.set_current_context(parser.context().clone()); @@ -254,19 +237,8 @@ impl GrammarVisitor for ParserAccumulatorState { ); } - fn scanner_definition_node_enter(&mut self, node: &ScannerDefinitionNode) { - if let ScannerDefinitionNode::Versioned(_, version_specifier) = node { - self.referenced_versions - .extend(version_specifier.versions().cloned()); - } - } - fn parser_definition_node_enter(&mut self, node: &ParserDefinitionNode) { match node { - ParserDefinitionNode::Versioned(_, version_specifier) => { - self.referenced_versions - .extend(version_specifier.versions().cloned()); - } ParserDefinitionNode::ScannerDefinition(scanner) => { self.top_level_scanner_names.insert(scanner.name().clone()); diff --git a/crates/solidity/outputs/cargo/slang_solidity/src/generated/generated/language.rs b/crates/solidity/outputs/cargo/slang_solidity/src/generated/generated/language.rs index b397491fff..c30451599b 100644 --- a/crates/solidity/outputs/cargo/slang_solidity/src/generated/generated/language.rs +++ b/crates/solidity/outputs/cargo/slang_solidity/src/generated/generated/language.rs @@ -31,6 +31,8 @@ use crate::parser_support::{ #[derive(Debug)] #[cfg_attr(feature = "slang_napi_interfaces", napi(namespace = "language"))] pub struct Language { + #[allow(dead_code)] + pub(crate) version_is_at_least_0_4_11: bool, pub(crate) version_is_at_least_0_4_12: bool, pub(crate) version_is_at_least_0_4_14: bool, pub(crate) version_is_at_least_0_4_16: bool, @@ -171,6 +173,7 @@ impl Language { pub fn new(version: Version) -> std::result::Result { if Self::SUPPORTED_VERSIONS.binary_search(&version).is_ok() { Ok(Self { + version_is_at_least_0_4_11: Version::new(0, 4, 11) <= version, version_is_at_least_0_4_12: Version::new(0, 4, 12) <= version, version_is_at_least_0_4_14: Version::new(0, 4, 14) <= version, version_is_at_least_0_4_16: Version::new(0, 4, 16) <= version, diff --git a/crates/testlang/outputs/cargo/slang_testlang/src/generated/generated/language.rs b/crates/testlang/outputs/cargo/slang_testlang/src/generated/generated/language.rs index aed3cf41f7..1a2da1f0ef 100644 --- a/crates/testlang/outputs/cargo/slang_testlang/src/generated/generated/language.rs +++ b/crates/testlang/outputs/cargo/slang_testlang/src/generated/generated/language.rs @@ -31,6 +31,7 @@ use crate::parser_support::{ #[derive(Debug)] #[cfg_attr(feature = "slang_napi_interfaces", napi(namespace = "language"))] pub struct Language { + #[allow(dead_code)] pub(crate) version_is_at_least_1_0_0: bool, pub(crate) version: Version, }