use std::sync::Arc; use crate::{interner::Interner, values::*}; #[salsa::query_group(CompilerDatabase)] pub trait Compiler: Interner { #[salsa::input] fn input_string(&self) -> Arc; /// Get the fields. fn fields(&self, class: Class) -> Arc>; /// Get the list of all classes fn all_classes(&self) -> Arc>; /// Get the list of all fields fn all_fields(&self) -> Arc>; } /// This function parses a dummy language with the following structure: /// /// Classes are defined one per line, consisting of a comma-separated list of fields. /// /// Example: /// /// ``` /// lorem,ipsum /// dolor,sit,amet, /// consectetur,adipiscing,elit /// ``` fn all_classes(db: &dyn Compiler) -> Arc> { let string = db.input_string(); let rows = string.split('\n'); let classes: Vec<_> = rows .filter(|string| !string.is_empty()) .map(|string| { let fields = string .trim() .split(',') .filter(|string| !string.is_empty()) .map(|name_str| { let name = name_str.to_owned(); let field_data = FieldData { name }; db.intern_field(field_data) }) .collect(); let class_data = ClassData { fields }; db.intern_class(class_data) }) .collect(); Arc::new(classes) } fn fields(db: &dyn Compiler, class: Class) -> Arc> { let class = db.lookup_intern_class(class); Arc::new(class.fields) } fn all_fields(db: &dyn Compiler) -> Arc> { Arc::new( db.all_classes() .iter() .cloned() .flat_map(|class| { let fields = db.fields(class); (0..fields.len()).map(move |i| fields[i]) }) .collect(), ) }