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}