Skip to main content

concinnity_core/behavior/
value.rs

1// The values a behavior body computes over, and the two operator vocabularies
2// its arithmetic and comparisons are expressed in.
3
4use crate::components::BehaviorLiteral;
5use crate::ecs::{Entity, TraceVal};
6
7/// A value flowing through a behavior body.
8#[derive(Clone, Copy, Debug, PartialEq)]
9pub enum Val {
10    /// A boolean.
11    Bool(bool),
12    /// A signed integer.
13    Int(i32),
14    /// A float.
15    Float(f32),
16    /// A 3-component vector.
17    Vec3([f32; 3]),
18    /// An entity handle.
19    Entity(Entity),
20}
21
22impl Val {
23    pub(crate) fn as_bool(self) -> Option<bool> {
24        match self {
25            Val::Bool(b) => Some(b),
26            _ => None,
27        }
28    }
29
30    pub(crate) fn as_entity(self) -> Option<Entity> {
31        match self {
32            Val::Entity(e) => Some(e),
33            _ => None,
34        }
35    }
36
37    pub(crate) fn as_vec3(self) -> Option<[f32; 3]> {
38        match self {
39            Val::Vec3(v) => Some(v),
40            _ => None,
41        }
42    }
43
44    /// The scalar reading of a numeric value, for mixed vector/scalar forms.
45    pub fn as_f32(self) -> Option<f32> {
46        match self {
47            Val::Int(i) => Some(i as f32),
48            Val::Float(f) => Some(f),
49            _ => None,
50        }
51    }
52
53    /// The runtime value an authored literal denotes.
54    pub fn from_literal(lit: &BehaviorLiteral) -> Val {
55        match *lit {
56            BehaviorLiteral::Bool(b) => Val::Bool(b),
57            BehaviorLiteral::Int(i) => Val::Int(i),
58            BehaviorLiteral::Float(f) => Val::Float(f),
59            BehaviorLiteral::Vec3(v) => Val::Vec3(v),
60        }
61    }
62
63    /// The authored form, for persistence. Entities have no authored form and
64    /// are never persisted, so they save as their declared-away default.
65    pub fn to_literal(self) -> BehaviorLiteral {
66        match self {
67            Val::Bool(b) => BehaviorLiteral::Bool(b),
68            Val::Int(i) => BehaviorLiteral::Int(i),
69            Val::Float(f) => BehaviorLiteral::Float(f),
70            Val::Vec3(v) => BehaviorLiteral::Vec3(v),
71            Val::Entity(_) => BehaviorLiteral::Int(0),
72        }
73    }
74
75    /// The cross-boundary form execution tracing publishes.
76    pub fn to_trace(self) -> TraceVal {
77        match self {
78            Val::Bool(b) => TraceVal::Bool(b),
79            Val::Int(i) => TraceVal::Int(i),
80            Val::Float(f) => TraceVal::Float(f),
81            Val::Vec3(v) => TraceVal::Vec3(v),
82            Val::Entity(e) => TraceVal::Entity(e.to_bits()),
83        }
84    }
85
86    /// Whether two values are the same shape, so a restored save can be
87    /// rejected when the world's declaration changed type under it.
88    pub fn same_type(self, other: Val) -> bool {
89        core::mem::discriminant(&self) == core::mem::discriminant(&other)
90    }
91}
92
93/// How two numbers combine.
94#[derive(Clone, Copy, Debug)]
95pub enum Arith {
96    /// Sum.
97    Add,
98    /// Difference.
99    Sub,
100    /// Product.
101    Mul,
102    /// Quotient.
103    Div,
104}
105
106/// How two values compare.
107#[derive(Clone, Copy, Debug)]
108pub enum Cmp {
109    /// Equal.
110    Eq,
111    /// Not equal.
112    Ne,
113    /// Less than.
114    Lt,
115    /// Less than or equal.
116    Le,
117    /// Greater than.
118    Gt,
119    /// Greater than or equal.
120    Ge,
121}