1use super::Address;
2use crate::error;
3use crate::lang::{Error, LineNumber, MaxValue};
4use std::convert::TryFrom;
5use std::rc::Rc;
6
7#[derive(Debug, Clone, PartialEq)]
10pub enum Val {
11 String(Rc<str>),
12 Single(f32),
13 Double(f64),
14 Integer(i16),
15 Return(Address),
16 Next(Address),
17}
18
19impl std::fmt::Display for Val {
20 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
21 use Val::*;
22 let mut s = match self {
23 String(s) => return write!(f, "{}", s),
24 Integer(num) => format!("{}", num),
25 Single(num) => {
26 let s = format!("{}", num);
27 if s.chars().filter(char::is_ascii_digit).count() > 9 {
28 format!("{:E}", num)
29 } else {
30 format!("{}", num)
31 }
32 }
33 Double(num) => {
34 let s = format!("{}", num);
35 if s.chars().filter(char::is_ascii_digit).count() > 17 {
36 format!("{:E}", num)
37 } else {
38 format!("{}", num)
39 }
40 }
41 Return(..) | Next(..) => {
42 debug_assert!(false);
43 return write!(f, "");
44 }
45 };
46 if !s.starts_with('-') {
47 s.insert(0, ' ');
48 }
49 write!(f, "{}", s)
50 }
51}
52
53impl TryFrom<LineNumber> for Val {
54 type Error = Error;
55 fn try_from(line_number: LineNumber) -> std::result::Result<Self, Self::Error> {
56 match line_number {
57 Some(num) => Ok(Val::Single(num as f32)),
58 None => Err(error!(UndefinedLine)),
59 }
60 }
61}
62
63impl TryFrom<Val> for LineNumber {
64 type Error = Error;
65 fn try_from(val: Val) -> std::result::Result<Self, Self::Error> {
66 let num = u16::try_from(val)?;
67 if num <= LineNumber::max_value() {
68 Ok(Some(num))
69 } else {
70 Err(error!(UndefinedLine))
71 }
72 }
73}
74
75impl TryFrom<Val> for u16 {
76 type Error = Error;
77 fn try_from(val: Val) -> std::result::Result<Self, Self::Error> {
78 match val {
79 Val::Integer(num) => {
80 if num >= 0 {
81 Ok(num as u16)
82 } else {
83 Err(error!(Overflow))
84 }
85 }
86 Val::Single(num) => {
87 let num = num.floor();
88 if num >= 0.0 && num <= u16::max_value() as f32 {
89 Ok(num as u16)
90 } else {
91 Err(error!(Overflow))
92 }
93 }
94 Val::Double(num) => {
95 let num = num.floor();
96 if num >= 0.0 && num <= u16::max_value() as f64 {
97 Ok(num as u16)
98 } else {
99 Err(error!(Overflow))
100 }
101 }
102 Val::String(_) | Val::Return(_) | Val::Next(..) => Err(error!(TypeMismatch)),
103 }
104 }
105}
106
107impl TryFrom<Val> for i16 {
108 type Error = Error;
109 fn try_from(val: Val) -> std::result::Result<Self, Self::Error> {
110 match val {
111 Val::Integer(num) => Ok(num),
112 Val::Single(num) => {
113 let num = num.floor();
114 if num >= i16::min_value() as f32 && num <= i16::max_value() as f32 {
115 Ok(num as i16)
116 } else {
117 Err(error!(Overflow))
118 }
119 }
120 Val::Double(num) => {
121 let num = num.floor();
122 if num >= i16::min_value() as f64 && num <= i16::max_value() as f64 {
123 Ok(num as i16)
124 } else {
125 Err(error!(Overflow))
126 }
127 }
128 Val::String(_) | Val::Return(_) | Val::Next(..) => Err(error!(TypeMismatch)),
129 }
130 }
131}
132
133impl TryFrom<Val> for u32 {
134 type Error = Error;
135 fn try_from(val: Val) -> std::result::Result<Self, Self::Error> {
136 match val {
137 Val::Integer(num) => {
138 if num >= 0 {
139 Ok(num as u32)
140 } else {
141 Err(error!(Overflow))
142 }
143 }
144 Val::Single(num) => {
145 let num = num.floor();
146 if num >= 0.0 && num <= u32::max_value() as f32 {
147 Ok(num as u32)
148 } else {
149 Err(error!(Overflow))
150 }
151 }
152 Val::Double(num) => {
153 let num = num.floor();
154 if num >= 0.0 && num <= u32::max_value() as f64 {
155 Ok(num as u32)
156 } else {
157 Err(error!(Overflow))
158 }
159 }
160 Val::String(_) | Val::Return(_) | Val::Next(..) => Err(error!(TypeMismatch)),
161 }
162 }
163}
164
165impl TryFrom<Val> for usize {
166 type Error = Error;
167 fn try_from(val: Val) -> std::result::Result<Self, Self::Error> {
168 match val {
169 Val::Integer(num) => {
170 if num >= 0 {
171 Ok(num as usize)
172 } else {
173 Err(error!(Overflow))
174 }
175 }
176 Val::Single(num) => {
177 let num = num.floor();
178 if num >= 0.0 && num <= usize::max_value() as f32 {
179 Ok(num as usize)
180 } else {
181 Err(error!(Overflow))
182 }
183 }
184 Val::Double(num) => {
185 let num = num.floor();
186 if num >= 0.0 && num <= usize::max_value() as f64 {
187 Ok(num as usize)
188 } else {
189 Err(error!(Overflow))
190 }
191 }
192 Val::String(_) | Val::Return(_) | Val::Next(..) => Err(error!(TypeMismatch)),
193 }
194 }
195}
196
197impl TryFrom<Val> for f32 {
198 type Error = Error;
199 fn try_from(val: Val) -> std::result::Result<Self, Self::Error> {
200 match val {
201 Val::Integer(num) => Ok(num as f32),
202 Val::Single(num) => Ok(num),
203 Val::Double(num) => Ok(num as f32),
204 Val::String(_) | Val::Return(_) | Val::Next(..) => Err(error!(TypeMismatch)),
205 }
206 }
207}
208
209impl TryFrom<Val> for f64 {
210 type Error = Error;
211 fn try_from(val: Val) -> std::result::Result<Self, Self::Error> {
212 match val {
213 Val::Integer(num) => Ok(num as f64),
214 Val::Single(num) => Ok(num as f64),
215 Val::Double(num) => Ok(num),
216 Val::String(_) | Val::Return(_) | Val::Next(..) => Err(error!(TypeMismatch)),
217 }
218 }
219}
220
221impl TryFrom<Val> for Rc<str> {
222 type Error = Error;
223 fn try_from(val: Val) -> std::result::Result<Self, Self::Error> {
224 match val {
225 Val::String(s) => Ok(s),
226 _ => Err(error!(TypeMismatch)),
227 }
228 }
229}
230
231impl From<&str> for Val {
232 fn from(string: &str) -> Self {
233 if string.starts_with('&') {
234 let string = &string[1..];
235 if string.starts_with('H') || string.starts_with('h') {
236 if let Ok(num) = i16::from_str_radix(&string[1..], 16) {
237 return Val::Integer(num);
238 }
239 } else if let Ok(num) = i16::from_str_radix(&string, 8) {
240 return Val::Integer(num);
241 }
242 }
243 let mut s = String::from(string).replace("D", "E").replace("d", "e");
244 match s.chars().last() {
245 Some('!') | Some('#') | Some('%') => {
246 s.pop();
247 }
248 _ => {}
249 };
250 if let Ok(num) = s.parse::<f64>() {
251 Val::Double(num)
252 } else {
253 Val::String(string.into())
254 }
255 }
256}
257
258impl TryFrom<usize> for Val {
259 type Error = Error;
260 fn try_from(num: usize) -> std::result::Result<Self, Self::Error> {
261 match i16::try_from(num) {
262 Ok(len) => Ok(Val::Integer(len)),
263 Err(_) => {
264 debug_assert!(false, "LEN VAL TOO BIG");
265 Err(error!(Overflow))
266 }
267 }
268 }
269}