1#![doc = include_str!("../README.md")]
2#![deny(missing_docs)]
3extern crate piston_meta;
4extern crate range;
5extern crate read_color;
6extern crate read_token;
7#[cfg(all(not(target_family = "wasm"), feature = "http"))]
8extern crate reqwest;
9#[macro_use]
10extern crate lazy_static;
11extern crate tree_mem_sort;
12extern crate vecmath;
13
14use piston_meta::{parse_errstr, syntax_errstr, MetaData, Syntax};
15use range::Range;
16use std::any::Any;
17use std::collections::HashMap;
18use std::fmt;
19use std::sync::{Arc, Mutex};
20#[cfg(all(not(target_family = "wasm"), feature = "threading"))]
21use threading::JoinHandle;
22
23pub mod ast;
24pub mod embed;
25mod lifetime;
26mod link;
27pub mod macros;
28mod mat4;
29mod module;
30mod prelude;
31pub mod runtime;
32#[cfg(all(not(target_family = "wasm"), feature = "threading"))]
33pub mod threading;
34mod ty;
35mod vec4;
36mod write;
37
38mod dyon_std;
39mod grab;
40
41pub use ast::Lazy;
42pub use link::Link;
43pub use mat4::Mat4;
44pub use module::Module;
45pub use prelude::{Dfn, Lt, Prelude};
46pub use runtime::Runtime;
47pub use ty::Type;
48pub use vec4::Vec4;
49
50pub const TINVOTS: &str = "There is no value on the stack";
52pub const CSIE: &str = "Call stack is empty";
54
55lazy_static! {
56 pub(crate) static ref LESS: Arc<String> = Arc::new("less".into());
57 pub(crate) static ref LESS_OR_EQUAL: Arc<String> = Arc::new("less_or_equal".into());
58 pub(crate) static ref GREATER: Arc<String> = Arc::new("greater".into());
59 pub(crate) static ref GREATER_OR_EQUAL: Arc<String> = Arc::new("greater_or_equal".into());
60 pub(crate) static ref EQUAL: Arc<String> = Arc::new("equal".into());
61 pub(crate) static ref NOT_EQUAL: Arc<String> = Arc::new("not_equal".into());
62 pub(crate) static ref AND_ALSO: Arc<String> = Arc::new("and_also".into());
63 pub(crate) static ref OR_ELSE: Arc<String> = Arc::new("or_else".into());
64 pub(crate) static ref ADD: Arc<String> = Arc::new("add".into());
65 pub(crate) static ref SUB: Arc<String> = Arc::new("sub".into());
66 pub(crate) static ref MUL: Arc<String> = Arc::new("mul".into());
67 pub(crate) static ref DIV: Arc<String> = Arc::new("div".into());
68 pub(crate) static ref REM: Arc<String> = Arc::new("rem".into());
69 pub(crate) static ref POW: Arc<String> = Arc::new("pow".into());
70 pub(crate) static ref DOT: Arc<String> = Arc::new("dot".into());
71 pub(crate) static ref CROSS: Arc<String> = Arc::new("cross".into());
72 pub(crate) static ref NOT: Arc<String> = Arc::new("not".into());
73 pub(crate) static ref NEG: Arc<String> = Arc::new("neg".into());
74 pub(crate) static ref NORM: Arc<String> = Arc::new("norm".into());
75 pub(crate) static ref T: Arc<String> = Arc::new("T".into());
76}
77
78pub type LazyInvariant = &'static [&'static [Lazy]];
80
81pub static LAZY_UNWRAP_OR: LazyInvariant = &[&[Lazy::UnwrapOk, Lazy::UnwrapSome]];
83pub static LAZY_AND: LazyInvariant = &[&[Lazy::Variable(Variable::Bool(false, None))]];
85pub static LAZY_OR: LazyInvariant = &[&[Lazy::Variable(Variable::Bool(true, None))]];
87pub static LAZY_NO: LazyInvariant = &[];
89
90pub type Array = Arc<Vec<Variable>>;
92pub type Object = Arc<HashMap<Arc<String>, Variable>>;
94pub type RustObject = Arc<Mutex<dyn Any>>;
96
97#[derive(Debug, Clone)]
99pub struct Error {
100 pub message: Variable,
102 pub trace: Vec<String>,
105}
106
107#[cfg(all(not(target_family = "wasm"), feature = "threading"))]
109#[derive(Clone)]
110pub struct Thread {
111 pub handle: Option<Arc<Mutex<JoinHandle<Result<Variable, String>>>>>,
113}
114
115#[cfg(all(not(target_family = "wasm"), feature = "threading"))]
116impl Thread {
117 pub fn new(handle: JoinHandle<Result<Variable, String>>) -> Thread {
119 Thread {
120 handle: Some(Arc::new(Mutex::new(handle))),
121 }
122 }
123
124 pub fn invalidate_handle(
127 rt: &mut Runtime,
128 var: Variable,
129 ) -> Result<JoinHandle<Result<Variable, String>>, String> {
130 let thread = match var {
131 Variable::Ref(ind) => {
132 use std::mem::replace;
133
134 match replace(
135 &mut rt.stack[ind],
136 Variable::Thread(Thread { handle: None }),
137 ) {
138 Variable::Thread(th) => th,
139 x => return Err(rt.expected(&x, "Thread")),
140 }
141 }
142 Variable::Thread(thread) => thread,
143 x => return Err(rt.expected(&x, "Thread")),
144 };
145 let handle = match thread.handle {
146 None => return Err("The Thread has already been invalidated".into()),
147 Some(thread) => thread,
148 };
149 let mutex = Arc::try_unwrap(handle).map_err(|_| {
150 format!(
151 "{}\nCan not access Thread because there is \
152 more than one reference to it",
153 rt.stack_trace()
154 )
155 })?;
156 mutex.into_inner().map_err(|err| {
157 format!(
158 "{}\nCan not lock Thread mutex:\n{}",
159 rt.stack_trace(),
160 err.to_string()
161 )
162 })
163 }
164}
165
166#[cfg(all(not(target_family = "wasm"), feature = "threading"))]
167impl fmt::Debug for Thread {
168 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
169 write!(f, "thread")
170 }
171}
172
173#[derive(Debug, Clone)]
175pub struct UnsafeRef(*mut Variable);
176
177#[derive(Clone)]
179pub struct ClosureEnvironment {
180 pub module: Arc<Module>,
182 pub relative: usize,
184}
185
186impl fmt::Debug for ClosureEnvironment {
187 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
188 write!(f, "ClosureEnvironment")
189 }
190}
191
192#[derive(Debug, Clone)]
194pub enum Variable {
195 Ref(usize),
197 Return,
199 Bool(bool, Option<Box<Vec<Variable>>>),
201 F64(f64, Option<Box<Vec<Variable>>>),
203 Vec4([f32; 4]),
205 Mat4(Box<[[f32; 4]; 4]>),
207 Str(Arc<String>),
209 Array(Array),
211 Object(Object),
213 Link(Box<Link>),
215 UnsafeRef(UnsafeRef),
217 RustObject(RustObject),
219 Option(Option<Box<Variable>>),
221 Result(Result<Box<Variable>, Box<Error>>),
223 #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
225 Thread(Thread),
226 Closure(Arc<ast::Closure>, Box<ClosureEnvironment>),
230 #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
232 In(Arc<Mutex<::std::sync::mpsc::Receiver<Variable>>>),
233}
234
235unsafe impl Send for Variable {}
239
240impl Variable {
241 pub fn f64(val: f64) -> Variable {
243 Variable::F64(val, None)
244 }
245
246 pub fn bool(val: bool) -> Variable {
248 Variable::Bool(val, None)
249 }
250
251 pub fn typeof_var(&self) -> Arc<String> {
253 use self::runtime::*;
254 use Variable::*;
255
256 match *self {
257 Str(_) => TEXT_TYPE.clone(),
258 F64(_, _) => F64_TYPE.clone(),
259 Vec4(_) => VEC4_TYPE.clone(),
260 Mat4(_) => MAT4_TYPE.clone(),
261 Return => RETURN_TYPE.clone(),
262 Bool(_, _) => BOOL_TYPE.clone(),
263 Object(_) => OBJECT_TYPE.clone(),
264 Array(_) => ARRAY_TYPE.clone(),
265 Link(_) => LINK_TYPE.clone(),
266 Ref(_) => REF_TYPE.clone(),
267 UnsafeRef(_) => UNSAFE_REF_TYPE.clone(),
268 RustObject(_) => RUST_OBJECT_TYPE.clone(),
269 Option(_) => OPTION_TYPE.clone(),
270 Result(_) => RESULT_TYPE.clone(),
271 #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
272 Thread(_) => THREAD_TYPE.clone(),
273 Closure(_, _) => CLOSURE_TYPE.clone(),
274 #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
275 In(_) => IN_TYPE.clone(),
276 }
277 }
278
279 fn deep_clone(&self, stack: &[Variable]) -> Variable {
280 use Variable::*;
281
282 match *self {
283 F64(_, _) => self.clone(),
284 Vec4(_) => self.clone(),
285 Mat4(_) => self.clone(),
286 Return => self.clone(),
287 Bool(_, _) => self.clone(),
288 Str(_) => self.clone(),
289 Object(ref obj) => {
290 let mut res = obj.clone();
291 for val in Arc::make_mut(&mut res).values_mut() {
292 *val = val.deep_clone(stack);
293 }
294 Object(res)
295 }
296 Array(ref arr) => {
297 let mut res = arr.clone();
298 for it in Arc::make_mut(&mut res) {
299 *it = it.deep_clone(stack);
300 }
301 Array(res)
302 }
303 Link(_) => self.clone(),
304 Ref(ind) => stack[ind].deep_clone(stack),
305 UnsafeRef(_) => panic!("Unsafe reference can not be cloned"),
306 RustObject(_) => self.clone(),
307 Option(None) => Variable::Option(None),
308 Option(Some(ref v)) => Option(Some(v.clone())),
310 Result(Ok(ref ok)) => Result(Ok(ok.clone())),
312 Result(Err(ref err)) => Result(Err(err.clone())),
314 #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
315 Thread(_) => self.clone(),
316 Closure(_, _) => self.clone(),
317 #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
318 In(_) => self.clone(),
319 }
320 }
321}
322
323impl PartialEq for Variable {
324 fn eq(&self, other: &Variable) -> bool {
325 match (self, other) {
326 (&Variable::Return, _) => false,
327 (&Variable::Bool(a, _), &Variable::Bool(b, _)) => a == b,
328 (&Variable::F64(a, _), &Variable::F64(b, _)) => a == b,
329 (&Variable::Str(ref a), &Variable::Str(ref b)) => a == b,
330 (&Variable::Object(ref a), &Variable::Object(ref b)) => a == b,
331 (&Variable::Array(ref a), &Variable::Array(ref b)) => a == b,
332 (&Variable::Ref(_), _) => false,
333 (&Variable::UnsafeRef(_), _) => false,
334 (&Variable::RustObject(_), _) => false,
335 _ => false,
336 }
337 }
338}
339
340#[derive(Clone, Copy, Debug)]
342pub enum FnIndex {
343 None,
345 Loaded(isize),
347 Void(FnVoidRef),
349 Return(FnReturnRef),
351 Lazy(FnReturnRef, LazyInvariant),
353 BinOp(FnBinOpRef),
355 UnOp(FnUnOpRef),
357}
358
359#[derive(Clone, Copy)]
361pub enum FnExt {
362 Void(fn(&mut Runtime) -> Result<(), String>),
364 Return(fn(&mut Runtime) -> Result<Variable, String>),
366 BinOp(fn(&Variable, &Variable) -> Result<Variable, String>),
368 UnOp(fn(&Variable) -> Result<Variable, String>),
370}
371
372impl From<fn(&mut Runtime) -> Result<(), String>> for FnExt {
373 fn from(val: fn(&mut Runtime) -> Result<(), String>) -> Self {
374 FnExt::Void(val)
375 }
376}
377
378impl From<fn(&mut Runtime) -> Result<Variable, String>> for FnExt {
379 fn from(val: fn(&mut Runtime) -> Result<Variable, String>) -> Self {
380 FnExt::Return(val)
381 }
382}
383
384impl From<fn(&Variable, &Variable) -> Result<Variable, String>> for FnExt {
385 fn from(val: fn(&Variable, &Variable) -> Result<Variable, String>) -> Self {
386 FnExt::BinOp(val)
387 }
388}
389
390impl From<fn(&Variable) -> Result<Variable, String>> for FnExt {
391 fn from(val: fn(&Variable) -> Result<Variable, String>) -> Self {
392 FnExt::UnOp(val)
393 }
394}
395
396impl fmt::Debug for FnExt {
397 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
398 write!(f, "FnExt")
399 }
400}
401
402#[derive(Copy)]
404pub struct FnUnOpRef(pub fn(&Variable) -> Result<Variable, String>);
405
406impl Clone for FnUnOpRef {
407 fn clone(&self) -> FnUnOpRef {
408 *self
409 }
410}
411
412impl fmt::Debug for FnUnOpRef {
413 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
414 write!(f, "FnUnOpRef")
415 }
416}
417
418#[derive(Copy)]
420pub struct FnBinOpRef(pub fn(&Variable, &Variable) -> Result<Variable, String>);
421
422impl Clone for FnBinOpRef {
423 fn clone(&self) -> FnBinOpRef {
424 *self
425 }
426}
427
428impl fmt::Debug for FnBinOpRef {
429 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
430 write!(f, "FnBinOpRef")
431 }
432}
433
434#[derive(Copy)]
436pub struct FnReturnRef(pub fn(&mut Runtime) -> Result<Variable, String>);
437
438impl Clone for FnReturnRef {
439 fn clone(&self) -> FnReturnRef {
440 *self
441 }
442}
443
444impl fmt::Debug for FnReturnRef {
445 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
446 write!(f, "FnExternalRef")
447 }
448}
449
450#[derive(Copy)]
452pub struct FnVoidRef(pub fn(&mut Runtime) -> Result<(), String>);
453
454impl Clone for FnVoidRef {
455 fn clone(&self) -> FnVoidRef {
456 *self
457 }
458}
459
460impl fmt::Debug for FnVoidRef {
461 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
462 write!(f, "FnExternalRef")
463 }
464}
465
466struct FnExternal {
467 namespace: Arc<Vec<Arc<String>>>,
468 name: Arc<String>,
469 f: FnExt,
470 p: Dfn,
471}
472
473impl Clone for FnExternal {
474 fn clone(&self) -> FnExternal {
475 FnExternal {
476 namespace: self.namespace.clone(),
477 name: self.name.clone(),
478 f: self.f,
479 p: self.p.clone(),
480 }
481 }
482}
483
484pub fn run(source: &str) -> Result<(), String> {
486 let mut module = Module::new();
487 load(source, &mut module)?;
488 let mut runtime = runtime::Runtime::new();
489 runtime.run(&Arc::new(module))?;
490 Ok(())
491}
492
493pub fn run_str(source: &str, d: Arc<String>) -> Result<(), String> {
495 let mut module = Module::new();
496 load_str(source, d, &mut module)?;
497 let mut runtime = runtime::Runtime::new();
498 runtime.run(&Arc::new(module))?;
499 Ok(())
500}
501
502pub struct Call {
504 args: Vec<Variable>,
505 name: Arc<String>,
506}
507
508impl Call {
509 pub fn new(name: &str) -> Call {
511 Call {
512 args: vec![],
513 name: Arc::new(name.into()),
514 }
515 }
516
517 pub fn arg<T: embed::PushVariable>(mut self, val: T) -> Self {
519 self.args.push(val.push_var());
520 self
521 }
522
523 pub fn vec4<T: embed::ConvertVec4>(mut self, val: T) -> Self {
525 self.args.push(Variable::Vec4(val.to()));
526 self
527 }
528
529 pub fn rust<T: 'static>(mut self, val: T) -> Self {
531 self.args
532 .push(Variable::RustObject(Arc::new(Mutex::new(val)) as RustObject));
533 self
534 }
535
536 pub fn run(&self, runtime: &mut Runtime, module: &Arc<Module>) -> Result<(), String> {
538 runtime.call_str(&self.name, &self.args, module)
539 }
540
541 pub fn run_ret<T: embed::PopVariable>(
543 &self,
544 runtime: &mut Runtime,
545 module: &Arc<Module>,
546 ) -> Result<T, String> {
547 let val = runtime.call_str_ret(&self.name, &self.args, module)?;
548 T::pop_var(runtime, runtime.get(&val))
549 }
550
551 pub fn run_vec4<T: embed::ConvertVec4>(
553 &self,
554 runtime: &mut Runtime,
555 module: &Arc<Module>,
556 ) -> Result<T, String> {
557 let val = runtime.call_str_ret(&self.name, &self.args, module)?;
558 match runtime.get(&val) {
559 &Variable::Vec4(val) => Ok(T::from(val)),
560 x => Err(runtime.expected(x, "vec4")),
561 }
562 }
563}
564
565pub fn load(source: &str, module: &mut Module) -> Result<(), String> {
567 use std::fs::File;
568 use std::io::Read;
569
570 let mut data_file =
571 File::open(source).map_err(|err| format!("Could not open `{}`, {}", source, err))?;
572 let mut data = Arc::new(String::new());
573 data_file.read_to_string(Arc::make_mut(&mut data))
574 .map_err(|err| format!("Could not open `{}`, {}", source, err))?;
575 load_str(source, data, module)
576}
577
578lazy_static! {
579 static ref SYNTAX_RULES: Result<Syntax, String> = {
580 let syntax = include_str!("../assets/syntax.txt");
581 syntax_errstr(syntax)
582 };
583}
584
585pub(crate) fn check_str(
592 source: &str,
593 d: Arc<String>,
594 module: &Module,
595) -> Result<Vec<lifetime::Node>, String> {
596 let syntax_rules = SYNTAX_RULES.as_ref().map_err(|err| err.clone())?;
597
598 let mut data = vec![];
599 parse_errstr(syntax_rules, &d, &mut data)
600 .map_err(|err| format!("In `{}:`\n{}", source, err))?;
601
602 let check_data = data.clone();
603 let prelude = Arc::new(Prelude::from_module(module));
604
605 let mut nodes = vec![];
606 let _ = lifetime::check_core(&mut nodes, &check_data, &prelude);
607 Ok(nodes)
608}
609
610pub fn load_str(source: &str, d: Arc<String>, module: &mut Module) -> Result<(), String> {
616 #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
617 struct MaybeThread<T>(std::thread::JoinHandle<T>);
618
619 #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
620 impl<T> MaybeThread<T>
621 where
622 T: Send + 'static,
623 {
624 fn spawn<F>(func: F) -> Self
625 where
626 F: FnOnce() -> T + Send + 'static,
627 {
628 Self(std::thread::spawn(func))
629 }
630 fn join(self) -> T {
631 self.0.join().unwrap()
632 }
633 }
634
635 #[cfg(any(target_family = "wasm", not(feature = "threading")))]
636 struct MaybeThread<T>(T);
637
638 #[cfg(any(target_family = "wasm", not(feature = "threading")))]
639 impl<T> MaybeThread<T> {
640 fn spawn<F>(func: F) -> Self where F: FnOnce() -> T {
641 Self(func())
642 }
643 fn join(self) -> T {
644 self.0
645 }
646 }
647
648 let syntax_rules = SYNTAX_RULES.as_ref().map_err(|err| err.clone())?;
649
650 let mut data = vec![];
651 parse_errstr(syntax_rules, &d, &mut data)
652 .map_err(|err| format!("In `{}:`\n{}", source, err))?;
653
654 let check_data = data.clone();
655 let prelude = Arc::new(Prelude::from_module(module));
656
657 let handle = MaybeThread::spawn(move || {
659 let check_data = check_data;
660 lifetime::check(&check_data, &prelude)
661 });
662
663 let mut ignored = vec![];
665 let conv_res = ast::convert(
666 Arc::new(source.into()),
667 d.clone(),
668 &data,
669 &mut ignored,
670 module,
671 );
672
673 match handle.join() {
675 Ok(refined_rets) => {
676 for (name, ty) in &refined_rets {
677 if let FnIndex::Loaded(f_index) = module.find_function(name, 0) {
678 let f = &mut module.functions[f_index as usize];
679 f.ret = ty.clone();
680 }
681 }
682 }
683 Err(err_msg) => {
684 use piston_meta::ParseErrorHandler;
685 use std::io::Write;
686
687 let (range, msg) = err_msg.decouple();
688
689 let mut buf: Vec<u8> = vec![];
690 writeln!(&mut buf, "In `{}`:\n", source).unwrap();
691 ParseErrorHandler::new(&d)
692 .write_msg(&mut buf, range, &msg)
693 .unwrap();
694 return Err(String::from_utf8(buf).unwrap());
695 }
696 }
697
698 check_ignored_meta_data(conv_res, source, &d, &data, &ignored)
699}
700
701pub fn load_meta(
704 source: &str,
705 d: Arc<String>,
706 data: &[Range<MetaData>],
707 module: &mut Module,
708) -> Result<(), String> {
709 let mut ignored = vec![];
711 let conv_res = ast::convert(
712 Arc::new(source.into()),
713 d.clone(),
714 data,
715 &mut ignored,
716 module,
717 );
718
719 check_ignored_meta_data(conv_res, source, &d, data, &ignored)
720}
721
722fn check_ignored_meta_data(
723 conv_res: Result<(), ()>,
724 source: &str,
725 d: &Arc<String>,
726 data: &[Range<MetaData>],
727 ignored: &[Range],
728) -> Result<(), String> {
729 use piston_meta::json;
730
731 if !ignored.is_empty() || conv_res.is_err() {
732 use piston_meta::ParseErrorHandler;
733 use std::io::Write;
734
735 let mut buf: Vec<u8> = vec![];
736 if !ignored.is_empty() {
737 writeln!(&mut buf, "Some meta data was ignored in the syntax").unwrap();
738 writeln!(&mut buf, "START IGNORED").unwrap();
739 json::write(&mut buf, &data[ignored[0].iter()]).unwrap();
740 writeln!(&mut buf, "END IGNORED").unwrap();
741
742 writeln!(&mut buf, "In `{}`:\n", source).unwrap();
743 ParseErrorHandler::new(d)
744 .write_msg(
745 &mut buf,
746 data[ignored[0].iter()][0].range(),
747 "Could not understand this",
748 )
749 .unwrap();
750 }
751 if let Err(()) = conv_res {
752 writeln!(&mut buf, "Conversion error").unwrap();
753 }
754 return Err(String::from_utf8(buf).unwrap());
755 }
756
757 Ok(())
758}
759
760pub fn error(res: Result<(), String>) -> bool {
762 match res {
763 Err(err) => {
764 println!();
765 println!(" --- ERROR --- ");
766 println!("{}", err);
767 true
768 }
769 Ok(()) => false,
770 }
771}