1use std::borrow::Cow;
10use std::collections::BTreeMap;
11use std::collections::HashSet;
12use std::ffi::OsStr;
13use std::ffi::OsString;
14use std::io::Cursor;
15use std::path::Path;
16use std::path::PathBuf;
17use std::sync::Arc;
18use std::sync::RwLock;
19use std::time::Instant;
20#[cfg(feature = "plot")]
21use crate::winit;
22use crate::error::*;
23use crate::intr::*;
24use crate::mod_node::*;
25#[cfg(feature = "plot")]
26use crate::plot::*;
27use crate::tree::*;
28use crate::utils::*;
29use crate::value::*;
30
31#[derive(Copy, Clone, Debug)]
33pub enum Input
34{
35 Std,
37 Null,
39}
40
41#[derive(Clone, Debug)]
43pub enum Output
44{
45 Std,
47 Null,
49 Cursor(Arc<RwLock<Cursor<Vec<u8>>>>),
51}
52
53#[cfg(feature = "plot")]
55pub type EventLoopProxy = winit::event_loop::EventLoopProxy<PlotterAppEvent>;
56
57#[cfg(not(feature = "plot"))]
59#[derive(Clone, Debug)]
60pub struct EventLoopProxy(());
61
62#[derive(Clone)]
70pub struct SharedEnv
71{
72 lib_path: OsString,
73 doc_path: OsString,
74 args: Vec<String>,
75 used_libs: HashSet<String>,
76 test_suites: HashSet<Vec<String>>,
77 intr_checker: Arc<dyn IntrCheck + Send + Sync>,
78 event_loop_proxy: Option<EventLoopProxy>,
79 instant: Instant,
80}
81
82impl SharedEnv
83{
84 pub fn new_with_intr_checker_and_event_loop_proxy(lib_path: OsString, doc_path: OsString, args: Vec<String>, intr_checker: Arc<dyn IntrCheck + Send + Sync>, event_loop_proxy: Option<EventLoopProxy>) -> Self
89 {
90 SharedEnv {
91 lib_path,
92 doc_path,
93 args,
94 used_libs: HashSet::new(),
95 test_suites: HashSet::new(),
96 intr_checker,
97 event_loop_proxy,
98 instant: Instant::now(),
99 }
100 }
101
102 pub fn new_with_intr_checker(lib_path: OsString, doc_path: OsString, args: Vec<String>, intr_checker: Arc<dyn IntrCheck + Send + Sync>) -> Self
106 { Self::new_with_intr_checker_and_event_loop_proxy(lib_path, doc_path, args, intr_checker, None) }
107
108 pub fn new(lib_path: OsString, doc_path: OsString, args: Vec<String>) -> Self
112 { Self::new_with_intr_checker(lib_path, doc_path, args, Arc::new(EmptyIntrChecker::new())) }
113
114 pub fn lib_path(&self) -> &OsStr
116 { self.lib_path.as_os_str() }
117
118 pub fn doc_path(&self) -> &OsStr
120 { self.doc_path.as_os_str() }
121
122 pub fn args(&self) -> &[String]
124 { self.args.as_slice() }
125
126 pub fn used_libs(&self) -> &HashSet<String>
128 { &self.used_libs }
129
130 pub fn has_used_lib(&self, lib: &String) -> bool
132 { self.used_libs.contains(lib) }
133
134 pub fn add_used_lib(&mut self, lib: String)
136 { self.used_libs.insert(lib); }
137
138 pub fn remove_used_lib(&mut self, lib: &String)
140 { self.used_libs.remove(lib); }
141
142 pub fn test_suites(&self) -> &HashSet<Vec<String>>
144 { &self.test_suites }
145
146 pub fn has_test_suite(&self, idents: &Vec<String>) -> bool
148 { self.test_suites.contains(idents) }
149
150 pub fn add_test_suite(&mut self, idents: Vec<String>)
152 { self.test_suites.insert(idents); }
153
154 pub fn remove_test_suite(&mut self, idents: &Vec<String>)
156 { self.test_suites.remove(idents); }
157
158 pub fn intr_checker(&self) -> &Arc<dyn IntrCheck + Send + Sync>
160 { &self.intr_checker }
161
162 pub fn event_loop_proxy(&self) -> Option<&EventLoopProxy>
165 {
166 match &self.event_loop_proxy {
167 Some(event_loop_proxy) => Some(event_loop_proxy),
168 None => None,
169 }
170 }
171
172 pub fn instant(&self) -> &Instant
174 { &self.instant }
175}
176
177#[derive(Clone)]
185pub struct Env
186{
187 root_mod: Arc<RwLock<ModNode<Value, ()>>>,
188 current_mod: Arc<RwLock<ModNode<Value, ()>>>,
189 mod_idents: Vec<String>,
190 stack: Vec<(Arc<RwLock<ModNode<Value, ()>>>, BTreeMap<String, Value>)>,
191 script_dir: PathBuf,
192 domain: Option<String>,
193 stdin: Input,
194 stdout: Output,
195 stderr: Output,
196 shared_env: Arc<RwLock<SharedEnv>>,
197}
198
199impl Env
200{
201 pub fn new_with_script_dir_and_domain_and_shared_env(root_mod: Arc<RwLock<ModNode<Value, ()>>>, script_dir: PathBuf, domain: Option<String>, shared_env: Arc<RwLock<SharedEnv>>) -> Self
206 {
207 Env {
208 root_mod: root_mod.clone(),
209 current_mod: root_mod,
210 mod_idents: Vec::new(),
211 stack: Vec::new(),
212 script_dir,
213 domain,
214 stdin: Input::Std,
215 stdout: Output::Std,
216 stderr: Output::Std,
217 shared_env,
218 }
219 }
220
221 pub fn new(root_mod: Arc<RwLock<ModNode<Value, ()>>>) -> Self
225 { Self::new_with_script_dir_and_domain_and_shared_env(root_mod, PathBuf::from("."), None, Arc::new(RwLock::new(SharedEnv::new(OsString::from("."), OsString::from("."), Vec::new())))) }
226
227 pub fn clone_without_stack(&self) -> Self
229 {
230 Env {
231 root_mod: self.root_mod.clone(),
232 current_mod: self.current_mod.clone(),
233 mod_idents: self.mod_idents.clone(),
234 stack: Vec::new(),
235 script_dir: self.script_dir.clone(),
236 domain: self.domain.clone(),
237 stdin: self.stdin,
238 stdout: self.stdout.clone(),
239 stderr: self.stderr.clone(),
240 shared_env: self.shared_env.clone(),
241 }
242 }
243
244 pub fn root_mod(&self) -> &Arc<RwLock<ModNode<Value, ()>>>
246 { &self.root_mod }
247
248 pub fn current_mod(&self) -> &Arc<RwLock<ModNode<Value, ()>>>
250 { &self.current_mod }
251
252 pub fn mod_idents(&self) -> &[String]
254 { self.mod_idents.as_slice() }
255
256 pub fn stack(&self) -> &[(Arc<RwLock<ModNode<Value, ()>>>, BTreeMap<String, Value>)]
258 { self.stack.as_slice() }
259
260 pub fn script_dir(&self) -> &Path
262 { self.script_dir.as_path() }
263
264 pub fn domain(&self) -> Option<&str>
266 {
267 match &self.domain {
268 Some(domain) => Some(domain.as_str()),
269 None => None,
270 }
271 }
272
273 pub fn stdin(&self) -> &Input
275 { &self.stdin }
276
277 pub fn set_stdin(&mut self, input: Input)
279 { self.stdin = input; }
280
281 pub fn stdout(&self) -> &Output
283 { &self.stdout }
284
285 pub fn set_stdout(&mut self, output: Output)
287 { self.stdout = output; }
288
289 pub fn stderr(&self) -> &Output
291 { &self.stderr }
292
293 pub fn set_stderr(&mut self, output: Output)
295 { self.stderr = output; }
296
297 pub fn shared_env(&self) -> &Arc<RwLock<SharedEnv>>
299 { &self.shared_env }
300
301 pub fn add_and_push_mod(&mut self, ident: String) -> Result<bool>
308 {
309 {
310 let current_mod_g = rw_lock_read(&self.current_mod)?;
311 if current_mod_g.has_mod(&ident) {
312 return Ok(false);
313 }
314 }
315 let new_mod: Arc<RwLock<ModNode<Value, ()>>> = Arc::new(RwLock::new(ModNode::new(())));
316 ModNode::add_mod(&self.current_mod, ident.clone(), new_mod.clone())?;
317 self.current_mod = new_mod;
318 self.mod_idents.push(ident);
319 Ok(true)
320 }
321
322 pub fn pop_mod(&mut self) -> Result<bool>
327 {
328 let parent = {
329 let current_mod_g = rw_lock_read(&self.current_mod)?;
330 current_mod_g.parent()
331 };
332 match parent {
333 Some(parent) => {
334 self.current_mod = parent;
335 self.mod_idents.pop();
336 Ok(true)
337 },
338 None => Ok(false),
339 }
340 }
341
342 pub fn add_fun(&self, ident: String, fun: Arc<Fun>) -> Result<bool>
347 {
348 let mut current_mod_g = rw_lock_write(&self.current_mod)?;
349 if current_mod_g.has_var(&ident) {
350 return Ok(false);
351 }
352 current_mod_g.add_var(ident.clone(), Value::Object(Arc::new(Object::Fun(self.mod_idents.clone(), ident, fun))));
353 Ok(true)
354 }
355
356 pub fn push_fun_mod_and_local_vars(&mut self, fun_mod_idents: &[String], args: &[Arg], arg_values: &[Value]) -> Result<bool>
361 {
362 let fun_mod = match ModNode::mod_from(&self.root_mod, fun_mod_idents, false)? {
363 Some(tmp_fun_mod) => tmp_fun_mod,
364 None => return Err(Error::NoFunMod),
365 };
366 if args.len() != arg_values.len() {
367 return Ok(false);
368 }
369 let mut local_vars: BTreeMap<String, Value> = BTreeMap::new();
370 for (arg, value) in args.iter().zip(arg_values.iter()) {
371 match arg {
372 Arg(ident, _) => {
373 local_vars.insert(ident.clone(), value.clone());
374 },
375 }
376 }
377 self.stack.push((fun_mod, local_vars));
378 Ok(true)
379 }
380
381 pub fn pop_fun_mod_and_local_vars(&mut self)
383 { self.stack.pop(); }
384
385 pub fn reset(&mut self) -> Result<()>
387 {
388 match self.mod_idents.first() {
389 Some(first_ident) => {
390 let mut root_mod_g = rw_lock_write(&self.root_mod)?;
391 root_mod_g.remove_mod(first_ident)?;
392 },
393 None => (),
394 }
395 self.current_mod = self.root_mod.clone();
396 self.mod_idents.clear();
397 self.stack.clear();
398 Ok(())
399 }
400
401 fn mod_tuple_for_name<'a>(&self, name: &'a Name, is_var: &mut bool, is_set: bool) -> Result<(Option<Arc<RwLock<ModNode<Value, ()>>>>, Cow<'a, String>, Option<Value>)>
402 {
403 *is_var = false;
404 match name {
405 Name::Abs(idents, ident) => {
406 match ModNode::mod_from(&self.root_mod, idents.as_slice(), false)? {
407 Some(tmp_mod) => Ok((Some(tmp_mod), Cow::Borrowed(ident), None)),
408 None => Ok((None, Cow::Borrowed(ident), None)),
409 }
410 },
411 Name::Rel(idents, ident) => {
412 let mod1 = match self.stack.last() {
413 Some((fun_mod, _)) => fun_mod.clone(),
414 None => self.current_mod.clone(),
415 };
416 if !idents.is_empty() {
417 match ModNode::mod_from(&mod1, idents.as_slice(), true)? {
418 Some(tmp_mod) => Ok((Some(tmp_mod), Cow::Borrowed(ident), None)),
419 None => {
420 match ModNode::mod_from(&self.root_mod, idents.as_slice(), false)? {
421 Some(tmp_mod) => Ok((Some(tmp_mod), Cow::Borrowed(ident), None)),
422 None => Ok((None, Cow::Borrowed(ident), None)),
423 }
424 }
425 }
426 } else {
427 let is_defined_var = {
428 let mod_g = rw_lock_read(&mod1)?;
429 mod_g.has_var(ident)
430 };
431 if is_defined_var {
432 Ok((Some(mod1), Cow::Borrowed(ident), None))
433 } else {
434 let mod_g = rw_lock_read(&mod1)?;
435 match mod_g.used_var(ident) {
436 Some(used_var) => Ok((used_var.mod1().to_arc(), Cow::Owned(used_var.ident().clone()), None)),
437 None => Ok((Some(mod1.clone()), Cow::Borrowed(ident), None)),
438 }
439 }
440 }
441 },
442 Name::Var(ident) => {
443 *is_var = true;
444 let mod1 = match self.stack.last() {
445 Some((fun_mod, _)) => fun_mod.clone(),
446 None => self.current_mod.clone(),
447 };
448 let local_var_value = if !is_set {
449 match self.stack.last() {
450 Some((_, local_vars)) => local_vars.get(ident).map(|v| v.clone()),
451 None => None,
452 }
453 } else {
454 None
455 };
456 if local_var_value.is_some() || (is_set && !self.stack.is_empty()) {
457 Ok((Some(mod1), Cow::Borrowed(ident), local_var_value))
458 } else {
459 let is_defined_var = {
460 let mod_g = rw_lock_read(&mod1)?;
461 mod_g.has_var(ident)
462 };
463 if is_defined_var {
464 Ok((Some(mod1), Cow::Borrowed(ident), None))
465 } else {
466 let mod_g = rw_lock_read(&mod1)?;
467 match mod_g.used_var(ident) {
468 Some(used_var) => Ok((used_var.mod1().to_arc(), Cow::Owned(used_var.ident().clone()), None)),
469 None => Ok((Some(mod1.clone()), Cow::Borrowed(ident), None)),
470 }
471 }
472 }
473 },
474 }
475 }
476
477 pub fn var(&self, name: &Name) -> Result<Option<Value>>
479 {
480 let mut is_var = false;
481 let (mod1, ident, value) = self.mod_tuple_for_name(name, &mut is_var, false)?;
482 match value {
483 Some(value) => return Ok(Some(value)),
484 None => (),
485 }
486 match mod1 {
487 Some(mod1) => {
488 let mut value: Option<Value>;
489 {
490 let mod1_g = rw_lock_read(&mod1)?;
491 value = mod1_g.var(&*ident).map(|v| v.clone());
492 }
493 if is_var && value.is_none() {
494 let root_mod_g = rw_lock_read(&self.root_mod)?;
495 value = root_mod_g.var(&*ident).map(|v| v.clone());
496 }
497 Ok(value)
498 },
499 None => Ok(None),
500 }
501 }
502
503 pub fn set_var(&mut self, name: &Name, value: Value) -> Result<bool>
506 {
507 let mut is_var = false;
508 let (mod1, ident, _) = self.mod_tuple_for_name(name, &mut is_var, true)?;
509 if is_var {
510 match self.stack.last_mut() {
511 Some((_, local_vars)) => {
512 local_vars.insert(ident.into_owned(), value);
513 return Ok(true)
514 },
515 None => (),
516 }
517 }
518 match mod1 {
519 Some(mod1) => {
520 let mut mod1_g = rw_lock_write(&mod1)?;
521 mod1_g.add_var(ident.into_owned(), value);
522 Ok(true)
523 },
524 None => Ok(false),
525 }
526 }
527
528 pub fn remove_local_var(&mut self, ident: &String) -> bool
531 {
532 match self.stack.last_mut() {
533 Some((_, local_vars)) => {
534 local_vars.remove(ident);
535 true
536 },
537 None => false,
538 }
539 }
540}
541
542#[cfg(test)]
543mod tests;