1use std::fmt::{Display, Formatter};
2
3#[derive(Debug, Clone, PartialEq)]
4pub struct Word(pub String);
5
6#[derive(Debug, Clone, PartialEq)]
7pub enum LogoValue {
8 Word(Word),
9 String(String),
10 List(Vec<LogoValue>)
11}
12
13impl Display for LogoValue {
14 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
15 match self {
16 LogoValue::Word(word) => write!(f, "{}", word.0),
17 LogoValue::String(str) => write!(f, "{}", str),
18 LogoValue::List(list) => {
19 write!(f, "[")?;
20 let str_vec: Vec<String> = list.iter().map(|x| format!("{}", x)).collect();
21 write!(f, "{}", str_vec.join(" "))?;
22 write!(f, "]")?;
23 Ok(())
24 }
25 }
26 }
27}
28
29#[derive(Clone, PartialEq)]
30pub struct LogoProcedure {
31 pub arg_names: Vec<String>,
32 pub code: Vec<LogoValue>
33}
34
35pub trait LogoConvertible {
36 fn to_logo(&self) -> LogoValue;
37 fn from_logo(value: LogoValue) -> Result<Self, String> where Self: Sized;
38}
39
40impl LogoConvertible for LogoValue {
41 fn to_logo(&self) -> LogoValue {
42 return self.clone();
43 }
44
45 fn from_logo(value: LogoValue) -> Result<Self, String> {
46 return Ok(value);
47 }
48}
49
50impl LogoConvertible for String {
51 fn to_logo(&self) -> LogoValue {
52 return LogoValue::String(self.clone());
53 }
54
55 fn from_logo(value: LogoValue) -> Result<Self, String> {
56 match value {
57 LogoValue::String(val) => Ok(val),
58 _ => Err("Type mismatch".to_string())
59 }
60 }
61}
62
63impl LogoConvertible for Word {
64 fn to_logo(&self) -> LogoValue {
65 return LogoValue::Word(self.clone());
66 }
67
68 fn from_logo(value: LogoValue) -> Result<Self, String> {
69 match value {
70 LogoValue::Word(val) => Ok(val),
71 _ => Err("Type mismatch".to_string())
72 }
73 }
74}
75
76impl LogoConvertible for f64 {
77 fn to_logo(&self) -> LogoValue {
78 return LogoValue::Word(Word(self.to_string()));
79 }
80
81 fn from_logo(value: LogoValue) -> Result<Self, String> {
82 match value {
83 LogoValue::Word(val) => {
84 match val.0.parse::<f64>() {
85 Ok(val) => Ok(val),
86 _ => Err("Type mismatch".to_string())
87 }
88 },
89 _ => Err("Type mismatch".to_string())
90 }
91 }
92}
93
94impl LogoConvertible for i32 {
95 fn to_logo(&self) -> LogoValue {
96 return LogoValue::Word(Word(self.to_string()));
97 }
98
99 fn from_logo(value: LogoValue) -> Result<Self, String> {
100 match value {
101 LogoValue::Word(val) => {
102 match val.0.parse::<i32>() {
103 Ok(val) => Ok(val),
104 _ => Err("Type mismatch".to_string())
105 }
106 },
107 _ => Err("Type mismatch".to_string())
108 }
109 }
110}
111
112impl LogoConvertible for bool {
113 fn to_logo(&self) -> LogoValue {
114 return LogoValue::Word(Word(self.to_string()));
115 }
116
117 fn from_logo(value: LogoValue) -> Result<Self, String> {
118 match value {
119 LogoValue::Word(val) => {
120 match val.0.parse::<bool>() {
121 Ok(val) => Ok(val),
122 _ => Err("Type mismatch".to_string())
123 }
124 },
125 _ => Err("Type mismatch".to_string())
126 }
127 }
128}
129
130impl<T: LogoConvertible> LogoConvertible for Vec<T> {
131 fn to_logo(&self) -> LogoValue {
132 let mut res = Vec::with_capacity(self.len());
133 for value in self {
134 res.push(value.to_logo());
135 }
136 return LogoValue::List(res);
137 }
138
139 fn from_logo(value: LogoValue) -> Result<Self, String> {
140 match value {
141 LogoValue::List(list) => {
142 let mut res = Vec::with_capacity(list.len());
143 for value in list {
144 res.push(T::from_logo(value)?);
145 }
146 Ok(res)
147 },
148 _ => Err("Type mismatch".to_string())
149 }
150 }
151}