mod collect;
mod resolve;
#[cfg(test)]
mod tests;
use std::collections::HashMap;
use crate::diagnostic::{Diagnostic, Severity};
use crate::parser::phenotyper_actions as ast;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TypeId(pub usize);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EnumId(pub usize);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct AliasId(pub usize);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FieldId(pub usize);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PrimitiveType {
String,
Int64,
Real64,
Bool,
Date,
Time,
DateTime,
}
#[derive(Debug, Clone)]
pub enum Symbol {
Phenotype(TypeId),
PluralCompanion { type_id: TypeId },
Enum(EnumId),
Alias(AliasId),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Requiredness {
Required,
Optional,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Cardinality {
One,
OneOrMore,
ZeroOrMore,
}
#[derive(Debug, Clone)]
pub struct TypeInfo {
pub id: TypeId,
pub singular_name: String,
pub plural_name: Option<String>,
pub fields: Vec<FieldInfo>,
}
#[derive(Debug, Clone)]
pub struct FieldInfo {
pub id: FieldId,
pub name: String,
pub requiredness: Requiredness,
}
#[derive(Debug, Clone)]
pub struct EnumInfo {
pub id: EnumId,
pub name: String,
pub members: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct AliasInfo {
pub id: AliasId,
pub name: String,
}
#[derive(Debug)]
pub struct SymbolTable {
pub namespace: Vec<String>,
pub types: Vec<TypeInfo>,
pub enums: Vec<EnumInfo>,
pub aliases: Vec<AliasInfo>,
names: HashMap<String, Symbol>,
}
impl SymbolTable {
pub fn resolve(&self, name: &str) -> Option<&Symbol> {
self.names.get(name)
}
pub fn resolve_field(&self, type_id: TypeId, field_name: &str) -> Option<&FieldInfo> {
self.types
.get(type_id.0)
.and_then(|ti| ti.fields.iter().find(|f| f.name == field_name))
}
pub fn type_info(&self, id: TypeId) -> Option<&TypeInfo> {
self.types.get(id.0)
}
pub fn enum_info(&self, id: EnumId) -> Option<&EnumInfo> {
self.enums.get(id.0)
}
}
pub fn build(ast: &ast::File, file: &str) -> (SymbolTable, Vec<Diagnostic>) {
let mut diags = Vec::new();
let mut table = collect::collect_symbols(ast, file, &mut diags);
resolve::resolve_references(ast, &mut table, file, &mut diags);
(table, diags)
}
fn error(file: &str, summary: String) -> Diagnostic {
Diagnostic {
severity: Severity::Error,
summary,
file: file.to_string(),
line: 0,
col: 0,
explanation: None,
suggestion: None,
}
}
#[allow(dead_code)]
fn warning(file: &str, summary: String) -> Diagnostic {
Diagnostic {
severity: Severity::Warning,
summary,
file: file.to_string(),
line: 0,
col: 0,
explanation: None,
suggestion: None,
}
}