dyon/ast/
mod.rs

1//! Dyon Abstract Syntax Tree (AST).
2
3use piston_meta::{Convert, MetaData};
4use range::Range;
5use std::cell::Cell;
6use std::collections::HashMap;
7use std::sync::{self, Arc};
8
9use crate::{
10    FnIndex,
11    Module,
12    Prelude,
13    Type,
14    Variable
15};
16
17mod infer_len;
18mod replace;
19
20/// Convert meta data and load it into a module.
21pub fn convert(
22    file: Arc<String>,
23    source: Arc<String>,
24    data: &[Range<MetaData>],
25    ignored: &mut Vec<Range>,
26    module: &mut Module,
27) -> Result<(), ()> {
28    let mut convert = Convert::new(data);
29
30    let namespace = if let Ok((range, val)) = Namespace::from_meta_data(convert, ignored) {
31        convert.update(range);
32        val.names
33    } else {
34        Arc::new(vec![])
35    };
36
37    let use_lookup = if let Ok((range, val)) = Uses::from_meta_data(convert, ignored) {
38        convert.update(range);
39        UseLookup::from_uses_module(&val, module)
40    } else {
41        UseLookup::new()
42    };
43
44    loop {
45        if let Ok((range, function)) =
46            Function::from_meta_data(&namespace, &file, &source, "fn", convert, ignored)
47        {
48            convert.update(range);
49            module.register(function);
50        } else if convert.remaining_data_len() > 0 {
51            return Err(());
52        } else {
53            break;
54        }
55    }
56    let mut new_functions = module.functions.clone();
57    for i in 0..new_functions.len() {
58        new_functions[i].get_locals(i, module, &use_lookup);
59    }
60    module.functions = new_functions;
61    Ok(())
62}
63
64/// Function alias.
65#[derive(Copy, Clone)]
66pub enum FnAlias {
67    /// An alias to a loaded function.
68    Loaded(usize),
69    /// An alias to an external function.
70    External(usize),
71}
72
73/// Used to look up calls to imported functions.
74pub struct UseLookup {
75    /// Stores namespace aliases.
76    /// The first key is the alias to namespace.
77    /// The second key is the alias to the function.
78    pub aliases: HashMap<Arc<String>, HashMap<Arc<String>, FnAlias>>,
79}
80
81impl Default for UseLookup {
82    fn default() -> UseLookup {
83        UseLookup::new()
84    }
85}
86
87impl UseLookup {
88    /// Creates a new use lookup.
89    pub fn new() -> UseLookup {
90        UseLookup {
91            aliases: HashMap::new(),
92        }
93    }
94
95    /// This is called when constructing the AST.
96    pub fn from_uses_module(uses: &Uses, module: &Module) -> UseLookup {
97        let mut aliases = HashMap::new();
98        // First, add all glob imports.
99        for use_import in &uses.use_imports {
100            if !use_import.fns.is_empty() {
101                continue;
102            }
103            if !aliases.contains_key(&use_import.alias) {
104                aliases.insert(use_import.alias.clone(), HashMap::new());
105            }
106            let fns = aliases.get_mut(&use_import.alias).unwrap();
107            for (i, f) in module.functions.iter().enumerate().rev() {
108                if *f.namespace == use_import.names {
109                    fns.insert(f.name.clone(), FnAlias::Loaded(i));
110                }
111            }
112            for (i, f) in module.ext_prelude.iter().enumerate().rev() {
113                if *f.namespace == use_import.names {
114                    fns.insert(f.name.clone(), FnAlias::External(i));
115                }
116            }
117        }
118        // Second, add specific functions, which shadows glob imports.
119        for use_import in &uses.use_imports {
120            if use_import.fns.is_empty() {
121                continue;
122            }
123            if !aliases.contains_key(&use_import.alias) {
124                aliases.insert(use_import.alias.clone(), HashMap::new());
125            }
126            let fns = aliases.get_mut(&use_import.alias).unwrap();
127            for use_fn in &use_import.fns {
128                for (i, f) in module.functions.iter().enumerate().rev() {
129                    if *f.namespace != use_import.names {
130                        continue;
131                    }
132                    if f.name == use_fn.0 {
133                        fns.insert(
134                            use_fn.1.as_ref().unwrap_or(&use_fn.0).clone(),
135                            FnAlias::Loaded(i),
136                        );
137                    } else if f.name.len() > use_fn.0.len()
138                        && f.name.starts_with(&**use_fn.0)
139                        && f.name.as_bytes()[use_fn.0.len()] == b'('
140                    {
141                        // A function with mutable information.
142                        let mut name: Arc<String> = use_fn.1.as_ref().unwrap_or(&use_fn.0).clone();
143                        Arc::make_mut(&mut name).push_str(&f.name.as_str()[use_fn.0.len()..]);
144                        fns.insert(name, FnAlias::Loaded(i));
145                    }
146                }
147                for (i, f) in module.ext_prelude.iter().enumerate().rev() {
148                    if *f.namespace != use_import.names {
149                        continue;
150                    }
151                    if f.name == use_fn.0 {
152                        fns.insert(
153                            use_fn.1.as_ref().unwrap_or(&use_fn.0).clone(),
154                            FnAlias::External(i),
155                        );
156                    } else if f.name.len() > use_fn.0.len()
157                        && f.name.starts_with(&**use_fn.0)
158                        && f.name.as_bytes()[use_fn.0.len()] == b'('
159                    {
160                        // A function with mutable information.
161                        let mut name: Arc<String> = use_fn.1.as_ref().unwrap_or(&use_fn.0).clone();
162                        Arc::make_mut(&mut name).push_str(&f.name.as_str()[use_fn.0.len()..]);
163                        fns.insert(f.name.clone(), FnAlias::External(i));
164                    }
165                }
166            }
167        }
168        UseLookup { aliases }
169    }
170
171    /// This is called from lifetime/type checker.
172    /// Here, external functions are treated as loaded.
173    pub fn from_uses_prelude(uses: &Uses, prelude: &Prelude) -> UseLookup {
174        let mut aliases = HashMap::new();
175        // First, add all glob imports.
176        for use_import in &uses.use_imports {
177            if !use_import.fns.is_empty() {
178                continue;
179            }
180            if !aliases.contains_key(&use_import.alias) {
181                aliases.insert(use_import.alias.clone(), HashMap::new());
182            }
183            let fns = aliases.get_mut(&use_import.alias).unwrap();
184            for (i, f) in prelude.namespaces.iter().enumerate().rev() {
185                if *f.0 == use_import.names {
186                    fns.insert(f.1.clone(), FnAlias::Loaded(i));
187                }
188            }
189        }
190        // Second, add specific functions, which shadows glob imports.
191        for use_import in &uses.use_imports {
192            if use_import.fns.is_empty() {
193                continue;
194            }
195            if !aliases.contains_key(&use_import.alias) {
196                aliases.insert(use_import.alias.clone(), HashMap::new());
197            }
198            let fns = aliases.get_mut(&use_import.alias).unwrap();
199            for use_fn in &use_import.fns {
200                for (i, f) in prelude.namespaces.iter().enumerate().rev() {
201                    if *f.0 != use_import.names {
202                        continue;
203                    }
204                    if f.1 == use_fn.0 {
205                        fns.insert(
206                            use_fn.1.as_ref().unwrap_or(&use_fn.0).clone(),
207                            FnAlias::Loaded(i),
208                        );
209                    } else if f.1.len() > use_fn.0.len()
210                        && f.1.starts_with(&**use_fn.0)
211                        && f.1.as_bytes()[use_fn.0.len()] == b'('
212                    {
213                        // A function with mutable information.
214                        let mut name: Arc<String> = use_fn.1.as_ref().unwrap_or(&use_fn.0).clone();
215                        Arc::make_mut(&mut name).push_str(&f.1.as_str()[use_fn.0.len()..]);
216                        fns.insert(name, FnAlias::Loaded(i));
217                    }
218                }
219            }
220        }
221        UseLookup { aliases }
222    }
223}
224
225/// Namespace, used to organize code in larger projects.
226///
227/// E.g. `ns math::algebra`.
228#[derive(Debug, Clone)]
229pub struct Namespace {
230    /// Names separated by `::`.
231    pub names: Arc<Vec<Arc<String>>>,
232}
233
234impl Namespace {
235    /// Creates namespace from meta data.
236    pub fn from_meta_data(
237        mut convert: Convert,
238        ignored: &mut Vec<Range>,
239    ) -> Result<(Range, Namespace), ()> {
240        let start = convert;
241        let node = "ns";
242        let start_range = convert.start_node(node)?;
243        convert.update(start_range);
244
245        let mut names: Vec<Arc<String>> = vec![];
246        loop {
247            if let Ok(range) = convert.end_node(node) {
248                convert.update(range);
249                break;
250            } else if let Ok((range, val)) = convert.meta_string("name") {
251                convert.update(range);
252                names.push(val);
253            } else {
254                let range = convert.ignore();
255                convert.update(range);
256                ignored.push(range);
257            }
258        }
259
260        Ok((
261            convert.subtract(start),
262            Namespace {
263                names: Arc::new(names),
264            },
265        ))
266    }
267}
268
269/// Uses, lists use imports.
270#[derive(Debug, Clone)]
271pub struct Uses {
272    /// List of use imports.
273    pub use_imports: Vec<UseImport>,
274}
275
276impl Uses {
277    /// Creates uses from meta data.
278    pub fn from_meta_data(
279        mut convert: Convert,
280        ignored: &mut Vec<Range>,
281    ) -> Result<(Range, Uses), ()> {
282        let start = convert;
283        let node = "uses";
284        let start_range = convert.start_node(node)?;
285        convert.update(start_range);
286
287        let mut use_imports = vec![];
288        loop {
289            if let Ok(range) = convert.end_node(node) {
290                convert.update(range);
291                break;
292            } else if let Ok((range, val)) = UseImport::from_meta_data(convert, ignored) {
293                convert.update(range);
294                use_imports.push(val);
295            } else {
296                let range = convert.ignore();
297                convert.update(range);
298                ignored.push(range);
299            }
300        }
301
302        Ok((convert.subtract(start), Uses { use_imports }))
303    }
304}
305
306/// Use import.
307#[derive(Debug, Clone)]
308pub struct UseImport {
309    /// Namespace to import from.
310    pub names: Vec<Arc<String>>,
311    /// Function imports.
312    pub fns: Vec<(Arc<String>, Option<Arc<String>>)>,
313    /// The shared namespace alias.
314    pub alias: Arc<String>,
315}
316
317impl UseImport {
318    /// Create use import from meta data.
319    pub fn from_meta_data(
320        mut convert: Convert,
321        ignored: &mut Vec<Range>,
322    ) -> Result<(Range, UseImport), ()> {
323        let start = convert;
324        let node = "use";
325        let start_range = convert.start_node(node)?;
326        convert.update(start_range);
327
328        let mut names: Vec<Arc<String>> = vec![];
329        let mut alias: Option<Arc<String>> = None;
330        let mut fns = vec![];
331        loop {
332            if let Ok(range) = convert.end_node(node) {
333                convert.update(range);
334                break;
335            } else if let Ok((range, val)) = convert.meta_string("name") {
336                convert.update(range);
337                names.push(val);
338            } else if let Ok((range, val)) = convert.meta_string("use_fn") {
339                convert.update(range);
340
341                let fn_alias = if let Ok((range, val)) = convert.meta_string("use_fn_alias") {
342                    convert.update(range);
343                    Some(val)
344                } else {
345                    None
346                };
347                fns.push((val, fn_alias));
348            } else if let Ok((range, val)) = convert.meta_string("alias") {
349                convert.update(range);
350                alias = Some(val);
351            } else {
352                let range = convert.ignore();
353                convert.update(range);
354                ignored.push(range);
355            }
356        }
357
358        let alias = alias.ok_or(())?;
359        Ok((convert.subtract(start), UseImport { names, fns, alias }))
360    }
361}
362
363/// Function.
364#[derive(Debug, Clone)]
365pub struct Function {
366    /// The namespace of the function.
367    pub namespace: Arc<Vec<Arc<String>>>,
368    /// The name of the function.
369    pub name: Arc<String>,
370    /// The file which the function was loaded from.
371    pub file: Arc<String>,
372    /// The source code which the function is loaded from.
373    pub source: Arc<String>,
374    /// Function arguments.
375    pub args: Vec<Arg>,
376    /// Lazy invariants.
377    pub lazy_inv: Vec<Vec<Lazy>>,
378    /// Current object references.
379    pub currents: Vec<Current>,
380    /// Function block.
381    pub block: Block,
382    /// The return type of function.
383    pub ret: Type,
384    /// Whether local variable references has been looked up.
385    pub looked_up: Arc<sync::atomic::AtomicBool>,
386    /// The range in source.
387    pub source_range: Range,
388    /// List of senders that receive function input by creating an in-type.
389    pub senders: Arc<(
390        sync::atomic::AtomicBool,
391        sync::Mutex<Vec<sync::mpsc::Sender<Variable>>>,
392    )>,
393}
394
395impl Function {
396    /// Creates function from meta data.
397    pub fn from_meta_data(
398        namespace: &Arc<Vec<Arc<String>>>,
399        file: &Arc<String>,
400        source: &Arc<String>,
401        node: &str,
402        mut convert: Convert,
403        ignored: &mut Vec<Range>,
404    ) -> Result<(Range, Function), ()> {
405        use std::sync::atomic::AtomicBool;
406        use std::sync::Mutex;
407
408        let start = convert;
409        let start_range = convert.start_node(node)?;
410        convert.update(start_range);
411
412        let mut name: Option<Arc<String>> = None;
413        let mut args: Vec<Arg> = vec![];
414        let mut currents: Vec<Current> = vec![];
415        let mut block: Option<Block> = None;
416        let mut expr: Option<Expression> = None;
417        let mut ret: Option<Type> = None;
418        let mut lazy_inv: Vec<Vec<Lazy>> = vec![];
419        loop {
420            if let Ok(range) = convert.end_node(node) {
421                convert.update(range);
422                break;
423            } else if let Ok((range, val)) = convert.meta_string("name") {
424                convert.update(range);
425                name = Some(val);
426            } else if let Ok((range, val, lazy)) =
427                Arg::from_meta_data(file, source, convert, ignored)
428            {
429                convert.update(range);
430                args.push(val);
431                lazy_inv.push(lazy);
432            } else if let Ok((range, val)) = Current::from_meta_data(convert, ignored) {
433                convert.update(range);
434                currents.push(val);
435            } else if let Ok((range, val)) = convert.meta_bool("returns") {
436                convert.update(range);
437                ret = Some(if val { Type::Any } else { Type::Void })
438            } else if let Ok((range, val)) = Type::from_meta_data("ret_type", convert, ignored) {
439                convert.update(range);
440                ret = Some(val);
441            } else if let Ok((range, val)) =
442                Block::from_meta_data(file, source, "block", convert, ignored)
443            {
444                convert.update(range);
445                block = Some(val);
446            } else if let Ok((range, val)) =
447                Expression::from_meta_data(file, source, "expr", convert, ignored)
448            {
449                convert.update(range);
450                expr = Some(val);
451                ret = Some(Type::Any);
452            } else if convert.start_node("ty").is_ok() {
453                // Ignore extra type information,
454                // since this is only used by type checker.
455                let range = convert.ignore();
456                convert.update(range);
457            } else {
458                let range = convert.ignore();
459                convert.update(range);
460                ignored.push(range);
461            }
462        }
463
464        let mut name = name.ok_or(())?;
465        let block = match expr {
466            None => block.ok_or(())?,
467            Some(expr) => {
468                let source_range = expr.source_range();
469                Block {
470                    expressions: vec![Expression::Return(Box::new(expr))],
471                    source_range,
472                }
473            }
474        };
475        let mutable_args = args.iter().any(|arg| arg.mutable);
476        if mutable_args {
477            let mut name_plus_args = String::from(&**name);
478            name_plus_args.push('(');
479            let mut first = true;
480            for arg in &args {
481                if !first {
482                    name_plus_args.push(',');
483                }
484                name_plus_args.push_str(if arg.mutable { "mut" } else { "_" });
485                first = false;
486            }
487            name_plus_args.push(')');
488            name = Arc::new(name_plus_args);
489        }
490        let ret = ret.ok_or(())?;
491        // Remove empty lazy invariants.
492        while let Some(true) = lazy_inv.last().map(|lz| lz.is_empty()) {
493            lazy_inv.pop();
494        }
495        Ok((
496            convert.subtract(start),
497            Function {
498                namespace: namespace.clone(),
499                looked_up: Arc::new(AtomicBool::new(false)),
500                name,
501                file: file.clone(),
502                source: source.clone(),
503                args,
504                lazy_inv,
505                currents,
506                block,
507                ret,
508                source_range: convert.source(start).unwrap(),
509                senders: Arc::new((AtomicBool::new(false), Mutex::new(vec![]))),
510            },
511        ))
512    }
513
514    /// Returns `true` if the function returns something.
515    pub fn returns(&self) -> bool {
516        self.ret != Type::Void
517    }
518
519    fn get_locals(&mut self, relative: usize, module: &Module, use_lookup: &UseLookup) {
520        use std::sync::atomic::Ordering;
521
522        // Ensure sequential order just to be safe.
523        if self.looked_up.load(Ordering::SeqCst) {
524            return;
525        }
526        let mut stack: Vec<Option<Arc<String>>> = vec![];
527        let mut closure_stack: Vec<usize> = vec![];
528        if self.returns() {
529            // Use return type because it has the same name.
530            stack.push(Some(crate::runtime::RETURN_TYPE.clone()));
531        }
532        for arg in &self.args {
533            stack.push(Some(arg.name.clone()));
534        }
535        for current in &self.currents {
536            stack.push(Some(current.name.clone()));
537        }
538        self.block.get_locals(relative, &mut stack, &mut closure_stack, module, use_lookup);
539        self.looked_up.store(true, Ordering::SeqCst);
540    }
541}
542
543/// Closure.
544#[derive(Debug, Clone)]
545pub struct Closure {
546    /// The file where the closure was declared/created.
547    pub file: Arc<String>,
548    /// The source of the closure.
549    pub source: Arc<String>,
550    /// Closure arguments.
551    pub args: Vec<Arg>,
552    /// Current object references.
553    pub currents: Vec<Current>,
554    /// Closure expression.
555    pub expr: Expression,
556    /// The return type of the closure.
557    pub ret: Type,
558    /// The range in source.
559    pub source_range: Range,
560}
561
562impl Closure {
563    /// Create closure from meta data.
564    pub fn from_meta_data(
565        file: &Arc<String>,
566        source: &Arc<String>,
567        node: &str,
568        mut convert: Convert,
569        ignored: &mut Vec<Range>,
570    ) -> Result<(Range, Closure), ()> {
571        let start = convert;
572        let start_range = convert.start_node(node)?;
573        convert.update(start_range);
574
575        let mut args: Vec<Arg> = vec![];
576        let mut currents: Vec<Current> = vec![];
577        let mut expr: Option<Expression> = None;
578        let mut ret: Option<Type> = None;
579        loop {
580            if let Ok(range) = convert.end_node(node) {
581                convert.update(range);
582                break;
583            } else if let Ok((range, val, _)) = Arg::from_meta_data(file, source, convert, ignored)
584            {
585                convert.update(range);
586                args.push(val);
587            } else if let Ok((range, val)) = Current::from_meta_data(convert, ignored) {
588                convert.update(range);
589                currents.push(val);
590            } else if let Ok((range, val)) = convert.meta_bool("returns") {
591                convert.update(range);
592                ret = Some(if val { Type::Any } else { Type::Void })
593            } else if let Ok((range, val)) = Type::from_meta_data("ret_type", convert, ignored) {
594                convert.update(range);
595                ret = Some(val);
596            } else if let Ok((range, val)) =
597                Expression::from_meta_data(file, source, "expr", convert, ignored)
598            {
599                convert.update(range);
600                expr = Some(val);
601                ret = Some(Type::Any);
602            } else {
603                let range = convert.ignore();
604                convert.update(range);
605                ignored.push(range);
606            }
607        }
608
609        let ret = ret.ok_or(())?;
610        let expr = expr.ok_or(())?;
611        Ok((
612            convert.subtract(start),
613            Closure {
614                file: file.clone(),
615                source: source.clone(),
616                args,
617                currents,
618                expr,
619                ret,
620                source_range: convert.source(start).unwrap(),
621            },
622        ))
623    }
624
625    /// Returns `true` if the closure return something.
626    pub fn returns(&self) -> bool {
627        self.ret != Type::Void
628    }
629
630    fn get_locals(
631        &mut self,
632        relative: usize,
633        stack: &mut Vec<Option<Arc<String>>>,
634        closure_stack: &mut Vec<usize>,
635        module: &Module,
636        use_lookup: &UseLookup,
637    ) {
638        // Start new closure.
639        // Need a closure stack because `grab` expressions are relative
640        // to closure environment, not the locals inside the closure.
641        let cs = closure_stack.len();
642        closure_stack.push(stack.len());
643        if self.returns() {
644            // Use return type because it has the same name.
645            stack.push(Some(crate::runtime::RETURN_TYPE.clone()));
646        }
647        for arg in &self.args {
648            stack.push(Some(arg.name.clone()));
649        }
650        for current in &self.currents {
651            stack.push(Some(current.name.clone()));
652        }
653        self.expr.get_locals(relative, stack, closure_stack, module, use_lookup);
654        closure_stack.truncate(cs);
655    }
656}
657
658/// Grab expression.
659#[derive(Debug, Clone)]
660pub struct Grab {
661    /// Grab level.
662    pub level: u16,
663    /// The sub-expression to compute.
664    pub expr: Expression,
665    /// The range in source.
666    pub source_range: Range,
667}
668
669impl Grab {
670    /// Creates grab expression from meta data.
671    pub fn from_meta_data(
672        file: &Arc<String>,
673        source: &Arc<String>,
674        mut convert: Convert,
675        ignored: &mut Vec<Range>,
676    ) -> Result<(Range, Grab), ()> {
677        let start = convert;
678        let node = "grab";
679        let start_range = convert.start_node(node)?;
680        convert.update(start_range);
681
682        let mut level: Option<u16> = None;
683        let mut expr: Option<Expression> = None;
684        loop {
685            if let Ok(range) = convert.end_node(node) {
686                convert.update(range);
687                break;
688            } else if let Ok((range, val)) = convert.meta_f64("grab_level") {
689                convert.update(range);
690                level = Some(val as u16);
691            } else if let Ok((range, val)) =
692                Expression::from_meta_data(file, source, "expr", convert, ignored)
693            {
694                convert.update(range);
695                expr = Some(val);
696            } else {
697                let range = convert.ignore();
698                convert.update(range);
699                ignored.push(range);
700            }
701        }
702
703        let level = level.unwrap_or(1);
704        let expr = expr.ok_or(())?;
705        Ok((
706            convert.subtract(start),
707            Grab {
708                level,
709                expr,
710                source_range: convert.source(start).unwrap(),
711            },
712        ))
713    }
714
715    fn precompute(&self) -> Option<Variable> {
716        self.expr.precompute()
717    }
718
719    fn get_locals(
720        &mut self,
721        relative: usize,
722        stack: &mut Vec<Option<Arc<String>>>,
723        closure_stack: &mut Vec<usize>,
724        module: &Module,
725        use_lookup: &UseLookup,
726    ) {
727        // Get closure environment.
728        let d = if closure_stack.len() < self.level as usize {
729            // Ignore negative difference, because
730            // lifetime checker will detect too high grab level.
731            0
732        } else {
733            closure_stack.len() - self.level as usize
734        };
735        let last = match closure_stack.get(d) {
736            None => return,
737            Some(&x) => x,
738        };
739        // Use environment outside closure.
740        let mut tmp_stack: Vec<_> = stack[0..last].into();
741        self.expr.get_locals(relative, &mut tmp_stack, closure_stack, module, use_lookup)
742    }
743}
744
745/// Try-expression, catches run-time errors from sub-expression.
746///
747/// E.g. `try foo()`.
748#[derive(Debug, Clone)]
749pub struct TryExpr {
750    /// Sub-expression to catch run-time errors from.
751    pub expr: Expression,
752    /// The range in source.
753    pub source_range: Range,
754}
755
756impl TryExpr {
757    /// Creates try expression from meta data.
758    pub fn from_meta_data(
759        file: &Arc<String>,
760        source: &Arc<String>,
761        mut convert: Convert,
762        ignored: &mut Vec<Range>,
763    ) -> Result<(Range, TryExpr), ()> {
764        let start = convert;
765        let node = "try_expr";
766        let start_range = convert.start_node(node)?;
767        convert.update(start_range);
768
769        let mut expr: Option<Expression> = None;
770        loop {
771            if let Ok(range) = convert.end_node(node) {
772                convert.update(range);
773                break;
774            } else if let Ok((range, val)) =
775                Expression::from_meta_data(file, source, "expr", convert, ignored)
776            {
777                convert.update(range);
778                expr = Some(val);
779            } else {
780                let range = convert.ignore();
781                convert.update(range);
782                ignored.push(range);
783            }
784        }
785
786        let expr = expr.ok_or(())?;
787        Ok((
788            convert.subtract(start),
789            TryExpr {
790                expr,
791                source_range: convert.source(start).unwrap(),
792            },
793        ))
794    }
795
796    fn get_locals(
797        &mut self,
798        relative: usize,
799        stack: &mut Vec<Option<Arc<String>>>,
800        closure_stack: &mut Vec<usize>,
801        module: &Module,
802        use_lookup: &UseLookup,
803    ) {
804        self.expr.get_locals(relative, stack, closure_stack, module, use_lookup)
805    }
806}
807
808/// Lazy invariant.
809#[derive(Debug, Clone, PartialEq)]
810pub enum Lazy {
811    /// Return a variable if result of argument is equal to the variable.
812    Variable(Variable),
813    /// Unwrap the Ok result.
814    UnwrapOk,
815    /// Unwrap the Err result.
816    UnwrapErr,
817    /// Unwrap the Some option.
818    UnwrapSome,
819}
820
821/// This is requires because `UnsafeRef(*mut Variable)` can not be sent across threads.
822/// The lack of `UnsafeRef` variant when sending across threads is guaranteed at language level.
823/// The interior of `UnsafeRef` can not be accessed outside this library.
824unsafe impl Sync for Lazy {}
825
826/// Function argument.
827#[derive(Debug, Clone)]
828pub struct Arg {
829    /// The name of the argument.
830    pub name: Arc<String>,
831    /// The lifetime of the argument.
832    pub lifetime: Option<Arc<String>>,
833    /// The type of the argument.
834    pub ty: Type,
835    /// The range in source.
836    pub source_range: Range,
837    /// Whether the argument is mutable.
838    pub mutable: bool,
839}
840
841impl Arg {
842    /// Creates function argument from meta data.
843    pub fn from_meta_data(
844        file: &Arc<String>,
845        source: &Arc<String>,
846        mut convert: Convert,
847        ignored: &mut Vec<Range>,
848    ) -> Result<(Range, Arg, Vec<Lazy>), ()> {
849        let start = convert;
850        let node = "arg";
851        let start_range = convert.start_node(node)?;
852        convert.update(start_range);
853
854        let mut name: Option<Arc<String>> = None;
855        let mut lifetime: Option<Arc<String>> = None;
856        let mut ty: Option<Type> = None;
857        let mut mutable = false;
858        let mut lazy: Vec<Lazy> = vec![];
859        loop {
860            if let Ok(range) = convert.end_node(node) {
861                convert.update(range);
862                break;
863            } else if let Ok((range, val)) = convert.meta_bool("mut") {
864                convert.update(range);
865                mutable = val;
866            } else if let Ok((range, val)) = convert.meta_string("name") {
867                convert.update(range);
868                name = Some(val);
869            } else if let Ok((range, val)) = convert.meta_string("lifetime") {
870                convert.update(range);
871                lifetime = Some(val);
872            } else if let Ok((range, val)) = Type::from_meta_data("type", convert, ignored) {
873                convert.update(range);
874                ty = Some(val);
875            } else if let Ok((range, val)) = Grab::from_meta_data(file, source, convert, ignored) {
876                convert.update(range);
877                if let Some(val) = val.precompute() {
878                    lazy.push(Lazy::Variable(val));
879                } else {
880                    return Err(());
881                }
882            } else if let Ok((range, _)) = convert.meta_bool("ok(_)") {
883                convert.update(range);
884                lazy.push(Lazy::UnwrapOk);
885            } else if let Ok((range, _)) = convert.meta_bool("err(_)") {
886                convert.update(range);
887                lazy.push(Lazy::UnwrapErr);
888            } else if let Ok((range, _)) = convert.meta_bool("some(_)") {
889                convert.update(range);
890                lazy.push(Lazy::UnwrapSome);
891            } else {
892                let range = convert.ignore();
893                convert.update(range);
894                ignored.push(range);
895            }
896        }
897
898        let name = name.ok_or(())?;
899        let ty = match ty {
900            None => Type::Any,
901            Some(ty) => ty,
902        };
903        Ok((
904            convert.subtract(start),
905            Arg {
906                name,
907                lifetime,
908                ty,
909                source_range: convert.source(start).unwrap(),
910                mutable,
911            },
912            lazy,
913        ))
914    }
915}
916
917/// Current object reference.
918///
919/// This puts the current object into scope for a function.
920#[derive(Debug, Clone)]
921pub struct Current {
922    /// The name of the current object.
923    pub name: Arc<String>,
924    /// The range in source.
925    pub source_range: Range,
926    /// Whether the current object is mutable.
927    pub mutable: bool,
928}
929
930impl Current {
931    /// Creates current object reference from meta data.
932    pub fn from_meta_data(
933        mut convert: Convert,
934        ignored: &mut Vec<Range>,
935    ) -> Result<(Range, Current), ()> {
936        let start = convert;
937        let node = "current";
938        let start_range = convert.start_node(node)?;
939        convert.update(start_range);
940
941        let mut name: Option<Arc<String>> = None;
942        let mut mutable = false;
943        loop {
944            if let Ok(range) = convert.end_node(node) {
945                convert.update(range);
946                break;
947            } else if let Ok((range, val)) = convert.meta_bool("mut") {
948                convert.update(range);
949                mutable = val;
950            } else if let Ok((range, val)) = convert.meta_string("name") {
951                convert.update(range);
952                name = Some(val);
953            } else if let Ok((range, _)) = Type::from_meta_data("type", convert, ignored) {
954                convert.update(range);
955                // Just ignore type for now.
956            } else {
957                let range = convert.ignore();
958                convert.update(range);
959                ignored.push(range);
960            }
961        }
962
963        let name = name.ok_or(())?;
964        Ok((
965            convert.subtract(start),
966            Current {
967                name,
968                source_range: convert.source(start).unwrap(),
969                mutable,
970            },
971        ))
972    }
973}
974
975/// Block.
976#[derive(Debug, Clone)]
977pub struct Block {
978    /// Sub-expression.
979    pub expressions: Vec<Expression>,
980    /// The range in source.
981    pub source_range: Range,
982}
983
984impl Block {
985    /// Creates block from meta data.
986    pub fn from_meta_data(
987        file: &Arc<String>,
988        source: &Arc<String>,
989        node: &str,
990        mut convert: Convert,
991        ignored: &mut Vec<Range>,
992    ) -> Result<(Range, Block), ()> {
993        let start = convert;
994        let start_range = convert.start_node(node)?;
995        convert.update(start_range);
996
997        let mut expressions = vec![];
998        loop {
999            if let Ok(range) = convert.end_node(node) {
1000                convert.update(range);
1001                break;
1002            } else if let Ok((range, val)) =
1003                Expression::from_meta_data(file, source, "expr", convert, ignored)
1004            {
1005                convert.update(range);
1006                expressions.push(val);
1007            } else {
1008                let range = convert.ignore();
1009                convert.update(range);
1010                ignored.push(range);
1011            }
1012        }
1013
1014        Ok((
1015            convert.subtract(start),
1016            Block {
1017                expressions,
1018                source_range: convert.source(start).unwrap(),
1019            },
1020        ))
1021    }
1022
1023    fn get_locals(
1024        &mut self,
1025        relative: usize,
1026        stack: &mut Vec<Option<Arc<String>>>,
1027        closure_stack: &mut Vec<usize>,
1028        module: &Module,
1029        use_lookup: &UseLookup,
1030    ) {
1031        let st = stack.len();
1032        for expr in &mut self.expressions {
1033            expr.get_locals(relative, stack, closure_stack, module, use_lookup);
1034        }
1035        stack.truncate(st);
1036    }
1037}
1038
1039/// Expression.
1040#[derive(Debug, Clone)]
1041pub enum Expression {
1042    /// Link expression.
1043    Link(Box<Link>),
1044    /// Object expression.
1045    Object(Box<Object>),
1046    /// Array expression.
1047    Array(Box<Array>),
1048    /// Array fill expression.
1049    ArrayFill(Box<ArrayFill>),
1050    /// Return expression.
1051    Return(Box<Expression>),
1052    /// Returns with value expression.
1053    ReturnVoid(Box<Range>),
1054    /// Break expression.
1055    Break(Box<Break>),
1056    /// Continue expression.
1057    Continue(Box<Continue>),
1058    /// Block expression.
1059    Block(Box<Block>),
1060    /// Go call expression.
1061    Go(Box<Go>),
1062    /// Call expression.
1063    Call(Box<Call>),
1064    /// Call external function.
1065    CallVoid(Box<CallVoid>),
1066    /// Call external function that returns something.
1067    CallReturn(Box<CallReturn>),
1068    /// Call external function with lazy invariant.
1069    CallLazy(Box<CallLazy>),
1070    /// Call loaded function.
1071    CallLoaded(Box<CallLoaded>),
1072    /// Binary operator.
1073    CallBinOp(Box<CallBinOp>),
1074    /// Unary operator.
1075    CallUnOp(Box<CallUnOp>),
1076    /// Item expression.
1077    Item(Box<Item>),
1078    /// Assignment expression.
1079    Assign(Box<Assign>),
1080    /// 4D vector expression.
1081    Vec4(Box<Vec4>),
1082    /// 4D matrix expression.
1083    Mat4(Box<Mat4>),
1084    /// For expression, e.g. `for i := 0; i < 10; i += 1 { ... }`.
1085    For(Box<For>),
1086    /// For-n expression.
1087    ForN(Box<ForN>),
1088    /// For-in expression.
1089    ForIn(Box<ForIn>),
1090    /// Sum for-n expression.
1091    Sum(Box<ForN>),
1092    /// Sum-in for-n expression.
1093    SumIn(Box<ForIn>),
1094    /// Component-wise 4D vector sum for-n-loop.
1095    SumVec4(Box<ForN>),
1096    /// Product for-n expression.
1097    Prod(Box<ForN>),
1098    /// Product-in for-n loop.
1099    ProdIn(Box<ForIn>),
1100    /// Component-wise 4D vector product for-n-loop.
1101    ProdVec4(Box<ForN>),
1102    /// Min for-n expression.
1103    Min(Box<ForN>),
1104    /// Min-in for-n expression.
1105    MinIn(Box<ForIn>),
1106    /// Max for-n expression.
1107    Max(Box<ForN>),
1108    /// Max-in for-n expression.
1109    MaxIn(Box<ForIn>),
1110    /// Sift for-n expression.
1111    Sift(Box<ForN>),
1112    /// Sift-in expression.
1113    SiftIn(Box<ForIn>),
1114    /// Any expression.
1115    Any(Box<ForN>),
1116    /// Any-in expression.
1117    AnyIn(Box<ForIn>),
1118    /// All-for expression.
1119    All(Box<ForN>),
1120    /// All-in expression.
1121    AllIn(Box<ForIn>),
1122    /// Link-for expression.
1123    LinkFor(Box<ForN>),
1124    /// Link-in expression.
1125    LinkIn(Box<ForIn>),
1126    /// If-expression.
1127    If(Box<If>),
1128    /// Variable.
1129    ///
1130    /// This means it contains no members that depends on other expressions.
1131    Variable(Box<(Range, Variable)>),
1132    /// Try expression using `?`.
1133    Try(Box<Expression>),
1134    /// 4D vector swizzle expression.
1135    Swizzle(Box<Swizzle>),
1136    /// Closure expression.
1137    Closure(Arc<Closure>),
1138    /// Call closure expression.
1139    CallClosure(Box<CallClosure>),
1140    /// Grab expression.
1141    Grab(Box<Grab>),
1142    /// Try expression, e.g. `try x`.
1143    TryExpr(Box<TryExpr>),
1144    /// In-type expression.
1145    In(Box<In>),
1146}
1147
1148// Required because the `Sync` impl of `Variable` is unsafe.
1149unsafe impl Sync for Expression {}
1150
1151impl Expression {
1152    /// Creates expression from meta data.
1153    pub fn from_meta_data(
1154        file: &Arc<String>,
1155        source: &Arc<String>,
1156        node: &str,
1157        mut convert: Convert,
1158        ignored: &mut Vec<Range>,
1159    ) -> Result<(Range, Expression), ()> {
1160        let start = convert;
1161        let start_range = convert.start_node(node)?;
1162        convert.update(start_range);
1163
1164        let mut result: Option<Expression> = None;
1165        loop {
1166            if let Ok(range) = convert.end_node(node) {
1167                convert.update(range);
1168                break;
1169            } else if let Ok((range, _)) = convert.meta_bool("mut") {
1170                // Ignore `mut` since it is handled by lifetime checker.
1171                convert.update(range);
1172            } else if let Ok((range, val)) = Link::from_meta_data(file, source, convert, ignored) {
1173                convert.update(range);
1174                result = Some(Expression::Link(Box::new(val)));
1175            } else if let Ok((range, val)) = Object::from_meta_data(file, source, convert, ignored)
1176            {
1177                convert.update(range);
1178                result = Some(Expression::Object(Box::new(val)));
1179            } else if let Ok((range, val)) = Array::from_meta_data(file, source, convert, ignored) {
1180                convert.update(range);
1181                result = Some(Expression::Array(Box::new(val)));
1182            } else if let Ok((range, val)) =
1183                ArrayFill::from_meta_data(file, source, convert, ignored)
1184            {
1185                convert.update(range);
1186                result = Some(Expression::ArrayFill(Box::new(val)));
1187            } else if let Ok((range, val)) =
1188                Expression::from_meta_data(file, source, "return", convert, ignored)
1189            {
1190                convert.update(range);
1191                result = Some(Expression::Return(Box::new(val)));
1192            } else if let Ok((range, _)) = convert.meta_bool("return_void") {
1193                convert.update(range);
1194                result = Some(Expression::ReturnVoid(Box::new(
1195                    convert.source(start).unwrap(),
1196                )));
1197            } else if let Ok((range, val)) = Break::from_meta_data(convert, ignored) {
1198                convert.update(range);
1199                result = Some(Expression::Break(Box::new(val)));
1200            } else if let Ok((range, val)) = Continue::from_meta_data(convert, ignored) {
1201                convert.update(range);
1202                result = Some(Expression::Continue(Box::new(val)));
1203            } else if let Ok((range, val)) =
1204                Block::from_meta_data(file, source, "block", convert, ignored)
1205            {
1206                convert.update(range);
1207                result = Some(Expression::Block(Box::new(val)));
1208            } else if let Ok((range, val)) =
1209                BinOpSeq::from_meta_data(file, source, "add", convert, ignored)
1210            {
1211                convert.update(range);
1212                result = Some(val.into_expression());
1213            } else if let Ok((range, val)) =
1214                UnOpExpression::from_meta_data("not", file, source, convert, ignored)
1215            {
1216                convert.update(range);
1217                result = Some(val);
1218            } else if let Ok((range, val)) =
1219                BinOpSeq::from_meta_data(file, source, "mul", convert, ignored)
1220            {
1221                convert.update(range);
1222                result = Some(val.into_expression());
1223            } else if let Ok((range, val)) =
1224                BinOpSeq::from_meta_data(file, source, "compare", convert, ignored)
1225            {
1226                convert.update(range);
1227                result = Some(val.into_expression());
1228            } else if let Ok((range, val)) = Item::from_meta_data(file, source, convert, ignored) {
1229                convert.update(range);
1230                result = Some(Expression::Item(Box::new(val)));
1231            } else if let Ok((range, val)) = Norm::from_meta_data(file, source, convert, ignored) {
1232                convert.update(range);
1233                result = Some(val.into_call_expr());
1234            } else if let Ok((range, val)) = convert.meta_string("text") {
1235                convert.update(range);
1236                result = Some(Expression::Variable(Box::new((
1237                    convert.source(start).unwrap(),
1238                    Variable::Str(val),
1239                ))));
1240            } else if let Ok((range, val)) = convert.meta_f64("num") {
1241                convert.update(range);
1242                result = Some(Expression::Variable(Box::new((
1243                    convert.source(start).unwrap(),
1244                    Variable::f64(val),
1245                ))));
1246            } else if let Ok((range, val)) = Vec4::from_meta_data(file, source, convert, ignored) {
1247                convert.update(range);
1248                result = Some(Expression::Vec4(Box::new(val)));
1249            } else if let Ok((range, val)) = Mat4::from_meta_data(file, source, convert, ignored) {
1250                convert.update(range);
1251                result = Some(Expression::Mat4(Box::new(val)));
1252            } else if let Ok((range, val)) =
1253                Vec4UnLoop::from_meta_data(file, source, convert, ignored)
1254            {
1255                convert.update(range);
1256                result = Some(val.into_expression());
1257            } else if let Ok((range, val)) = convert.meta_bool("bool") {
1258                convert.update(range);
1259                result = Some(Expression::Variable(Box::new((
1260                    convert.source(start).unwrap(),
1261                    Variable::bool(val),
1262                ))));
1263            } else if let Ok((range, val)) = convert.meta_string("color") {
1264                convert.update(range);
1265                if let Some((rgb, a)) = read_color::rgb_maybe_a(&mut val.chars()) {
1266                    let v = [
1267                        f32::from(rgb[0]) / 255.0,
1268                        f32::from(rgb[1]) / 255.0,
1269                        f32::from(rgb[2]) / 255.0,
1270                        f32::from(a.unwrap_or(255)) / 255.0,
1271                    ];
1272                    result = Some(Expression::Variable(Box::new((range, Variable::Vec4(v)))));
1273                } else {
1274                    return Err(());
1275                }
1276            } else if let Ok((range, val)) = Go::from_meta_data(file, source, convert, ignored) {
1277                convert.update(range);
1278                result = Some(Expression::Go(Box::new(val)));
1279            } else if let Ok((range, val)) = Call::from_meta_data(file, source, convert, ignored) {
1280                convert.update(range);
1281                result = Some(Expression::Call(Box::new(val)));
1282            } else if let Ok((range, val)) =
1283                Call::named_from_meta_data(file, source, convert, ignored)
1284            {
1285                convert.update(range);
1286                result = Some(Expression::Call(Box::new(val)));
1287            } else if let Ok((range, val)) = Assign::from_meta_data(file, source, convert, ignored)
1288            {
1289                convert.update(range);
1290                result = Some(Expression::Assign(Box::new(val)));
1291            } else if let Ok((range, val)) = For::from_meta_data(file, source, convert, ignored) {
1292                convert.update(range);
1293                result = Some(Expression::For(Box::new(val)));
1294            } else if let Ok((range, val)) =
1295                ForN::from_meta_data(file, source, "for_n", convert, ignored)
1296            {
1297                convert.update(range);
1298                result = Some(Expression::ForN(Box::new(val)));
1299            } else if let Ok((range, val)) =
1300                ForN::from_meta_data(file, source, "sum", convert, ignored)
1301            {
1302                convert.update(range);
1303                result = Some(Expression::Sum(Box::new(val)));
1304            } else if let Ok((range, val)) =
1305                ForN::from_meta_data(file, source, "sum_vec4", convert, ignored)
1306            {
1307                convert.update(range);
1308                result = Some(Expression::SumVec4(Box::new(val)));
1309            } else if let Ok((range, val)) =
1310                ForN::from_meta_data(file, source, "prod", convert, ignored)
1311            {
1312                convert.update(range);
1313                result = Some(Expression::Prod(Box::new(val)));
1314            } else if let Ok((range, val)) =
1315                ForN::from_meta_data(file, source, "prod_vec4", convert, ignored)
1316            {
1317                convert.update(range);
1318                result = Some(Expression::ProdVec4(Box::new(val)));
1319            } else if let Ok((range, val)) =
1320                ForN::from_meta_data(file, source, "min", convert, ignored)
1321            {
1322                convert.update(range);
1323                result = Some(Expression::Min(Box::new(val)));
1324            } else if let Ok((range, val)) =
1325                ForN::from_meta_data(file, source, "max", convert, ignored)
1326            {
1327                convert.update(range);
1328                result = Some(Expression::Max(Box::new(val)));
1329            } else if let Ok((range, val)) =
1330                ForN::from_meta_data(file, source, "sift", convert, ignored)
1331            {
1332                convert.update(range);
1333                result = Some(Expression::Sift(Box::new(val)));
1334            } else if let Ok((range, val)) =
1335                ForN::from_meta_data(file, source, "any", convert, ignored)
1336            {
1337                convert.update(range);
1338                result = Some(Expression::Any(Box::new(val)));
1339            } else if let Ok((range, val)) =
1340                ForN::from_meta_data(file, source, "all", convert, ignored)
1341            {
1342                convert.update(range);
1343                result = Some(Expression::All(Box::new(val)));
1344            } else if let Ok((range, val)) =
1345                ForN::from_meta_data(file, source, "link_for", convert, ignored)
1346            {
1347                convert.update(range);
1348                result = Some(Expression::LinkFor(Box::new(val)));
1349            } else if let Ok((range, val)) = Loop::from_meta_data(file, source, convert, ignored) {
1350                convert.update(range);
1351                result = Some(val.into_expression());
1352            } else if let Ok((range, val)) = If::from_meta_data(file, source, convert, ignored) {
1353                convert.update(range);
1354                result = Some(Expression::If(Box::new(val)));
1355            } else if let Ok((range, _)) = convert.meta_bool("try") {
1356                convert.update(range);
1357                result = Some(Expression::Try(Box::new(result.unwrap())));
1358            } else if let Ok((range, val)) = Swizzle::from_meta_data(file, source, convert, ignored)
1359            {
1360                convert.update(range);
1361                result = Some(Expression::Swizzle(Box::new(val)));
1362            } else if let Ok((range, val)) =
1363                Closure::from_meta_data(file, source, "closure", convert, ignored)
1364            {
1365                convert.update(range);
1366                result = Some(Expression::Closure(Arc::new(val)));
1367            } else if let Ok((range, val)) =
1368                CallClosure::from_meta_data(file, source, convert, ignored)
1369            {
1370                convert.update(range);
1371                result = Some(Expression::CallClosure(Box::new(val)));
1372            } else if let Ok((range, val)) =
1373                CallClosure::named_from_meta_data(file, source, convert, ignored)
1374            {
1375                convert.update(range);
1376                result = Some(Expression::CallClosure(Box::new(val)));
1377            } else if let Ok((range, val)) = Grab::from_meta_data(file, source, convert, ignored) {
1378                convert.update(range);
1379                if let Some(v) = val.precompute() {
1380                    result = Some(Expression::Variable(Box::new((val.source_range, v))));
1381                } else {
1382                    result = Some(Expression::Grab(Box::new(val)));
1383                }
1384            } else if let Ok((range, val)) = TryExpr::from_meta_data(file, source, convert, ignored)
1385            {
1386                convert.update(range);
1387                result = Some(Expression::TryExpr(Box::new(val)));
1388            } else if let Ok((range, val)) = In::from_meta_data("in", convert, ignored) {
1389                convert.update(range);
1390                result = Some(Expression::In(Box::new(val)));
1391            } else if let Ok((range, val)) =
1392                ForIn::from_meta_data(file, source, "for_in", convert, ignored)
1393            {
1394                convert.update(range);
1395                result = Some(Expression::ForIn(Box::new(val)));
1396            } else if let Ok((range, val)) =
1397                ForIn::from_meta_data(file, source, "sum_in", convert, ignored)
1398            {
1399                convert.update(range);
1400                result = Some(Expression::SumIn(Box::new(val)));
1401            } else if let Ok((range, val)) =
1402                ForIn::from_meta_data(file, source, "prod_in", convert, ignored)
1403            {
1404                convert.update(range);
1405                result = Some(Expression::ProdIn(Box::new(val)));
1406            } else if let Ok((range, val)) =
1407                ForIn::from_meta_data(file, source, "min_in", convert, ignored)
1408            {
1409                convert.update(range);
1410                result = Some(Expression::MinIn(Box::new(val)));
1411            } else if let Ok((range, val)) =
1412                ForIn::from_meta_data(file, source, "max_in", convert, ignored)
1413            {
1414                convert.update(range);
1415                result = Some(Expression::MaxIn(Box::new(val)));
1416            } else if let Ok((range, val)) =
1417                ForIn::from_meta_data(file, source, "sift_in", convert, ignored)
1418            {
1419                convert.update(range);
1420                result = Some(Expression::SiftIn(Box::new(val)));
1421            } else if let Ok((range, val)) =
1422                ForIn::from_meta_data(file, source, "any_in", convert, ignored)
1423            {
1424                convert.update(range);
1425                result = Some(Expression::AnyIn(Box::new(val)));
1426            } else if let Ok((range, val)) =
1427                ForIn::from_meta_data(file, source, "all_in", convert, ignored)
1428            {
1429                convert.update(range);
1430                result = Some(Expression::AllIn(Box::new(val)));
1431            } else if let Ok((range, val)) =
1432                ForIn::from_meta_data(file, source, "link_in", convert, ignored)
1433            {
1434                convert.update(range);
1435                result = Some(Expression::LinkIn(Box::new(val)));
1436            } else {
1437                let range = convert.ignore();
1438                convert.update(range);
1439                ignored.push(range);
1440            }
1441        }
1442
1443        let result = result.ok_or(())?;
1444        Ok((convert.subtract(start), result))
1445    }
1446
1447    fn precompute(&self) -> Option<Variable> {
1448        use self::Expression::*;
1449
1450        match *self {
1451            ArrayFill(ref array_fill) => array_fill.precompute(),
1452            Array(ref array) => array.precompute(),
1453            Object(ref obj) => obj.precompute(),
1454            Vec4(ref vec4) => vec4.precompute(),
1455            Link(ref link) => link.precompute(),
1456            Variable(ref range_var) => Some(range_var.1.clone()),
1457            _ => None,
1458        }
1459    }
1460
1461    /// Gets the range in source.
1462    pub fn source_range(&self) -> Range {
1463        use self::Expression::*;
1464
1465        match *self {
1466            Link(ref link) => link.source_range,
1467            Object(ref obj) => obj.source_range,
1468            Array(ref arr) => arr.source_range,
1469            ArrayFill(ref arr_fill) => arr_fill.source_range,
1470            Return(ref expr) => expr.source_range(),
1471            ReturnVoid(ref range) => **range,
1472            Break(ref br) => br.source_range,
1473            Continue(ref c) => c.source_range,
1474            Block(ref bl) => bl.source_range,
1475            #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
1476            Go(ref go) => go.source_range,
1477            #[cfg(not(all(not(target_family = "wasm"), feature = "threading")))]
1478            Go(ref go) => match **go {},
1479            Call(ref call) => call.info.source_range,
1480            CallVoid(ref call) => call.info.source_range,
1481            CallReturn(ref call) => call.info.source_range,
1482            CallBinOp(ref call) => call.info.source_range,
1483            CallUnOp(ref call) => call.info.source_range,
1484            CallLazy(ref call) => call.info.source_range,
1485            CallLoaded(ref call) => call.info.source_range,
1486            Item(ref it) => it.source_range,
1487            Assign(ref assign) => assign.source_range,
1488            Vec4(ref vec4) => vec4.source_range,
1489            Mat4(ref mat4) => mat4.source_range,
1490            For(ref for_expr) => for_expr.source_range,
1491            ForN(ref for_n_expr) => for_n_expr.source_range,
1492            #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
1493            ForIn(ref for_in_expr) => for_in_expr.source_range,
1494            #[cfg(not(all(not(target_family = "wasm"), feature = "threading")))]
1495            ForIn(ref for_in_expr) |
1496            SumIn(ref for_in_expr) |
1497            ProdIn(ref for_in_expr) |
1498            MinIn(ref for_in_expr) |
1499            MaxIn(ref for_in_expr) |
1500            SiftIn(ref for_in_expr) |
1501            AnyIn(ref for_in_expr) |
1502            AllIn(ref for_in_expr) |
1503            LinkIn(ref for_in_expr) => match **for_in_expr {},
1504            Sum(ref for_n_expr) => for_n_expr.source_range,
1505            #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
1506            SumIn(ref for_in_expr) => for_in_expr.source_range,
1507            SumVec4(ref for_n_expr) => for_n_expr.source_range,
1508            Prod(ref for_n_expr) => for_n_expr.source_range,
1509            #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
1510            ProdIn(ref for_in_expr) => for_in_expr.source_range,
1511            ProdVec4(ref for_n_expr) => for_n_expr.source_range,
1512            Min(ref for_n_expr) => for_n_expr.source_range,
1513            #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
1514            MinIn(ref for_in_expr) => for_in_expr.source_range,
1515            Max(ref for_n_expr) => for_n_expr.source_range,
1516            #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
1517            MaxIn(ref for_in_expr) => for_in_expr.source_range,
1518            Sift(ref for_n_expr) => for_n_expr.source_range,
1519            #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
1520            SiftIn(ref for_in_expr) => for_in_expr.source_range,
1521            Any(ref for_n_expr) => for_n_expr.source_range,
1522            #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
1523            AnyIn(ref for_in_expr) => for_in_expr.source_range,
1524            All(ref for_n_expr) => for_n_expr.source_range,
1525            #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
1526            AllIn(ref for_in_expr) => for_in_expr.source_range,
1527            LinkFor(ref for_n_expr) => for_n_expr.source_range,
1528            #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
1529            LinkIn(ref for_in_expr) => for_in_expr.source_range,
1530            If(ref if_expr) => if_expr.source_range,
1531            Variable(ref range_var) => range_var.0,
1532            Try(ref expr) => expr.source_range(),
1533            Swizzle(ref swizzle) => swizzle.source_range,
1534            Closure(ref closure) => closure.source_range,
1535            CallClosure(ref call) => call.source_range,
1536            Grab(ref grab) => grab.source_range,
1537            TryExpr(ref try_expr) => try_expr.source_range,
1538            #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
1539            In(ref in_expr) => in_expr.source_range,
1540            #[cfg(not(all(not(target_family = "wasm"), feature = "threading")))]
1541            In(ref in_expr) => match **in_expr {},
1542        }
1543    }
1544
1545    fn get_locals(
1546        &mut self,
1547        relative: usize,
1548        stack: &mut Vec<Option<Arc<String>>>,
1549        closure_stack: &mut Vec<usize>,
1550        module: &Module,
1551        use_lookup: &UseLookup,
1552    ) {
1553        use self::Expression::*;
1554
1555        match *self {
1556            Link(ref mut link) =>
1557                link.get_locals(relative, stack, closure_stack, module, use_lookup),
1558            Object(ref mut obj) =>
1559                obj.get_locals(relative, stack, closure_stack, module, use_lookup),
1560            Array(ref mut arr) =>
1561                arr.get_locals(relative, stack, closure_stack, module, use_lookup),
1562            ArrayFill(ref mut arr_fill) =>
1563                arr_fill.get_locals(relative, stack, closure_stack, module, use_lookup),
1564            Return(ref mut expr) => {
1565                let st = stack.len();
1566                expr.get_locals(relative, stack, closure_stack, module, use_lookup);
1567                stack.truncate(st);
1568            }
1569            ReturnVoid(_) => {}
1570            Break(_) => {}
1571            Continue(_) => {}
1572            Block(ref mut bl) =>
1573                bl.get_locals(relative, stack, closure_stack, module, use_lookup),
1574            Go(ref mut go) => go.get_locals(relative, stack, closure_stack, module, use_lookup),
1575            Call(ref mut call) => {
1576                call.get_locals(relative, stack, closure_stack, module, use_lookup);
1577                match call.f_index {
1578                    FnIndex::Void(f) => {
1579                        *self = Expression::CallVoid(Box::new(self::CallVoid {
1580                            args: call.args.clone(),
1581                            fun: f,
1582                            info: call.info.clone(),
1583                        }))
1584                    }
1585                    FnIndex::Return(f) => {
1586                        *self = Expression::CallReturn(Box::new(self::CallReturn {
1587                            args: call.args.clone(),
1588                            fun: f,
1589                            info: call.info.clone(),
1590                        }))
1591                    }
1592                    FnIndex::BinOp(f) => {
1593                        *self = Expression::CallBinOp(Box::new(self::CallBinOp {
1594                            left: call.args[0].clone(),
1595                            right: call.args[1].clone(),
1596                            fun: f,
1597                            info: call.info.clone(),
1598                        }))
1599                    }
1600                    FnIndex::UnOp(f) => {
1601                        *self = Expression::CallUnOp(Box::new(self::CallUnOp {
1602                            arg: call.args[0].clone(),
1603                            fun: f,
1604                            info: call.info.clone(),
1605                        }))
1606                    }
1607                    FnIndex::Lazy(f, lazy_inv) => {
1608                        *self = Expression::CallLazy(Box::new(self::CallLazy {
1609                            args: call.args.clone(),
1610                            fun: f,
1611                            lazy_inv,
1612                            info: call.info.clone(),
1613                        }))
1614                    }
1615                    FnIndex::Loaded(f) => {
1616                        *self = Expression::CallLoaded(Box::new(self::CallLoaded {
1617                            args: call.args.clone(),
1618                            custom_source: call.custom_source.clone(),
1619                            fun: f,
1620                            info: call.info.clone(),
1621                        }))
1622                    }
1623                    FnIndex::None => {}
1624                }
1625            }
1626            CallVoid(_) => unimplemented!("`CallVoid` is transformed from `Call`"),
1627            CallReturn(_) => unimplemented!("`CallReturn` is transformed from `Call`"),
1628            CallLazy(_) => unimplemented!("`CallLazy` is transformed from `Call`"),
1629            CallLoaded(_) => unimplemented!("`CallLoaded` is transformed from `Call`"),
1630            CallBinOp(_) => unimplemented!("`CallBinOp` is transformed from `Call`"),
1631            CallUnOp(_) => unimplemented!("`CallUnOp` is transformed from `Call`"),
1632            Item(ref mut it) =>
1633                it.get_locals(relative, stack, closure_stack, module, use_lookup),
1634            Assign(ref mut assign) =>
1635                assign.get_locals(relative, stack, closure_stack, module, use_lookup),
1636            Vec4(ref mut vec4) =>
1637                vec4.get_locals(relative, stack, closure_stack, module, use_lookup),
1638            Mat4(ref mut mat4) =>
1639                mat4.get_locals(relative, stack, closure_stack, module, use_lookup),
1640            For(ref mut for_expr) =>
1641                for_expr.get_locals(relative, stack, closure_stack, module, use_lookup),
1642            ForN(ref mut for_n_expr) =>
1643                for_n_expr.get_locals(relative, stack, closure_stack, module, use_lookup),
1644            ForIn(ref mut for_n_expr) |
1645            SumIn(ref mut for_n_expr) |
1646            ProdIn(ref mut for_n_expr) |
1647            MinIn(ref mut for_n_expr) |
1648            MaxIn(ref mut for_n_expr) |
1649            SiftIn(ref mut for_n_expr) |
1650            AnyIn(ref mut for_n_expr) |
1651            AllIn(ref mut for_n_expr) |
1652            LinkIn(ref mut for_n_expr) => {
1653                for_n_expr.get_locals(relative, stack, closure_stack, module, use_lookup)
1654            }
1655            Sum(ref mut for_n_expr) |
1656            SumVec4(ref mut for_n_expr) |
1657            Prod(ref mut for_n_expr) |
1658            ProdVec4(ref mut for_n_expr) |
1659            Min(ref mut for_n_expr) |
1660            Max(ref mut for_n_expr) |
1661            Sift(ref mut for_n_expr) |
1662            Any(ref mut for_n_expr) |
1663            All(ref mut for_n_expr) |
1664            LinkFor(ref mut for_n_expr) =>
1665                for_n_expr.get_locals(relative, stack, closure_stack, module, use_lookup),
1666            If(ref mut if_expr) =>
1667                if_expr.get_locals(relative, stack, closure_stack, module, use_lookup),
1668            Variable(_) => {}
1669            Try(ref mut expr) =>
1670                expr.get_locals(relative, stack, closure_stack, module, use_lookup),
1671            Swizzle(ref mut swizzle) =>
1672                swizzle.expr.get_locals(relative, stack, closure_stack, module, use_lookup),
1673            Closure(ref mut closure) => Arc::make_mut(closure).get_locals(
1674                relative,
1675                stack,
1676                closure_stack,
1677                module,
1678                use_lookup,
1679            ),
1680            CallClosure(ref mut call) =>
1681                call.get_locals(relative, stack, closure_stack, module, use_lookup),
1682            Grab(ref mut grab) =>
1683                grab.get_locals(relative, stack, closure_stack, module, use_lookup),
1684            TryExpr(ref mut try_expr) =>
1685                try_expr.get_locals(relative, stack, closure_stack, module, use_lookup),
1686            In(ref mut in_expr) => in_expr.get_locals(relative, module, use_lookup),
1687        }
1688    }
1689}
1690
1691/// Link expression, e.g. `link {a b}`.
1692#[derive(Debug, Clone)]
1693pub struct Link {
1694    /// Link item expressions.
1695    pub items: Vec<Expression>,
1696    /// The range in source.
1697    pub source_range: Range,
1698}
1699
1700impl Link {
1701    /// Creates link expression from meta data.
1702    pub fn from_meta_data(
1703        file: &Arc<String>,
1704        source: &Arc<String>,
1705        mut convert: Convert,
1706        ignored: &mut Vec<Range>,
1707    ) -> Result<(Range, Link), ()> {
1708        let start = convert;
1709        let node = "link";
1710        let start_range = convert.start_node(node)?;
1711        convert.update(start_range);
1712
1713        let mut items: Vec<Expression> = vec![];
1714        loop {
1715            if let Ok(range) = convert.end_node(node) {
1716                convert.update(range);
1717                break;
1718            } else if let Ok((range, val)) =
1719                Expression::from_meta_data(file, source, "link_item", convert, ignored)
1720            {
1721                convert.update(range);
1722                items.push(val);
1723            } else {
1724                let range = convert.ignore();
1725                convert.update(range);
1726                ignored.push(range);
1727            }
1728        }
1729
1730        Ok((
1731            convert.subtract(start),
1732            Link {
1733                items,
1734                source_range: convert.source(start).unwrap(),
1735            },
1736        ))
1737    }
1738
1739    fn precompute(&self) -> Option<Variable> {
1740        let mut link = crate::link::Link::new();
1741        for it in &self.items {
1742            if let Some(v) = it.precompute() {
1743                if link.push(&v).is_err() {
1744                    return None;
1745                };
1746            } else {
1747                return None;
1748            }
1749        }
1750        Some(Variable::Link(Box::new(link)))
1751    }
1752
1753    fn get_locals(
1754        &mut self,
1755        relative: usize,
1756        stack: &mut Vec<Option<Arc<String>>>,
1757        closure_stack: &mut Vec<usize>,
1758        module: &Module,
1759        use_lookup: &UseLookup,
1760    ) {
1761        let st = stack.len();
1762        for expr in &mut self.items {
1763            expr.get_locals(relative, stack, closure_stack, module, use_lookup);
1764        }
1765        stack.truncate(st);
1766    }
1767}
1768
1769/// Object expression.
1770#[derive(Debug, Clone)]
1771pub struct Object {
1772    /// Key-value pair expressions.
1773    pub key_values: Vec<(Arc<String>, Expression)>,
1774    /// The range in source.
1775    pub source_range: Range,
1776}
1777
1778impl Object {
1779    /// Creates object expression from meta data.
1780    pub fn from_meta_data(
1781        file: &Arc<String>,
1782        source: &Arc<String>,
1783        mut convert: Convert,
1784        ignored: &mut Vec<Range>,
1785    ) -> Result<(Range, Object), ()> {
1786        let start = convert;
1787        let node = "object";
1788        let start_range = convert.start_node(node)?;
1789        convert.update(start_range);
1790
1791        let mut key_values = vec![];
1792        loop {
1793            if let Ok(range) = convert.end_node(node) {
1794                convert.update(range);
1795                break;
1796            } else if let Ok((range, val)) =
1797                Object::key_value_from_meta_data(file, source, convert, ignored)
1798            {
1799                convert.update(range);
1800                key_values.push(val);
1801            } else {
1802                let range = convert.ignore();
1803                convert.update(range);
1804                ignored.push(range);
1805            }
1806        }
1807
1808        Ok((
1809            convert.subtract(start),
1810            Object {
1811                key_values,
1812                source_range: convert.source(start).unwrap(),
1813            },
1814        ))
1815    }
1816
1817    fn precompute(&self) -> Option<Variable> {
1818        let mut object: HashMap<_, _> = HashMap::new();
1819        for &(ref key, ref value) in &self.key_values {
1820            if let Some(v) = value.precompute() {
1821                object.insert(key.clone(), v);
1822            } else {
1823                return None;
1824            }
1825        }
1826        Some(Variable::Object(Arc::new(object)))
1827    }
1828
1829    fn key_value_from_meta_data(
1830        file: &Arc<String>,
1831        source: &Arc<String>,
1832        mut convert: Convert,
1833        ignored: &mut Vec<Range>,
1834    ) -> Result<(Range, (Arc<String>, Expression)), ()> {
1835        let start = convert;
1836        let node = "key_value";
1837        let start_range = convert.start_node(node)?;
1838        convert.update(start_range);
1839
1840        let mut key: Option<Arc<String>> = None;
1841        let mut value: Option<Expression> = None;
1842        loop {
1843            if let Ok(range) = convert.end_node(node) {
1844                convert.update(range);
1845                break;
1846            } else if let Ok((range, val)) = convert.meta_string("key") {
1847                convert.update(range);
1848                key = Some(val);
1849            } else if let Ok((range, val)) =
1850                Expression::from_meta_data(file, source, "val", convert, ignored)
1851            {
1852                convert.update(range);
1853                value = Some(val);
1854            } else {
1855                let range = convert.ignore();
1856                convert.update(range);
1857                ignored.push(range);
1858            }
1859        }
1860
1861        let key = key.ok_or(())?;
1862        let value = value.ok_or(())?;
1863        Ok((convert.subtract(start), (key, value)))
1864    }
1865
1866    fn get_locals(
1867        &mut self,
1868        relative: usize,
1869        stack: &mut Vec<Option<Arc<String>>>,
1870        closure_stack: &mut Vec<usize>,
1871        module: &Module,
1872        use_lookup: &UseLookup,
1873    ) {
1874        let st = stack.len();
1875        for &mut (_, ref mut expr) in &mut self.key_values {
1876            expr.get_locals(relative, stack, closure_stack, module, use_lookup);
1877            stack.truncate(st);
1878        }
1879    }
1880}
1881
1882/// Array expression, e.g. `[a, b, c]`.
1883#[derive(Debug, Clone)]
1884pub struct Array {
1885    /// Array item expressions.
1886    pub items: Vec<Expression>,
1887    /// The range in source.
1888    pub source_range: Range,
1889}
1890
1891impl Array {
1892    /// Creates array expression from meta data.
1893    pub fn from_meta_data(
1894        file: &Arc<String>,
1895        source: &Arc<String>,
1896        mut convert: Convert,
1897        ignored: &mut Vec<Range>,
1898    ) -> Result<(Range, Array), ()> {
1899        let start = convert;
1900        let node = "array";
1901        let start_range = convert.start_node(node)?;
1902        convert.update(start_range);
1903
1904        let mut items = vec![];
1905        loop {
1906            if let Ok(range) = convert.end_node(node) {
1907                convert.update(range);
1908                break;
1909            } else if let Ok((range, val)) =
1910                Expression::from_meta_data(file, source, "array_item", convert, ignored)
1911            {
1912                convert.update(range);
1913                items.push(val);
1914            } else {
1915                let range = convert.ignore();
1916                convert.update(range);
1917                ignored.push(range);
1918            }
1919        }
1920
1921        Ok((
1922            convert.subtract(start),
1923            Array {
1924                items,
1925                source_range: convert.source(start).unwrap(),
1926            },
1927        ))
1928    }
1929
1930    fn precompute(&self) -> Option<Variable> {
1931        let mut res = Vec::with_capacity(self.items.len());
1932        for item in &self.items {
1933            if let Some(v) = item.precompute() {
1934                res.push(v);
1935            } else {
1936                return None;
1937            }
1938        }
1939        Some(Variable::Array(Arc::new(res)))
1940    }
1941
1942    fn get_locals(
1943        &mut self,
1944        relative: usize,
1945        stack: &mut Vec<Option<Arc<String>>>,
1946        closure_stack: &mut Vec<usize>,
1947        module: &Module,
1948        use_lookup: &UseLookup,
1949    ) {
1950        let st = stack.len();
1951        for item in &mut self.items {
1952            item.get_locals(relative, stack, closure_stack, module, use_lookup);
1953            stack.truncate(st);
1954        }
1955    }
1956}
1957
1958/// Array fill expression, e.g. `[a; n]`.
1959#[derive(Debug, Clone)]
1960pub struct ArrayFill {
1961    /// The `a` in `[a; n]`.
1962    pub fill: Expression,
1963    /// The `n` in `[a; n]`.
1964    pub n: Expression,
1965    /// The range in source.
1966    pub source_range: Range,
1967}
1968
1969impl ArrayFill {
1970    /// Creates array fill expression from meta data.
1971    pub fn from_meta_data(
1972        file: &Arc<String>,
1973        source: &Arc<String>,
1974        mut convert: Convert,
1975        ignored: &mut Vec<Range>,
1976    ) -> Result<(Range, ArrayFill), ()> {
1977        let start = convert;
1978        let node = "array_fill";
1979        let start_range = convert.start_node(node)?;
1980        convert.update(start_range);
1981
1982        let mut fill: Option<Expression> = None;
1983        let mut n: Option<Expression> = None;
1984        loop {
1985            if let Ok(range) = convert.end_node(node) {
1986                convert.update(range);
1987                break;
1988            } else if let Ok((range, val)) =
1989                Expression::from_meta_data(file, source, "fill", convert, ignored)
1990            {
1991                convert.update(range);
1992                fill = Some(val);
1993            } else if let Ok((range, val)) =
1994                Expression::from_meta_data(file, source, "n", convert, ignored)
1995            {
1996                convert.update(range);
1997                n = Some(val);
1998            } else {
1999                let range = convert.ignore();
2000                convert.update(range);
2001                ignored.push(range);
2002            }
2003        }
2004
2005        let fill = fill.ok_or(())?;
2006        let n = n.ok_or(())?;
2007        Ok((
2008            convert.subtract(start),
2009            ArrayFill {
2010                fill,
2011                n,
2012                source_range: convert.source(start).unwrap(),
2013            },
2014        ))
2015    }
2016
2017    fn precompute(&self) -> Option<Variable> {
2018        if let Expression::Variable(ref range_var) = self.n {
2019            if let (_, Variable::F64(n, _)) = **range_var {
2020                if let Expression::Variable(ref x) = self.fill {
2021                    return Some(Variable::Array(Arc::new(vec![x.1.clone(); n as usize])));
2022                }
2023            }
2024        }
2025        None
2026    }
2027
2028    fn get_locals(
2029        &mut self,
2030        relative: usize,
2031        stack: &mut Vec<Option<Arc<String>>>,
2032        closure_stack: &mut Vec<usize>,
2033        module: &Module,
2034        use_lookup: &UseLookup,
2035    ) {
2036        let st = stack.len();
2037        self.fill.get_locals(relative, stack, closure_stack, module, use_lookup);
2038        stack.truncate(st);
2039        self.n.get_locals(relative, stack, closure_stack, module, use_lookup);
2040        stack.truncate(st);
2041    }
2042}
2043
2044/// Parse sequence of binary operators.
2045#[derive(Debug, Clone)]
2046pub struct BinOpSeq {
2047    /// Item expressions.
2048    pub items: Vec<Expression>,
2049    /// Binary operators.
2050    pub ops: Vec<BinOp>,
2051    /// The range in source.
2052    pub source_range: Range,
2053}
2054
2055impl BinOpSeq {
2056    /// Creates multiply expression from meta data.
2057    pub fn from_meta_data(
2058        file: &Arc<String>,
2059        source: &Arc<String>,
2060        node: &str,
2061        mut convert: Convert,
2062        ignored: &mut Vec<Range>,
2063    ) -> Result<(Range, BinOpSeq), ()> {
2064        let start = convert;
2065        let start_range = convert.start_node(node)?;
2066        convert.update(start_range);
2067
2068        let mut items = vec![];
2069        let mut ops = vec![];
2070        loop {
2071            if let Ok(range) = convert.end_node(node) {
2072                convert.update(range);
2073                break;
2074            } else if let Ok((range, val)) =
2075                UnOpExpression::from_meta_data("neg", file, source, convert, ignored)
2076            {
2077                convert.update(range);
2078                items.push(val);
2079            } else if let Ok((range, val)) =
2080                BinOpSeq::from_meta_data(file, source, "pow", convert, ignored)
2081            {
2082                convert.update(range);
2083                items.push(val.into_expression());
2084            } else if let Ok((range, val)) =
2085                Expression::from_meta_data(file, source, "expr", convert, ignored)
2086            {
2087                convert.update(range);
2088                items.push(val);
2089            } else if let Ok((range, _)) = convert.meta_bool("*.") {
2090                convert.update(range);
2091                ops.push(BinOp::Dot);
2092            } else if let Ok((range, _)) = convert.meta_bool("x") {
2093                convert.update(range);
2094                ops.push(BinOp::Cross);
2095            } else if let Ok((range, _)) = convert.meta_bool("*") {
2096                convert.update(range);
2097                ops.push(BinOp::Mul);
2098            } else if let Ok((range, _)) = convert.meta_bool("/") {
2099                convert.update(range);
2100                ops.push(BinOp::Div);
2101            } else if let Ok((range, _)) = convert.meta_bool("%") {
2102                convert.update(range);
2103                ops.push(BinOp::Rem);
2104            } else if let Ok((range, _)) = convert.meta_bool("+") {
2105                convert.update(range);
2106                ops.push(BinOp::Add);
2107            } else if let Ok((range, _)) = convert.meta_bool("-") {
2108                convert.update(range);
2109                ops.push(BinOp::Sub);
2110            } else if let Ok((range, _)) = convert.meta_bool("||") {
2111                convert.update(range);
2112                ops.push(BinOp::OrElse);
2113            } else if let Ok((range, _)) = convert.meta_bool("^") {
2114                convert.update(range);
2115                ops.push(BinOp::Pow);
2116            } else if let Ok((range, _)) = convert.meta_bool("&&") {
2117                convert.update(range);
2118                ops.push(BinOp::AndAlso);
2119            } else if let Ok((range, _)) = convert.meta_bool("<") {
2120                convert.update(range);
2121                ops.push(BinOp::Less);
2122            } else if let Ok((range, _)) = convert.meta_bool("<=") {
2123                convert.update(range);
2124                ops.push(BinOp::LessOrEqual);
2125            } else if let Ok((range, _)) = convert.meta_bool(">") {
2126                convert.update(range);
2127                ops.push(BinOp::Greater);
2128            } else if let Ok((range, _)) = convert.meta_bool(">=") {
2129                convert.update(range);
2130                ops.push(BinOp::GreaterOrEqual);
2131            } else if let Ok((range, _)) = convert.meta_bool("==") {
2132                convert.update(range);
2133                ops.push(BinOp::Equal);
2134            } else if let Ok((range, _)) = convert.meta_bool("!=") {
2135                convert.update(range);
2136                ops.push(BinOp::NotEqual);
2137            } else {
2138                let range = convert.ignore();
2139                convert.update(range);
2140                ignored.push(range);
2141            }
2142        }
2143
2144        if items.is_empty() {
2145            return Err(());
2146        }
2147        Ok((
2148            convert.subtract(start),
2149            BinOpSeq {
2150                items,
2151                ops,
2152                source_range: convert.source(start).unwrap(),
2153            },
2154        ))
2155    }
2156
2157    fn into_expression(mut self) -> Expression {
2158        if self.items.len() == 1 {
2159            self.items[0].clone()
2160        } else {
2161            let op = self.ops.pop().expect("Expected a binary operation");
2162            let last = self.items.pop().expect("Expected argument");
2163            let source_range = self.source_range;
2164            BinOpExpression {
2165                op,
2166                left: self.into_expression(),
2167                right: last,
2168                source_range,
2169            }
2170            .into_expression()
2171        }
2172    }
2173}
2174
2175/// Binary operator.
2176#[derive(Debug, Copy, Clone)]
2177pub enum BinOp {
2178    /// Addition operator (`+`).
2179    Add,
2180    /// Subtraction operator (`-`).
2181    Sub,
2182    /// Multiply operator (`*`).
2183    Mul,
2184    /// Dot product operator (`*.`).
2185    Dot,
2186    /// Cross product operator (`x`).
2187    Cross,
2188    /// Division operator (`/`).
2189    Div,
2190    /// Remainder operator (`%`).
2191    Rem,
2192    /// Power operator (`^`).
2193    Pow,
2194    /// Lazy OR operator (`||`).
2195    OrElse,
2196    /// Lazy AND operator (`&&`).
2197    AndAlso,
2198    /// Less.
2199    Less,
2200    /// Less or equal.
2201    LessOrEqual,
2202    /// Greater.
2203    Greater,
2204    /// Greater or equal.
2205    GreaterOrEqual,
2206    /// Equal.
2207    Equal,
2208    /// Not equal.
2209    NotEqual,
2210}
2211
2212pub(crate) const BINOP_PREC_POW: u8 = 3;
2213pub(crate) const BINOP_PREC_MUL: u8 = 2;
2214pub(crate) const BINOP_PREC_ADD: u8 = 1;
2215pub(crate) const BINOP_PREC_EQ: u8 = 0;
2216
2217impl BinOp {
2218    /// Returns symbol of binary operator.
2219    pub fn symbol(self) -> &'static str {
2220        match self {
2221            BinOp::Add => "+",
2222            BinOp::Sub => "-",
2223            BinOp::Mul => "*",
2224            BinOp::Dot => "*.",
2225            BinOp::Cross => "x",
2226            BinOp::Div => "/",
2227            BinOp::Rem => "%",
2228            BinOp::Pow => "^",
2229            BinOp::OrElse => "||",
2230            BinOp::AndAlso => "&&",
2231            BinOp::Less => "<",
2232            BinOp::LessOrEqual => "<=",
2233            BinOp::Greater => ">",
2234            BinOp::GreaterOrEqual => ">=",
2235            BinOp::Equal => "==",
2236            BinOp::NotEqual => "!=",
2237        }
2238    }
2239
2240    /// Returns symbol of binary operator in boolean variant.
2241    pub fn symbol_bool(self) -> &'static str {
2242        match self {
2243            BinOp::Add => "or",
2244            BinOp::Mul => "and",
2245            _ => self.symbol(),
2246        }
2247    }
2248
2249    /// Returns the operator precedence level.
2250    /// Used to put parentheses in right places when printing out closures.
2251    pub fn precedence(self) -> u8 {
2252        match self {
2253            BinOp::Less
2254            | BinOp::LessOrEqual
2255            | BinOp::Greater
2256            | BinOp::GreaterOrEqual
2257            | BinOp::Equal
2258            | BinOp::NotEqual => BINOP_PREC_EQ,
2259            BinOp::OrElse => BINOP_PREC_ADD,
2260            BinOp::AndAlso => BINOP_PREC_MUL,
2261            BinOp::Add | BinOp::Sub => BINOP_PREC_ADD,
2262            BinOp::Mul | BinOp::Dot | BinOp::Cross | BinOp::Div | BinOp::Rem => BINOP_PREC_MUL,
2263            BinOp::Pow => BINOP_PREC_POW,
2264        }
2265    }
2266}
2267
2268/// An item id.
2269///
2270/// This is the thing that's inside the square brackets, e.g. `foo[i]`.
2271#[derive(Debug, Clone)]
2272pub enum Id {
2273    /// A string.
2274    String(Range, Arc<String>),
2275    /// A number.
2276    F64(Range, f64),
2277    /// An expression.
2278    Expression(Expression),
2279}
2280
2281impl Id {
2282    /// Gets the range in source.
2283    pub fn source_range(&self) -> Range {
2284        match *self {
2285            Id::String(range, _) => range,
2286            Id::F64(range, _) => range,
2287            Id::Expression(ref expr) => expr.source_range(),
2288        }
2289    }
2290
2291    fn get_locals(
2292        &mut self,
2293        relative: usize,
2294        stack: &mut Vec<Option<Arc<String>>>,
2295        closure_stack: &mut Vec<usize>,
2296        module: &Module,
2297        use_lookup: &UseLookup,
2298    ) -> bool {
2299        match *self {
2300            Id::String(_, _) => false,
2301            Id::F64(_, _) => false,
2302            Id::Expression(ref mut expr) => {
2303                let st = stack.len();
2304                expr.get_locals(relative, stack, closure_stack, module, use_lookup);
2305                stack.truncate(st);
2306                true
2307            }
2308        }
2309    }
2310}
2311
2312/// Item.
2313#[derive(Debug, Clone)]
2314pub struct Item {
2315    /// The name of item.
2316    pub name: Arc<String>,
2317    /// Dynamical looked up stack id.
2318    ///
2319    /// This is checked against the static stack id when
2320    /// the Cargo feature "debug_lookup" is enabled.
2321    pub stack_id: Cell<Option<usize>>,
2322    /// Statical looked up stack id.
2323    ///
2324    /// This is used when the Cargo feature "debug_lookup" is disabled.
2325    pub static_stack_id: Cell<Option<usize>>,
2326    /// Whether the item is a current object.
2327    pub current: bool,
2328    /// Whether there is a `?` after the item.
2329    pub try_flag: bool,
2330    /// Item ids.
2331    pub ids: Vec<Id>,
2332    /// Stores indices of ids that should propagate errors.
2333    pub try_ids: Vec<usize>,
2334    /// The range in source.
2335    pub source_range: Range,
2336}
2337
2338impl Item {
2339    /// Creates item from variable.
2340    pub fn from_variable(name: Arc<String>, source_range: Range) -> Item {
2341        Item {
2342            name,
2343            current: false,
2344            stack_id: Cell::new(None),
2345            static_stack_id: Cell::new(None),
2346            try_flag: false,
2347            ids: vec![],
2348            try_ids: vec![],
2349            source_range,
2350        }
2351    }
2352
2353    /// Truncates item extra to a given length.
2354    fn trunc(&self, n: usize) -> Item {
2355        Item {
2356            name: self.name.clone(),
2357            current: self.current,
2358            stack_id: Cell::new(None),
2359            static_stack_id: Cell::new(None),
2360            try_flag: self.try_flag,
2361            ids: self.ids.iter().take(n).cloned().collect(),
2362            try_ids: {
2363                let mut try_ids = vec![];
2364                for &ind in &self.try_ids {
2365                    if ind >= n {
2366                        break;
2367                    }
2368                    try_ids.push(ind);
2369                }
2370                try_ids
2371            },
2372            source_range: self.source_range,
2373        }
2374    }
2375
2376    /// Creates item from meta data.
2377    pub fn from_meta_data(
2378        file: &Arc<String>,
2379        source: &Arc<String>,
2380        mut convert: Convert,
2381        ignored: &mut Vec<Range>,
2382    ) -> Result<(Range, Item), ()> {
2383        let start = convert;
2384        let node = "item";
2385        let start_range = convert.start_node(node)?;
2386        convert.update(start_range);
2387
2388        let mut name: Option<Arc<String>> = None;
2389        let mut current = false;
2390        let mut ids = vec![];
2391        let mut try_ids = vec![];
2392        let mut try_flag = false;
2393        loop {
2394            if let Ok(range) = convert.end_node(node) {
2395                convert.update(range);
2396                break;
2397            } else if let Ok((range, val)) = convert.meta_string("name") {
2398                convert.update(range);
2399                name = Some(val);
2400            } else if let Ok((range, _)) = convert.meta_bool("current") {
2401                convert.update(range);
2402                current = true;
2403            } else if let Ok((range, _)) = convert.meta_bool("try_item") {
2404                convert.update(range);
2405                try_flag = true;
2406                // Ignore item extra node, which is there to help the type checker.
2407            } else if let Ok(range) = convert.start_node("item_extra") {
2408                convert.update(range);
2409            } else if let Ok(range) = convert.end_node("item_extra") {
2410                convert.update(range);
2411            } else if let Ok((range, val)) = convert.meta_string("id") {
2412                let start_id = convert;
2413                convert.update(range);
2414                ids.push(Id::String(convert.source(start_id).unwrap(), val));
2415            } else if let Ok((range, val)) = convert.meta_f64("id") {
2416                let start_id = convert;
2417                convert.update(range);
2418                ids.push(Id::F64(convert.source(start_id).unwrap(), val));
2419            } else if let Ok((range, val)) =
2420                Expression::from_meta_data(file, source, "id", convert, ignored)
2421            {
2422                convert.update(range);
2423                ids.push(Id::Expression(val));
2424            } else if let Ok((range, _)) = convert.meta_bool("try_id") {
2425                convert.update(range);
2426                // id is pushed before the `?` operator, therefore subtract 1.
2427                try_ids.push(ids.len() - 1);
2428            } else {
2429                let range = convert.ignore();
2430                convert.update(range);
2431                ignored.push(range);
2432            }
2433        }
2434
2435        let name = name.ok_or(())?;
2436        Ok((
2437            convert.subtract(start),
2438            Item {
2439                name,
2440                stack_id: Cell::new(None),
2441                static_stack_id: Cell::new(None),
2442                current,
2443                try_flag,
2444                ids,
2445                try_ids,
2446                source_range: convert.source(start).unwrap(),
2447            },
2448        ))
2449    }
2450
2451    fn get_locals(
2452        &mut self,
2453        relative: usize,
2454        stack: &mut Vec<Option<Arc<String>>>,
2455        closure_stack: &mut Vec<usize>,
2456        module: &Module,
2457        use_lookup: &UseLookup,
2458    ) {
2459        let st = stack.len();
2460        for (i, n) in stack.iter().rev().enumerate() {
2461            if let Some(ref n) = *n {
2462                if **n == **self.name {
2463                    self.static_stack_id.set(Some(i + 1));
2464                    break;
2465                }
2466            }
2467        }
2468        for id in &mut self.ids {
2469            if id.get_locals(relative, stack, closure_stack, module, use_lookup) {
2470                stack.push(None);
2471            }
2472        }
2473        stack.truncate(st);
2474    }
2475}
2476
2477/// Go call.
2478#[cfg(all(not(target_family = "wasm"), feature = "threading"))]
2479#[derive(Debug, Clone)]
2480pub struct Go {
2481    /// Function call.
2482    pub call: Call,
2483    /// The range in source.
2484    pub source_range: Range,
2485}
2486
2487/// Go call.
2488#[cfg(not(all(not(target_family = "wasm"), feature = "threading")))]
2489#[derive(Debug, Clone)]
2490pub enum Go {}
2491
2492impl Go {
2493    #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
2494    /// Creates go call from meta data.
2495    pub fn from_meta_data(
2496        file: &Arc<String>,
2497        source: &Arc<String>,
2498        mut convert: Convert,
2499        ignored: &mut Vec<Range>,
2500    ) -> Result<(Range, Go), ()> {
2501        let start = convert;
2502        let node = "go";
2503        let start_range = convert.start_node(node)?;
2504        convert.update(start_range);
2505
2506        let mut call: Option<Call> = None;
2507        loop {
2508            if let Ok(range) = convert.end_node(node) {
2509                convert.update(range);
2510                break;
2511            } else if let Ok((range, val)) = Call::from_meta_data(file, source, convert, ignored) {
2512                convert.update(range);
2513                call = Some(val);
2514            } else if let Ok((range, val)) =
2515                Call::named_from_meta_data(file, source, convert, ignored)
2516            {
2517                convert.update(range);
2518                call = Some(val);
2519            } else {
2520                let range = convert.ignore();
2521                convert.update(range);
2522                ignored.push(range);
2523            }
2524        }
2525
2526        let call = call.ok_or(())?;
2527        Ok((
2528            convert.subtract(start),
2529            Go {
2530                call,
2531                source_range: convert.source(start).unwrap(),
2532            },
2533        ))
2534    }
2535
2536    #[cfg(not(all(not(target_family = "wasm"), feature = "threading")))]
2537    /// Creates go call from meta data.
2538    pub fn from_meta_data(
2539        _file: &Arc<String>,
2540        _source: &Arc<String>,
2541        _convert: Convert,
2542        _ignored: &mut Vec<Range>,
2543    ) -> Result<(Range, Go), ()> {
2544        Err(())
2545    }
2546
2547    #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
2548    fn get_locals(
2549        &mut self,
2550        relative: usize,
2551        stack: &mut Vec<Option<Arc<String>>>,
2552        closure_stack: &mut Vec<usize>,
2553        module: &Module,
2554        use_lookup: &UseLookup,
2555    ) {
2556        let st = stack.len();
2557        for arg in &mut self.call.args {
2558            let st = stack.len();
2559            arg.get_locals(relative, stack, closure_stack, module, use_lookup);
2560            stack.truncate(st);
2561        }
2562        stack.truncate(st);
2563    }
2564
2565    #[cfg(not(all(not(target_family = "wasm"), feature = "threading")))]
2566    fn get_locals(
2567        &mut self,
2568        _relative: usize,
2569        _stack: &mut Vec<Option<Arc<String>>>,
2570        _closure_stack: &mut Vec<usize>,
2571        _module: &Module,
2572        _use_lookup: &UseLookup,
2573    ) {}
2574}
2575
2576/// Call info.
2577#[derive(Debug, Clone)]
2578pub struct CallInfo {
2579    /// Name of function.
2580    pub name: Arc<String>,
2581    /// Alias.
2582    pub alias: Option<Arc<String>>,
2583    /// The range in source.
2584    pub source_range: Range,
2585}
2586
2587/// Loaded function call.
2588#[derive(Debug, Clone)]
2589pub struct CallLoaded {
2590    /// Arguments.
2591    pub args: Vec<Expression>,
2592    /// Relative to function you call from.
2593    pub fun: isize,
2594    /// Info about the call.
2595    pub info: Box<CallInfo>,
2596    /// A custom source, such as when calling a function inside a loaded module.
2597    pub custom_source: Option<Arc<String>>,
2598}
2599
2600/// External function call.
2601#[derive(Debug, Clone)]
2602pub struct CallLazy {
2603    /// Arguments.
2604    pub args: Vec<Expression>,
2605    /// Function pointer.
2606    pub fun: crate::FnReturnRef,
2607    /// Lazy invariant.
2608    pub lazy_inv: crate::LazyInvariant,
2609    /// Info about the call.
2610    pub info: Box<CallInfo>,
2611}
2612
2613/// External function call.
2614#[derive(Debug, Clone)]
2615pub struct CallBinOp {
2616    /// Left argument.
2617    pub left: Expression,
2618    /// Right argument.
2619    pub right: Expression,
2620    /// Function pointer.
2621    pub fun: crate::FnBinOpRef,
2622    /// Info about the call.
2623    pub info: Box<CallInfo>,
2624}
2625
2626/// External function call.
2627#[derive(Debug, Clone)]
2628pub struct CallUnOp {
2629    /// Argument.
2630    pub arg: Expression,
2631    /// Function pointer.
2632    pub fun: crate::FnUnOpRef,
2633    /// Info about the call.
2634    pub info: Box<CallInfo>,
2635}
2636
2637/// External function call.
2638#[derive(Debug, Clone)]
2639pub struct CallReturn {
2640    /// Arguments.
2641    pub args: Vec<Expression>,
2642    /// Function pointer.
2643    pub fun: crate::FnReturnRef,
2644    /// Info about the call.
2645    pub info: Box<CallInfo>,
2646}
2647
2648/// External function call.
2649#[derive(Debug, Clone)]
2650pub struct CallVoid {
2651    /// Arguments.
2652    pub args: Vec<Expression>,
2653    /// Function pointer.
2654    pub fun: crate::FnVoidRef,
2655    /// Info about the call.
2656    pub info: Box<CallInfo>,
2657}
2658
2659/// Function call.
2660#[derive(Debug, Clone)]
2661pub struct Call {
2662    /// Arguments.
2663    pub args: Vec<Expression>,
2664    /// Function index.
2665    pub f_index: FnIndex,
2666    /// Info about the call.
2667    pub info: Box<CallInfo>,
2668    /// A custom source, such as when calling a function inside a loaded module.
2669    pub custom_source: Option<Arc<String>>,
2670}
2671
2672impl Call {
2673    /// Creates call from meta data.
2674    pub fn from_meta_data(
2675        file: &Arc<String>,
2676        source: &Arc<String>,
2677        mut convert: Convert,
2678        ignored: &mut Vec<Range>,
2679    ) -> Result<(Range, Call), ()> {
2680        let start = convert;
2681        let node = "call";
2682        let start_range = convert.start_node(node)?;
2683        convert.update(start_range);
2684
2685        let mut alias: Option<Arc<String>> = None;
2686        let mut name: Option<Arc<String>> = None;
2687        let mut args = vec![];
2688        let mut mutable: Vec<bool> = vec![];
2689        loop {
2690            if let Ok(range) = convert.end_node(node) {
2691                convert.update(range);
2692                break;
2693            } else if let Ok((range, val)) = convert.meta_string("alias") {
2694                convert.update(range);
2695                alias = Some(val);
2696            } else if let Ok((range, val)) = convert.meta_string("name") {
2697                convert.update(range);
2698                name = Some(val);
2699            } else if let Ok((range, val)) =
2700                Expression::from_meta_data(file, source, "call_arg", convert, ignored)
2701            {
2702                let mut peek = convert;
2703                mutable.push(match peek.start_node("call_arg") {
2704                    Ok(r) => {
2705                        peek.update(r);
2706                        peek.meta_bool("mut").is_ok()
2707                    }
2708                    _ => unreachable!(),
2709                });
2710                convert.update(range);
2711                args.push(val);
2712            } else {
2713                let range = convert.ignore();
2714                convert.update(range);
2715                ignored.push(range);
2716            }
2717        }
2718
2719        let mut name = name.ok_or(())?;
2720
2721        // Append mutability information to function name.
2722        if mutable.iter().any(|&arg| arg) {
2723            let mut name_plus_args = String::from(&**name);
2724            name_plus_args.push('(');
2725            let mut first = true;
2726            for &arg in &mutable {
2727                if !first {
2728                    name_plus_args.push(',');
2729                }
2730                name_plus_args.push_str(if arg { "mut" } else { "_" });
2731                first = false;
2732            }
2733            name_plus_args.push(')');
2734            name = Arc::new(name_plus_args);
2735        }
2736
2737        Ok((
2738            convert.subtract(start),
2739            Call {
2740                args,
2741                f_index: FnIndex::None,
2742                custom_source: None,
2743                info: Box::new(CallInfo {
2744                    alias,
2745                    name,
2746                    source_range: convert.source(start).unwrap(),
2747                }),
2748            },
2749        ))
2750    }
2751
2752    /// Creates named argument call from meta data.
2753    pub fn named_from_meta_data(
2754        file: &Arc<String>,
2755        source: &Arc<String>,
2756        mut convert: Convert,
2757        ignored: &mut Vec<Range>,
2758    ) -> Result<(Range, Call), ()> {
2759        let start = convert;
2760        let node = "named_call";
2761        let start_range = convert.start_node(node)?;
2762        convert.update(start_range);
2763
2764        let mut alias: Option<Arc<String>> = None;
2765        let mut name = String::new();
2766        let mut args = vec![];
2767        let mut mutable: Vec<bool> = vec![];
2768        loop {
2769            if let Ok(range) = convert.end_node(node) {
2770                convert.update(range);
2771                break;
2772            } else if let Ok((range, val)) = convert.meta_string("alias") {
2773                convert.update(range);
2774                alias = Some(val);
2775            } else if let Ok((range, val)) = convert.meta_string("word") {
2776                convert.update(range);
2777                if !name.is_empty() {
2778                    name.push('_');
2779                    name.push_str(&val);
2780                } else {
2781                    name.push_str(&val);
2782                    name.push('_');
2783                }
2784            } else if let Ok((range, val)) =
2785                Expression::from_meta_data(file, source, "call_arg", convert, ignored)
2786            {
2787                let mut peek = convert;
2788                mutable.push(match peek.start_node("call_arg") {
2789                    Ok(r) => {
2790                        peek.update(r);
2791                        peek.meta_bool("mut").is_ok()
2792                    }
2793                    _ => unreachable!(),
2794                });
2795                convert.update(range);
2796                args.push(val);
2797            } else {
2798                let range = convert.ignore();
2799                convert.update(range);
2800                ignored.push(range);
2801            }
2802        }
2803
2804        // Append mutability information to function name.
2805        if mutable.iter().any(|&arg| arg) {
2806            name.push('(');
2807            let mut first = true;
2808            for &arg in &mutable {
2809                if !first {
2810                    name.push(',');
2811                }
2812                name.push_str(if arg { "mut" } else { "_" });
2813                first = false;
2814            }
2815            name.push(')');
2816        }
2817
2818        Ok((
2819            convert.subtract(start),
2820            Call {
2821                args,
2822                f_index: FnIndex::None,
2823                custom_source: None,
2824                info: Box::new(CallInfo {
2825                    alias,
2826                    name: Arc::new(name),
2827                    source_range: convert.source(start).unwrap(),
2828                }),
2829            },
2830        ))
2831    }
2832
2833    fn get_locals(
2834        &mut self,
2835        relative: usize,
2836        stack: &mut Vec<Option<Arc<String>>>,
2837        closure_stack: &mut Vec<usize>,
2838        module: &Module,
2839        use_lookup: &UseLookup,
2840    ) {
2841        use crate::{
2842            FnBinOpRef,
2843            FnExt,
2844            FnReturnRef,
2845            FnUnOpRef,
2846            FnVoidRef,
2847        };
2848
2849        let st = stack.len();
2850        let f_index = if let Some(ref alias) = self.info.alias {
2851            if let Some(&i) = use_lookup
2852                .aliases
2853                .get(alias)
2854                .and_then(|map| map.get(&self.info.name))
2855            {
2856                match i {
2857                    FnAlias::Loaded(i) => FnIndex::Loaded(i as isize - relative as isize),
2858                    FnAlias::External(i) => {
2859                        let f = &module.ext_prelude[i];
2860                        match f.f {
2861                            FnExt::Void(ff) => FnIndex::Void(FnVoidRef(ff)),
2862                            FnExt::Return(ff) => FnIndex::Return(FnReturnRef(ff)),
2863                            FnExt::BinOp(ff) => FnIndex::BinOp(FnBinOpRef(ff)),
2864                            FnExt::UnOp(ff) => FnIndex::UnOp(FnUnOpRef(ff)),
2865                        }
2866                    }
2867                }
2868            } else {
2869                FnIndex::None
2870            }
2871        } else {
2872            module.find_function(&self.info.name, relative)
2873        };
2874        self.f_index = f_index;
2875        match f_index {
2876            FnIndex::Loaded(f_index) => {
2877                let index = (f_index + relative as isize) as usize;
2878                if module.functions[index].returns() {
2879                    stack.push(None);
2880                }
2881            }
2882            FnIndex::Void(_)
2883            | FnIndex::Return(_)
2884            | FnIndex::Lazy(_, _)
2885            | FnIndex::BinOp(_)
2886            | FnIndex::UnOp(_) => {
2887                // Don't push return since last value in block
2888                // is used as return value.
2889            }
2890            FnIndex::None => {}
2891        }
2892        for arg in &mut self.args {
2893            let arg_st = stack.len();
2894            arg.get_locals(relative, stack, closure_stack, module, use_lookup);
2895            stack.truncate(arg_st);
2896            if let FnIndex::BinOp(_) = f_index {
2897            } else {
2898                match *arg {
2899                    Expression::Swizzle(ref swizzle) => {
2900                        for _ in 0..swizzle.len() {
2901                            stack.push(None);
2902                        }
2903                    }
2904                    _ => {
2905                        stack.push(None);
2906                    }
2907                }
2908            }
2909        }
2910        stack.truncate(st);
2911    }
2912
2913    /// Computes number of arguments including swizzles.
2914    pub fn arg_len(&self) -> usize {
2915        let mut sum = 0;
2916        for arg in &self.args {
2917            match *arg {
2918                Expression::Swizzle(ref swizzle) => {
2919                    sum += swizzle.len();
2920                }
2921                _ => {
2922                    sum += 1;
2923                }
2924            }
2925        }
2926        sum
2927    }
2928}
2929
2930/// Closure call.
2931#[derive(Debug, Clone)]
2932pub struct CallClosure {
2933    /// The closure.
2934    pub item: Item,
2935    /// Closure argument expressions.
2936    pub args: Vec<Expression>,
2937    /// The range in source.
2938    pub source_range: Range,
2939}
2940
2941impl CallClosure {
2942    /// Creates closure call from meta data.
2943    pub fn from_meta_data(
2944        file: &Arc<String>,
2945        source: &Arc<String>,
2946        mut convert: Convert,
2947        ignored: &mut Vec<Range>,
2948    ) -> Result<(Range, CallClosure), ()> {
2949        let start = convert;
2950        let node = "call_closure";
2951        let start_range = convert.start_node(node)?;
2952        convert.update(start_range);
2953
2954        let mut item: Option<Item> = None;
2955        let mut args = vec![];
2956        let mut mutable: Vec<bool> = vec![];
2957        loop {
2958            if let Ok(range) = convert.end_node(node) {
2959                convert.update(range);
2960                break;
2961            } else if let Ok((range, val)) = Item::from_meta_data(file, source, convert, ignored) {
2962                convert.update(range);
2963                item = Some(val);
2964            } else if let Ok((range, val)) =
2965                Expression::from_meta_data(file, source, "call_arg", convert, ignored)
2966            {
2967                let mut peek = convert;
2968                mutable.push(match peek.start_node("call_arg") {
2969                    Ok(r) => {
2970                        peek.update(r);
2971                        peek.meta_bool("mut").is_ok()
2972                    }
2973                    _ => unreachable!(),
2974                });
2975                convert.update(range);
2976                args.push(val);
2977            } else {
2978                let range = convert.ignore();
2979                convert.update(range);
2980                ignored.push(range);
2981            }
2982        }
2983
2984        let item = item.ok_or(())?;
2985        Ok((
2986            convert.subtract(start),
2987            CallClosure {
2988                item,
2989                args,
2990                source_range: convert.source(start).unwrap(),
2991            },
2992        ))
2993    }
2994
2995    /// Creates named argument closure call from meta data.
2996    pub fn named_from_meta_data(
2997        file: &Arc<String>,
2998        source: &Arc<String>,
2999        mut convert: Convert,
3000        ignored: &mut Vec<Range>,
3001    ) -> Result<(Range, CallClosure), ()> {
3002        let start = convert;
3003        let node = "named_call_closure";
3004        let start_range = convert.start_node(node)?;
3005        convert.update(start_range);
3006
3007        let mut item: Option<Item> = None;
3008        let mut name = String::new();
3009        let mut args = vec![];
3010        let mut mutable: Vec<bool> = vec![];
3011        loop {
3012            if let Ok(range) = convert.end_node(node) {
3013                convert.update(range);
3014                break;
3015            } else if let Ok((range, val)) = Item::from_meta_data(file, source, convert, ignored) {
3016                convert.update(range);
3017                item = Some(val);
3018            } else if let Ok((range, val)) = convert.meta_string("word") {
3019                convert.update(range);
3020                if !name.is_empty() {
3021                    name.push('_');
3022                }
3023                name.push_str(&val);
3024            } else if let Ok((range, val)) =
3025                Expression::from_meta_data(file, source, "call_arg", convert, ignored)
3026            {
3027                let mut peek = convert;
3028                mutable.push(match peek.start_node("call_arg") {
3029                    Ok(r) => {
3030                        peek.update(r);
3031                        peek.meta_bool("mut").is_ok()
3032                    }
3033                    _ => unreachable!(),
3034                });
3035                convert.update(range);
3036                args.push(val);
3037            } else {
3038                let range = convert.ignore();
3039                convert.update(range);
3040                ignored.push(range);
3041            }
3042        }
3043
3044        let mut item = item.ok_or(())?;
3045        {
3046            if item.ids.is_empty() {
3047                // Append name to item.
3048                let n = Arc::make_mut(&mut item.name);
3049                n.push_str("__");
3050                n.push_str(&name);
3051            } else {
3052                let last = item.ids.len() - 1;
3053                if let Id::String(_, ref mut n) = item.ids[last] {
3054                    // Append name to last id.
3055                    let n = Arc::make_mut(n);
3056                    n.push_str("__");
3057                    n.push_str(&name);
3058                }
3059            }
3060        }
3061        Ok((
3062            convert.subtract(start),
3063            CallClosure {
3064                item,
3065                args,
3066                source_range: convert.source(start).unwrap(),
3067            },
3068        ))
3069    }
3070
3071    fn get_locals(
3072        &mut self,
3073        relative: usize,
3074        stack: &mut Vec<Option<Arc<String>>>,
3075        closure_stack: &mut Vec<usize>,
3076        module: &Module,
3077        use_lookup: &UseLookup,
3078    ) {
3079        let st = stack.len();
3080        self.item.get_locals(relative, stack, closure_stack, module, use_lookup);
3081        // All closures must return a value.
3082        // Use return type because it has the same name.
3083        stack.push(Some(crate::runtime::RETURN_TYPE.clone()));
3084        for arg in &mut self.args {
3085            let arg_st = stack.len();
3086            arg.get_locals(relative, stack, closure_stack, module, use_lookup);
3087            stack.truncate(arg_st);
3088            match *arg {
3089                Expression::Swizzle(ref swizzle) => {
3090                    for _ in 0..swizzle.len() {
3091                        stack.push(None);
3092                    }
3093                }
3094                _ => {
3095                    stack.push(None);
3096                }
3097            }
3098        }
3099        stack.truncate(st);
3100    }
3101
3102    /// Computes number of arguments including swizzles.
3103    pub fn arg_len(&self) -> usize {
3104        let mut sum = 0;
3105        for arg in &self.args {
3106            match *arg {
3107                Expression::Swizzle(ref swizzle) => {
3108                    sum += swizzle.len();
3109                }
3110                _ => {
3111                    sum += 1;
3112                }
3113            }
3114        }
3115        sum
3116    }
3117}
3118
3119/// 4D vector norm.
3120#[derive(Debug, Clone)]
3121pub struct Norm {
3122    /// Expression argument.
3123    pub expr: Expression,
3124    /// The range in source.
3125    pub source_range: Range,
3126}
3127
3128impl Norm {
3129    /// Creates 4D vector norm from meta data.
3130    pub fn from_meta_data(
3131        file: &Arc<String>,
3132        source: &Arc<String>,
3133        mut convert: Convert,
3134        ignored: &mut Vec<Range>,
3135    ) -> Result<(Range, Norm), ()> {
3136        let start = convert;
3137        let node = "norm";
3138        let start_range = convert.start_node(node)?;
3139        convert.update(start_range);
3140
3141        let mut expr: Option<Expression> = None;
3142        loop {
3143            if let Ok(range) = convert.end_node(node) {
3144                convert.update(range);
3145                break;
3146            } else if let Ok((range, val)) =
3147                Expression::from_meta_data(file, source, "expr", convert, ignored)
3148            {
3149                convert.update(range);
3150                expr = Some(val);
3151            } else {
3152                let range = convert.ignore();
3153                convert.update(range);
3154                ignored.push(range);
3155            }
3156        }
3157
3158        let expr = expr.ok_or(())?;
3159        Ok((
3160            convert.subtract(start),
3161            Norm {
3162                expr,
3163                source_range: convert.source(start).unwrap(),
3164            },
3165        ))
3166    }
3167
3168    fn into_call_expr(self) -> Expression {
3169        Expression::Call(Box::new(Call {
3170            args: vec![self.expr],
3171            custom_source: None,
3172            f_index: FnIndex::None,
3173            info: Box::new(CallInfo {
3174                alias: None,
3175                name: crate::NORM.clone(),
3176                source_range: self.source_range,
3177            }),
3178        }))
3179    }
3180}
3181
3182/// Binary operator expression.
3183#[derive(Debug, Clone)]
3184pub struct BinOpExpression {
3185    /// Binary operator.
3186    pub op: BinOp,
3187    /// Left side expression.
3188    pub left: Expression,
3189    /// Right side expression.
3190    pub right: Expression,
3191    /// The range in source.
3192    pub source_range: Range,
3193}
3194
3195impl BinOpExpression {
3196    fn into_expression(self) -> Expression {
3197        use self::BinOp::*;
3198
3199        Expression::Call(Box::new(Call {
3200            args: vec![self.left, self.right],
3201            custom_source: None,
3202            f_index: FnIndex::None,
3203            info: Box::new(CallInfo {
3204                alias: None,
3205                name: match self.op {
3206                    Add => crate::ADD.clone(),
3207                    Sub => crate::SUB.clone(),
3208                    Mul => crate::MUL.clone(),
3209                    Div => crate::DIV.clone(),
3210                    Rem => crate::REM.clone(),
3211                    Pow => crate::POW.clone(),
3212                    Dot => crate::DOT.clone(),
3213                    Cross => crate::CROSS.clone(),
3214                    AndAlso => crate::AND_ALSO.clone(),
3215                    OrElse => crate::OR_ELSE.clone(),
3216                    Less => crate::LESS.clone(),
3217                    LessOrEqual => crate::LESS_OR_EQUAL.clone(),
3218                    Greater => crate::GREATER.clone(),
3219                    GreaterOrEqual => crate::GREATER_OR_EQUAL.clone(),
3220                    Equal => crate::EQUAL.clone(),
3221                    NotEqual => crate::NOT_EQUAL.clone(),
3222                },
3223                source_range: self.source_range,
3224            }),
3225        }))
3226    }
3227}
3228
3229/// Unary operator expression.
3230pub struct UnOpExpression;
3231
3232impl UnOpExpression {
3233    /// Creates unary operator expression from meta data.
3234    pub fn from_meta_data(
3235        node: &str,
3236        file: &Arc<String>,
3237        source: &Arc<String>,
3238        mut convert: Convert,
3239        ignored: &mut Vec<Range>,
3240    ) -> Result<(Range, Expression), ()> {
3241        let start = convert;
3242        let start_range = convert.start_node(node)?;
3243        convert.update(start_range);
3244
3245        let mut expr: Option<Expression> = None;
3246        loop {
3247            if let Ok(range) = convert.end_node(node) {
3248                convert.update(range);
3249                break;
3250            } else if let Ok((range, val)) =
3251                Expression::from_meta_data(file, source, "expr", convert, ignored)
3252            {
3253                convert.update(range);
3254                expr = Some(val);
3255            } else {
3256                let range = convert.ignore();
3257                convert.update(range);
3258                ignored.push(range);
3259            }
3260        }
3261
3262        let expr = expr.ok_or(())?;
3263        Ok((convert.subtract(start), {
3264            let name = match node {
3265                "not" => crate::NOT.clone(),
3266                "neg" => crate::NEG.clone(),
3267                _ => return Err(()),
3268            };
3269            Expression::Call(Box::new(Call {
3270                args: vec![expr],
3271                custom_source: None,
3272                f_index: FnIndex::None,
3273                info: Box::new(CallInfo {
3274                    alias: None,
3275                    name,
3276                    source_range: convert.source(start).unwrap(),
3277                }),
3278            }))
3279        }))
3280    }
3281}
3282
3283/// Assignment expression.
3284#[derive(Debug, Clone)]
3285pub struct Assign {
3286    /// Assignment operator.
3287    pub op: AssignOp,
3288    /// Left side expression.
3289    pub left: Expression,
3290    /// Right side expression.
3291    pub right: Expression,
3292    /// The range in source.
3293    pub source_range: Range,
3294}
3295
3296impl Assign {
3297    /// Creates assignment expression from meta data.
3298    pub fn from_meta_data(
3299        file: &Arc<String>,
3300        source: &Arc<String>,
3301        mut convert: Convert,
3302        ignored: &mut Vec<Range>,
3303    ) -> Result<(Range, Assign), ()> {
3304        let start = convert;
3305        let node = "assign";
3306        let start_range = convert.start_node(node)?;
3307        convert.update(start_range);
3308
3309        let mut op: Option<AssignOp> = None;
3310        let mut left: Option<Expression> = None;
3311        let mut right: Option<Expression> = None;
3312        loop {
3313            if let Ok(range) = convert.end_node(node) {
3314                convert.update(range);
3315                break;
3316            } else if let Ok((range, _)) = convert.meta_bool(":=") {
3317                convert.update(range);
3318                op = Some(AssignOp::Assign);
3319            } else if let Ok((range, _)) = convert.meta_bool("=") {
3320                convert.update(range);
3321                op = Some(AssignOp::Set);
3322            } else if let Ok((range, _)) = convert.meta_bool("+=") {
3323                convert.update(range);
3324                op = Some(AssignOp::Add);
3325            } else if let Ok((range, _)) = convert.meta_bool("-=") {
3326                convert.update(range);
3327                op = Some(AssignOp::Sub);
3328            } else if let Ok((range, _)) = convert.meta_bool("*=") {
3329                convert.update(range);
3330                op = Some(AssignOp::Mul);
3331            } else if let Ok((range, _)) = convert.meta_bool("/=") {
3332                convert.update(range);
3333                op = Some(AssignOp::Div);
3334            } else if let Ok((range, _)) = convert.meta_bool("%=") {
3335                convert.update(range);
3336                op = Some(AssignOp::Rem);
3337            } else if let Ok((range, _)) = convert.meta_bool("^=") {
3338                convert.update(range);
3339                op = Some(AssignOp::Pow);
3340            } else if let Ok((range, val)) =
3341                Expression::from_meta_data(file, source, "left", convert, ignored)
3342            {
3343                convert.update(range);
3344                left = Some(val);
3345            } else if let Ok((range, val)) =
3346                Expression::from_meta_data(file, source, "right", convert, ignored)
3347            {
3348                convert.update(range);
3349                right = Some(val);
3350            } else {
3351                let range = convert.ignore();
3352                convert.update(range);
3353                ignored.push(range);
3354            }
3355        }
3356
3357        let op = op.ok_or(())?;
3358        let left = left.ok_or(())?;
3359        let right = right.ok_or(())?;
3360        Ok((
3361            convert.subtract(start),
3362            Assign {
3363                op,
3364                left,
3365                right,
3366                source_range: convert.source(start).unwrap(),
3367            },
3368        ))
3369    }
3370
3371    fn get_locals(
3372        &mut self,
3373        relative: usize,
3374        stack: &mut Vec<Option<Arc<String>>>,
3375        closure_stack: &mut Vec<usize>,
3376        module: &Module,
3377        use_lookup: &UseLookup,
3378    ) {
3379        // Declared locals in right expressions are popped from the stack.
3380        let st = stack.len();
3381        self.right.get_locals(relative, stack, closure_stack, module, use_lookup);
3382        stack.truncate(st);
3383
3384        // Declare new local when there is an item with no extra.
3385        if let Expression::Item(ref item) = self.left {
3386            if item.ids.is_empty() && self.op == AssignOp::Assign {
3387                stack.push(Some(item.name.clone()));
3388                return;
3389            }
3390        }
3391
3392        self.left.get_locals(relative, stack, closure_stack, module, use_lookup);
3393        stack.truncate(st);
3394    }
3395}
3396
3397/// Assignment operator.
3398#[derive(Debug, Copy, Clone, PartialEq, Eq)]
3399pub enum AssignOp {
3400    /// :=
3401    Assign,
3402    /// =
3403    Set,
3404    /// +=
3405    Add,
3406    /// -=
3407    Sub,
3408    /// *=
3409    Mul,
3410    /// /=
3411    Div,
3412    /// %=
3413    Rem,
3414    /// ^=
3415    Pow,
3416}
3417
3418impl AssignOp {
3419    /// Returns symbol of assignment operator.
3420    pub fn symbol(self) -> &'static str {
3421        use self::AssignOp::*;
3422
3423        match self {
3424            Assign => ":=",
3425            Set => "=",
3426            Add => "+=",
3427            Sub => "-=",
3428            Mul => "*=",
3429            Div => "/=",
3430            Rem => "%=",
3431            Pow => "^=",
3432        }
3433    }
3434}
3435
3436/// 4D matrix expression.
3437#[derive(Debug, Clone)]
3438pub struct Mat4 {
3439    /// Row vector argument expressions.
3440    pub args: Vec<Expression>,
3441    /// The range in source.
3442    pub source_range: Range,
3443}
3444
3445impl Mat4 {
3446    /// Creates 4D matrix from meta data.
3447    pub fn from_meta_data(
3448        file: &Arc<String>,
3449        source: &Arc<String>,
3450        mut convert: Convert,
3451        ignored: &mut Vec<Range>,
3452    ) -> Result<(Range, Mat4), ()> {
3453        let start = convert;
3454        let node = "mat4";
3455        let start_range = convert.start_node(node)?;
3456        convert.update(start_range);
3457
3458        let mut x: Option<Expression> = None;
3459        let mut y: Option<Expression> = None;
3460        let mut z: Option<Expression> = None;
3461        let mut w: Option<Expression> = None;
3462        loop {
3463            if let Ok(range) = convert.end_node(node) {
3464                convert.update(range);
3465                break;
3466            } else if let Ok((range, val)) =
3467                Expression::from_meta_data(file, source, "ex", convert, ignored)
3468            {
3469                convert.update(range);
3470                x = Some(val);
3471            } else if let Ok((range, val)) =
3472                Expression::from_meta_data(file, source, "ey", convert, ignored)
3473            {
3474                convert.update(range);
3475                y = Some(val);
3476            } else if let Ok((range, val)) =
3477                Expression::from_meta_data(file, source, "ez", convert, ignored)
3478            {
3479                convert.update(range);
3480                z = Some(val);
3481            } else if let Ok((range, val)) =
3482                Expression::from_meta_data(file, source, "ew", convert, ignored)
3483            {
3484                convert.update(range);
3485                w = Some(val);
3486            } else {
3487                let range = convert.ignore();
3488                convert.update(range);
3489                ignored.push(range);
3490            }
3491        }
3492
3493        let x = x.ok_or(())?;
3494        let y = y.unwrap_or_else(|| {
3495            Expression::Variable(Box::new((
3496                Range::empty(0),
3497                Variable::Vec4([0.0, 1.0, 0.0, 0.0]),
3498            )))
3499        });
3500        let z = z.unwrap_or_else(|| {
3501            Expression::Variable(Box::new((
3502                Range::empty(0),
3503                Variable::Vec4([0.0, 0.0, 1.0, 0.0]),
3504            )))
3505        });
3506        let w = w.unwrap_or_else(|| {
3507            Expression::Variable(Box::new((
3508                Range::empty(0),
3509                Variable::Vec4([0.0, 0.0, 0.0, 1.0]),
3510            )))
3511        });
3512        Ok((
3513            convert.subtract(start),
3514            Mat4 {
3515                args: vec![x, y, z, w],
3516                source_range: convert.source(start).unwrap(),
3517            },
3518        ))
3519    }
3520
3521    fn get_locals(
3522        &mut self,
3523        relative: usize,
3524        stack: &mut Vec<Option<Arc<String>>>,
3525        closure_stack: &mut Vec<usize>,
3526        module: &Module,
3527        use_lookup: &UseLookup,
3528    ) {
3529        let st = stack.len();
3530        for arg in &mut self.args {
3531            let arg_st = stack.len();
3532            arg.get_locals(relative, stack, closure_stack, module, use_lookup);
3533            stack.truncate(arg_st);
3534            stack.push(None);
3535        }
3536        stack.truncate(st);
3537    }
3538}
3539
3540/// 4D vector expression.
3541#[derive(Debug, Clone)]
3542pub struct Vec4 {
3543    /// Component expressions.
3544    pub args: Vec<Expression>,
3545    /// The range in source.
3546    pub source_range: Range,
3547}
3548
3549impl Vec4 {
3550    /// Creates 4D vector from meta data.
3551    pub fn from_meta_data(
3552        file: &Arc<String>,
3553        source: &Arc<String>,
3554        mut convert: Convert,
3555        ignored: &mut Vec<Range>,
3556    ) -> Result<(Range, Vec4), ()> {
3557        let start = convert;
3558        let node = "vec4";
3559        let start_range = convert.start_node(node)?;
3560        convert.update(start_range);
3561
3562        let mut x: Option<Expression> = None;
3563        let mut y: Option<Expression> = None;
3564        let mut z: Option<Expression> = None;
3565        let mut w: Option<Expression> = None;
3566        loop {
3567            if let Ok(range) = convert.end_node(node) {
3568                convert.update(range);
3569                break;
3570            } else if let Ok((range, val)) =
3571                Expression::from_meta_data(file, source, "x", convert, ignored)
3572            {
3573                convert.update(range);
3574                x = Some(val);
3575            } else if let Ok((range, val)) =
3576                Expression::from_meta_data(file, source, "y", convert, ignored)
3577            {
3578                convert.update(range);
3579                y = Some(val);
3580            } else if let Ok((range, val)) =
3581                Expression::from_meta_data(file, source, "z", convert, ignored)
3582            {
3583                convert.update(range);
3584                z = Some(val);
3585            } else if let Ok((range, val)) =
3586                Expression::from_meta_data(file, source, "w", convert, ignored)
3587            {
3588                convert.update(range);
3589                w = Some(val);
3590            } else {
3591                let range = convert.ignore();
3592                convert.update(range);
3593                ignored.push(range);
3594            }
3595        }
3596
3597        let x = x.ok_or(())?;
3598        let y = y.unwrap_or_else(|| {
3599            Expression::Variable(Box::new((Range::empty(0), Variable::f64(0.0))))
3600        });
3601        let z = z.unwrap_or_else(|| {
3602            Expression::Variable(Box::new((Range::empty(0), Variable::f64(0.0))))
3603        });
3604        let w = w.unwrap_or_else(|| {
3605            Expression::Variable(Box::new((Range::empty(0), Variable::f64(0.0))))
3606        });
3607        Ok((
3608            convert.subtract(start),
3609            Vec4 {
3610                args: vec![x, y, z, w],
3611                source_range: convert.source(start).unwrap(),
3612            },
3613        ))
3614    }
3615
3616    fn precompute(&self) -> Option<Variable> {
3617        let mut v: [f32; 4] = [0.0; 4];
3618        for i in 0..self.args.len().min(4) {
3619            if let Some(val) = self.args[i].precompute() {
3620                if let Variable::F64(val, _) = val {
3621                    v[i] = val as f32;
3622                } else {
3623                    return None;
3624                }
3625            } else {
3626                return None;
3627            }
3628        }
3629        Some(Variable::Vec4(v))
3630    }
3631
3632    fn get_locals(
3633        &mut self,
3634        relative: usize,
3635        stack: &mut Vec<Option<Arc<String>>>,
3636        closure_stack: &mut Vec<usize>,
3637        module: &Module,
3638        use_lookup: &UseLookup,
3639    ) {
3640        let st = stack.len();
3641        for arg in &mut self.args {
3642            let arg_st = stack.len();
3643            arg.get_locals(relative, stack, closure_stack, module, use_lookup);
3644            stack.truncate(arg_st);
3645            match *arg {
3646                Expression::Swizzle(ref swizzle) => {
3647                    for _ in 0..swizzle.len() {
3648                        stack.push(None);
3649                    }
3650                }
3651                _ => {
3652                    stack.push(None);
3653                }
3654            }
3655        }
3656        stack.truncate(st);
3657    }
3658}
3659
3660/// 4D vector unloop expression.
3661#[derive(Debug, Clone)]
3662pub struct Vec4UnLoop {
3663    /// Name of the variable.
3664    pub name: Arc<String>,
3665    /// Expression of the loop.
3666    pub expr: Expression,
3667    /// The length of the loop.
3668    pub len: u8,
3669    /// The range in source.
3670    pub source_range: Range,
3671}
3672
3673impl Vec4UnLoop {
3674    /// Creates 4D vector-unloop from meta data.
3675    pub fn from_meta_data(
3676        file: &Arc<String>,
3677        source: &Arc<String>,
3678        mut convert: Convert,
3679        ignored: &mut Vec<Range>,
3680    ) -> Result<(Range, Vec4UnLoop), ()> {
3681        let start = convert;
3682        let node = "vec4_un_loop";
3683        let start_range = convert.start_node(node)?;
3684        convert.update(start_range);
3685
3686        let mut name: Option<Arc<String>> = None;
3687        let mut expr: Option<Expression> = None;
3688        let mut len: u8 = 4;
3689        loop {
3690            if let Ok(range) = convert.end_node(node) {
3691                convert.update(range);
3692                break;
3693            } else if let Ok((range, _)) = convert.meta_bool("4") {
3694                convert.update(range);
3695                len = 4;
3696            } else if let Ok((range, _)) = convert.meta_bool("3") {
3697                convert.update(range);
3698                len = 3;
3699            } else if let Ok((range, _)) = convert.meta_bool("2") {
3700                convert.update(range);
3701                len = 2;
3702            } else if let Ok((range, val)) = convert.meta_string("name") {
3703                convert.update(range);
3704                name = Some(val);
3705            } else if let Ok((range, val)) =
3706                Expression::from_meta_data(file, source, "expr", convert, ignored)
3707            {
3708                convert.update(range);
3709                expr = Some(val);
3710            } else {
3711                let range = convert.ignore();
3712                convert.update(range);
3713                ignored.push(range);
3714            }
3715        }
3716
3717        let name = name.ok_or(())?;
3718        let expr = expr.ok_or(())?;
3719        Ok((
3720            convert.subtract(start),
3721            Vec4UnLoop {
3722                name,
3723                expr,
3724                len,
3725                source_range: convert.source(start).unwrap(),
3726            },
3727        ))
3728    }
3729
3730    fn into_expression(self) -> Expression {
3731        let source_range = self.source_range;
3732
3733        let zero = || Expression::Variable(Box::new((source_range, Variable::f64(0.0))));
3734
3735        let replace_0 = replace::number(&self.expr, &self.name, 0.0);
3736        let replace_1 = replace::number(&self.expr, &self.name, 1.0);
3737        let replace_2 = if self.len > 2 {
3738            replace::number(&self.expr, &self.name, 2.0)
3739        } else {
3740            zero()
3741        };
3742        let replace_3 = if self.len > 3 {
3743            replace::number(&self.expr, &self.name, 3.0)
3744        } else {
3745            zero()
3746        };
3747
3748        Expression::Vec4(Box::new(Vec4 {
3749            args: vec![replace_0, replace_1, replace_2, replace_3],
3750            source_range,
3751        }))
3752    }
3753}
3754
3755/// Swizzle expression.
3756#[derive(Debug, Clone)]
3757pub struct Swizzle {
3758    /// First component swizzle.
3759    pub sw0: usize,
3760    /// Second component swizzle.
3761    pub sw1: usize,
3762    /// Third component swizzle.
3763    pub sw2: Option<usize>,
3764    /// Fourth component swizzle.
3765    pub sw3: Option<usize>,
3766    /// 4D vector expression.
3767    pub expr: Expression,
3768    /// The range in source.
3769    pub source_range: Range,
3770}
3771
3772impl Swizzle {
3773    /// Create swizzle from meta data.
3774    pub fn from_meta_data(
3775        file: &Arc<String>,
3776        source: &Arc<String>,
3777        mut convert: Convert,
3778        ignored: &mut Vec<Range>,
3779    ) -> Result<(Range, Swizzle), ()> {
3780        let start = convert;
3781        let node = "swizzle";
3782        let start_range = convert.start_node(node)?;
3783        convert.update(start_range);
3784
3785        let mut sw0: Option<usize> = None;
3786        let mut sw1: Option<usize> = None;
3787        let mut sw2: Option<usize> = None;
3788        let mut sw3: Option<usize> = None;
3789        let mut expr: Option<Expression> = None;
3790        loop {
3791            if let Ok(range) = convert.end_node(node) {
3792                convert.update(range);
3793                break;
3794            } else if let Ok((range, val)) = Sw::from_meta_data("sw0", convert, ignored) {
3795                convert.update(range);
3796                sw0 = Some(val.ind);
3797            } else if let Ok((range, val)) = Sw::from_meta_data("sw1", convert, ignored) {
3798                convert.update(range);
3799                sw1 = Some(val.ind);
3800            } else if let Ok((range, val)) = Sw::from_meta_data("sw2", convert, ignored) {
3801                convert.update(range);
3802                sw2 = Some(val.ind);
3803            } else if let Ok((range, val)) = Sw::from_meta_data("sw3", convert, ignored) {
3804                convert.update(range);
3805                sw3 = Some(val.ind);
3806            } else if let Ok((range, val)) =
3807                Expression::from_meta_data(file, source, "expr", convert, ignored)
3808            {
3809                convert.update(range);
3810                expr = Some(val);
3811            } else {
3812                let range = convert.ignore();
3813                convert.update(range);
3814                ignored.push(range);
3815            }
3816        }
3817
3818        let sw0 = sw0.ok_or(())?;
3819        let sw1 = sw1.ok_or(())?;
3820        let expr = expr.ok_or(())?;
3821        Ok((
3822            convert.subtract(start),
3823            Swizzle {
3824                sw0,
3825                sw1,
3826                sw2,
3827                sw3,
3828                expr,
3829                source_range: convert.source(start).unwrap(),
3830            },
3831        ))
3832    }
3833
3834    fn len(&self) -> usize {
3835        2 + if self.sw2.is_some() { 1 } else { 0 } + if self.sw3.is_some() { 1 } else { 0 }
3836    }
3837}
3838
3839/// Component swizzle expression.
3840#[derive(Debug, Clone)]
3841pub struct Sw {
3842    /// The component index of the swizzle.
3843    pub ind: usize,
3844    /// The range in source.
3845    pub source_range: Range,
3846}
3847
3848impl Sw {
3849    /// Creates component swizzle from meta data.
3850    pub fn from_meta_data(
3851        node: &str,
3852        mut convert: Convert,
3853        ignored: &mut Vec<Range>,
3854    ) -> Result<(Range, Sw), ()> {
3855        let start = convert;
3856        let start_range = convert.start_node(node)?;
3857        convert.update(start_range);
3858
3859        let mut ind: Option<usize> = None;
3860        loop {
3861            if let Ok(range) = convert.end_node(node) {
3862                convert.update(range);
3863                break;
3864            } else if let Ok((range, _)) = convert.meta_bool("x") {
3865                convert.update(range);
3866                ind = Some(0);
3867            } else if let Ok((range, _)) = convert.meta_bool("y") {
3868                convert.update(range);
3869                ind = Some(1);
3870            } else if let Ok((range, _)) = convert.meta_bool("z") {
3871                convert.update(range);
3872                ind = Some(2);
3873            } else if let Ok((range, _)) = convert.meta_bool("w") {
3874                convert.update(range);
3875                ind = Some(3);
3876            } else {
3877                let range = convert.ignore();
3878                convert.update(range);
3879                ignored.push(range);
3880            }
3881        }
3882
3883        let ind = ind.ok_or(())?;
3884        Ok((
3885            convert.subtract(start),
3886            Sw {
3887                ind,
3888                source_range: convert.source(start).unwrap(),
3889            },
3890        ))
3891    }
3892}
3893
3894/// For-expression.
3895#[derive(Debug, Clone)]
3896pub struct For {
3897    /// The initial expression.
3898    pub init: Expression,
3899    /// Expression evaluated for determining whether to continue or not.
3900    pub cond: Expression,
3901    /// Expression evaluated at each step.
3902    pub step: Expression,
3903    /// Block expression.
3904    pub block: Block,
3905    /// Loop label.
3906    pub label: Option<Arc<String>>,
3907    /// The range in source.
3908    pub source_range: Range,
3909}
3910
3911impl For {
3912    /// Creates For-expression from meta data.
3913    pub fn from_meta_data(
3914        file: &Arc<String>,
3915        source: &Arc<String>,
3916        mut convert: Convert,
3917        ignored: &mut Vec<Range>,
3918    ) -> Result<(Range, For), ()> {
3919        let start = convert;
3920        let node = "for";
3921        let start_range = convert.start_node(node)?;
3922        convert.update(start_range);
3923
3924        let mut init: Option<Expression> = None;
3925        let mut cond: Option<Expression> = None;
3926        let mut step: Option<Expression> = None;
3927        let mut block: Option<Block> = None;
3928        let mut label: Option<Arc<String>> = None;
3929        loop {
3930            if let Ok(range) = convert.end_node(node) {
3931                convert.update(range);
3932                break;
3933            } else if let Ok((range, val)) =
3934                Expression::from_meta_data(file, source, "init", convert, ignored)
3935            {
3936                convert.update(range);
3937                init = Some(val);
3938            } else if let Ok((range, val)) =
3939                Expression::from_meta_data(file, source, "cond", convert, ignored)
3940            {
3941                convert.update(range);
3942                cond = Some(val);
3943            } else if let Ok((range, val)) =
3944                Expression::from_meta_data(file, source, "step", convert, ignored)
3945            {
3946                convert.update(range);
3947                step = Some(val);
3948            } else if let Ok((range, val)) =
3949                Block::from_meta_data(file, source, "block", convert, ignored)
3950            {
3951                convert.update(range);
3952                block = Some(val);
3953            } else if let Ok((range, val)) = convert.meta_string("label") {
3954                convert.update(range);
3955                label = Some(val);
3956            } else {
3957                let range = convert.ignore();
3958                convert.update(range);
3959                ignored.push(range);
3960            }
3961        }
3962
3963        let init = init.ok_or(())?;
3964        let cond = cond.ok_or(())?;
3965        let step = step.ok_or(())?;
3966        let block = block.ok_or(())?;
3967        Ok((
3968            convert.subtract(start),
3969            For {
3970                init,
3971                cond,
3972                step,
3973                block,
3974                label,
3975                source_range: convert.source(start).unwrap(),
3976            },
3977        ))
3978    }
3979
3980    fn get_locals(
3981        &mut self,
3982        relative: usize,
3983        stack: &mut Vec<Option<Arc<String>>>,
3984        closure_stack: &mut Vec<usize>,
3985        module: &Module,
3986        use_lookup: &UseLookup,
3987    ) {
3988        let st = stack.len();
3989        self.init.get_locals(relative, stack, closure_stack, module, use_lookup);
3990        let after_init = stack.len();
3991        self.cond.get_locals(relative, stack, closure_stack, module, use_lookup);
3992        stack.truncate(after_init);
3993        self.step.get_locals(relative, stack, closure_stack, module, use_lookup);
3994        stack.truncate(after_init);
3995        self.block.get_locals(relative, stack, closure_stack, module, use_lookup);
3996        stack.truncate(st);
3997    }
3998}
3999
4000/// For-In expression.
4001#[derive(Debug, Clone)]
4002#[cfg(all(not(target_family = "wasm"), feature = "threading"))]
4003pub struct ForIn {
4004    /// Name of the loop variable.
4005    pub name: Arc<String>,
4006    /// The in-type expression to read from.
4007    pub iter: Expression,
4008    /// Block expression.
4009    pub block: Block,
4010    /// Loop label.
4011    pub label: Option<Arc<String>>,
4012    /// The range in source.
4013    pub source_range: Range,
4014}
4015
4016/// For-In expression.
4017#[derive(Debug, Clone)]
4018#[cfg(not(all(not(target_family = "wasm"), feature = "threading")))]
4019pub enum ForIn {}
4020
4021impl ForIn {
4022    /// Creates For-In expression from meta data.
4023    #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
4024    pub fn from_meta_data(
4025        file: &Arc<String>,
4026        source: &Arc<String>,
4027        node: &str,
4028        mut convert: Convert,
4029        ignored: &mut Vec<Range>,
4030    ) -> Result<(Range, ForIn), ()> {
4031        let start = convert;
4032        let start_range = convert.start_node(node)?;
4033        convert.update(start_range);
4034
4035        let mut name: Option<Arc<String>> = None;
4036        let mut iter: Option<Expression> = None;
4037        let mut block: Option<Block> = None;
4038        let mut label: Option<Arc<String>> = None;
4039        loop {
4040            if let Ok(range) = convert.end_node(node) {
4041                convert.update(range);
4042                break;
4043            } else if let Ok((range, val)) = convert.meta_string("name") {
4044                convert.update(range);
4045                name = Some(val);
4046            } else if let Ok((range, val)) =
4047                Expression::from_meta_data(file, source, "iter", convert, ignored)
4048            {
4049                convert.update(range);
4050                iter = Some(val);
4051            } else if let Ok((range, val)) =
4052                Block::from_meta_data(file, source, "block", convert, ignored)
4053            {
4054                convert.update(range);
4055                block = Some(val);
4056            } else if let Ok((range, val)) = convert.meta_string("label") {
4057                convert.update(range);
4058                label = Some(val);
4059            } else {
4060                let range = convert.ignore();
4061                convert.update(range);
4062                ignored.push(range);
4063            }
4064        }
4065
4066        let name = name.ok_or(())?;
4067        let iter = iter.ok_or(())?;
4068        let block = block.ok_or(())?;
4069        Ok((
4070            convert.subtract(start),
4071            ForIn {
4072                name,
4073                iter,
4074                block,
4075                label,
4076                source_range: convert.source(start).unwrap(),
4077            },
4078        ))
4079    }
4080
4081    /// Creates For-In expression from meta data.
4082    #[cfg(not(all(not(target_family = "wasm"), feature = "threading")))]
4083    pub fn from_meta_data(
4084        _file: &Arc<String>,
4085        _source: &Arc<String>,
4086        _node: &str,
4087        _convert: Convert,
4088        _ignored: &mut Vec<Range>,
4089    ) -> Result<(Range, ForIn), ()> {
4090        Err(())
4091    }
4092
4093    #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
4094    fn get_locals(
4095        &mut self,
4096        relative: usize,
4097        stack: &mut Vec<Option<Arc<String>>>,
4098        closure_stack: &mut Vec<usize>,
4099        module: &Module,
4100        use_lookup: &UseLookup,
4101    ) {
4102        let st = stack.len();
4103        self.iter.get_locals(relative, stack, closure_stack, module, use_lookup);
4104        stack.truncate(st);
4105        stack.push(Some(self.name.clone()));
4106        self.block.get_locals(relative, stack, closure_stack, module, use_lookup);
4107        stack.truncate(st);
4108    }
4109
4110    #[cfg(not(all(not(target_family = "wasm"), feature = "threading")))]
4111    fn get_locals(
4112        &mut self,
4113        _relative: usize,
4114        _stack: &mut Vec<Option<Arc<String>>>,
4115        _closure_stack: &mut Vec<usize>,
4116        _module: &Module,
4117        _use_lookup: &UseLookup,
4118    ) {}
4119}
4120
4121/// For-N expression.
4122#[derive(Debug, Clone)]
4123pub struct ForN {
4124    /// Name of index variable.
4125    pub name: Arc<String>,
4126    /// Start expression.
4127    ///
4128    /// This is evaluated before starting the loop.
4129    pub start: Option<Expression>,
4130    /// End expression.
4131    ///
4132    /// This is evaluated before starting the loop.
4133    pub end: Expression,
4134    /// Bloc expression.
4135    pub block: Block,
4136    /// Loop label.
4137    pub label: Option<Arc<String>>,
4138    /// The range in source.
4139    pub source_range: Range,
4140}
4141
4142impl ForN {
4143    /// Creates For-N expression from meta data.
4144    pub fn from_meta_data(
4145        file: &Arc<String>,
4146        source: &Arc<String>,
4147        node: &str,
4148        mut convert: Convert,
4149        ignored: &mut Vec<Range>,
4150    ) -> Result<(Range, ForN), ()> {
4151        let start = convert;
4152        let start_range = convert.start_node(node)?;
4153        convert.update(start_range);
4154
4155        let mut indices: Vec<(Arc<String>, Option<Expression>, Option<Expression>)> = vec![];
4156        let mut block: Option<Block> = None;
4157        let mut label: Option<Arc<String>> = None;
4158        loop {
4159            if let Ok(range) = convert.end_node(node) {
4160                convert.update(range);
4161                break;
4162            } else if let Ok((range, val)) =
4163                Block::from_meta_data(file, source, "block", convert, ignored)
4164            {
4165                convert.update(range);
4166                block = Some(val);
4167            } else if let Ok((range, val)) = convert.meta_string("label") {
4168                convert.update(range);
4169                label = Some(val);
4170            } else if let Ok((range, val)) = convert.meta_string("name") {
4171                convert.update(range);
4172                let mut start_expr: Option<Expression> = None;
4173                let mut end_expr: Option<Expression> = None;
4174                if let Ok((range, val)) =
4175                    Expression::from_meta_data(file, source, "start", convert, ignored)
4176                {
4177                    convert.update(range);
4178                    start_expr = Some(val);
4179                }
4180                if let Ok((range, val)) =
4181                    Expression::from_meta_data(file, source, "end", convert, ignored)
4182                {
4183                    convert.update(range);
4184                    end_expr = Some(val);
4185                }
4186                indices.push((val, start_expr, end_expr));
4187            } else {
4188                let range = convert.ignore();
4189                convert.update(range);
4190                ignored.push(range);
4191            }
4192        }
4193
4194        ForN::create(
4195            node,
4196            convert.subtract(start),
4197            convert.source(start).unwrap(),
4198            label,
4199            &indices,
4200            block,
4201        )
4202    }
4203
4204    fn create(
4205        node: &str,
4206        range: Range,
4207        source_range: Range,
4208        label: Option<Arc<String>>,
4209        indices: &[(Arc<String>, Option<Expression>, Option<Expression>)],
4210        mut block: Option<Block>,
4211    ) -> Result<(Range, ForN), ()> {
4212        if indices.is_empty() {
4213            return Err(());
4214        }
4215
4216        let name: Arc<String> = indices[0].0.clone();
4217        let start_expr = indices[0].1.clone();
4218        let mut end_expr = indices[0].2.clone();
4219
4220        if indices.len() > 1 {
4221            let (_, new_for_n) =
4222                ForN::create(node, range, source_range, None, &indices[1..], block)?;
4223            block = Some(Block {
4224                source_range,
4225                expressions: vec![match node {
4226                    "for_n" => Expression::ForN(Box::new(new_for_n)),
4227                    "sum" => Expression::Sum(Box::new(new_for_n)),
4228                    "sum_vec4" => Expression::SumVec4(Box::new(new_for_n)),
4229                    "prod" => Expression::Prod(Box::new(new_for_n)),
4230                    "prod_vec4" => Expression::ProdVec4(Box::new(new_for_n)),
4231                    "any" => Expression::Any(Box::new(new_for_n)),
4232                    "all" => Expression::All(Box::new(new_for_n)),
4233                    "min" => Expression::Min(Box::new(new_for_n)),
4234                    "max" => Expression::Max(Box::new(new_for_n)),
4235                    "sift" => Expression::Sift(Box::new(new_for_n)),
4236                    "link_for" => Expression::LinkFor(Box::new(new_for_n)),
4237                    _ => return Err(()),
4238                }],
4239            });
4240        }
4241
4242        let block = block.ok_or(())?;
4243
4244        // Infer list length from index.
4245        if end_expr.is_none() {
4246            end_expr = infer_len::infer(&block, &name);
4247        }
4248
4249        let end_expr = end_expr.ok_or(())?;
4250        Ok((
4251            range,
4252            ForN {
4253                name,
4254                start: start_expr,
4255                end: end_expr,
4256                block,
4257                label,
4258                source_range,
4259            },
4260        ))
4261    }
4262
4263    fn get_locals(
4264        &mut self,
4265        relative: usize,
4266        stack: &mut Vec<Option<Arc<String>>>,
4267        closure_stack: &mut Vec<usize>,
4268        module: &Module,
4269        use_lookup: &UseLookup,
4270    ) {
4271        let st = stack.len();
4272        if let Some(ref mut start) = self.start {
4273            start.get_locals(relative, stack, closure_stack, module, use_lookup);
4274            stack.truncate(st);
4275        }
4276        self.end.get_locals(relative, stack, closure_stack, module, use_lookup);
4277        stack.truncate(st);
4278        stack.push(Some(self.name.clone()));
4279        self.block.get_locals(relative, stack, closure_stack, module, use_lookup);
4280        stack.truncate(st);
4281    }
4282}
4283
4284/// Loop expression.
4285#[derive(Debug, Clone)]
4286pub struct Loop {
4287    /// Block expression.
4288    pub block: Block,
4289    /// Loop label.
4290    pub label: Option<Arc<String>>,
4291    /// The range in source.
4292    pub source_range: Range,
4293}
4294
4295impl Loop {
4296    /// Creates loop expression from meta data.
4297    pub fn from_meta_data(
4298        file: &Arc<String>,
4299        source: &Arc<String>,
4300        mut convert: Convert,
4301        ignored: &mut Vec<Range>,
4302    ) -> Result<(Range, Loop), ()> {
4303        let start = convert;
4304        let node = "loop";
4305        let start_range = convert.start_node(node)?;
4306        convert.update(start_range);
4307
4308        let mut block: Option<Block> = None;
4309        let mut label: Option<Arc<String>> = None;
4310        loop {
4311            if let Ok(range) = convert.end_node(node) {
4312                convert.update(range);
4313                break;
4314            } else if let Ok((range, val)) =
4315                Block::from_meta_data(file, source, "block", convert, ignored)
4316            {
4317                convert.update(range);
4318                block = Some(val);
4319            } else if let Ok((range, val)) = convert.meta_string("label") {
4320                convert.update(range);
4321                label = Some(val);
4322            } else {
4323                let range = convert.ignore();
4324                convert.update(range);
4325                ignored.push(range);
4326            }
4327        }
4328
4329        let block = block.ok_or(())?;
4330        Ok((
4331            convert.subtract(start),
4332            Loop {
4333                block,
4334                label,
4335                source_range: convert.source(start).unwrap(),
4336            },
4337        ))
4338    }
4339
4340    fn into_expression(self) -> Expression {
4341        let source_range = self.source_range;
4342        Expression::For(Box::new(For {
4343            block: self.block,
4344            label: self.label,
4345            init: Expression::Block(Box::new(Block {
4346                expressions: vec![],
4347                source_range,
4348            })),
4349            step: Expression::Block(Box::new(Block {
4350                expressions: vec![],
4351                source_range,
4352            })),
4353            cond: Expression::Variable(Box::new((source_range, Variable::bool(true)))),
4354            source_range,
4355        }))
4356    }
4357}
4358
4359/// Break expression.
4360#[derive(Debug, Clone)]
4361pub struct Break {
4362    /// Loop label.
4363    pub label: Option<Arc<String>>,
4364    /// The range in source.
4365    pub source_range: Range,
4366}
4367
4368impl Break {
4369    /// Creates break expression from meta data.
4370    pub fn from_meta_data(
4371        mut convert: Convert,
4372        ignored: &mut Vec<Range>,
4373    ) -> Result<(Range, Break), ()> {
4374        let start = convert;
4375        let node = "break";
4376        let start_range = convert.start_node(node)?;
4377        convert.update(start_range);
4378
4379        let mut label: Option<Arc<String>> = None;
4380        loop {
4381            if let Ok(range) = convert.end_node(node) {
4382                convert.update(range);
4383                break;
4384            } else if let Ok((range, val)) = convert.meta_string("label") {
4385                convert.update(range);
4386                label = Some(val);
4387            } else {
4388                let range = convert.ignore();
4389                convert.update(range);
4390                ignored.push(range);
4391            }
4392        }
4393
4394        Ok((
4395            convert.subtract(start),
4396            Break {
4397                label,
4398                source_range: convert.source(start).unwrap(),
4399            },
4400        ))
4401    }
4402}
4403
4404/// Continue expression.
4405#[derive(Debug, Clone)]
4406pub struct Continue {
4407    /// The loop label.
4408    pub label: Option<Arc<String>>,
4409    /// The range in source.
4410    pub source_range: Range,
4411}
4412
4413impl Continue {
4414    /// Creates continue expression from meta data.
4415    pub fn from_meta_data(
4416        mut convert: Convert,
4417        ignored: &mut Vec<Range>,
4418    ) -> Result<(Range, Continue), ()> {
4419        let start = convert;
4420        let node = "continue";
4421        let start_range = convert.start_node(node)?;
4422        convert.update(start_range);
4423
4424        let mut label: Option<Arc<String>> = None;
4425        loop {
4426            if let Ok(range) = convert.end_node(node) {
4427                convert.update(range);
4428                break;
4429            } else if let Ok((range, val)) = convert.meta_string("label") {
4430                convert.update(range);
4431                label = Some(val);
4432            } else {
4433                let range = convert.ignore();
4434                convert.update(range);
4435                ignored.push(range);
4436            }
4437        }
4438
4439        Ok((
4440            convert.subtract(start),
4441            Continue {
4442                label,
4443                source_range: convert.source(start).unwrap(),
4444            },
4445        ))
4446    }
4447}
4448
4449/// If-expression.
4450#[derive(Debug, Clone)]
4451pub struct If {
4452    /// Condition.
4453    pub cond: Expression,
4454    /// True block.
4455    pub true_block: Block,
4456    /// Else-if conditions.
4457    pub else_if_conds: Vec<Expression>,
4458    /// Else-if blocks.
4459    pub else_if_blocks: Vec<Block>,
4460    /// Else block.
4461    pub else_block: Option<Block>,
4462    /// The range in source.
4463    pub source_range: Range,
4464}
4465
4466impl If {
4467    /// Creates if-expression from meta data.
4468    pub fn from_meta_data(
4469        file: &Arc<String>,
4470        source: &Arc<String>,
4471        mut convert: Convert,
4472        ignored: &mut Vec<Range>,
4473    ) -> Result<(Range, If), ()> {
4474        let start = convert;
4475        let node = "if";
4476        let start_range = convert.start_node(node)?;
4477        convert.update(start_range);
4478
4479        let mut cond: Option<Expression> = None;
4480        let mut true_block: Option<Block> = None;
4481        let mut else_if_conds: Vec<Expression> = vec![];
4482        let mut else_if_blocks: Vec<Block> = vec![];
4483        let mut else_block: Option<Block> = None;
4484        loop {
4485            if let Ok(range) = convert.end_node(node) {
4486                convert.update(range);
4487                break;
4488            } else if let Ok((range, val)) =
4489                Expression::from_meta_data(file, source, "cond", convert, ignored)
4490            {
4491                convert.update(range);
4492                cond = Some(val);
4493            } else if let Ok((range, val)) =
4494                Block::from_meta_data(file, source, "true_block", convert, ignored)
4495            {
4496                convert.update(range);
4497                true_block = Some(val);
4498            } else if let Ok((range, val)) =
4499                Expression::from_meta_data(file, source, "else_if_cond", convert, ignored)
4500            {
4501                convert.update(range);
4502                else_if_conds.push(val);
4503            } else if let Ok((range, val)) =
4504                Block::from_meta_data(file, source, "else_if_block", convert, ignored)
4505            {
4506                convert.update(range);
4507                else_if_blocks.push(val);
4508            } else if let Ok((range, val)) =
4509                Block::from_meta_data(file, source, "else_block", convert, ignored)
4510            {
4511                convert.update(range);
4512                else_block = Some(val);
4513            } else {
4514                let range = convert.ignore();
4515                convert.update(range);
4516                ignored.push(range);
4517            }
4518        }
4519
4520        let cond = cond.ok_or(())?;
4521        let true_block = true_block.ok_or(())?;
4522        Ok((
4523            convert.subtract(start),
4524            If {
4525                cond,
4526                true_block,
4527                else_if_conds,
4528                else_if_blocks,
4529                else_block,
4530                source_range: convert.source(start).unwrap(),
4531            },
4532        ))
4533    }
4534
4535    fn get_locals(
4536        &mut self,
4537        relative: usize,
4538        stack: &mut Vec<Option<Arc<String>>>,
4539        closure_stack: &mut Vec<usize>,
4540        module: &Module,
4541        use_lookup: &UseLookup,
4542    ) {
4543        let st = stack.len();
4544        self.cond.get_locals(relative, stack, closure_stack, module, use_lookup);
4545        stack.truncate(st);
4546        self.true_block.get_locals(relative, stack, closure_stack, module, use_lookup);
4547        stack.truncate(st);
4548        // Does not matter that conditions are looked up before blocks,
4549        // since the stack gets truncated anyway.
4550        for else_if_cond in &mut self.else_if_conds {
4551            else_if_cond.get_locals(relative, stack, closure_stack, module, use_lookup);
4552            stack.truncate(st);
4553        }
4554        for else_if_block in &mut self.else_if_blocks {
4555            else_if_block.get_locals(relative, stack, closure_stack, module, use_lookup);
4556            stack.truncate(st);
4557        }
4558        if let Some(ref mut else_block) = self.else_block {
4559            else_block.get_locals(relative, stack, closure_stack, module, use_lookup);
4560            stack.truncate(st);
4561        }
4562    }
4563}
4564
4565/// Stores `in <function>` expression.
4566#[derive(Debug, Clone)]
4567#[cfg(all(not(target_family = "wasm"), feature = "threading"))]
4568pub struct In {
4569    /// Alias, e.g. `in foo::my_function`.
4570    pub alias: Option<Arc<String>>,
4571    /// Name of function.
4572    pub name: Arc<String>,
4573    /// Function index.
4574    pub f_index: Cell<FnIndex>,
4575    /// Range is source file.
4576    pub source_range: Range,
4577}
4578
4579/// Stores `in <function>` expression.
4580#[derive(Debug, Clone)]
4581#[cfg(not(all(not(target_family = "wasm"), feature = "threading")))]
4582pub enum In {}
4583
4584impl In {
4585    /// Creates in expression from meta data.
4586    #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
4587    pub fn from_meta_data(
4588        node: &'static str,
4589        mut convert: Convert,
4590        ignored: &mut Vec<Range>,
4591    ) -> Result<(Range, In), ()> {
4592        let start = convert;
4593        let start_range = convert.start_node(node)?;
4594        convert.update(start_range);
4595
4596        let mut name: Option<Arc<String>> = None;
4597        let mut alias: Option<Arc<String>> = None;
4598        loop {
4599            if let Ok(range) = convert.end_node(node) {
4600                convert.update(range);
4601                break;
4602            } else if let Ok((range, val)) = convert.meta_string("alias") {
4603                convert.update(range);
4604                alias = Some(val);
4605            } else if let Ok((range, val)) = convert.meta_string("name") {
4606                convert.update(range);
4607                name = Some(val);
4608            } else {
4609                let range = convert.ignore();
4610                convert.update(range);
4611                ignored.push(range);
4612            }
4613        }
4614
4615        let name = name.ok_or(())?;
4616        Ok((
4617            convert.subtract(start),
4618            In {
4619                alias,
4620                name,
4621                f_index: Cell::new(FnIndex::None),
4622                source_range: convert.source(start).unwrap(),
4623            },
4624        ))
4625    }
4626
4627    /// Creates in expression from meta data.
4628    #[cfg(not(all(not(target_family = "wasm"), feature = "threading")))]
4629    pub fn from_meta_data(
4630        _node: &'static str,
4631        _convert: Convert,
4632        _ignored: &mut Vec<Range>,
4633    ) -> Result<(Range, In), ()> {
4634        Err(())
4635    }
4636
4637    #[cfg(all(not(target_family = "wasm"), feature = "threading"))]
4638    fn get_locals(&mut self, relative: usize, module: &Module, use_lookup: &UseLookup) {
4639        use crate::{
4640            FnBinOpRef,
4641            FnExt,
4642            FnReturnRef,
4643            FnUnOpRef,
4644            FnVoidRef,
4645        };
4646
4647        let f_index = if let Some(ref alias) = self.alias {
4648            if let Some(&i) = use_lookup
4649                .aliases
4650                .get(alias)
4651                .and_then(|map| map.get(&self.name))
4652            {
4653                match i {
4654                    FnAlias::Loaded(i) => FnIndex::Loaded(i as isize - relative as isize),
4655                    FnAlias::External(i) => {
4656                        let f = &module.ext_prelude[i];
4657                        match f.f {
4658                            FnExt::Void(ff) => FnIndex::Void(FnVoidRef(ff)),
4659                            FnExt::Return(ff) => FnIndex::Return(FnReturnRef(ff)),
4660                            FnExt::BinOp(ff) => FnIndex::BinOp(FnBinOpRef(ff)),
4661                            FnExt::UnOp(ff) => FnIndex::UnOp(FnUnOpRef(ff)),
4662                        }
4663                    }
4664                }
4665            } else {
4666                FnIndex::None
4667            }
4668        } else {
4669            module.find_function(&self.name, relative)
4670        };
4671        self.f_index.set(f_index);
4672    }
4673
4674    #[cfg(not(all(not(target_family = "wasm"), feature = "threading")))]
4675    fn get_locals(&mut self, _relative: usize, _module: &Module, _use_lookup: &UseLookup) {}
4676}