1use super::*;
2use crate::parser::*;
3use std::collections::HashMap;
4
5#[derive(Debug, Clone)]
6pub enum Expr {
7 True,
8 False,
9 ResourceEq(Reference<ResourceId>, Reference<StateId>),
10 ResourceNe(Reference<ResourceId>, Reference<StateId>),
11 Not(Box<Expr>),
12 And(Box<Expr>, Box<Expr>),
13 Or(Box<Expr>, Box<Expr>),
14 Implies(Box<Expr>, Box<Expr>),
15}
16
17impl Expr {
18 pub fn resolve_resource(&mut self, map: &HashMap<String, ResourceId>) -> Result<(), RlError> {
19 match self {
20 Expr::True => Ok(()),
21 Expr::False => Ok(()),
22 Expr::ResourceEq(resource, _) => match resource {
23 Reference::Unresolved(name, pos) => match map.get(name) {
24 Some(id) => {
25 *resource = Reference::Resolved(*id);
26 Ok(())
27 }
28 None => Err(RlError::Resolve {
29 element: format!("resource '{}'", name),
30 position: pos.clone(),
31 }),
32 },
33 Reference::Resolved(_) => Ok(()),
34 },
35 Expr::ResourceNe(resource, _) => match resource {
36 Reference::Unresolved(name, pos) => match map.get(name) {
37 Some(id) => {
38 *resource = Reference::Resolved(*id);
39 Ok(())
40 }
41 None => Err(RlError::Resolve {
42 element: format!("resource '{}'", name),
43 position: pos.clone(),
44 }),
45 },
46 Reference::Resolved(_) => Ok(()),
47 },
48 Expr::Not(e) => e.resolve_resource(map),
49 Expr::And(l, r) => {
50 l.resolve_resource(map)?;
51 r.resolve_resource(map)
52 }
53 Expr::Or(l, r) => {
54 l.resolve_resource(map)?;
55 r.resolve_resource(map)
56 }
57 Expr::Implies(l, r) => {
58 l.resolve_resource(map)?;
59 r.resolve_resource(map)
60 }
61 }
62 }
63
64 pub fn resolve_state(&mut self, map: &HashMap<String, StateId>) -> Result<(), RlError> {
65 match self {
66 Expr::True => Ok(()),
67 Expr::False => Ok(()),
68 Expr::ResourceEq(_, state) => match state {
69 Reference::Unresolved(name, pos) => match map.get(name) {
70 Some(id) => {
71 *state = Reference::Resolved(*id);
72 Ok(())
73 }
74 None => Err(RlError::Resolve {
75 element: format!("state '{}'", name),
76 position: pos.clone(),
77 }),
78 },
79 Reference::Resolved(_) => Ok(()),
80 },
81 Expr::ResourceNe(_, state) => match state {
82 Reference::Unresolved(name, pos) => match map.get(name) {
83 Some(id) => {
84 *state = Reference::Resolved(*id);
85 Ok(())
86 }
87 None => Err(RlError::Resolve {
88 element: format!("state '{}'", name),
89 position: pos.clone(),
90 }),
91 },
92 Reference::Resolved(_) => Ok(()),
93 },
94 Expr::Not(e) => e.resolve_state(map),
95 Expr::And(l, r) => {
96 l.resolve_state(map)?;
97 r.resolve_state(map)
98 }
99 Expr::Or(l, r) => {
100 l.resolve_state(map)?;
101 r.resolve_state(map)
102 }
103 Expr::Implies(l, r) => {
104 l.resolve_state(map)?;
105 r.resolve_state(map)
106 }
107 }
108 }
109}
110
111impl ToLang for Expr {
112 fn to_lang(&self, skillset: &Skillset) -> String {
113 match self {
114 Expr::True => String::from("true"),
115 Expr::False => String::from("false"),
116 Expr::ResourceEq(resource, state) => {
117 format!(
118 "{} == {}",
119 resource.to_lang(skillset),
120 state.to_lang(skillset)
121 )
122 }
123 Expr::ResourceNe(resource, state) => {
124 format!(
125 "{} != {}",
126 resource.to_lang(skillset),
127 state.to_lang(skillset)
128 )
129 }
130 Expr::Not(e) => format!("(not {})", e.to_lang(skillset)),
131 Expr::And(l, r) => format!("({} and {})", l.to_lang(skillset), r.to_lang(skillset)),
132 Expr::Or(l, r) => format!("({} or {})", l.to_lang(skillset), r.to_lang(skillset)),
133 Expr::Implies(l, r) => format!("({} => {})", l.to_lang(skillset), r.to_lang(skillset)),
134 }
135 }
136}