forked from adl-lang/adl
-
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.
tests for apply_explicit_annotations
- Loading branch information
Showing
6 changed files
with
153 additions
and
62 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,4 +2,5 @@ pub mod adlgen; | |
pub mod adlrt; | ||
pub mod parser; | ||
pub mod processing; | ||
pub mod utils; | ||
|
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 |
---|---|---|
@@ -0,0 +1,136 @@ | ||
use crate::adlgen::sys::{adlast2 as adlast}; | ||
use crate::parser::{RawModule, ExplicitAnnotationRef}; | ||
|
||
type TypeExpr0 = adlast::TypeExpr<adlast::ScopedName>; | ||
type Module0 = adlast::Module<TypeExpr0>; | ||
|
||
|
||
/// Attach explicit annotations to the appropriate nodes in the AST. On failure, returns | ||
/// the nodes that could not be attached. | ||
pub fn apply_explicit_annotations(raw_module: RawModule) -> Result<Module0, Vec<UnResolvedExplicitAnnotation>> { | ||
let (mut module0, explicit_annotations) = raw_module; | ||
let mut unresolved = Vec::new(); | ||
|
||
for ea in explicit_annotations { | ||
let aref = find_annotations_ref(&ea.refr, &mut module0); | ||
match aref { | ||
Some(aref) => { aref.0.insert(ea.scoped_name,ea.value); } | ||
None => { unresolved.push(ea.refr); } | ||
} | ||
} | ||
|
||
if unresolved.is_empty() { | ||
Ok(module0) | ||
} else { | ||
Err(unresolved) | ||
} | ||
} | ||
|
||
/// Find the referenced annotations hashmap | ||
fn find_annotations_ref<'a>(ear: &ExplicitAnnotationRef, module0: &'a mut Module0) -> Option<&'a mut adlast::Annotations> { | ||
match ear { | ||
ExplicitAnnotationRef::Module => { | ||
Some(&mut module0.annotations) | ||
} | ||
ExplicitAnnotationRef::Decl(decl_name) => { | ||
if let Some(decl) = module0.decls.get_mut(decl_name) { | ||
return Some(&mut decl.annotations); | ||
} | ||
None | ||
} | ||
ExplicitAnnotationRef::Field((decl_name, field_name)) => { | ||
if let Some(decl) = module0.decls.get_mut(decl_name) { | ||
let ofields = match &mut decl.r#type { | ||
adlast::DeclType::Struct(s) => Some(&mut s.fields), | ||
adlast::DeclType::Union(u) => Some(&mut u.fields), | ||
_ => None, | ||
}; | ||
if let Some(fields) = ofields { | ||
let ofield = fields.iter_mut().find(|f| f.name.value == *field_name); | ||
if let Some(field) = ofield { | ||
return Some(&mut field.annotations); | ||
} | ||
} | ||
} | ||
None | ||
} | ||
} | ||
} | ||
|
||
type UnResolvedExplicitAnnotation = ExplicitAnnotationRef; | ||
|
||
|
||
#[cfg(test)] | ||
mod tests { | ||
use nom_locate::LocatedSpan; | ||
use crate::{parser::raw_module, utils::ast::mk_scoped_name}; | ||
use crate::adlgen::sys::{adlast2 as adlast}; | ||
|
||
|
||
#[test] | ||
fn explicit_annotations_ok() { | ||
let rm = raw_module(LocatedSpan::new(OK_ADL)).unwrap().1; | ||
|
||
// We should have 3 explicit annotations to attach | ||
assert_eq!(rm.1.len(), 3); | ||
|
||
let m0 = super::apply_explicit_annotations(rm).unwrap(); | ||
assert_eq!(m0.annotations.0.get(&mk_scoped_name("", "A")), Some(&serde_json::Value::from(1i32))); | ||
assert_eq!(m0.annotations.0.get(&mk_scoped_name("", "E")), Some(&serde_json::Value::from(6i32))); | ||
|
||
let decl = m0.decls.get("Y").unwrap(); | ||
assert_eq!(decl.annotations.0.get(&mk_scoped_name("", "B")), Some(&serde_json::Value::from(2i32))); | ||
assert_eq!(decl.annotations.0.get(&mk_scoped_name("", "F")), Some(&serde_json::Value::from(7i32))); | ||
|
||
let field = if let adlast::DeclType::Struct(s) = &decl.r#type { | ||
s.fields.iter().find(|f| f.name.value == "z") | ||
} else { | ||
None | ||
}.unwrap(); | ||
assert_eq!(field.annotations.0.get(&mk_scoped_name("", "C")), Some(&serde_json::Value::from(3i32))); | ||
assert_eq!(field.annotations.0.get(&mk_scoped_name("", "G")), Some(&serde_json::Value::from(8i32))); | ||
} | ||
|
||
const OK_ADL: &str = " | ||
@A 1 | ||
module X { | ||
@B 2 | ||
struct Y { | ||
@C 3 | ||
Word64 z; | ||
}; | ||
annotation E 6; | ||
annotation Y F 7; | ||
annotation Y::z G 8; | ||
} | ||
"; | ||
|
||
#[test] | ||
fn explicit_annotations_bad() { | ||
let rm = raw_module(LocatedSpan::new(BAD_ADL)).unwrap().1; | ||
|
||
// We should have 3 explicit annotations to attach | ||
assert_eq!(rm.1.len(), 3); | ||
|
||
let err = super::apply_explicit_annotations(rm).unwrap_err(); | ||
|
||
// All of which should have failed | ||
assert_eq!(err.len(), 3); | ||
} | ||
|
||
const BAD_ADL: &str = " | ||
module X { | ||
struct Y { | ||
Word64 z; | ||
}; | ||
annotation A F 7; | ||
annotation A::z G 8; | ||
annotation Y::q G 9; | ||
} | ||
"; | ||
|
||
|
||
} |
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,64 +1,12 @@ | ||
use crate::adlgen::sys::{adlast2 as adlast}; | ||
use crate::parser::{RawModule, ExplicitAnnotationRef}; | ||
|
||
type TypeExpr0 = adlast::TypeExpr<adlast::ScopedName>; | ||
pub type Module0 = adlast::Module<TypeExpr0>; | ||
|
||
pub mod annotations; | ||
|
||
pub trait AdlLoader { | ||
/// Find and load the specified ADL module | ||
fn load(module_name: adlast::ModuleName) -> Result<Option<RawModule>, anyhow::Error>; | ||
} | ||
|
||
/// Attach explicit annotations to the appropriate nodes in the AST. On failure, returns | ||
/// the nodes that could not be attached. | ||
pub fn apply_explicit_annotations(raw_module: RawModule) -> Result<Module0, Vec<UnResolvedExplicitAnnotation>> { | ||
let (mut module0, explicit_annotations) = raw_module; | ||
let mut unresolved = Vec::new(); | ||
|
||
for ea in explicit_annotations { | ||
let aref = find_annotations_ref(&ea.refr, &mut module0); | ||
match aref { | ||
Some(aref) => { aref.0.insert(ea.scoped_name,ea.value); } | ||
None => { unresolved.push(ea.refr); } | ||
} | ||
} | ||
|
||
if unresolved.is_empty() { | ||
Ok(module0) | ||
} else { | ||
Err(unresolved) | ||
} | ||
} | ||
|
||
/// Find the referenced annotations hashmap | ||
fn find_annotations_ref<'a>(ear: &ExplicitAnnotationRef, module0: &'a mut Module0) -> Option<&'a mut adlast::Annotations> { | ||
match ear { | ||
ExplicitAnnotationRef::Module => { | ||
Some(&mut module0.annotations) | ||
} | ||
ExplicitAnnotationRef::Decl(decl_name) => { | ||
if let Some(decl) = module0.decls.get_mut(decl_name) { | ||
return Some(&mut decl.annotations); | ||
} | ||
None | ||
} | ||
ExplicitAnnotationRef::Field((decl_name, field_name)) => { | ||
if let Some(decl) = module0.decls.get_mut(decl_name) { | ||
let ofields = match &mut decl.r#type { | ||
adlast::DeclType::Struct(s) => Some(&mut s.fields), | ||
adlast::DeclType::Union(u) => Some(&mut u.fields), | ||
_ => None, | ||
}; | ||
if let Some(fields) = ofields { | ||
let ofield = fields.iter_mut().find(|f| f.name.value == *field_name); | ||
if let Some(field) = ofield { | ||
return Some(&mut field.annotations); | ||
} | ||
} | ||
} | ||
None | ||
} | ||
} | ||
fn load(module_name: adlast::ModuleName) -> Result<Module0, anyhow::Error>; | ||
} | ||
|
||
type UnResolvedExplicitAnnotation = ExplicitAnnotationRef; |
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,10 @@ | ||
|
||
use crate::adlgen::sys::{adlast2 as adlast}; | ||
|
||
pub fn mk_scoped_name(mname: &str, name: &str) -> adlast::ScopedName { | ||
adlast::ScopedName::new(mname.to_string(), name.to_string()) | ||
} | ||
|
||
pub fn mk_typeexpr0(type_ref: adlast::ScopedName) -> adlast::TypeExpr<adlast::ScopedName> { | ||
adlast::TypeExpr{type_ref, parameters: vec![]} | ||
} |
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 @@ | ||
pub mod ast; |