1use crate::data::data::PreviousInfo;
2use crate::data::position::Position;
3use crate::data::warnings::DisplayWarnings;
4use crate::data::{
5 ast::*,
6 context::ContextStepInfo,
7 data::Data,
8 literal::ContentType,
9 message::*,
10 primitive::{closure::capture_variables, PrimitiveNull, PrimitiveString},
11 Literal, Memory, MemoryType, MessageData, MSG,
12};
13use crate::error_format::*;
14use crate::interpreter::variable_handler::{
15 exec_path_actions, expr_to_literal,
16 forget_memories::{forget_scope_memories, remove_message_data_memories},
17 get_var_from_mem,
18 interval::*,
19 memory::*,
20 resolve_fn_args, search_goto_var_memory,
21};
22use crate::parser::ExitCondition;
23use std::collections::HashMap;
24use std::sync::mpsc;
25
26fn get_var_info<'a>(
27 expr: &'a Expr,
28 path: Option<&[(Interval, PathState)]>,
29 data: &'a mut Data,
30 msg_data: &mut MessageData,
31 sender: &Option<mpsc::Sender<MSG>>,
32) -> Result<
33 (
34 &'a mut Literal,
35 String,
36 MemoryType,
37 Option<Vec<(Interval, PathLiteral)>>,
38 ),
39 ErrorInfo,
40> {
41 match expr {
42 Expr::PathExpr { literal, path } => {
43 get_var_info(literal, Some(path), data, msg_data, sender)
44 }
45 Expr::IdentExpr(var) => match search_in_memory_type(var, data) {
46 Ok(_) => get_var_from_mem(
47 var.to_owned(),
48 &DisplayWarnings::On,
49 path,
50 data,
51 msg_data,
52 sender,
53 ),
54 Err(_) => {
57 let lit = PrimitiveNull::get_literal(var.interval.to_owned());
58
59 data.step_vars.insert(var.ident.to_owned(), lit);
60 get_var_from_mem(
61 var.to_owned(),
62 &DisplayWarnings::On,
63 path,
64 data,
65 msg_data,
66 sender,
67 )
68 }
69 },
70 e => Err(gen_error_info(
71 Position::new(interval_from_expr(e), &data.context.flow),
72 ERROR_GET_VAR_INFO.to_owned(),
73 )),
74 }
75}
76
77fn check_if_inserted_step<'a>(name: &str, interval: &Interval, data: &'a Data) -> Option<String> {
78 match data
79 .flow
80 .flow_instructions
81 .get_key_value(&InstructionScope::InsertStep(InsertStep {
82 name: name.to_owned(),
83 original_name: None,
84 from_flow: "".to_owned(),
85 interval: interval.clone(),
86 })) {
87 Some((InstructionScope::InsertStep(insert_step), _expr)) => {
88 Some(insert_step.from_flow.to_owned())
89 }
90 _ => None,
91 }
92}
93
94pub fn match_actions(
95 function: &ObjectType,
96 mut msg_data: MessageData,
97 data: &mut Data,
98 sender: &Option<mpsc::Sender<MSG>>,
99) -> Result<MessageData, ErrorInfo> {
100 match function {
101 ObjectType::Say(arg) => {
102 let lit =
103 expr_to_literal(arg, &DisplayWarnings::On, None, data, &mut msg_data, sender)?;
104
105 if lit.secure_variable {
107 let err = gen_error_info(
108 Position::new(lit.interval, &data.context.flow),
109 "Secure variable can not be displayed".to_owned(),
110 );
111
112 MSG::send_error_msg(&sender, &mut msg_data, Err(err));
113 Ok(msg_data)
114 } else {
115 let msg = Message::new(lit, &data.context.flow)?;
116 MSG::send(&sender, MSG::Message(msg.clone()));
117 Ok(Message::add_to_message(msg_data, MessageType::Msg(msg)))
118 }
119 }
120 ObjectType::Debug(args, interval) => {
121 let args = resolve_fn_args(args, data, &mut msg_data, &DisplayWarnings::On, sender)?;
122
123 let lit = args.args_to_debug(interval.to_owned());
124
125 if lit.secure_variable {
127 let err = gen_error_info(
128 Position::new(lit.interval, &data.context.flow),
129 "Secure variable can not be displayed".to_owned(),
130 );
131
132 MSG::send_error_msg(&sender, &mut msg_data, Err(err));
133 Ok(msg_data)
134 } else {
135 let msg = Message::new(lit, &data.context.flow)?;
136 MSG::send(&sender, MSG::Message(msg.clone()));
137 Ok(Message::add_to_message(msg_data, MessageType::Msg(msg)))
138 }
139 }
140 ObjectType::Log {
141 expr,
142 interval,
143 log_lvl,
144 } => {
145 let args = resolve_fn_args(expr, data, &mut msg_data, &DisplayWarnings::On, sender)?;
146 let log_msg = args.args_to_log();
147
148 MSG::send(
149 &sender,
150 MSG::Log {
151 flow: data.context.flow.to_owned(),
152 line: interval.start_line,
153 message: log_msg,
154 log_lvl: log_lvl.to_owned(),
155 },
156 );
157
158 Ok(msg_data)
159 }
160 ObjectType::Use(arg) => {
161 expr_to_literal(arg, &DisplayWarnings::On, None, data, &mut msg_data, sender)?;
162 Ok(msg_data)
163 }
164 ObjectType::Do(DoType::Update(assign_type, old, new)) => {
165 let (
170 tmp_flows,
171 tmp_extern_flows,
172 tmp_flow,
173 tmp_default_flow,
174 mut tmp_context,
175 tmp_event,
176 tmp_env,
177 tmp_loop_indexes,
178 tmp_loop_index,
179 mut tmp_step_count,
180 tmp_step_limit,
181 tmp_step_vars,
182 tmp_custom_component,
183 tmp_native_component,
184 ) = data.copy_scope();
185
186 let mut new_scope_data = Data::new(
187 &tmp_flows,
188 &tmp_extern_flows,
189 &tmp_flow,
190 tmp_default_flow,
191 &mut tmp_context,
192 &tmp_event,
193 &tmp_env,
194 tmp_loop_indexes,
195 tmp_loop_index,
196 &mut tmp_step_count,
197 tmp_step_limit,
198 tmp_step_vars,
199 data.previous_info.clone(),
200 &tmp_custom_component,
201 &tmp_native_component,
202 );
203 let mut new_value =
206 expr_to_literal(new, &DisplayWarnings::On, None, data, &mut msg_data, sender)?;
207
208 if new_value.secure_variable {
210 let err = gen_error_info(
211 Position::new(new_value.interval, &data.context.flow),
212 "Assignation of secure variable is not allowed".to_owned(),
213 );
214
215 MSG::send_error_msg(&sender, &mut msg_data, Err(err));
216 return Ok(msg_data);
217 }
218
219 let memory: HashMap<String, Literal> = data.get_all_memories();
221 capture_variables(&mut &mut new_value, memory, &data.context.flow);
222
223 let (lit, name, mem_type, path) = get_var_info(old, None, data, &mut msg_data, sender)?;
224
225 let primitive = match assign_type {
226 AssignType::AdditionAssignment => {
227 Some(lit.primitive.clone() + new_value.primitive.clone())
228 }
229 AssignType::SubtractionAssignment => {
230 Some(lit.primitive.clone() - new_value.primitive.clone())
231 }
232 AssignType::DivisionAssignment => {
233 Some(lit.primitive.clone() / new_value.primitive.clone())
234 }
235 AssignType::MultiplicationAssignment => {
236 Some(lit.primitive.clone() * new_value.primitive.clone())
237 }
238 AssignType::RemainderAssignment => {
239 Some(lit.primitive.clone() % new_value.primitive.clone())
240 }
241 AssignType::Assignment => None,
242 };
243
244 match primitive {
245 Some(Ok(primitive)) => {
246 new_value = Literal {
247 content_type: new_value.content_type,
248 interval: new_value.interval,
249 additional_info: None,
250 secure_variable: false,
251 primitive,
252 };
253 }
254 Some(Err(err)) => {
255 new_value = PrimitiveString::get_literal(&err, lit.interval);
256 MSG::send_error_msg(
257 &sender,
258 &mut msg_data,
259 Err(gen_error_info(
260 Position::new(new_value.interval, &new_scope_data.context.flow),
261 err,
262 )),
263 );
264 }
265 None => {}
266 }
267
268 let (new_value, update) = if let MemoryType::Constant = mem_type {
271 MSG::send_error_msg(
272 &sender,
273 &mut msg_data,
274 Err(gen_error_info(
275 Position::new(new_value.interval, &new_scope_data.context.flow),
276 format!("const variables are immutable"),
277 )),
278 );
279
280 (None, false)
281 } else {
282 (Some(new_value), true)
283 };
284
285 exec_path_actions(
286 lit,
287 &DisplayWarnings::On,
288 &mem_type,
289 new_value,
290 &path,
291 &ContentType::get(&lit),
292 &mut new_scope_data,
293 &mut msg_data,
294 sender,
295 )?;
296
297 save_literal_in_mem(
298 lit.to_owned(),
299 name,
300 &mem_type,
301 update,
302 data,
303 &mut msg_data,
304 sender,
305 );
306
307 Ok(msg_data)
308 }
309 ObjectType::Do(DoType::Exec(expr)) => {
310 expr_to_literal(
311 expr,
312 &DisplayWarnings::On,
313 None,
314 data,
315 &mut msg_data,
316 sender,
317 )?;
318 Ok(msg_data)
319 }
320 ObjectType::Goto(GotoType::Step(step), interval) => {
321 let step = search_goto_var_memory(step, &mut msg_data, data, sender)?;
322
323 match data.previous_info {
325 Some(ref mut previous_info) => {
326 previous_info.goto(data.context.flow.clone(), data.context.step.clone());
327 }
328 None => {
329 data.previous_info = Some(PreviousInfo::new(
330 data.context.flow.clone(),
331 data.context.step.clone(),
332 ))
333 }
334 }
335
336 let insert_from_flow = check_if_inserted_step(&step, interval, &data);
337
338 data.context.step = match insert_from_flow {
340 Some(from_flow) => ContextStepInfo::InsertedStep {
341 step: step.to_string(),
342 flow: from_flow,
343 },
344 None => ContextStepInfo::Normal(step.to_string()),
345 };
346
347 MSG::send(
348 &sender,
349 MSG::Next {
350 flow: None,
351 step: Some(data.context.step.clone()),
352 bot: None,
353 },
354 );
355
356 msg_data.exit_condition = Some(ExitCondition::Goto);
357
358 if step == "end" {
359 msg_data.exit_condition = Some(ExitCondition::End);
360 }
361
362 Ok(msg_data)
363 }
364 ObjectType::Goto(GotoType::Flow(flow), ..) => {
365 let flow = search_goto_var_memory(&flow, &mut msg_data, data, sender)?;
366
367 MSG::send(
368 &sender,
369 MSG::Next {
370 flow: Some(flow.to_string()),
371 step: None,
372 bot: None,
373 },
374 );
375
376 match data.previous_info {
378 Some(ref mut previous_info) => {
379 previous_info.goto(data.context.flow.clone(), data.context.step.clone());
380 }
381 None => {
382 data.previous_info = Some(PreviousInfo::new(
383 data.context.flow.clone(),
384 data.context.step.clone(),
385 ))
386 }
387 }
388 data.context.step = ContextStepInfo::Normal("start".to_string());
390 data.context.flow = flow.to_string();
391
392 msg_data.exit_condition = Some(ExitCondition::Goto);
393
394 Ok(msg_data)
395 }
396 ObjectType::Goto(
397 GotoType::StepFlow {
398 step,
399 flow,
400 bot: None,
401 },
402 interval,
403 ) => {
404 let step = match step {
405 Some(step) => search_goto_var_memory(&step, &mut msg_data, data, sender)?,
406 None => "start".to_owned(), };
408 let flow = match flow {
409 Some(flow) => search_goto_var_memory(&flow, &mut msg_data, data, sender)?,
410 None => data.context.flow.to_owned(), };
412
413 let mut flow_opt = Some(flow.clone());
414
415 msg_data.exit_condition = Some(ExitCondition::Goto);
416
417 if step == "end" {
418 msg_data.exit_condition = Some(ExitCondition::End);
419 flow_opt = None;
420 }
421
422 match data.previous_info {
424 Some(ref mut previous_info) => {
425 previous_info.goto(data.context.flow.clone(), data.context.step.clone());
426 }
427 None => {
428 data.previous_info = Some(PreviousInfo::new(
429 data.context.flow.clone(),
430 data.context.step.clone(),
431 ))
432 }
433 }
434
435 data.context.flow = flow.to_string();
437
438 let insert_from_flow = check_if_inserted_step(&step, interval, &data);
439
440 data.context.step = match insert_from_flow {
442 Some(from_flow) => ContextStepInfo::InsertedStep {
443 step: step.to_string(),
444 flow: from_flow,
445 },
446 None => ContextStepInfo::Normal(step.to_string()),
447 };
448
449 MSG::send(
450 &sender,
451 MSG::Next {
452 flow: flow_opt,
453 step: Some(data.context.step.clone()),
454 bot: None,
455 },
456 );
457
458 Ok(msg_data)
459 }
460
461 ObjectType::Goto(
462 GotoType::StepFlow {
463 step,
464 flow,
465 bot: Some(next_bot),
466 },
467 ..,
468 ) => {
469 let step = match step {
470 Some(step) => ContextStepInfo::UnknownFlow(search_goto_var_memory(
471 &step,
472 &mut msg_data,
473 data,
474 sender,
475 )?),
476 None => ContextStepInfo::Normal("start".to_owned()), };
478 let flow = match flow {
479 Some(flow) => search_goto_var_memory(&flow, &mut msg_data, data, sender).ok(),
480 None => None,
481 };
482
483 let bot = search_goto_var_memory(&next_bot, &mut msg_data, data, sender)?;
484
485 msg_data.exit_condition = Some(ExitCondition::End);
486
487 MSG::send(
488 &sender,
489 MSG::Next {
490 step: Some(step),
491 flow: flow,
492 bot: Some(bot), },
494 );
495
496 Ok(msg_data)
497 }
498
499 ObjectType::Previous(previous_type, _) => {
500 let flow_opt;
501 let mut step_opt = None;
502
503 match (previous_type, &mut data.previous_info) {
504 (PreviousType::Flow(_interval), Some(ref mut previous_info)) => {
505 let tmp_f = previous_info.flow.clone();
506 flow_opt = Some(tmp_f.clone());
507
508 previous_info.flow = data.context.flow.clone();
509 previous_info.step_at_flow =
510 (data.context.step.clone(), data.context.flow.clone());
511
512 data.context.flow = tmp_f;
513 data.context.step = ContextStepInfo::Normal("start".to_string());
514 }
515 (PreviousType::Step(_interval), Some(ref mut previous_info)) => {
516 let (tmp_s, tmp_f) = previous_info.step_at_flow.clone();
517 flow_opt = Some(tmp_f.clone());
518 step_opt = Some(tmp_s.clone());
519
520 if data.context.flow != tmp_f {
521 previous_info.flow = tmp_f.clone();
522 }
523 previous_info.step_at_flow =
524 (data.context.step.clone(), data.context.flow.clone());
525
526 data.context.flow = tmp_f;
527 data.context.step = tmp_s;
528 }
529 (_, None) => {
530 flow_opt = None;
531 step_opt = Some(ContextStepInfo::Normal("end".to_owned()));
532
533 data.context.step = ContextStepInfo::Normal("end".to_string());
534 }
535 }
536
537 msg_data.exit_condition = Some(ExitCondition::Goto);
538
539 MSG::send(
540 &sender,
541 MSG::Next {
542 flow: flow_opt,
543 step: step_opt,
544 bot: None,
545 },
546 );
547
548 Ok(msg_data)
549 }
550 ObjectType::Remember(name, variable) => {
551 let mut new_value = expr_to_literal(
552 variable,
553 &DisplayWarnings::On,
554 None,
555 data,
556 &mut msg_data,
557 sender,
558 )?;
559
560 if new_value.secure_variable {
562 let err = gen_error_info(
563 Position::new(new_value.interval, &data.context.flow),
564 "Assignation of secure variable is not allowed".to_owned(),
565 );
566
567 MSG::send_error_msg(&sender, &mut msg_data, Err(err));
568 return Ok(msg_data);
569 }
570
571 let memory: HashMap<String, Literal> = data.get_all_memories();
573 capture_variables(&mut &mut new_value, memory, &data.context.flow);
574
575 msg_data.add_to_memory(&name.ident, new_value.clone());
576
577 MSG::send(
578 &sender,
579 MSG::Remember(Memory::new(name.ident.to_owned(), new_value.clone())),
580 );
581
582 data.context
583 .current
584 .insert(name.ident.to_owned(), new_value);
585 Ok(msg_data)
586 }
587 ObjectType::Forget(memory, _interval) => {
588 remove_message_data_memories(&memory, &mut msg_data);
590 forget_scope_memories(&memory, data);
592
593 MSG::send(&sender, MSG::Forget(memory.to_owned()));
594
595 Ok(msg_data)
596 }
597
598 reserved => Err(gen_error_info(
599 Position::new(interval_from_reserved_fn(reserved), &data.context.flow),
600 ERROR_START_INSTRUCTIONS.to_owned(),
601 )),
602 }
603}