bean_script/
data.rs

1use std::{cell::RefCell, hash::Hash, rc::Rc};
2
3use crate::{
4	error::{Error, ErrorSource},
5	pat_check,
6	scope::ScopeRef,
7};
8
9pub enum DataType {
10	Boolean,
11	Number,
12	String,
13	Name,
14	Scope,
15	None,
16	Or(Box<DataType>, Box<DataType>),
17	Any,
18}
19
20impl DataType {
21	pub fn from_string(string: &String) -> Result<DataType, Error> {
22		if string == "boolean" {
23			Ok(DataType::Boolean)
24		} else if string == "number" {
25			Ok(DataType::Number)
26		} else if string == "string" {
27			Ok(DataType::String)
28		} else if string == "name" {
29			Ok(DataType::Name)
30		} else if string == "scope" {
31			Ok(DataType::Scope)
32		} else if string == "none" {
33			Ok(DataType::None)
34		} else if string == "any" {
35			Ok(DataType::Any)
36		} else {
37			Err(Error::new(
38				&format!("Invalid type string {}.", string),
39				ErrorSource::Internal,
40			))
41		}
42	}
43
44	pub fn to_string(&self) -> String {
45		match self {
46			DataType::Boolean => String::from("boolean"),
47			DataType::Number => String::from("number"),
48			DataType::String => String::from("string"),
49			DataType::Name => String::from("name"),
50			DataType::Scope => String::from("scope"),
51			DataType::None => String::from("none"),
52			DataType::Any => String::from("any"),
53			DataType::Or(a, b) => a.to_string() + " | " + &b.to_string(),
54		}
55	}
56
57	pub fn matches(&self, data: &Data) -> bool {
58		match self {
59			DataType::Boolean => pat_check!(Data::Boolean(_) = data),
60			DataType::Number => pat_check!(Data::Number(_) = data),
61			DataType::String => pat_check!(Data::String(_) = data),
62			DataType::Name => pat_check!(Data::Name { .. } = data),
63			DataType::Scope => pat_check!(Data::Scope(_) = data),
64			DataType::None => pat_check!(Data::None = data),
65			DataType::Or(a, b) => a.matches(data) || b.matches(data),
66			DataType::Any => true,
67		}
68	}
69}
70
71#[derive(Clone, Debug)]
72pub enum Data {
73	Boolean(bool),
74	Number(f64),
75	String(String),
76	Name { scope: ScopeRef, name: String },
77	Scope(ScopeRef),
78	None,
79}
80
81impl Data {
82	pub fn get_type(&self) -> DataType {
83		match self {
84			Data::Boolean(_) => DataType::Boolean,
85			Data::Number(_) => DataType::Number,
86			Data::String(_) => DataType::String,
87			Data::Name { .. } => DataType::Name,
88			Data::Scope(_) => DataType::Scope,
89			Data::None => DataType::None,
90		}
91	}
92}
93
94impl PartialEq for Data {
95	fn eq(&self, other: &Self) -> bool {
96		match (self, other) {
97			(Self::Boolean(l), Self::Boolean(r)) => l == r,
98			(Self::Number(l), Self::Number(r)) => l == r,
99			(Self::String(l), Self::String(r)) => l == r,
100			(Self::None, Self::None) => true,
101			(
102				Self::Name { scope, name },
103				Self::Name {
104					scope: r_scope,
105					name: r_name,
106				},
107			) => Rc::ptr_eq(scope, r_scope) && name == r_name,
108			(Self::Scope(l), Self::Scope(r)) => Rc::ptr_eq(l, r),
109			_ => false,
110		}
111	}
112}
113
114impl Eq for Data {}
115
116impl Hash for Data {
117	fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
118		core::mem::discriminant(self).hash(state);
119	}
120}
121
122impl Default for Data {
123	fn default() -> Self {
124		Data::None
125	}
126}
127
128impl ToString for Data {
129	fn to_string(&self) -> String {
130		match self {
131			Data::Boolean(v) => {
132				if *v {
133					String::from("true")
134				} else {
135					String::from("false")
136				}
137			}
138			Data::Number(v) => v.to_string(),
139			Data::String(s) => s.clone(),
140			Data::Name { scope: _, name } => format!("<{}>", name),
141			Data::Scope(scope) => RefCell::borrow(&scope).to_string(),
142			Data::None => String::from("[none]"),
143		}
144	}
145}