1#![deny(missing_docs)]
8
9use std::{
10    collections::{HashMap, HashSet},
11    fmt::{Debug, Display, Write},
12};
13
14use environment::Environment;
15use identifier::Identifier;
16use interpreter::{eval, Expression};
17use lexer::{tokenize, tokenize_and_filter, transform, Token};
18use parser::{parse, Element};
19use serde::{Deserialize, Serialize};
20use translation::translate;
21
22#[doc(hidden)]
23pub mod environment;
24#[doc(hidden)]
25pub mod interpreter;
26#[doc(hidden)]
27pub mod lexer;
28#[doc(hidden)]
29pub mod parser;
30#[doc(hidden)]
31pub mod preludes;
32#[doc(hidden)]
33pub mod translation;
34pub mod identifier;
35
36#[derive(Debug, PartialEq, Eq, Deserialize, Serialize, Clone)]
38pub struct WanderError(pub String);
39
40pub trait HostType: Debug + PartialEq + Eq + Serialize + Clone + Display + Serialize {}
42impl<T> HostType for T where T: Debug + PartialEq + Eq + Serialize + Clone + Display + Serialize {}
43
44pub trait TypeChecker<T: HostType> {
46    fn check(&self, value: WanderValue<T>, tag: WanderValue<T>) -> Result<bool, WanderError>;
48}
49
50pub struct EpsilonChecker {}
52
53impl<T: HostType> TypeChecker<T> for EpsilonChecker {
54    fn check(&self, _value: WanderValue<T>, _tag: WanderValue<T>) -> Result<bool, WanderError> {
55        Ok(true)
56    }
57}
58
59#[derive(Debug, PartialEq, Eq, Deserialize, Serialize, Clone)]
61pub struct NoHostType {}
62
63impl Display for NoHostType {
64    fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65        panic!("NoHostType should never be displayed.")
66    }
67}
68
69pub struct HostFunctionBinding {
71    pub name: String,
73    pub parameters: Vec<(String, Option<String>)>,
75    pub result: Option<String>,
77    pub doc_string: String,
80}
81
82pub trait HostFunction<T: HostType> {
85    fn run(
87        &self,
88        arguments: &[WanderValue<T>],
89        bindings: &Environment<T>,
90    ) -> Result<WanderValue<T>, WanderError>;
91    fn binding(&self) -> HostFunctionBinding;
93}
94
95pub type TokenTransformer = fn(&[Token]) -> Result<Vec<Token>, WanderError>;
97
98#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
101pub struct HostValue<T> {
102    pub value: T,
105}
106
107#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
110pub enum WanderValue<T: Clone + PartialEq + Eq> {
111    Bool(bool),
113    Int(i64),
115    String(String),
117    Identifier(Identifier),
119    Nothing,
121    Lambda(String, Option<String>, Option<String>, Box<Element>),
123    List(Vec<WanderValue<T>>),
125    Tuple(Vec<WanderValue<T>>),
127    Set(HashSet<WanderValue<T>>),
129    Record(HashMap<String, WanderValue<T>>),
131    HostValue(HostValue<T>),
133}
134
135impl<T: Clone + PartialEq + Eq> core::hash::Hash for WanderValue<T> {
136    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
137        core::mem::discriminant(self).hash(state);
138    }
139}
140
141#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
144pub struct PartialApplication<T: Clone + PartialEq + Eq> {
145    arguments: Vec<WanderValue<T>>,
146    callee: WanderValue<T>,
147}
148
149pub fn write_integer(integer: &i64) -> String {
151    format!("{}", integer)
152}
153
154pub fn write_float(float: &f64) -> String {
156    let res = format!("{}", float);
157    if res.contains('.') {
158        res
159    } else {
160        res + ".0"
161    }
162}
163
164pub fn write_string(string: &str) -> String {
171    let escaped_string = string
173        .replace('\\', "\\\\")
174        .replace('"', "\\\"")
175        .replace('\n', "\\n")
178        .replace('\r', "\\r")
179        .replace('\t', "\\t");
180    format!("\"{}\"", escaped_string)
181}
182
183fn write_list_or_tuple_wander_value<T: Clone + Display + PartialEq + Eq + Debug>(
184    open: &str,
185    close: char,
186    contents: &Vec<WanderValue<T>>,
187    f: &mut std::fmt::Formatter<'_>,
188) -> std::fmt::Result {
189    f.write_str(open).unwrap();
190    let mut i = 0;
191    for value in contents {
192        write!(f, "{value}").unwrap();
193        i += 1;
194        if i < contents.len() {
195            write!(f, " ").unwrap();
196        }
197    }
198    write!(f, "{close}")
199}
200
201fn write_set<T: Clone + Display + PartialEq + Eq + Debug>(
202    contents: &HashSet<WanderValue<T>>,
203    f: &mut std::fmt::Formatter<'_>,
204) -> std::fmt::Result {
205    f.write_str("#(").unwrap();
206    let mut i = 0;
207    for value in contents {
208        write!(f, "{value}").unwrap();
209        i += 1;
210        if i < contents.len() {
211            write!(f, " ").unwrap();
212        }
213    }
214    f.write_char(')')
215}
216
217fn write_host_value<T: Display + PartialEq + Eq>(
218    value: &HostValue<T>,
219    f: &mut std::fmt::Formatter<'_>,
220) -> std::fmt::Result {
221    write!(f, "{}", value.value)
222}
223
224fn write_record<T: Clone + Display + PartialEq + Eq + Debug>(
225    contents: &HashMap<String, WanderValue<T>>,
226    f: &mut std::fmt::Formatter<'_>,
227) -> std::fmt::Result {
228    write!(f, "{{").unwrap();
229    let mut i = 0;
230    for (name, value) in contents {
231        write!(f, "{name} = {value}").unwrap();
232        i += 1;
233        if i < contents.len() {
234            write!(f, " ").unwrap();
235        }
236    }
237    write!(f, "}}")
238}
239
240impl<T: Clone + Display + PartialEq + Eq + std::fmt::Debug> Display for WanderValue<T> {
241    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
242        match self {
243            WanderValue::Bool(value) => write!(f, "{}", value),
244            WanderValue::Int(value) => write!(f, "{}", value),
245            WanderValue::String(value) => f.write_str(&write_string(value)),
246            WanderValue::Identifier(value) => write!(f, "<{}>", value.id()),
247            WanderValue::Nothing => write!(f, "nothing"),
248            WanderValue::List(contents) => write_list_or_tuple_wander_value("[", ']', contents, f),
249            WanderValue::HostValue(value) => write_host_value(value, f),
250            WanderValue::Tuple(contents) => {
251                write_list_or_tuple_wander_value("'(", ')', contents, f)
252            }
253            WanderValue::Record(values) => write_record(values, f),
254            WanderValue::Lambda(p, i, o, b) => write!(
255                f,
256                "[lambda {:?}]",
257                WanderValue::Lambda::<T>(p.clone(), i.clone(), o.clone(), b.clone())
258            ),
259            WanderValue::Set(contents) => write_set(contents, f),
260        }
261    }
262}
263
264pub fn run<T: HostType + Display>(
266    script: &str,
267    bindings: &mut Environment<T>,
268) -> Result<WanderValue<T>, WanderError> {
269    let tokens = tokenize_and_filter(script)?;
270    let tokens = transform(&tokens, bindings)?;
271    let elements = parse(tokens)?;
272    let expression = translate(elements)?;
273    eval(&expression, bindings)
274}
275
276#[derive(Debug, Serialize)]
277pub struct Introspection {
279    pub tokens_ws: Vec<Token>,
281    pub tokens: Vec<Token>,
283    pub tokens_transformed: Vec<Token>,
285    pub element: Element,
287    pub expression: Expression,
289}
290
291pub fn introspect<T: HostType>(
293    script: &str,
294    bindings: &Environment<T>,
295) -> Result<Introspection, WanderError> {
296    let tokens_ws = tokenize(script).or(Ok(vec![]))?;
297    let tokens = tokenize_and_filter(script).or(Ok(vec![]))?;
298    let tokens_transformed = transform(&tokens.clone(), bindings).or(Ok(vec![]))?;
299    let element = parse(tokens_transformed.clone()).or(Ok(Element::String("Error".to_owned())))?; let expression = translate(element.clone()).or(Ok(Expression::String("Error".to_owned())))?; Ok(Introspection {
302        tokens_ws,
303        tokens,
304        tokens_transformed,
305        element,
306        expression,
307    })
308}