1use crate::node::NodeId;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4pub struct ExpressionId(pub u64);
5
6#[derive(Debug, Clone, PartialEq, Eq, Hash)]
7pub struct PropertyPath(pub String);
8
9impl PropertyPath {
10 pub fn new(path: impl Into<String>) -> Self {
11 Self(path.into())
12 }
13}
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
16pub struct VirtualPropertyId(pub u64);
17
18impl VirtualPropertyId {
19 pub const fn new(value: u64) -> Self {
20 Self(value)
21 }
22}
23
24#[derive(Debug, Clone, PartialEq)]
25pub enum ExpressionValue {
26 Number(f64),
27 Boolean(bool),
28 String(String),
29}
30
31impl ExpressionValue {
32 pub fn type_name(&self) -> &'static str {
33 match self {
34 Self::Number(_) => "number",
35 Self::Boolean(_) => "boolean",
36 Self::String(_) => "string",
37 }
38 }
39
40 pub fn as_f64(&self) -> Option<f64> {
41 match self {
42 Self::Number(n) => Some(*n),
43 Self::Boolean(b) => Some(if *b { 1.0 } else { 0.0 }),
44 Self::String(s) => s.parse().ok(),
45 }
46 }
47
48 pub fn as_bool(&self) -> bool {
49 match self {
50 Self::Boolean(b) => *b,
51 Self::Number(n) => n.abs() > f64::EPSILON,
52 Self::String(s) => !s.is_empty(),
53 }
54 }
55
56 pub fn as_string(&self) -> String {
57 match self {
58 Self::String(s) => s.clone(),
59 Self::Number(n) => n.to_string(),
60 Self::Boolean(b) => b.to_string(),
61 }
62 }
63}
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
66pub enum BinaryOp {
67 Add,
68 Sub,
69 Mul,
70 Div,
71 Mod,
72 Gt,
73 Lt,
74 Gte,
75 Lte,
76 Eq,
77 Neq,
78 And,
79 Or,
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq)]
83pub enum UnaryOp {
84 Neg,
85 Not,
86}
87
88#[derive(Debug, Clone, PartialEq, Eq, Hash)]
89pub enum GlobalVar {
90 Frame,
91 Time,
92 Fps,
93 Width,
94 Height,
95 Custom(String),
96}
97
98#[derive(Debug, Clone, Copy, PartialEq, Eq)]
99pub enum BuiltinFn {
100 Min,
101 Max,
102 Abs,
103 Floor,
104 Ceil,
105 Round,
106 Sin,
107 Cos,
108 Clamp,
109 Lerp,
110 Pow,
111 Mod,
112 Fract,
113 Smoothstep,
114 Linear,
115 Step,
116 TextHeight,
117 TextWidth,
118 Uppercase,
119 Lowercase,
120}
121
122#[derive(Debug, Clone, PartialEq)]
123pub enum ExprNode {
124 Literal(ExpressionValue),
125 Binary(Box<ExprNode>, BinaryOp, Box<ExprNode>),
126 Unary(UnaryOp, Box<ExprNode>),
127 Builtin(BuiltinFn, Vec<ExprNode>),
128 Global(GlobalVar),
129 SymbolicPath(Vec<String>),
130 Node(NodeId),
131 PropertyValue(NodeId, PropertyPath),
132 VirtualProperty(VirtualPropertyId),
133 Conditional(Box<ExprNode>, Box<ExprNode>, Box<ExprNode>),
134}
135
136#[derive(Debug, Clone, PartialEq, Eq, Hash)]
137pub enum ExpressionReference {
138 Node {
139 node_id: NodeId,
140 },
141 PropertyValue {
142 node_id: NodeId,
143 property_path: PropertyPath,
144 },
145 VirtualProperty {
146 id: VirtualPropertyId,
147 },
148 SymbolicPath {
149 segments: Vec<String>,
150 },
151}
152
153#[derive(Debug, Clone, PartialEq)]
154pub struct Expression {
155 pub id: ExpressionId,
156 pub ast: ExprNode,
157 pub references: Vec<ExpressionReference>,
158 pub source: String,
159}