forked from NomicFoundation/slang
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
306 additions
and
262 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,117 +1,33 @@ | ||
use std::collections::BTreeMap; | ||
use std::collections::BTreeSet; | ||
use std::rc::Rc; | ||
|
||
use anyhow::Result; | ||
use codegen_language_definition::model::{BuiltIn, BuiltInField, BuiltInFunction, BuiltInType}; | ||
use codegen_language_definition::model::Language; | ||
use infra_utils::codegen::CodegenFileSystem; | ||
use infra_utils::paths::PathExtensions; | ||
use semver::Version; | ||
use serde::Serialize; | ||
|
||
use crate::LanguageModel; | ||
|
||
#[derive(Default, Serialize)] | ||
pub struct BindingsModel { | ||
binding_rules_source: String, | ||
built_ins_source: BTreeMap<Version, String>, | ||
built_ins_versions: BTreeSet<Version>, | ||
file_extension: String, | ||
} | ||
|
||
impl BindingsModel { | ||
pub fn from_language(language: &LanguageModel) -> Result<Self> { | ||
pub fn from_language(language: &Rc<Language>) -> Result<Self> { | ||
// We use `CodegenFileSystem` here to ensure the rules are rebuilt if the rules file changes | ||
let binding_rules_dir = language.definition.binding_rules_file.unwrap_parent(); | ||
let binding_rules_dir = language.binding_rules_file.unwrap_parent(); | ||
let mut fs = CodegenFileSystem::new(binding_rules_dir)?; | ||
let binding_rules_source = fs.read_file(&language.definition.binding_rules_file)?; | ||
|
||
let mut built_ins_source = BTreeMap::new(); | ||
let mut last_contents = None; | ||
for version in &language.definition.versions { | ||
let built_ins = filter_built_ins_for_version(&language.definition.built_ins, version); | ||
let contents = (language.render_built_ins)(&built_ins); | ||
match last_contents { | ||
None => last_contents = Some(contents), | ||
Some(ref last) if last == &contents => (), | ||
_ => { | ||
let last = last_contents.replace(contents); | ||
built_ins_source.insert(version.clone(), last.unwrap()); | ||
} | ||
} | ||
} | ||
if let Some(version) = language.definition.versions.last() { | ||
built_ins_source.insert(version.clone(), last_contents.unwrap()); | ||
} | ||
let binding_rules_source = fs.read_file(&language.binding_rules_file)?; | ||
let built_ins_versions = language.collect_built_ins_versions(); | ||
let file_extension = language.file_extension.clone().unwrap_or_default(); | ||
|
||
Ok(Self { | ||
binding_rules_source, | ||
built_ins_source, | ||
}) | ||
} | ||
} | ||
|
||
fn filter_built_ins_for_version(built_ins: &[BuiltIn], version: &Version) -> Vec<BuiltIn> { | ||
built_ins | ||
.iter() | ||
.filter_map(|built_in| match built_in { | ||
BuiltIn::BuiltInFunction { item } => filter_built_in_function(item, version) | ||
.map(|item| BuiltIn::BuiltInFunction { item: item.into() }), | ||
BuiltIn::BuiltInType { item } => filter_built_in_type(item, version) | ||
.map(|item| BuiltIn::BuiltInType { item: item.into() }), | ||
BuiltIn::BuiltInVariable { item } => filter_built_in_field(item, version) | ||
.map(|item| BuiltIn::BuiltInVariable { item: item.into() }), | ||
}) | ||
.collect() | ||
} | ||
|
||
fn filter_built_in_function( | ||
function: &BuiltInFunction, | ||
version: &Version, | ||
) -> Option<BuiltInFunction> { | ||
if function | ||
.enabled | ||
.as_ref() | ||
.map_or(true, |enabled| enabled.contains(version)) | ||
{ | ||
Some(function.clone()) | ||
} else { | ||
None | ||
} | ||
} | ||
|
||
fn filter_built_in_field(field: &BuiltInField, version: &Version) -> Option<BuiltInField> { | ||
if field | ||
.enabled | ||
.as_ref() | ||
.map_or(true, |enabled| enabled.contains(version)) | ||
{ | ||
Some(field.clone()) | ||
} else { | ||
None | ||
} | ||
} | ||
|
||
fn filter_built_in_type(typ: &BuiltInType, version: &Version) -> Option<BuiltInType> { | ||
if typ | ||
.enabled | ||
.as_ref() | ||
.map_or(true, |enabled| enabled.contains(version)) | ||
{ | ||
let fields = typ | ||
.fields | ||
.iter() | ||
.filter_map(|field| filter_built_in_field(field, version)) | ||
.collect(); | ||
let functions = typ | ||
.functions | ||
.iter() | ||
.filter_map(|function| filter_built_in_function(function, version)) | ||
.collect(); | ||
|
||
Some(BuiltInType { | ||
name: typ.name.clone(), | ||
fields, | ||
functions, | ||
enabled: typ.enabled.clone(), | ||
built_ins_versions, | ||
file_extension, | ||
}) | ||
} else { | ||
None | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
use std::path::Path; | ||
use std::rc::Rc; | ||
|
||
use anyhow::Result; | ||
use codegen_language_definition::model::{ | ||
BuiltIn, BuiltInField, BuiltInFunction, BuiltInType, Language, | ||
}; | ||
use semver::Version; | ||
|
||
pub fn render_built_ins( | ||
language: &Rc<Language>, | ||
output_dir: &Path, | ||
render_fn: impl Fn(&[BuiltIn]) -> 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 output_path = output_dir.join(format!("{version}{file_extension}")); | ||
std::fs::write(output_path, contents)?; | ||
} | ||
Ok(()) | ||
} | ||
|
||
fn filter_built_ins_for_version(built_ins: &[BuiltIn], version: &Version) -> Vec<BuiltIn> { | ||
built_ins | ||
.iter() | ||
.filter_map(|built_in| match built_in { | ||
BuiltIn::BuiltInFunction { item } => filter_built_in_function(item, version) | ||
.map(|item| BuiltIn::BuiltInFunction { item: item.into() }), | ||
BuiltIn::BuiltInType { item } => filter_built_in_type(item, version) | ||
.map(|item| BuiltIn::BuiltInType { item: item.into() }), | ||
BuiltIn::BuiltInVariable { item } => filter_built_in_field(item, version) | ||
.map(|item| BuiltIn::BuiltInVariable { item: item.into() }), | ||
}) | ||
.collect() | ||
} | ||
|
||
fn filter_built_in_function( | ||
function: &BuiltInFunction, | ||
version: &Version, | ||
) -> Option<BuiltInFunction> { | ||
if function | ||
.enabled | ||
.as_ref() | ||
.map_or(true, |enabled| enabled.contains(version)) | ||
{ | ||
Some(function.clone()) | ||
} else { | ||
None | ||
} | ||
} | ||
|
||
fn filter_built_in_field(field: &BuiltInField, version: &Version) -> Option<BuiltInField> { | ||
if field | ||
.enabled | ||
.as_ref() | ||
.map_or(true, |enabled| enabled.contains(version)) | ||
{ | ||
Some(field.clone()) | ||
} else { | ||
None | ||
} | ||
} | ||
|
||
fn filter_built_in_type(typ: &BuiltInType, version: &Version) -> Option<BuiltInType> { | ||
if typ | ||
.enabled | ||
.as_ref() | ||
.map_or(true, |enabled| enabled.contains(version)) | ||
{ | ||
let fields = typ | ||
.fields | ||
.iter() | ||
.filter_map(|field| filter_built_in_field(field, version)) | ||
.collect(); | ||
let functions = typ | ||
.functions | ||
.iter() | ||
.filter_map(|function| filter_built_in_function(function, version)) | ||
.collect(); | ||
|
||
Some(BuiltInType { | ||
name: typ.name.clone(), | ||
fields, | ||
functions, | ||
enabled: typ.enabled.clone(), | ||
}) | ||
} else { | ||
None | ||
} | ||
} |
Oops, something went wrong.