ucglib/build/
ir.rs

1//! The ir module holds the definitions of our ucg Intermediate Representation before it is converted
2//! to an output artifact.
3use std::convert::From;
4use std::fmt;
5use std::fmt::{Display, Formatter};
6use std::rc::Rc;
7use std::string::ToString;
8
9use crate::error;
10
11/// The Intermediate representation of a compiled UCG AST.
12#[derive(PartialEq, Debug, Clone)]
13pub enum Val {
14    Empty,
15    Boolean(bool),
16    Int(i64),
17    Float(f64),
18    Str(String),
19    List(Vec<Rc<Val>>),
20    Tuple(Vec<(String, Rc<Val>)>),
21    Env(Vec<(String, String)>),
22}
23
24impl Val {
25    /// Returns the Type of a Val as a string.
26    pub fn type_name(&self) -> String {
27        match self {
28            &Val::Empty => "EmptyValue".to_string(),
29            &Val::Boolean(_) => "Boolean".to_string(),
30            &Val::Int(_) => "Integer".to_string(),
31            &Val::Float(_) => "Float".to_string(),
32            &Val::Str(_) => "String".to_string(),
33            &Val::List(_) => "List".to_string(),
34            &Val::Tuple(_) => "Tuple".to_string(),
35            &Val::Env(_) => "Env".to_string(),
36        }
37    }
38
39    /// Returns true if called with a Val of the same type as itself.
40    pub fn type_equal(&self, target: &Self) -> bool {
41        enum_type_equality!(
42            self,
43            target,
44            &Val::Empty,
45            &Val::Boolean(_),
46            &Val::Int(_),
47            &Val::Float(_),
48            &Val::Str(_),
49            &Val::List(_),
50            &Val::Tuple(_),
51            &Val::Env(_)
52        )
53    }
54
55    pub fn equal(&self, target: &Self) -> Result<bool, error::BuildError> {
56        // first we do a type equality comparison
57        match (self, target) {
58            // Empty values are always equal.
59            (&Val::Empty, &Val::Empty) => Ok(true),
60            (&Val::Int(ref i), &Val::Int(ref ii)) => Ok(i == ii),
61            (&Val::Float(ref f), &Val::Float(ref ff)) => Ok(f == ff),
62            (&Val::Boolean(ref b), &Val::Boolean(ref bb)) => Ok(b == bb),
63            (&Val::Str(ref s), &Val::Str(ref ss)) => Ok(s == ss),
64            (&Val::List(ref ldef), &Val::List(ref rdef)) => {
65                if ldef.len() != rdef.len() {
66                    Ok(false)
67                } else {
68                    for (i, lv) in ldef.iter().enumerate() {
69                        if !lv.equal(rdef[i].as_ref())? {
70                            return Ok(false);
71                        }
72                    }
73                    Ok(true)
74                }
75            }
76            (&Val::Tuple(ref ldef), &Val::Tuple(ref rdef)) => {
77                if ldef.len() != rdef.len() {
78                    Ok(false)
79                } else {
80                    for (i, lv) in ldef.iter().enumerate() {
81                        let field_target = &rdef[i];
82                        if lv.0 != field_target.0 {
83                            // field name equality
84                            return Ok(false);
85                        } else {
86                            // field value equality.
87                            if !lv.1.equal(field_target.1.as_ref())? {
88                                return Ok(false);
89                            }
90                        }
91                    }
92                    Ok(true)
93                }
94            }
95            // EMPTY is always comparable for equality.
96            (&Val::Empty, _) => Ok(false),
97            (_, &Val::Empty) => Ok(false),
98            (me, tgt) => Err(error::BuildError::new(
99                format!("Expected {} but got ({})", me.type_name(), tgt),
100                error::ErrorType::TypeFail,
101            )),
102        }
103    }
104
105    /// Returns the fields if this Val is a tuple. None otherwise.
106    pub fn get_fields(&self) -> Option<&Vec<(String, Rc<Val>)>> {
107        if let &Val::Tuple(ref fs) = self {
108            Some(fs)
109        } else {
110            None
111        }
112    }
113
114    pub fn is_int(&self) -> bool {
115        if let &Val::Int(_) = self {
116            return true;
117        }
118        return false;
119    }
120
121    pub fn is_empty(&self) -> bool {
122        if let &Val::Empty = self {
123            return true;
124        }
125        return false;
126    }
127
128    pub fn is_float(&self) -> bool {
129        if let &Val::Float(_) = self {
130            return true;
131        }
132        return false;
133    }
134
135    pub fn is_string(&self) -> bool {
136        if let &Val::Str(_) = self {
137            return true;
138        }
139        return false;
140    }
141
142    pub fn is_tuple(&self) -> bool {
143        if let &Val::Tuple(_) = self {
144            return true;
145        }
146        return false;
147    }
148
149    pub fn is_env(&self) -> bool {
150        if let &Val::Env(_) = self {
151            return true;
152        }
153        return false;
154    }
155
156    pub fn is_list(&self) -> bool {
157        if let &Val::List(_) = self {
158            return true;
159        }
160        return false;
161    }
162
163    pub fn is_bool(&self) -> bool {
164        if let &Val::Boolean(_) = self {
165            return true;
166        }
167        return false;
168    }
169
170    pub fn is_str(&self) -> bool {
171        if let &Val::Str(_) = self {
172            return true;
173        }
174        return false;
175    }
176}
177
178impl Display for Val {
179    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
180        match self {
181            &Val::Boolean(b) => write!(f, "{}", b),
182            &Val::Empty => write!(f, "NULL"),
183            &Val::Float(ref ff) => write!(f, "{}", ff),
184            &Val::Int(ref i) => write!(f, "{}", i),
185            &Val::Str(ref s) => write!(f, "\"{}\"", s.replace("\"", "\\\"")),
186            &Val::List(ref def) => {
187                write!(f, "[")?;
188                for v in def.iter() {
189                    write!(f, "{}, ", v)?;
190                }
191                write!(f, "]")
192            }
193            &Val::Tuple(ref def) => {
194                write!(f, "{{\n")?;
195                for v in def.iter() {
196                    write!(f, "\t{} = {},\n", v.0, v.1)?;
197                }
198                write!(f, "}}")
199            }
200            &Val::Env(ref def) => {
201                write!(f, "{{\n")?;
202                for v in def.iter() {
203                    write!(f, "\t{}=\"{}\"\n", v.0, v.1)?;
204                }
205                write!(f, "}}")
206            }
207        }
208    }
209}
210
211impl From<Val> for String {
212    fn from(v: Val) -> String {
213        match v {
214            Val::Int(ref i) => format!("{}", i),
215            Val::Float(ref f) => format!("{}", f),
216            Val::Str(ref s) => s.to_string(),
217            Val::Boolean(ref b) => format!("{}", b),
218            Val::Empty => "NULL".to_string(),
219            val => format!("{}", val),
220        }
221    }
222}
223
224impl From<String> for Val {
225    fn from(s: String) -> Val {
226        Val::Str(s)
227    }
228}