Skip to content

Commit

Permalink
Drive-by tweaks and docs (#561)
Browse files Browse the repository at this point in the history
Not touching the grammar definition-related code since that's about to
be changed by
https://github.com/AntonyBlakey/slang/tree/AntonyBlakey/to_rust_types.

Somewhat related to #234,
I noticed that we have public extension traits that seem to only work
with the `LanguageDefinition` type. Maybe we should change these
one-function traits to free functions that accept the language
definition as the argument, instead?

Also not feeling strongly about
84912e8,
thought it's more of a nice-to-have.
  • Loading branch information
Xanewok authored Aug 10, 2023
1 parent 19b42e5 commit cb6a138
Show file tree
Hide file tree
Showing 9 changed files with 47 additions and 17 deletions.
5 changes: 5 additions & 0 deletions .changeset/sharp-garlics-clean.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"changelog": patch
---

Add preliminary documentation for the `solidity_language` Rust package
1 change: 1 addition & 0 deletions crates/codegen/ebnf/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[package]
name = "codegen_ebnf"
description = "EBNF snippet serializer for language definitions"
version.workspace = true
rust-version.workspace = true
edition.workspace = true
Expand Down
4 changes: 4 additions & 0 deletions crates/codegen/ebnf/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//! Provides an [`EbnfSerializer`], which allows to serialize a [`LanguageDefinition`](`codegen_schema::types::LanguageDefinition`)
//! into EBNF snippets.
//!
//! Used for documentation and for comments in the generated parser code.
mod nodes;
mod parser;
mod precedence_parser;
Expand Down
10 changes: 9 additions & 1 deletion crates/codegen/ebnf/src/serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::nodes::EbnfNode;

const MAX_LINE_WIDTH: usize = 80;

/// Serializes [`LanguageDefinition`](`codegen_schema::types::LanguageDefinition`) into EBNF snippets.
pub struct EbnfSerializer {
language: LanguageDefinitionRef,
outputs: IndexMap<String, String>,
Expand All @@ -17,7 +18,7 @@ pub struct EbnfSerializer {
impl EbnfSerializer {
/// Returns `None` if version is not found.
/// Otherwise, returns a map of LHS names to EBNF snippets.
/// Some productions (like `PrecedenceParser`) generate more than one statement.
/// Some productions (like ([`PrecedenceParser`](`ProductionDefinition::PrecedenceParser`)) generate more than one statement.
pub fn serialize_version(
language: &LanguageDefinitionRef,
production: &ProductionRef,
Expand Down Expand Up @@ -57,6 +58,12 @@ impl EbnfSerializer {
return Some(instance.outputs);
}

/// Serializes a single EBNF statement.
///
/// Example:
/// ```ebnf
/// UNSIGNED_INTEGER_TYPE = "uint" «INTEGER_TYPE_SIZE»?;
/// ```
pub fn serialize_statement(&mut self, name: &str, root_node: &EbnfNode) {
let mut buffer = String::new();

Expand Down Expand Up @@ -116,6 +123,7 @@ impl EbnfSerializer {
return choices.join(&format!("\n{padding} | ", padding = " ".repeat(name_width)));
}

/// Serialize and append an EBNF node to the buffer.
pub fn serialize_node(&mut self, top_node: &EbnfNode, buffer: &mut String) {
match top_node {
EbnfNode::Choice { nodes } => {
Expand Down
1 change: 1 addition & 0 deletions crates/codegen/spec/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[package]
name = "codegen_spec"
description = "Language specification generator"
version.workspace = true
rust-version.workspace = true
edition.workspace = true
Expand Down
12 changes: 12 additions & 0 deletions crates/codegen/spec/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
//! Generates a human-readable specification for the [`LanguageDefinitionRef`].
//!
//! At the time of writing, the generated pages include:
//! - A list of supported versions
//! - A grammar page for each version
//! - A reference page for each version
//!
//! and the auxiliary snippet files included by the grammar mkdocs pages.
//!
//! Exposes a [`SpecGeneratorExtensions`] trait that generates all the pages in a given [`CodegenContext`].
mod grammar;
mod markdown;
mod navigation;
Expand All @@ -17,7 +27,9 @@ use crate::{
snippets::Snippets,
};

/// Extension trait for [`LanguageDefinitionRef`] that generates the specification files.
pub trait SpecGeneratorExtensions {
/// Generates the specification files in `output_dir`.
fn generate_spec(&self, output_dir: &Path) -> Result<()>;
}

Expand Down
3 changes: 1 addition & 2 deletions crates/solidity/inputs/language/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[package]
name = "solidity_language"
description = "Solidity language definition compilation"
version.workspace = true
rust-version.workspace = true
edition.workspace = true
Expand All @@ -15,6 +16,4 @@ infra_utils = { workspace = true }
[dependencies]
anyhow = { workspace = true }
bson = { workspace = true }
cargo-emit = { workspace = true }
codegen_schema = { workspace = true }
infra_utils = { workspace = true }
3 changes: 2 additions & 1 deletion crates/solidity/inputs/language/build.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::path::Path;

use anyhow::Result;
use cargo_emit::rustc_env;
use cargo_emit::{rerun_if_changed, rustc_env};
use codegen_schema::types::{LanguageDefinition, LanguageDefinitionRef};
use infra_utils::{cargo::CargoWorkspace, paths::PathExtensions};

Expand All @@ -20,6 +20,7 @@ fn main() -> Result<()> {
"{}",
bin_file_path.unwrap_str()
);
rerun_if_changed!(bin_file_path.unwrap_str());

return Ok(());
}
Expand Down
25 changes: 12 additions & 13 deletions crates/solidity/inputs/language/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
use std::path::PathBuf;

//! This crate is responsible for compiling the language definition and exposing it to downstream crates.
//!
//! While it's possible to directly compile the language, we do it here once, to ensure that:
//! 1. Expensive parsing and validation is done only once.
//! 2. Errors are reported only once, instead of repeating for every crate.
//!
//! Call the [`SolidityLanguageExtensions::load_solidity`] method to load the precompiled language definition.
use anyhow::Result;
use cargo_emit::rerun_if_changed;
use codegen_schema::types::{LanguageDefinition, LanguageDefinitionRef};
use infra_utils::paths::PathExtensions;

pub trait SolidityLanguageExtensions {
/// Loads the precompiled Solidity language definition.
fn load_solidity() -> Result<LanguageDefinitionRef>;
}

// Set by the build script.
static LANGUAGE_DEFINITION_BIN: &'static str = env!("COMPILED_SOLIDITY_LANGUAGE_DEFINITION_BIN");

impl SolidityLanguageExtensions for LanguageDefinition {
/// We compile the language definition only once, and then expose it here to all downstream crates.
/// This ensures that:
/// 1. Expensive parsing and validation is done only once.
/// 2. Errors are reported only once, instead of repeating for every crate.
fn load_solidity() -> Result<LanguageDefinitionRef> {
let bin_file_path = PathBuf::from(env!("COMPILED_SOLIDITY_LANGUAGE_DEFINITION_BIN"));

rerun_if_changed!(bin_file_path.unwrap_str());

let buffer = std::fs::read(&bin_file_path)?;
let buffer = std::fs::read(LANGUAGE_DEFINITION_BIN)?;
let language: LanguageDefinition = bson::from_slice(&buffer)?;

return Ok(LanguageDefinitionRef::new(language));
Expand Down

0 comments on commit cb6a138

Please sign in to comment.