microcad_lang/eval/statements/
mod.rs1use crate::{eval::*, model::*};
9
10mod assignment_statement;
11mod expression_statement;
12mod if_statement;
13mod marker;
14mod return_statement;
15mod use_statement;
16
17pub use use_statement::*;
18
19impl Eval for Statement {
20 fn eval(&self, context: &mut EvalContext) -> EvalResult<Value> {
21 match self {
22 Self::Workbench(w) => {
23 w.grant(context)?;
24 Ok(Value::None)
25 }
26 Self::Module(m) => {
27 m.grant(context)?;
28 Ok(Value::None)
29 }
30 Self::Function(f) => {
31 f.grant(context)?;
32 Ok(Value::None)
33 }
34 Self::Use(u) => {
35 u.eval(context)?;
36 Ok(Value::None)
37 }
38 Self::Assignment(a) => {
39 a.eval(context)?;
40 Ok(Value::None)
41 }
42 Self::If(i) => i.eval(context),
43 Self::Expression(e) => e.eval(context),
44 Self::InnerAttribute(i) => {
45 i.grant(context)?;
46 Ok(Value::None)
47 }
48 Self::Init(i) => {
49 i.grant(context)?;
50 Ok(Value::None)
51 }
52 Self::Return(r) => r.eval(context),
53 }
54 }
55}
56
57impl Eval<Option<Model>> for Statement {
58 fn eval(&self, context: &mut EvalContext) -> EvalResult<Option<Model>> {
59 let model: Option<Model> = match self {
60 Self::Workbench(w) => {
61 w.grant(context)?;
62 None
63 }
64 Self::Module(m) => {
65 m.eval(context)?;
66 None
67 }
68 Self::Function(f) => {
69 f.grant(context)?;
70 None
71 }
72 Self::Init(i) => {
73 i.grant(context)?;
74 None
75 }
76 Self::Return(r) => {
77 r.grant(context)?;
78 None
79 }
80 Self::Use(u) => {
81 u.eval(context)?;
82 None
83 }
84 Self::Assignment(a) => {
85 a.eval(context)?;
86 None
87 }
88 Self::If(i) => i.eval(context)?,
89 Self::Expression(e) => e.eval(context)?,
90 Self::InnerAttribute(a) => {
91 a.grant(context)?;
92 None
93 }
94 };
95
96 if let Some(ref model) = model {
97 if model.deduce_output_type() == OutputType::InvalidMixed {
98 context.error(self, EvalError::CannotMixGeometry)?;
99 }
100 }
101
102 Ok(model)
103 }
104}
105
106impl Eval<Value> for StatementList {
107 fn eval(&self, context: &mut EvalContext) -> EvalResult<Value> {
108 let mut result = Value::None;
109 for statement in self.iter() {
110 log::trace!("Evaluating statement: {statement}");
111 match statement.eval(context)? {
112 Value::Return(result) => {
113 return Ok(Value::Return(result));
114 }
115 value => result = value,
116 }
117 }
118 Ok(result)
119 }
120}
121
122impl Eval<Attributes> for StatementList {
124 fn eval(&self, context: &mut EvalContext) -> EvalResult<Attributes> {
125 let mut attributes = Vec::new();
126 for statement in self.iter() {
127 if let Statement::InnerAttribute(attribute) = statement {
128 attributes.append(&mut attribute.eval(context)?);
129 }
130 }
131
132 Ok(Attributes(attributes))
133 }
134}
135
136impl Eval<Models> for StatementList {
137 fn eval(&self, context: &mut EvalContext) -> EvalResult<Models> {
138 let mut models = Models::default();
139 let mut output_type = OutputType::NotDetermined;
140
141 for statement in self.iter() {
142 if let Some(model) = statement.eval(context)? {
143 output_type = output_type.merge(&model.deduce_output_type());
144 if output_type == OutputType::InvalidMixed {
145 context.error(statement, EvalError::CannotMixGeometry)?;
146 }
147 models.push(model);
148 }
149 }
150 models.deduce_output_type();
151 Ok(models)
152 }
153}