kaiju_core/
validator.rs

1#![allow(clippy::too_many_arguments)]
2
3use crate::error::*;
4use crate::program::*;
5use std::collections::{HashMap, HashSet};
6
7pub trait DeepValidator {
8    fn filter_module(_module: &Module, _program: &Program, _validator: &Validator) -> bool {
9        true
10    }
11    fn filter_struct(
12        _struct_: &Struct,
13        _module: &Module,
14        _program: &Program,
15        _validator: &Validator,
16    ) -> bool {
17        true
18    }
19    fn filter_function(
20        _function: &Function,
21        _module: &Module,
22        _program: &Program,
23        _validator: &Validator,
24    ) -> bool {
25        true
26    }
27    fn filter_op(
28        _op: &Operation,
29        _function: &Function,
30        _module: &Module,
31        _program: &Program,
32        _validator: &Validator,
33    ) -> bool {
34        true
35    }
36    fn validate_program(_program: &Program, _validator: &Validator) -> SimpleResult<()> {
37        Ok(())
38    }
39    fn validate_module(
40        _module: &Module,
41        _program: &Program,
42        _validator: &Validator,
43    ) -> SimpleResult<()> {
44        Ok(())
45    }
46    fn validate_op(
47        _op: &Operation,
48        _function: &Function,
49        _module: &Module,
50        _program: &Program,
51        _rule: &Rule,
52        _validator: &Validator,
53    ) -> SimpleResult<()> {
54        Ok(())
55    }
56    fn transform_module(
57        module: Module,
58        _program: &Program,
59        _validator: &Validator,
60    ) -> SimpleResult<Module> {
61        Ok(module)
62    }
63}
64
65pub struct EmptyDeepValidator {}
66impl DeepValidator for EmptyDeepValidator {
67    fn transform_module(
68        module: Module,
69        _program: &Program,
70        _validator: &Validator,
71    ) -> SimpleResult<Module> {
72        transform_module_auto_types(module)
73    }
74}
75
76pub struct Rule {
77    pub id: String,
78    pub params: Vec<OpParam>,
79    pub targets: Vec<Type>,
80}
81
82impl Rule {
83    pub fn from_op_rule(rule: &OpRule) -> Self {
84        Self {
85            id: rule.id.clone(),
86            params: rule.params.clone(),
87            targets: rule.targets.clone(),
88        }
89    }
90}
91
92type ModuleTypeIDs = HashMap<String, Option<String>>;
93type ModuleFunctionIDs = HashMap<String, Option<Type>>;
94type FunctionVariablesIDs = HashMap<String, Type>;
95
96pub fn resolve_module_types(module: &Module, program: &Program) -> SimpleResult<ModuleTypeIDs> {
97    let mut types = HashMap::new();
98    types.insert("i8".to_owned(), None);
99    types.insert("i16".to_owned(), None);
100    types.insert("i32".to_owned(), None);
101    types.insert("i64".to_owned(), None);
102    types.insert("u8".to_owned(), None);
103    types.insert("i16".to_owned(), None);
104    types.insert("u32".to_owned(), None);
105    types.insert("u64".to_owned(), None);
106    types.insert("f32".to_owned(), None);
107    types.insert("f64".to_owned(), None);
108    types.insert("isize".to_owned(), None);
109    types.insert("usize".to_owned(), None);
110    for s in &module.structs {
111        if types.contains_key(&s.id) {
112            return Err(SimpleError::new(format!(
113                "Struct name already taken: {}",
114                s.id
115            )));
116        }
117        types.insert(s.id.clone(), Some(module.path.clone()));
118    }
119    for i in &module.imports {
120        if let Some(m) = program.find_module(&i.module) {
121            for n in &i.names {
122                if let Some(s) = m.find_struct(n) {
123                    if types.contains_key(&s.id) {
124                        return Err(SimpleError::new(format!(
125                            "Struct name already taken: {}",
126                            s.id
127                        )));
128                    }
129                    types.insert(s.id.clone(), Some(m.path.clone()));
130                }
131            }
132        } else {
133            return Err(SimpleError::new(format!(
134                "There is no module: {}",
135                i.module
136            )));
137        }
138    }
139    Ok(types)
140}
141
142pub fn resolve_module_functions(
143    module: &Module,
144    program: &Program,
145) -> SimpleResult<ModuleFunctionIDs> {
146    let mut functions = HashMap::new();
147    for f in &module.functions {
148        if functions.contains_key(&f.header.id) {
149            return Err(SimpleError::new(format!(
150                "Function name already taken: {}",
151                f.header.id
152            )));
153        }
154        functions.insert(f.header.id.clone(), f.header.typeid.clone());
155    }
156    for i in &module.imports {
157        if let Some(m) = program.find_module(&i.module) {
158            for n in &i.names {
159                if let Some(f) = m.find_function(n) {
160                    if functions.contains_key(&f.header.id) {
161                        return Err(SimpleError::new(format!(
162                            "Function name already taken: {}",
163                            f.header.id
164                        )));
165                    }
166                    functions.insert(f.header.id.clone(), f.header.typeid.clone());
167                }
168            }
169        } else {
170            return Err(SimpleError::new(format!(
171                "There is no module: {}",
172                i.module
173            )));
174        }
175    }
176    Ok(functions)
177}
178
179pub fn resolve_function_variables(
180    function: &Function,
181    module: &Module,
182) -> SimpleResult<FunctionVariablesIDs> {
183    let mut variables = HashMap::new();
184    for g in &module.globals {
185        if variables.contains_key(&g.id) {
186            return Err(SimpleError::new(format!(
187                "Variable name already taken: {}",
188                g.id
189            )));
190        }
191        variables.insert(g.id.clone(), g.typeid.clone());
192    }
193    if let Some(ref t) = function.header.typeid {
194        variables.insert("_".to_owned(), t.clone());
195    }
196    for p in &function.header.params {
197        if variables.contains_key(&p.id) {
198            return Err(SimpleError::new(format!(
199                "Function `{}`: Variable name already taken: {}",
200                function.header.id, p.id,
201            )));
202        }
203        variables.insert(p.id.clone(), p.typeid.clone());
204    }
205    for l in &function.locals {
206        if variables.contains_key(&l.id) {
207            return Err(SimpleError::new(format!(
208                "Function `{}`: Local variable name already taken: {}",
209                function.header.id, l.id,
210            )));
211        }
212        variables.insert(l.id.clone(), l.typeid.clone());
213    }
214    Ok(variables)
215}
216
217pub fn transform_module_auto_types(mut module: Module) -> SimpleResult<Module> {
218    let integer_type = if let Some(m) = module.meta.iter().find(|m| m.id == "auto_integer_type") {
219        if let Some(MetaValue::String(n)) = m.args.first() {
220            n.to_owned()
221        } else {
222            "i32".to_owned()
223        }
224    } else {
225        "i32".to_owned()
226    };
227    let float_type = if let Some(m) = module.meta.iter().find(|m| m.id == "auto_float_type") {
228        if let Some(MetaValue::String(n)) = m.args.first() {
229            n.to_owned()
230        } else {
231            "f32".to_owned()
232        }
233    } else {
234        "f32".to_owned()
235    };
236    let string_type = if let Some(m) = module.meta.iter().find(|m| m.id == "auto_string_type") {
237        if let Some(MetaValue::String(n)) = m.args.first() {
238            n.to_owned()
239        } else {
240            "u8".to_owned()
241        }
242    } else {
243        "u8".to_owned()
244    };
245    module.functions = module
246        .functions
247        .iter()
248        .map(|f| transform_function_auto_types(f.clone(), &integer_type, &float_type, &string_type))
249        .collect::<SimpleResult<Vec<_>>>()?;
250    Ok(module)
251}
252
253pub fn transform_function_auto_types(
254    mut function: Function,
255    integer_type: &str,
256    float_type: &str,
257    string_type: &str,
258) -> SimpleResult<Function> {
259    function.body = function
260        .body
261        .iter()
262        .map(|o| match o.clone() {
263            BlockOp::Operation(mut op) => {
264                op.params = op
265                    .params
266                    .iter()
267                    .map(|v| {
268                        transform_value_auto_types(v.clone(), integer_type, float_type, string_type)
269                    })
270                    .collect::<SimpleResult<Vec<_>>>()?;
271                op.targets = op
272                    .targets
273                    .iter()
274                    .map(|v| {
275                        transform_value_auto_types(v.clone(), integer_type, float_type, string_type)
276                    })
277                    .collect::<SimpleResult<Vec<_>>>()?;
278                Ok(BlockOp::Operation(op))
279            }
280            BlockOp::Label(n) => Ok(BlockOp::Label(n)),
281        })
282        .collect::<SimpleResult<Vec<_>>>()?;
283    Ok(function)
284}
285
286pub fn transform_value_auto_types(
287    value: Value,
288    integer_type: &str,
289    float_type: &str,
290    string_type: &str,
291) -> SimpleResult<Value> {
292    match value {
293        Value::Ref(v, a) => Ok(Value::Ref(
294            Box::new(transform_value_auto_types(
295                *v,
296                integer_type,
297                float_type,
298                string_type,
299            )?),
300            a,
301        )),
302        Value::Deref(v, a) => Ok(Value::Deref(
303            Box::new(transform_value_auto_types(
304                *v,
305                integer_type,
306                float_type,
307                string_type,
308            )?),
309            a,
310        )),
311        Value::FunctionCall(i, v, a) => Ok(Value::FunctionCall(
312            i,
313            v.into_iter()
314                .map(|v| transform_value_auto_types(v, integer_type, float_type, string_type))
315                .collect::<SimpleResult<Vec<_>>>()?,
316            a,
317        )),
318        Value::Tuple(v, a) => Ok(Value::Tuple(
319            v.into_iter()
320                .map(|v| transform_value_auto_types(v, integer_type, float_type, string_type))
321                .collect::<SimpleResult<Vec<_>>>()?,
322            a,
323        )),
324        Value::String(v, t) => {
325            if let Type::Pointer(t) = t {
326                if let Type::Identifier(i) = *t {
327                    Ok(Value::String(
328                        v,
329                        Type::Pointer(Box::new(Type::Identifier(if i == "{string}" {
330                            string_type.to_owned()
331                        } else {
332                            i
333                        }))),
334                    ))
335                } else {
336                    Err(SimpleError::new(format!(
337                        "Type is not identifier: {}",
338                        t.to_string()
339                    )))
340                }
341            } else {
342                Err(SimpleError::new(format!(
343                    "Type is not pointer: {}",
344                    t.to_string()
345                )))
346            }
347        }
348        Value::Number(v) => match v {
349            Number::Integer(v, t) => {
350                if let Type::Identifier(i) = t {
351                    Ok(Value::Number(Number::Integer(
352                        v,
353                        Type::Identifier(if i == "{integer}" {
354                            integer_type.to_owned()
355                        } else {
356                            i
357                        }),
358                    )))
359                } else {
360                    Err(SimpleError::new(format!(
361                        "Type is not identifier: {}",
362                        t.to_string()
363                    )))
364                }
365            }
366            Number::Float(v, t) => {
367                if let Type::Identifier(i) = t {
368                    Ok(Value::Number(Number::Float(
369                        v,
370                        Type::Identifier(if i == "{float}" {
371                            float_type.to_owned()
372                        } else {
373                            i
374                        }),
375                    )))
376                } else {
377                    Err(SimpleError::new(format!(
378                        "Type is not identifier: {}",
379                        t.to_string()
380                    )))
381                }
382            }
383        },
384        Value::OperationInline(i, v, a) => Ok(Value::OperationInline(
385            i,
386            v.into_iter()
387                .map(|v| transform_value_auto_types(v, integer_type, float_type, string_type))
388                .collect::<SimpleResult<Vec<_>>>()?,
389            a,
390        )),
391        Value::Variable(i, a) => Ok(Value::Variable(i, a)),
392    }
393}
394
395pub struct Validator {
396    meta: Vec<Meta>,
397    rules: Vec<Rule>,
398}
399
400impl Validator {
401    #[inline]
402    pub fn new(ops_descriptor: &OpsDescriptor) -> Self {
403        Self::with_filter(ops_descriptor, |_, _| true)
404    }
405
406    pub fn with_filter<F>(ops_descriptor: &OpsDescriptor, filter: F) -> Self
407    where
408        F: Fn(&OpRule, &OpsDescriptor) -> bool,
409    {
410        Self {
411            meta: ops_descriptor.meta.clone(),
412            rules: ops_descriptor
413                .rules
414                .iter()
415                .filter_map(|r| {
416                    if filter(r, ops_descriptor) {
417                        Some(Rule::from_op_rule(r))
418                    } else {
419                        None
420                    }
421                })
422                .collect(),
423        }
424    }
425
426    pub fn meta(&self) -> &[Meta] {
427        &self.meta
428    }
429
430    pub fn rules(&self) -> &[Rule] {
431        &self.rules
432    }
433
434    pub fn filter_program<V>(&self, program: &mut Program)
435    where
436        V: DeepValidator,
437    {
438        let mut modules = program
439            .modules
440            .iter()
441            .filter(|m| V::filter_module(m, program, self))
442            .cloned()
443            .collect();
444        for m in &mut modules {
445            self.filter_module::<V>(m, program);
446        }
447        program.modules = modules;
448    }
449
450    fn filter_module<V>(&self, module: &mut Module, program: &Program)
451    where
452        V: DeepValidator,
453    {
454        let structs = module
455            .structs
456            .iter()
457            .filter(|s| V::filter_struct(s, module, program, self))
458            .cloned()
459            .collect();
460        let mut functions = module
461            .functions
462            .iter()
463            .filter(|f| V::filter_function(f, module, program, self))
464            .cloned()
465            .collect();
466        for f in &mut functions {
467            self.filter_function::<V>(f, module, program);
468        }
469        module.structs = structs;
470        module.functions = functions;
471    }
472
473    fn filter_function<V>(&self, function: &mut Function, module: &Module, program: &Program)
474    where
475        V: DeepValidator,
476    {
477        let body = function
478            .body
479            .iter()
480            .filter(|o| {
481                if let BlockOp::Operation(o) = o {
482                    V::filter_op(&o, function, module, program, self)
483                } else {
484                    true
485                }
486            })
487            .cloned()
488            .collect();
489        function.body = body;
490    }
491
492    pub fn validate_program<V>(&self, program: &Program) -> SimpleResult<()>
493    where
494        V: DeepValidator,
495    {
496        for module in &program.modules {
497            self.ensure_no_duplicates_module(module)?;
498            self.validate_module::<V>(module, program)?;
499        }
500        V::validate_program(program, self)
501    }
502
503    pub fn transform_program<V>(&self, program: &mut Program) -> SimpleResult<()>
504    where
505        V: DeepValidator,
506    {
507        program.modules = program
508            .modules
509            .iter()
510            .map(|m| V::transform_module(m.clone(), program, self))
511            .collect::<SimpleResult<Vec<Module>>>()?;
512        Ok(())
513    }
514
515    fn ensure_no_duplicates_module(&self, module: &Module) -> SimpleResult<()> {
516        let mut ids = HashSet::new();
517        for i in &module.imports {
518            for name in &i.names {
519                if ids.contains(name) {
520                    return Err(SimpleError::new(format!(
521                        "Import name `{}` is already taken",
522                        name
523                    )));
524                }
525                ids.insert(name.clone());
526            }
527        }
528        for g in &module.globals {
529            if ids.contains(&g.id) {
530                return Err(SimpleError::new(format!(
531                    "Global name `{}` is already taken",
532                    g.id
533                )));
534            }
535            ids.insert(g.id.clone());
536        }
537        for e in &module.externs {
538            if ids.contains(&e.item.id) {
539                return Err(SimpleError::new(format!(
540                    "Export name `{}` is already taken",
541                    e.item.id
542                )));
543            }
544            ids.insert(e.item.id.clone());
545        }
546        for s in &module.structs {
547            if ids.contains(&s.id) {
548                return Err(SimpleError::new(format!(
549                    "Struct name `{}` is already taken",
550                    s.id
551                )));
552            }
553            ids.insert(s.id.clone());
554        }
555        for f in &module.functions {
556            if ids.contains(&f.header.id) {
557                return Err(SimpleError::new(format!(
558                    "Function name `{}` is already taken",
559                    f.header.id
560                )));
561            }
562            ids.insert(f.header.id.clone());
563        }
564        Ok(())
565    }
566
567    fn validate_module<V>(&self, module: &Module, program: &Program) -> SimpleResult<()>
568    where
569        V: DeepValidator,
570    {
571        let types = resolve_module_types(module, program)?;
572        let functions = resolve_module_functions(module, program)?;
573        for s in &module.structs {
574            Self::validate_struct(s, program)?;
575        }
576        for g in &module.globals {
577            Self::validate_type(&g.typeid, &types)?;
578        }
579        for e in &module.externs {
580            Self::validate_function_header(&e.item, &types)?;
581        }
582        for f in &module.functions {
583            let variables = resolve_function_variables(f, module)?;
584            self.validate_function::<V>(f, module, program, &types, &functions, &variables)?;
585        }
586        V::validate_module(module, program, self)
587    }
588
589    fn validate_struct(struct_: &Struct, program: &Program) -> SimpleResult<()> {
590        let mut stack = vec![];
591        Self::validate_struct_inner(struct_, program, &mut stack)
592    }
593
594    fn validate_struct_inner(
595        struct_: &Struct,
596        program: &Program,
597        stack: &mut Vec<String>,
598    ) -> SimpleResult<()> {
599        stack.push(struct_.id.clone());
600        for f in &struct_.fields {
601            Self::validate_struct_type(&f.typeid, program, stack)?;
602        }
603        stack.pop();
604        Ok(())
605    }
606
607    fn validate_struct_type(
608        type_: &Type,
609        program: &Program,
610        stack: &mut Vec<String>,
611    ) -> SimpleResult<()> {
612        match type_ {
613            Type::Identifier(ref t) => {
614                if let Some(s) = program.find_struct(t) {
615                    if stack.iter().any(|t| t == &s.id) {
616                        return Err(SimpleError::new(format!(
617                            "Type `{}` is found to be in infinite loop of fields types with chain: {}\nConsider using pointer to that type instead",
618                            s.id,
619                            stack.join(" => "),
620                        )));
621                    }
622                    Self::validate_struct_inner(s, program, stack)?;
623                }
624                Ok(())
625            }
626            Type::Tuple(ref v) => {
627                for t in v {
628                    Self::validate_struct_type(t, program, stack)?;
629                }
630                Ok(())
631            }
632            _ => Ok(()),
633        }
634    }
635
636    fn validate_function<V>(
637        &self,
638        function: &Function,
639        module: &Module,
640        program: &Program,
641        types: &ModuleTypeIDs,
642        functions: &ModuleFunctionIDs,
643        variables: &FunctionVariablesIDs,
644    ) -> SimpleResult<()>
645    where
646        V: DeepValidator,
647    {
648        Self::validate_function_header(&function.header, types)?;
649        for v in &function.locals {
650            Self::validate_type(&v.typeid, types)?;
651        }
652        for o in &function.body {
653            if let BlockOp::Operation(ref o) = o {
654                self.validate_op::<V>(o, function, module, program, types, functions, variables)?;
655            }
656        }
657        Ok(())
658    }
659
660    fn validate_function_header(
661        header: &FunctionHeader,
662        types: &ModuleTypeIDs,
663    ) -> SimpleResult<()> {
664        for p in &header.params {
665            Self::validate_type(&p.typeid, types)?;
666        }
667        if let Some(ref t) = header.typeid {
668            Self::validate_type(t, types)?;
669        }
670        Ok(())
671    }
672
673    fn validate_type(typeid: &Type, types: &ModuleTypeIDs) -> SimpleResult<()> {
674        match typeid {
675            Type::Identifier(ref t) => {
676                if !t.is_empty() && !types.contains_key(t) {
677                    Err(SimpleError::new(format!("Found unknown type: `{}`", t)))
678                } else {
679                    Ok(())
680                }
681            }
682            Type::Pointer(ref t) => Self::validate_type(t, types),
683            Type::Tuple(ref tt) => {
684                for t in tt {
685                    Self::validate_type(t, types)?;
686                }
687                Ok(())
688            }
689        }
690    }
691
692    fn validate_op<V>(
693        &self,
694        op: &Operation,
695        function: &Function,
696        module: &Module,
697        program: &Program,
698        types: &ModuleTypeIDs,
699        functions: &ModuleFunctionIDs,
700        variables: &FunctionVariablesIDs,
701    ) -> SimpleResult<()>
702    where
703        V: DeepValidator,
704    {
705        if let Some(rule) = self.rules.iter().find(|r| r.id == op.id) {
706            if rule.params.len() != op.params.len() {
707                return Err(SimpleError::new(format!(
708                    "Operation `{}` expects {} parameter(s)",
709                    op.id,
710                    rule.params.len()
711                )));
712            }
713            if rule.targets.len() != op.targets.len() {
714                return Err(SimpleError::new(format!(
715                    "Operation `{}` expects {} target(s)",
716                    op.id,
717                    rule.targets.len()
718                )));
719            }
720            for i in 0..rule.params.len() {
721                let pr = &rule.params[i];
722                let po = &op.params[i];
723                match self.find_value_type(po, types, functions, variables, program) {
724                    Ok(t) => {
725                        if let Err(err) = Self::validate_type(&t, types) {
726                            Err(SimpleError::new(format!(
727                                "Operation `{}`: {}",
728                                op.id, err.message
729                            )))
730                        } else if t == pr.typeid {
731                            Ok(())
732                        } else {
733                            Err(SimpleError::new(format!(
734                                "Operation `{}` parameter `{}` with type `{}` is not type of `{}`",
735                                op.id,
736                                pr.id,
737                                t.to_string(),
738                                pr.typeid.to_string(),
739                            )))
740                        }
741                    }
742                    Err(err) => Err(SimpleError::new(format!(
743                        "Operation `{}`: {}",
744                        op.id, err.message
745                    ))),
746                }?;
747            }
748            for i in 0..rule.targets.len() {
749                let ta = &rule.targets[i];
750                let tb = &op.targets[i];
751                match self.find_value_type(tb, types, functions, variables, program) {
752                    Ok(ref t) => {
753                        if let Err(err) = Self::validate_type(&t, types) {
754                            Err(SimpleError::new(format!(
755                                "Operation `{}`: {}",
756                                op.id, err.message
757                            )))
758                        } else if t == ta {
759                            Ok(())
760                        } else {
761                            Err(SimpleError::new(format!(
762                                "Operation `{}` target #`{}` with type `{}` is not type of `{}`",
763                                op.id,
764                                i,
765                                t.to_string(),
766                                ta.to_string(),
767                            )))
768                        }
769                    }
770                    Err(err) => Err(SimpleError::new(format!(
771                        "Operation `{}`: {}",
772                        op.id, err.message
773                    ))),
774                }?;
775            }
776            if let Err(err) = V::validate_op(op, function, module, program, rule, self) {
777                Err(SimpleError::new(format!(
778                    "Operation `{}`: {}",
779                    op.id, err.message
780                )))
781            } else {
782                Ok(())
783            }
784        } else {
785            Err(SimpleError::new(format!(
786                "Operation is not supported: {}",
787                op.id
788            )))
789        }
790    }
791
792    fn find_value_type(
793        &self,
794        value: &Value,
795        types: &ModuleTypeIDs,
796        functions: &ModuleFunctionIDs,
797        variables: &FunctionVariablesIDs,
798        program: &Program,
799    ) -> SimpleResult<Type> {
800        match value {
801            Value::Ref(ref v, ref a) => {
802                let t = Type::Pointer(Box::new(
803                    self.find_value_type(v, types, functions, variables, program)?,
804                ));
805                if let Some(ref a) = a {
806                    self.find_access_value_type(&t, a, types, program)
807                } else {
808                    Ok(t)
809                }
810            }
811            Value::Deref(ref v, ref a) => {
812                let t = self.find_value_type(v, types, functions, variables, program)?;
813                if let Type::Pointer(t) = t {
814                    if let Some(ref a) = a {
815                        self.find_access_value_type(&t, a, types, program)
816                    } else {
817                        Ok(*t)
818                    }
819                } else {
820                    Err(SimpleError::new(format!(
821                        "Trying to dereference non-pointer type: {}",
822                        t.to_string()
823                    )))
824                }
825            }
826            Value::FunctionCall(ref fc, _, ref a) => {
827                self.find_function_call_value_type(fc, a, functions, types, program)
828            }
829            Value::Tuple(ref t, ref a) => {
830                self.find_tuple_value_type(t, a, types, functions, variables, program)
831            }
832            Value::String(_, ref t) => Ok(t.clone()),
833            Value::Number(ref n) => Ok(match n {
834                Number::Integer(_, ref t) => t.clone(),
835                Number::Float(_, ref t) => t.clone(),
836            }),
837            Value::OperationInline(ref n, _, ref a) => {
838                self.find_operation_inline_value_type(n, a, types, program)
839            }
840            Value::Variable(ref id, ref a) => {
841                if let Some(t) = variables.iter().find(|v| v.0 == id) {
842                    if let Some(ref a) = a {
843                        self.find_access_value_type(&t.1, a, types, program)
844                    } else {
845                        Ok(t.1.clone())
846                    }
847                } else {
848                    Err(SimpleError::new(format!(
849                        "Could not find variable `{}` in scope",
850                        id
851                    )))
852                }
853            }
854        }
855    }
856
857    fn find_function_call_value_type(
858        &self,
859        id: &str,
860        access: &Option<Box<Access>>,
861        functions: &ModuleFunctionIDs,
862        types: &ModuleTypeIDs,
863        program: &Program,
864    ) -> SimpleResult<Type> {
865        if let Some(t) = functions.get(id) {
866            if let Some(t) = t {
867                if let Some(a) = access {
868                    self.find_access_value_type(t, a, types, program)
869                } else {
870                    Ok(t.clone())
871                }
872            } else if access.is_none() {
873                Ok(Type::default())
874            } else {
875                Err(SimpleError::new("Trying to access empty type".to_owned()))
876            }
877        } else {
878            Err(SimpleError::new(format!(
879                "Trying to call unknown function: {:?}",
880                id
881            )))
882        }
883    }
884
885    fn find_tuple_value_type(
886        &self,
887        values: &[Value],
888        access: &Option<Box<Access>>,
889        types: &ModuleTypeIDs,
890        functions: &ModuleFunctionIDs,
891        variables: &FunctionVariablesIDs,
892        program: &Program,
893    ) -> SimpleResult<Type> {
894        let result = Type::Tuple(
895            values
896                .iter()
897                .map(|t| self.find_value_type(t, types, functions, variables, program))
898                .collect::<Result<Vec<Type>, SimpleError>>()?,
899        );
900        if let Some(ref a) = access {
901            self.find_access_value_type(&result, a, types, program)
902        } else {
903            Ok(result)
904        }
905    }
906
907    fn find_access_value_type(
908        &self,
909        typeid: &Type,
910        access: &Access,
911        types: &ModuleTypeIDs,
912        program: &Program,
913    ) -> SimpleResult<Type> {
914        match access {
915            Access::Tuple(i, a) => match typeid {
916                Type::Tuple(ref t) => {
917                    let i = *i as usize;
918                    if i < t.len() {
919                        if let Some(ref a) = a {
920                            self.find_access_value_type(&t[i], a, types, program)
921                        } else {
922                            Ok(t[i].clone())
923                        }
924                    } else {
925                        Err(SimpleError::new(format!(
926                            "Tuple does not have field #{}",
927                            i
928                        )))
929                    }
930                }
931                _ => Err(SimpleError::new(
932                    "Only tuples can be accessed by index".to_owned(),
933                )),
934            },
935            Access::Variable(id, a) => match typeid {
936                Type::Identifier(ref i) => {
937                    if let Some(m) = types.get(i).unwrap() {
938                        if let Some(s) = program.find_module_struct(m, i) {
939                            if let Some(v) = s.fields.iter().find(|v| &v.id == id) {
940                                if let Some(a) = a {
941                                    self.find_access_value_type(&v.typeid, a, types, program)
942                                } else {
943                                    Ok(v.typeid.clone())
944                                }
945                            } else {
946                                Err(SimpleError::new(format!(
947                                    "Could not find field `{}` in type: {:?}",
948                                    id, s.id
949                                )))
950                            }
951                        } else {
952                            Err(SimpleError::new(format!(
953                                "Atomic struct {} does not have any fields",
954                                i
955                            )))
956                        }
957                    } else {
958                        Err(SimpleError::new(format!(
959                            "Atomic struct {} does not have any fields",
960                            i
961                        )))
962                    }
963                }
964                _ => Err(SimpleError::new(
965                    "Only structs can be accessed by variable".to_owned(),
966                )),
967            },
968        }
969    }
970
971    fn find_operation_inline_value_type(
972        &self,
973        id: &str,
974        access: &Option<Box<Access>>,
975        types: &ModuleTypeIDs,
976        program: &Program,
977    ) -> SimpleResult<Type> {
978        if let Some(rule) = self.rules.iter().find(|r| r.id == id) {
979            if rule.targets.len() == 1 {
980                if let Some(a) = access {
981                    self.find_access_value_type(&rule.targets[0], a, types, program)
982                } else {
983                    Ok(rule.targets[0].clone())
984                }
985            } else {
986                Err(SimpleError::new(format!(
987                    "Trying to inline operation of not one target: {}",
988                    id
989                )))
990            }
991        } else {
992            Err(SimpleError::new(format!(
993                "Trying to inline unknown operation: {}",
994                id
995            )))
996        }
997    }
998}