logo_interp/
core.rs

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}