Skip to content

Commit

Permalink
Introduce built-in contexts in language definition
Browse files Browse the repository at this point in the history
  • Loading branch information
ggiraldez committed Dec 24, 2024
1 parent 0900ce7 commit 2e0d21e
Show file tree
Hide file tree
Showing 28 changed files with 539 additions and 470 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ pub(crate) fn analyze_references(analysis: &mut Analysis) {
check_item(analysis, item, &enablement);
}

for built_in in &language.built_ins {
check_built_in(analysis, built_in, &enablement);
for built_in_context in &language.built_ins {
for built_in in &built_in_context.definitions {
check_built_in(analysis, built_in, &enablement);
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions crates/codegen/language/definition/src/model/built_ins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ use strum_macros::EnumDiscriminants;

use crate::model::VersionSpecifier;

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[derive_spanned_type(Clone, Debug, ParseInputTokens, WriteOutputTokens)]
pub struct BuiltInContext {
pub name: String,
pub definitions: Vec<BuiltIn>,
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[derive_spanned_type(Clone, Debug, EnumDiscriminants, ParseInputTokens, WriteOutputTokens)]
pub enum BuiltIn {
Expand Down
35 changes: 19 additions & 16 deletions crates/codegen/language/definition/src/model/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use indexmap::IndexSet;
use semver::Version;
use serde::{Deserialize, Serialize};

use crate::model::{BuiltIn, Field, Identifier, Item, TriviaParser, VersionSpecifier};
use super::BuiltIn;
use crate::model::{BuiltInContext, Field, Identifier, Item, TriviaParser, VersionSpecifier};

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[derive_spanned_type(Clone, Debug, ParseInputTokens, WriteOutputTokens)]
Expand All @@ -25,7 +26,7 @@ pub struct Language {
pub versions: IndexSet<Version>,

pub sections: Vec<Section>,
pub built_ins: Vec<BuiltIn>,
pub built_ins: Vec<BuiltInContext>,
}

impl Language {
Expand Down Expand Up @@ -125,22 +126,24 @@ impl Language {
}
};

for item in &self.built_ins {
match item {
BuiltIn::BuiltInFunction { item } => {
add_spec(&item.enabled);
}
BuiltIn::BuiltInType { item } => {
add_spec(&item.enabled);
for field in &item.fields {
add_spec(&field.enabled);
for context in &self.built_ins {
for item in &context.definitions {
match item {
BuiltIn::BuiltInFunction { item } => {
add_spec(&item.enabled);
}
for function in &item.functions {
add_spec(&function.enabled);
BuiltIn::BuiltInType { item } => {
add_spec(&item.enabled);
for field in &item.fields {
add_spec(&field.enabled);
}
for function in &item.functions {
add_spec(&function.enabled);
}
}
BuiltIn::BuiltInVariable { item } => {
add_spec(&item.enabled);
}
}
BuiltIn::BuiltInVariable { item } => {
add_spec(&item.enabled);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ fn get_spanned_type(input: Type) -> Type {
// These are model Types that have a derived 'SpannedXXX' type.
// Let's use that instead:
"BuiltIn"
| "BuiltInContext"
| "BuiltInField"
| "BuiltInFunction"
| "BuiltInParameter"
Expand Down
18 changes: 14 additions & 4 deletions crates/codegen/runtime/generator/src/built_ins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::rc::Rc;

use anyhow::Result;
use codegen_language_definition::model::{
BuiltIn, BuiltInField, BuiltInFunction, BuiltInType, Language,
BuiltIn, BuiltInContext, BuiltInField, BuiltInFunction, BuiltInType, Language,
};
use infra_utils::codegen::CodegenFileSystem;
use semver::Version;
Expand All @@ -12,13 +12,23 @@ pub fn render_built_ins(
file_system: &mut CodegenFileSystem,
language: &Rc<Language>,
output_dir: &Path,
render_fn: impl Fn(&[BuiltIn]) -> String,
render_fn: impl Fn(&[BuiltInContext]) -> String,
) -> Result<()> {
let versions = language.collect_built_ins_versions();
let file_extension = language.file_extension.clone().unwrap_or_default();
for version in &versions {
let built_ins = filter_built_ins_for_version(&language.built_ins, version);
let contents = render_fn(&built_ins);
let built_in_contexts = language
.built_ins
.iter()
.map(|context| {
let definitions = filter_built_ins_for_version(&context.definitions, version);
BuiltInContext {
definitions,
..context.clone()
}
})
.collect::<Vec<_>>();
let contents = render_fn(&built_in_contexts);

let output_path = output_dir.join(format!("{version}{file_extension}"));
file_system.write_file(output_path, contents)?;
Expand Down
4 changes: 2 additions & 2 deletions crates/solidity/inputs/language/bindings/rules.msgb
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ inherit .star_extension
;; internal contract named '%BuiltIns%' (renamed from '$BuiltIns$') so we need
;; to export all its members and type members directly as a source unit
;; definition.
;; __SLANG_SOLIDITY_BUILT_INS_CONTRACT_NAME__ keep in sync with built-ins generation.
;; __SLANG_SOLIDITY_BUILT_INS_CONTRACT_NAME__ keep in sync with language definition.
@source_unit [SourceUnit [SourceUnitMembers
[SourceUnitMember @contract [ContractDefinition name: ["%BuiltIns%"]]]
[SourceUnitMember @contract [ContractDefinition name: ["%SolidityBuiltIns%"]]]
]] {
if (is-system-file FILE_PATH) {
edge @source_unit.defs -> @contract.instance
Expand Down
75 changes: 38 additions & 37 deletions crates/solidity/inputs/language/src/bindings.rs
Original file line number Diff line number Diff line change
@@ -1,55 +1,56 @@
use std::fmt::{Error, Write};

use codegen_language_definition::model::BuiltIn;
use codegen_language_definition::model::{BuiltIn, BuiltInContext};

pub fn render_built_ins(built_ins: &[BuiltIn]) -> String {
try_render_built_ins(built_ins).expect("Failed to render built-ins")
pub fn render_built_ins(built_in_contexts: &[BuiltInContext]) -> String {
try_render_built_ins(built_in_contexts).expect("Failed to render built-ins")
}

fn try_render_built_ins(built_ins: &[BuiltIn]) -> Result<String, Error> {
fn try_render_built_ins(built_in_contexts: &[BuiltInContext]) -> Result<String, Error> {
let mut buffer = String::new();
// __SLANG_SOLIDITY_BUILT_INS_CONTRACT_NAME__ keep in sync with binding rules
writeln!(buffer, "contract $BuiltIns$ {{")?;
for item in built_ins {
match item {
BuiltIn::BuiltInFunction { item } => {
writeln!(
buffer,
" function {name}({parameters}) public{return_type};",
name = item.name,
parameters = item.parameters.join(", "),
return_type = item
.return_type
.as_ref()
.map(|return_type| format!(" returns ({return_type})"))
.unwrap_or_default(),
)?;
}
BuiltIn::BuiltInType { item } => {
writeln!(buffer, " struct {name} {{", name = item.name)?;
for field in &item.fields {
writeln!(buffer, " {field_def};", field_def = field.definition)?;
}
for function in &item.functions {
for context in built_in_contexts {
writeln!(buffer, "contract {context} {{", context = context.name)?;
for item in &context.definitions {
match item {
BuiltIn::BuiltInFunction { item } => {
writeln!(
buffer,
" function({parameters}){return_type} {name};",
name = function.name,
return_type = function
" function {name}({parameters}) public{return_type};",
name = item.name,
parameters = item.parameters.join(", "),
return_type = item
.return_type
.as_deref()
.as_ref()
.map(|return_type| format!(" returns ({return_type})"))
.unwrap_or_default(),
parameters = function.parameters.join(", "),
)?;
}
writeln!(buffer, " }}")?;
}
BuiltIn::BuiltInVariable { item } => {
writeln!(buffer, " {var_def};", var_def = item.definition)?;
BuiltIn::BuiltInType { item } => {
writeln!(buffer, " struct {name} {{", name = item.name)?;
for field in &item.fields {
writeln!(buffer, " {field_def};", field_def = field.definition)?;
}
for function in &item.functions {
writeln!(
buffer,
" function({parameters}){return_type} {name};",
name = function.name,
return_type = function
.return_type
.as_deref()
.map(|return_type| format!(" returns ({return_type})"))
.unwrap_or_default(),
parameters = function.parameters.join(", "),
)?;
}
writeln!(buffer, " }}")?;
}
BuiltIn::BuiltInVariable { item } => {
writeln!(buffer, " {var_def};", var_def = item.definition)?;
}
}
}
writeln!(buffer, "}}")?;
}
writeln!(buffer, "}}")?;
Ok(buffer)
}
Loading

0 comments on commit 2e0d21e

Please sign in to comment.