use crate::ast::Side;
use crate::span::Span;
use std::collections::{BTreeMap, HashMap};
pub struct Program {
pub vars: VarTable,
pub scene: ResolvedScene,
pub wires: Vec<ResolvedWire>,
pub sheet: SheetInputs,
}
#[derive(Default, Clone)]
pub struct SheetInputs {
pub class_rules: Vec<(String, AttrMap)>,
pub element_rules: Vec<(String, AttrMap)>,
pub defines: Vec<(String, AttrMap)>,
pub templates: Vec<(String, AttrMap)>,
pub wire_defaults: AttrMap,
}
pub struct ResolvedScene {
pub attrs: AttrMap,
pub nodes: Vec<ResolvedInst>,
}
pub struct ResolvedInst {
pub id: Option<String>,
pub shape: ShapeKind,
pub type_chain: Vec<String>,
pub applied_styles: Vec<String>,
pub label: Option<String>,
pub attrs: AttrMap,
pub markers: Markers,
pub children: Vec<ResolvedInst>,
pub span: Span,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ShapeKind {
Box,
Oval,
Hex,
Slant,
Cyl,
Diamond,
Cloud,
Poly,
Path,
Text,
Line,
Icon,
Image,
}
impl ShapeKind {
pub fn parse(s: &str) -> Option<Self> {
Some(match s {
"box" => Self::Box,
"oval" => Self::Oval,
"hex" => Self::Hex,
"slant" => Self::Slant,
"cyl" => Self::Cyl,
"diamond" => Self::Diamond,
"cloud" => Self::Cloud,
"poly" => Self::Poly,
"path" => Self::Path,
"line" => Self::Line,
"icon" => Self::Icon,
"image" => Self::Image,
_ => return None,
})
}
pub fn as_str(self) -> &'static str {
match self {
Self::Box => "box",
Self::Oval => "oval",
Self::Hex => "hex",
Self::Slant => "slant",
Self::Cyl => "cyl",
Self::Diamond => "diamond",
Self::Cloud => "cloud",
Self::Poly => "poly",
Self::Path => "path",
Self::Text => "text",
Self::Line => "line",
Self::Icon => "icon",
Self::Image => "image",
}
}
}
#[derive(Default, Clone, Debug)]
pub struct AttrMap {
pub map: BTreeMap<String, ResolvedValue>,
}
impl AttrMap {
pub fn new() -> Self {
Self::default()
}
pub fn insert(&mut self, name: impl Into<String>, value: ResolvedValue) {
self.map.insert(name.into(), value);
}
pub fn get(&self, name: &str) -> Option<&ResolvedValue> {
self.map.get(name)
}
pub fn number(&self, name: &str) -> Option<f64> {
self.get(name).and_then(ResolvedValue::as_number)
}
}
#[derive(Clone, Debug)]
pub enum ResolvedValue {
Number(f64),
String(String),
Hex(String),
Ident(String),
RawCss(String),
Tuple(Vec<ResolvedValue>),
List(Vec<ResolvedValue>),
Call(ResolvedCall),
LiveVar {
name: String,
raw: bool,
baked: Option<Box<ResolvedValue>>,
},
}
impl ResolvedValue {
pub fn as_number(&self) -> Option<f64> {
match self {
ResolvedValue::Number(n) => Some(*n),
ResolvedValue::LiveVar { baked: Some(b), .. } => b.as_number(),
_ => None,
}
}
}
#[derive(Clone, Debug)]
pub struct ResolvedCall {
pub name: String,
pub args: Vec<ResolvedValue>,
}
#[derive(Clone, Debug, Default)]
pub struct VarTable {
pub entries: HashMap<String, VarEntry>,
}
#[derive(Clone, Debug)]
pub struct VarEntry {
pub kind: VarKind,
pub value: ResolvedValue,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum VarKind {
Layout,
Visual,
}
impl VarTable {
pub fn new() -> Self {
Self {
entries: HashMap::new(),
}
}
pub fn get(&self, name: &str) -> Option<&VarEntry> {
self.entries.get(name)
}
pub fn set(&mut self, name: impl Into<String>, kind: VarKind, value: ResolvedValue) {
self.entries.insert(name.into(), VarEntry { kind, value });
}
}
#[derive(Clone, Debug, Default)]
pub struct Markers {
pub start: MarkerKind,
pub end: MarkerKind,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum MarkerKind {
#[default]
None,
Arrow,
Dot,
Diamond,
Crow,
}
impl MarkerKind {
pub fn parse(s: &str) -> Option<Self> {
Some(match s {
"none" => Self::None,
"arrow" => Self::Arrow,
"dot" => Self::Dot,
"diamond" => Self::Diamond,
"crow" => Self::Crow,
_ => return None,
})
}
pub fn from_marker(m: crate::ast::WireMarker) -> Self {
match m {
crate::ast::WireMarker::None => Self::None,
crate::ast::WireMarker::Arrow => Self::Arrow,
crate::ast::WireMarker::Crow => Self::Crow,
crate::ast::WireMarker::Dot => Self::Dot,
crate::ast::WireMarker::Diamond => Self::Diamond,
}
}
}
pub struct ResolvedWire {
pub endpoints: Vec<ResolvedEndpoint>,
pub attrs: AttrMap,
pub applied_styles: Vec<String>,
pub markers: Markers,
pub texts: Vec<ResolvedText>,
pub span: Span,
}
pub struct ResolvedEndpoint {
pub path: String,
pub side: Option<Side>,
pub span: Span,
}
#[derive(Clone)]
pub struct ResolvedText {
pub text: String,
pub at: WireAt,
pub attrs: AttrMap,
}
#[derive(Clone, Debug)]
pub enum WireAt {
Auto,
Fraction(f64),
}