intuicio_frontend_simpleton/
script.rs

1use crate::{parser, Array, Boolean, Function, Integer, Map, Real, Reference, Text, Type};
2use bincode::{DefaultOptions, Options};
3use intuicio_core::{
4    context::Context,
5    crate_version,
6    function::FunctionQuery,
7    object::Object,
8    registry::Registry,
9    script::{
10        BytesContentParser, ScriptContent, ScriptContentProvider, ScriptExpression, ScriptFunction,
11        ScriptFunctionParameter, ScriptFunctionSignature, ScriptHandle, ScriptModule,
12        ScriptOperation, ScriptPackage, ScriptStruct, ScriptStructField,
13    },
14    types::TypeQuery,
15    IntuicioVersion, Visibility,
16};
17use serde::{Deserialize, Serialize};
18use std::{collections::HashMap, error::Error, path::PathBuf};
19
20const CLOSURES: &str = "_closures";
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
23pub enum SimpletonScriptLiteral {
24    Null,
25    Boolean(Boolean),
26    Integer(Integer),
27    Real(Real),
28    Text(Text),
29    Array {
30        items_count: usize,
31    },
32    Map {
33        items_count: usize,
34    },
35    Object {
36        name: String,
37        module_name: String,
38        fields_count: usize,
39    },
40}
41
42impl SimpletonScriptLiteral {
43    fn evaluate(&self, context: &mut Context, registry: &Registry) {
44        match self {
45            Self::Null => context.stack().push(Reference::null()),
46            Self::Boolean(value) => context
47                .stack()
48                .push(Reference::new_boolean(*value, registry)),
49            Self::Integer(value) => context
50                .stack()
51                .push(Reference::new_integer(*value, registry)),
52            Self::Real(value) => context.stack().push(Reference::new_real(*value, registry)),
53            Self::Text(value) => context
54                .stack()
55                .push(Reference::new_text(value.to_owned(), registry)),
56            Self::Array { items_count } => {
57                let mut result = Array::with_capacity(*items_count);
58                for _ in 0..*items_count {
59                    result.push(context.stack().pop::<Reference>().unwrap());
60                }
61                context.stack().push(Reference::new_array(result, registry))
62            }
63            Self::Map { items_count } => {
64                let mut result = Map::with_capacity(*items_count);
65                for _ in 0..*items_count {
66                    let key = context
67                        .stack()
68                        .pop::<Reference>()
69                        .unwrap()
70                        .read::<Text>()
71                        .unwrap()
72                        .to_owned();
73                    let value = context.stack().pop::<Reference>().unwrap();
74                    result.insert(key, value);
75                }
76                context.stack().push(Reference::new_map(result, registry))
77            }
78            Self::Object {
79                name,
80                module_name,
81                fields_count,
82            } => {
83                let type_ = registry
84                    .find_type(TypeQuery {
85                        name: Some(name.into()),
86                        module_name: Some(module_name.into()),
87                        ..Default::default()
88                    })
89                    .unwrap();
90                let mut result = Object::new(type_);
91                for _ in 0..*fields_count {
92                    let name = context.stack().pop::<Reference>().unwrap();
93
94                    *result
95                        .write_field::<Reference>(name.read::<Text>().unwrap().as_str())
96                        .unwrap() = context.stack().pop::<Reference>().unwrap();
97                }
98                context.stack().push(Reference::new_raw(result))
99            }
100        };
101    }
102}
103
104#[derive(Debug, Serialize, Deserialize)]
105pub enum SimpletonScriptExpression {
106    FindStruct { name: String, module_name: String },
107    FindFunction { name: String, module_name: String },
108    Literal(SimpletonScriptLiteral),
109    StackDrop,
110    StackDuplicate,
111    StackSwap,
112    StackUnwrapBoolean,
113    StackValueOr(bool),
114    GetField { name: String },
115    SetField { name: String },
116}
117
118impl ScriptExpression for SimpletonScriptExpression {
119    fn evaluate(&self, context: &mut Context, registry: &Registry) {
120        match self {
121            Self::FindStruct { name, module_name } => {
122                context.stack().push(Reference::new_type(
123                    Type::new(
124                        registry
125                            .find_type(TypeQuery {
126                                name: Some(name.into()),
127                                module_name: Some(module_name.into()),
128                                ..Default::default()
129                            })
130                            .unwrap_or_else(|| {
131                                panic!("Could not find struct: {}::{}", module_name, name)
132                            }),
133                    ),
134                    registry,
135                ));
136            }
137            Self::FindFunction { name, module_name } => {
138                context.stack().push(Reference::new_function(
139                    Function::new(
140                        registry
141                            .find_function(FunctionQuery {
142                                name: Some(name.into()),
143                                module_name: Some(module_name.into()),
144                                ..Default::default()
145                            })
146                            .unwrap_or_else(|| {
147                                panic!("Could not find function: {}::{}", module_name, name)
148                            }),
149                    ),
150                    registry,
151                ));
152            }
153            Self::Literal(literal) => {
154                literal.evaluate(context, registry);
155            }
156            Self::StackDrop => {
157                context.stack().drop();
158            }
159            Self::StackDuplicate => {
160                let object = context
161                    .stack()
162                    .pop::<Reference>()
163                    .expect("Could not pop object from stack to duplicate!");
164                context.stack().push(object.clone());
165                context.stack().push(object);
166            }
167            Self::StackSwap => {
168                let a = context
169                    .stack()
170                    .pop::<Reference>()
171                    .expect("Could not pop first object from stack to swap!");
172                let b = context
173                    .stack()
174                    .pop::<Reference>()
175                    .expect("Could not pop second object from stack to swap!");
176                context.stack().push(a);
177                context.stack().push(b);
178            }
179            Self::StackUnwrapBoolean => {
180                let value = context
181                    .stack()
182                    .pop::<Reference>()
183                    .expect("Could not pop value from stack to unwrap as boolean!");
184                context.stack().push(
185                    *value
186                        .read::<Boolean>()
187                        .expect("Value got from stack is not a boleean!"),
188                );
189            }
190            Self::StackValueOr(value) => {
191                let object = context.stack().pop::<Reference>().unwrap_or_else(|| {
192                    panic!("Could not pop object from stack to tell if scope should continue!")
193                });
194                if object.is_null() {
195                    context.stack().push(*value);
196                } else {
197                    context.stack().push(object);
198                    context.stack().push(!*value);
199                }
200            }
201            Self::GetField { name } => {
202                let object = context.stack().pop::<Reference>().unwrap_or_else(|| {
203                    panic!(
204                        "Could not pop parent object of `{}` field from stack!",
205                        name
206                    )
207                });
208                if object.is_null() {
209                    panic!("Trying to read `{}` field of null reference!", name);
210                }
211                let value = object
212                    .read_object()
213                    .unwrap_or_else(|| {
214                        panic!("Could not read object of `{}` field got from stack!", name)
215                    })
216                    .read_field::<Reference>(name)
217                    .unwrap_or_else(|| {
218                        panic!("Could not read `{}` field of object got from stack!", name)
219                    })
220                    .clone();
221                context.stack().push(value);
222            }
223            Self::SetField { name } => {
224                let mut object = context.stack().pop::<Reference>().unwrap_or_else(|| {
225                    panic!(
226                        "Could not pop parent object of `{}` field from stack!",
227                        name
228                    )
229                });
230                if object.is_null() {
231                    panic!("Trying to write `{}` field of null reference!", name);
232                }
233                let value = context.stack().pop::<Reference>().unwrap();
234                *object
235                    .write_object()
236                    .unwrap_or_else(|| {
237                        panic!("Could not write object of `{}` field got from stack!", name)
238                    })
239                    .write_field::<Reference>(name)
240                    .unwrap_or_else(|| {
241                        panic!("Could not write `{}` field of object got from stack!", name)
242                    }) = value;
243            }
244        }
245    }
246}
247
248#[derive(Debug, Clone, Serialize, Deserialize)]
249pub enum SimpletonLiteral {
250    Null,
251    Boolean(Boolean),
252    Integer(Integer),
253    Real(Real),
254    Text(Text),
255    Array {
256        items: Vec<SimpletonExpressionStart>,
257    },
258    Map {
259        items: Vec<(String, SimpletonExpressionStart)>,
260    },
261    Object {
262        name: String,
263        module_name: String,
264        fields: Vec<(String, SimpletonExpressionStart)>,
265    },
266}
267
268impl SimpletonLiteral {
269    pub fn compile(
270        &self,
271        result: &mut Vec<ScriptOperation<SimpletonScriptExpression>>,
272        registers: &mut Vec<String>,
273        closures: &mut Vec<SimpletonFunction>,
274        closures_index: &mut usize,
275    ) -> SimpletonScriptLiteral {
276        match self {
277            Self::Null => SimpletonScriptLiteral::Null,
278            Self::Boolean(value) => SimpletonScriptLiteral::Boolean(*value),
279            Self::Integer(value) => SimpletonScriptLiteral::Integer(*value),
280            Self::Real(value) => SimpletonScriptLiteral::Real(*value),
281            Self::Text(value) => SimpletonScriptLiteral::Text(value.to_owned()),
282            Self::Array { items } => {
283                for item in items.iter().rev() {
284                    item.compile(result, registers, closures, closures_index);
285                }
286                SimpletonScriptLiteral::Array {
287                    items_count: items.len(),
288                }
289            }
290            Self::Map { items } => {
291                for (key, value) in items.iter().rev() {
292                    value.compile(result, registers, closures, closures_index);
293                    result.push(ScriptOperation::Expression {
294                        expression: SimpletonScriptExpression::Literal(
295                            SimpletonScriptLiteral::Text(key.to_owned()),
296                        ),
297                    });
298                }
299                SimpletonScriptLiteral::Map {
300                    items_count: items.len(),
301                }
302            }
303            Self::Object {
304                name,
305                module_name,
306                fields,
307            } => {
308                for (key, value) in fields.iter().rev() {
309                    value.compile(result, registers, closures, closures_index);
310                    result.push(ScriptOperation::Expression {
311                        expression: SimpletonScriptExpression::Literal(
312                            SimpletonScriptLiteral::Text(key.to_owned()),
313                        ),
314                    });
315                }
316                SimpletonScriptLiteral::Object {
317                    name: name.to_owned(),
318                    module_name: module_name.to_owned(),
319                    fields_count: fields.len(),
320                }
321            }
322        }
323    }
324}
325
326#[derive(Debug, Clone, Serialize, Deserialize)]
327pub enum SimpletonExpressionStart {
328    FindStruct {
329        name: String,
330        module_name: String,
331        next: Option<SimpletonExpressionNext>,
332    },
333    FindFunction {
334        name: String,
335        module_name: String,
336        next: Option<SimpletonExpressionNext>,
337    },
338    Closure {
339        captures: Vec<String>,
340        arguments: Vec<String>,
341        statements: Vec<SimpletonStatement>,
342        next: Option<SimpletonExpressionNext>,
343    },
344    Literal {
345        literal: SimpletonLiteral,
346        next: Option<SimpletonExpressionNext>,
347    },
348    GetVariable {
349        name: String,
350        next: Option<SimpletonExpressionNext>,
351    },
352    CallFunction {
353        name: String,
354        module_name: String,
355        arguments: Vec<SimpletonExpressionStart>,
356        next: Option<SimpletonExpressionNext>,
357    },
358}
359
360impl SimpletonExpressionStart {
361    pub fn compile(
362        &self,
363        result: &mut Vec<ScriptOperation<SimpletonScriptExpression>>,
364        registers: &mut Vec<String>,
365        closures: &mut Vec<SimpletonFunction>,
366        closures_index: &mut usize,
367    ) {
368        match self {
369            Self::FindStruct {
370                name,
371                module_name,
372                next,
373            } => {
374                result.push(ScriptOperation::Expression {
375                    expression: SimpletonScriptExpression::FindStruct {
376                        name: name.to_owned(),
377                        module_name: module_name.to_owned(),
378                    },
379                });
380                if let Some(next) = next {
381                    next.compile(result, registers, closures, closures_index);
382                }
383            }
384            Self::FindFunction {
385                name,
386                module_name,
387                next,
388            } => {
389                result.push(ScriptOperation::Expression {
390                    expression: SimpletonScriptExpression::FindFunction {
391                        name: name.to_owned(),
392                        module_name: module_name.to_owned(),
393                    },
394                });
395                if let Some(next) = next {
396                    next.compile(result, registers, closures, closures_index);
397                }
398            }
399            Self::Closure {
400                captures,
401                arguments,
402                statements,
403                next,
404            } => {
405                let name = format!("_{}", *closures_index);
406                *closures_index += 1;
407                closures.push(SimpletonFunction {
408                    name: name.to_owned(),
409                    arguments: captures.iter().chain(arguments.iter()).cloned().collect(),
410                    statements: statements.to_owned(),
411                });
412                for capture in captures.iter().rev() {
413                    let index = registers.iter().position(|n| n == capture).unwrap();
414                    result.push(ScriptOperation::PushFromRegister { index });
415                    result.push(ScriptOperation::Expression {
416                        expression: SimpletonScriptExpression::StackDuplicate,
417                    });
418                    result.push(ScriptOperation::PopToRegister { index });
419                }
420                result.push(ScriptOperation::Expression {
421                    expression: SimpletonScriptExpression::Literal(SimpletonScriptLiteral::Array {
422                        items_count: captures.len(),
423                    }),
424                });
425                result.push(ScriptOperation::Expression {
426                    expression: SimpletonScriptExpression::FindFunction {
427                        name,
428                        module_name: CLOSURES.to_owned(),
429                    },
430                });
431                result.push(ScriptOperation::CallFunction {
432                    query: FunctionQuery {
433                        name: Some("new".to_owned().into()),
434                        module_name: Some("closure".to_owned().into()),
435                        ..Default::default()
436                    },
437                });
438                if let Some(next) = next {
439                    next.compile(result, registers, closures, closures_index);
440                }
441            }
442            Self::Literal { literal, next } => {
443                let literal = literal.compile(result, registers, closures, closures_index);
444                result.push(ScriptOperation::Expression {
445                    expression: SimpletonScriptExpression::Literal(literal),
446                });
447                if let Some(next) = next {
448                    next.compile(result, registers, closures, closures_index);
449                }
450            }
451            Self::GetVariable { name, next } => {
452                let index = registers
453                    .iter()
454                    .position(|n| n == name.as_str())
455                    .unwrap_or_else(|| panic!("Variable `{}` not found!", name));
456                result.push(ScriptOperation::PushFromRegister { index });
457                result.push(ScriptOperation::Expression {
458                    expression: SimpletonScriptExpression::StackDuplicate,
459                });
460                result.push(ScriptOperation::PopToRegister { index });
461                if let Some(next) = next {
462                    next.compile(result, registers, closures, closures_index);
463                }
464            }
465            Self::CallFunction {
466                name,
467                module_name,
468                arguments,
469                next,
470            } => {
471                for argument in arguments.iter().rev() {
472                    argument.compile(result, registers, closures, closures_index);
473                }
474                result.push(ScriptOperation::CallFunction {
475                    query: FunctionQuery {
476                        name: Some(name.to_owned().into()),
477                        module_name: Some(module_name.to_owned().into()),
478                        ..Default::default()
479                    },
480                });
481                if let Some(next) = next {
482                    next.compile(result, registers, closures, closures_index);
483                }
484            }
485        }
486    }
487
488    pub fn compile_assign(
489        &self,
490        result: &mut Vec<ScriptOperation<SimpletonScriptExpression>>,
491        registers: &mut Vec<String>,
492        closures: &mut Vec<SimpletonFunction>,
493        closures_index: &mut usize,
494    ) {
495        match self {
496            Self::FindStruct {
497                name,
498                module_name,
499                next,
500            } => {
501                result.push(ScriptOperation::Expression {
502                    expression: SimpletonScriptExpression::FindStruct {
503                        name: name.to_owned(),
504                        module_name: module_name.to_owned(),
505                    },
506                });
507                if let Some(next) = next {
508                    next.compile(result, registers, closures, closures_index);
509                } else {
510                    panic!("Trying to assign value to structure type!");
511                }
512            }
513            Self::FindFunction {
514                name,
515                module_name,
516                next,
517            } => {
518                result.push(ScriptOperation::Expression {
519                    expression: SimpletonScriptExpression::FindFunction {
520                        name: name.to_owned(),
521                        module_name: module_name.to_owned(),
522                    },
523                });
524                if let Some(next) = next {
525                    next.compile(result, registers, closures, closures_index);
526                } else {
527                    panic!("Trying to assign value to function type!");
528                }
529            }
530            Self::Closure {
531                captures,
532                arguments,
533                statements,
534                next,
535            } => {
536                let name = format!("_{}", *closures_index);
537                *closures_index += 1;
538                closures.push(SimpletonFunction {
539                    name: name.to_owned(),
540                    arguments: captures.iter().chain(arguments.iter()).cloned().collect(),
541                    statements: statements.to_owned(),
542                });
543                for capture in captures.iter().rev() {
544                    let index = registers.iter().position(|n| n == capture).unwrap();
545                    result.push(ScriptOperation::PushFromRegister { index });
546                    result.push(ScriptOperation::Expression {
547                        expression: SimpletonScriptExpression::StackDuplicate,
548                    });
549                    result.push(ScriptOperation::PopToRegister { index });
550                }
551                result.push(ScriptOperation::Expression {
552                    expression: SimpletonScriptExpression::Literal(SimpletonScriptLiteral::Array {
553                        items_count: captures.len(),
554                    }),
555                });
556                result.push(ScriptOperation::Expression {
557                    expression: SimpletonScriptExpression::FindFunction {
558                        name,
559                        module_name: CLOSURES.to_owned(),
560                    },
561                });
562                result.push(ScriptOperation::CallFunction {
563                    query: FunctionQuery {
564                        name: Some("new".to_owned().into()),
565                        module_name: Some("closure".to_owned().into()),
566                        ..Default::default()
567                    },
568                });
569                if let Some(next) = next {
570                    next.compile(result, registers, closures, closures_index);
571                } else {
572                    panic!("Trying to assign value to closure!");
573                }
574            }
575            Self::Literal { literal, next } => {
576                let literal = literal.compile(result, registers, closures, closures_index);
577                result.push(ScriptOperation::Expression {
578                    expression: SimpletonScriptExpression::Literal(literal),
579                });
580                if let Some(next) = next {
581                    next.compile_assign(result, registers, closures, closures_index);
582                } else {
583                    panic!("Trying to assign value to literal!");
584                }
585            }
586            Self::GetVariable { name, next } => {
587                let index = registers.iter().position(|n| n == name.as_str()).unwrap();
588                if let Some(next) = next {
589                    result.push(ScriptOperation::PushFromRegister { index });
590                    result.push(ScriptOperation::Expression {
591                        expression: SimpletonScriptExpression::StackDuplicate,
592                    });
593                    result.push(ScriptOperation::PopToRegister { index });
594                    next.compile_assign(result, registers, closures, closures_index);
595                } else {
596                    result.push(ScriptOperation::PopToRegister { index });
597                }
598            }
599            Self::CallFunction {
600                name,
601                module_name,
602                arguments,
603                next,
604            } => {
605                for argument in arguments.iter().rev() {
606                    argument.compile(result, registers, closures, closures_index);
607                }
608                result.push(ScriptOperation::CallFunction {
609                    query: FunctionQuery {
610                        name: Some(name.to_owned().into()),
611                        module_name: Some(module_name.to_owned().into()),
612                        ..Default::default()
613                    },
614                });
615                if let Some(next) = next {
616                    next.compile_assign(result, registers, closures, closures_index);
617                } else {
618                    panic!("Trying to assign value to function call!");
619                }
620            }
621        }
622    }
623}
624
625#[derive(Debug, Clone, Serialize, Deserialize)]
626pub enum SimpletonExpressionNext {
627    GetField {
628        name: String,
629        next: Option<Box<SimpletonExpressionNext>>,
630    },
631    GetArrayItem {
632        index: Box<SimpletonExpressionStart>,
633        next: Option<Box<SimpletonExpressionNext>>,
634    },
635    GetMapItem {
636        index: Box<SimpletonExpressionStart>,
637        next: Option<Box<SimpletonExpressionNext>>,
638    },
639}
640
641impl SimpletonExpressionNext {
642    pub fn compile(
643        &self,
644        result: &mut Vec<ScriptOperation<SimpletonScriptExpression>>,
645        registers: &mut Vec<String>,
646        closures: &mut Vec<SimpletonFunction>,
647        closures_index: &mut usize,
648    ) {
649        match self {
650            Self::GetField { name, next } => {
651                result.push(ScriptOperation::Expression {
652                    expression: SimpletonScriptExpression::GetField {
653                        name: name.to_owned(),
654                    },
655                });
656                if let Some(next) = next {
657                    next.compile(result, registers, closures, closures_index);
658                }
659            }
660            Self::GetArrayItem { index, next } => {
661                index.compile(result, registers, closures, closures_index);
662                result.push(ScriptOperation::Expression {
663                    expression: SimpletonScriptExpression::StackSwap,
664                });
665                result.push(ScriptOperation::CallFunction {
666                    query: FunctionQuery {
667                        name: Some("get".into()),
668                        module_name: Some("array".into()),
669                        ..Default::default()
670                    },
671                });
672                if let Some(next) = next {
673                    next.compile(result, registers, closures, closures_index);
674                }
675            }
676            Self::GetMapItem { index, next } => {
677                index.compile(result, registers, closures, closures_index);
678                result.push(ScriptOperation::Expression {
679                    expression: SimpletonScriptExpression::StackSwap,
680                });
681                result.push(ScriptOperation::CallFunction {
682                    query: FunctionQuery {
683                        name: Some("get".into()),
684                        module_name: Some("map".into()),
685                        ..Default::default()
686                    },
687                });
688                if let Some(next) = next {
689                    next.compile(result, registers, closures, closures_index);
690                }
691            }
692        }
693    }
694
695    pub fn compile_assign(
696        &self,
697        result: &mut Vec<ScriptOperation<SimpletonScriptExpression>>,
698        registers: &mut Vec<String>,
699        closures: &mut Vec<SimpletonFunction>,
700        closures_index: &mut usize,
701    ) {
702        match self {
703            Self::GetField { name, next } => {
704                if let Some(next) = next {
705                    result.push(ScriptOperation::Expression {
706                        expression: SimpletonScriptExpression::GetField {
707                            name: name.to_owned(),
708                        },
709                    });
710                    next.compile_assign(result, registers, closures, closures_index);
711                } else {
712                    result.push(ScriptOperation::Expression {
713                        expression: SimpletonScriptExpression::SetField {
714                            name: name.to_owned(),
715                        },
716                    });
717                }
718            }
719            Self::GetArrayItem { index, next } => {
720                if let Some(next) = next {
721                    index.compile(result, registers, closures, closures_index);
722                    result.push(ScriptOperation::Expression {
723                        expression: SimpletonScriptExpression::StackSwap,
724                    });
725                    result.push(ScriptOperation::CallFunction {
726                        query: FunctionQuery {
727                            name: Some("get".into()),
728                            module_name: Some("array".into()),
729                            ..Default::default()
730                        },
731                    });
732                    next.compile_assign(result, registers, closures, closures_index);
733                } else {
734                    index.compile(result, registers, closures, closures_index);
735                    result.push(ScriptOperation::Expression {
736                        expression: SimpletonScriptExpression::StackSwap,
737                    });
738                    result.push(ScriptOperation::CallFunction {
739                        query: FunctionQuery {
740                            name: Some("set".into()),
741                            module_name: Some("array".into()),
742                            ..Default::default()
743                        },
744                    });
745                    result.push(ScriptOperation::Expression {
746                        expression: SimpletonScriptExpression::StackDrop,
747                    });
748                }
749            }
750            Self::GetMapItem { index, next } => {
751                if let Some(next) = next {
752                    index.compile(result, registers, closures, closures_index);
753                    result.push(ScriptOperation::Expression {
754                        expression: SimpletonScriptExpression::StackSwap,
755                    });
756                    result.push(ScriptOperation::CallFunction {
757                        query: FunctionQuery {
758                            name: Some("get".into()),
759                            module_name: Some("map".into()),
760                            ..Default::default()
761                        },
762                    });
763                    next.compile_assign(result, registers, closures, closures_index);
764                } else {
765                    index.compile(result, registers, closures, closures_index);
766                    result.push(ScriptOperation::Expression {
767                        expression: SimpletonScriptExpression::StackSwap,
768                    });
769                    result.push(ScriptOperation::CallFunction {
770                        query: FunctionQuery {
771                            name: Some("set".into()),
772                            module_name: Some("map".into()),
773                            ..Default::default()
774                        },
775                    });
776                    result.push(ScriptOperation::Expression {
777                        expression: SimpletonScriptExpression::StackDrop,
778                    });
779                }
780            }
781        }
782    }
783}
784
785#[derive(Debug, Clone, Serialize, Deserialize)]
786pub enum SimpletonStatement {
787    CreateVariable {
788        name: String,
789        value: SimpletonExpressionStart,
790    },
791    AssignValue {
792        object: SimpletonExpressionStart,
793        value: SimpletonExpressionStart,
794    },
795    Expression(SimpletonExpressionStart),
796    Return(SimpletonExpressionStart),
797    IfElse {
798        condition: SimpletonExpressionStart,
799        success: Vec<SimpletonStatement>,
800        failure: Option<Vec<SimpletonStatement>>,
801    },
802    While {
803        condition: SimpletonExpressionStart,
804        statements: Vec<SimpletonStatement>,
805    },
806    For {
807        variable: String,
808        iterator: SimpletonExpressionStart,
809        statements: Vec<SimpletonStatement>,
810    },
811}
812
813impl SimpletonStatement {
814    pub fn recursive_any(&self, f: &impl Fn(&Self) -> bool) -> bool {
815        if f(self) {
816            return true;
817        }
818        match self {
819            Self::IfElse {
820                success, failure, ..
821            } => {
822                for item in success {
823                    if item.recursive_any(f) {
824                        return true;
825                    }
826                }
827                if let Some(failure) = failure.as_ref() {
828                    for item in failure {
829                        if item.recursive_any(f) {
830                            return true;
831                        }
832                    }
833                }
834            }
835            Self::While { statements, .. } => {
836                for item in statements {
837                    if item.recursive_any(f) {
838                        return true;
839                    }
840                }
841            }
842            Self::For { statements, .. } => {
843                for item in statements {
844                    if item.recursive_any(f) {
845                        return true;
846                    }
847                }
848            }
849            _ => {}
850        }
851        false
852    }
853
854    pub fn compile(
855        &self,
856        result: &mut Vec<ScriptOperation<SimpletonScriptExpression>>,
857        registers: &mut Vec<String>,
858        closures: &mut Vec<SimpletonFunction>,
859        closures_index: &mut usize,
860        subscope_level: usize,
861    ) {
862        match self {
863            Self::CreateVariable { name, value } => {
864                if !registers.iter().any(|n| n == name) {
865                    registers.push(name.to_owned());
866                }
867                result.push(ScriptOperation::DefineRegister {
868                    query: TypeQuery::of::<Reference>(),
869                });
870                value.compile(result, registers, closures, closures_index);
871                result.push(ScriptOperation::PopToRegister {
872                    index: registers.iter().position(|n| n == name).unwrap(),
873                });
874            }
875            Self::AssignValue { object, value } => {
876                value.compile(result, registers, closures, closures_index);
877                object.compile_assign(result, registers, closures, closures_index);
878            }
879            Self::Expression(expression) => {
880                expression.compile(result, registers, closures, closures_index);
881                result.push(ScriptOperation::Expression {
882                    expression: SimpletonScriptExpression::StackDrop,
883                });
884            }
885            Self::Return(expression) => {
886                expression.compile(result, registers, closures, closures_index);
887                for _ in 0..(subscope_level + 1) {
888                    result.push(ScriptOperation::Expression {
889                        expression: SimpletonScriptExpression::Literal(
890                            SimpletonScriptLiteral::Boolean(false),
891                        ),
892                    });
893                    result.push(ScriptOperation::Expression {
894                        expression: SimpletonScriptExpression::StackUnwrapBoolean,
895                    });
896                }
897                result.push(ScriptOperation::ContinueScopeConditionally);
898            }
899            Self::IfElse {
900                condition,
901                success,
902                failure,
903            } => {
904                condition.compile(result, registers, closures, closures_index);
905                result.push(ScriptOperation::Expression {
906                    expression: SimpletonScriptExpression::StackUnwrapBoolean,
907                });
908                // success body
909                let mut success_operations = vec![];
910                for statement in success {
911                    statement.compile(
912                        &mut success_operations,
913                        registers,
914                        closures,
915                        closures_index,
916                        subscope_level + 1,
917                    );
918                }
919                success_operations.push(ScriptOperation::Expression {
920                    expression: SimpletonScriptExpression::Literal(
921                        SimpletonScriptLiteral::Boolean(true),
922                    ),
923                });
924                success_operations.push(ScriptOperation::Expression {
925                    expression: SimpletonScriptExpression::StackUnwrapBoolean,
926                });
927                // failure body
928                let mut failure_operations = vec![];
929                if let Some(failure) = failure {
930                    for statement in failure {
931                        statement.compile(
932                            &mut failure_operations,
933                            registers,
934                            closures,
935                            closures_index,
936                            subscope_level + 1,
937                        );
938                    }
939                }
940                failure_operations.push(ScriptOperation::Expression {
941                    expression: SimpletonScriptExpression::Literal(
942                        SimpletonScriptLiteral::Boolean(true),
943                    ),
944                });
945                failure_operations.push(ScriptOperation::Expression {
946                    expression: SimpletonScriptExpression::StackUnwrapBoolean,
947                });
948                // main body
949                result.push(ScriptOperation::BranchScope {
950                    scope_success: ScriptHandle::new(success_operations),
951                    scope_failure: Some(ScriptHandle::new(failure_operations)),
952                });
953                result.push(ScriptOperation::ContinueScopeConditionally);
954            }
955            Self::While {
956                condition,
957                statements,
958            } => {
959                let mut operations = vec![];
960                // loop body
961                for statement in statements {
962                    if statement.recursive_any(&|statement| {
963                        matches!(statement, SimpletonStatement::Return(_))
964                    }) {
965                        panic!("Cannot return values inside while loops!");
966                    }
967                    statement.compile(&mut operations, registers, closures, closures_index, 0);
968                }
969                condition.compile(&mut operations, registers, closures, closures_index);
970                operations.push(ScriptOperation::Expression {
971                    expression: SimpletonScriptExpression::StackUnwrapBoolean,
972                });
973                // main body
974                condition.compile(result, registers, closures, closures_index);
975                result.push(ScriptOperation::Expression {
976                    expression: SimpletonScriptExpression::StackUnwrapBoolean,
977                });
978                result.push(ScriptOperation::LoopScope {
979                    scope: ScriptHandle::new(operations),
980                });
981            }
982            Self::For {
983                variable,
984                iterator,
985                statements,
986            } => {
987                let mut operations = vec![];
988                // loop body
989                if !registers.iter().any(|n| n == variable) {
990                    registers.push(variable.to_owned());
991                }
992                operations.push(ScriptOperation::DefineRegister {
993                    query: TypeQuery::of::<Reference>(),
994                });
995                let index = registers
996                    .iter()
997                    .position(|n| n == variable.as_str())
998                    .unwrap();
999                operations.push(ScriptOperation::PopToRegister { index });
1000                for statement in statements {
1001                    if statement.recursive_any(&|statement| {
1002                        matches!(statement, SimpletonStatement::Return(_))
1003                    }) {
1004                        panic!("Cannot return values inside for loops!");
1005                    }
1006                    statement.compile(&mut operations, registers, closures, closures_index, 0);
1007                }
1008                operations.push(ScriptOperation::Expression {
1009                    expression: SimpletonScriptExpression::StackDuplicate,
1010                });
1011                operations.push(ScriptOperation::CallFunction {
1012                    query: FunctionQuery {
1013                        name: Some("next".to_owned().into()),
1014                        module_name: Some("iter".to_owned().into()),
1015                        ..Default::default()
1016                    },
1017                });
1018                operations.push(ScriptOperation::Expression {
1019                    expression: SimpletonScriptExpression::StackValueOr(false),
1020                });
1021                // main body
1022                iterator.compile(result, registers, closures, closures_index);
1023                result.push(ScriptOperation::Expression {
1024                    expression: SimpletonScriptExpression::StackDuplicate,
1025                });
1026                result.push(ScriptOperation::CallFunction {
1027                    query: FunctionQuery {
1028                        name: Some("next".to_owned().into()),
1029                        module_name: Some("iter".to_owned().into()),
1030                        ..Default::default()
1031                    },
1032                });
1033                result.push(ScriptOperation::Expression {
1034                    expression: SimpletonScriptExpression::StackValueOr(false),
1035                });
1036                result.push(ScriptOperation::LoopScope {
1037                    scope: ScriptHandle::new(operations),
1038                });
1039                result.push(ScriptOperation::Expression {
1040                    expression: SimpletonScriptExpression::StackDrop,
1041                });
1042            }
1043        }
1044    }
1045}
1046
1047#[derive(Debug, Clone, Serialize, Deserialize)]
1048pub struct SimpletonFunction {
1049    pub name: String,
1050    pub arguments: Vec<String>,
1051    pub statements: Vec<SimpletonStatement>,
1052}
1053
1054impl SimpletonFunction {
1055    pub fn compile(
1056        &self,
1057        module_name: &str,
1058        closures: &mut Vec<SimpletonFunction>,
1059        closures_index: &mut usize,
1060    ) -> ScriptFunction<'static, SimpletonScriptExpression> {
1061        let signature = ScriptFunctionSignature {
1062            meta: None,
1063            name: self.name.to_owned(),
1064            module_name: Some(module_name.to_owned()),
1065            type_query: None,
1066            visibility: Visibility::Public,
1067            inputs: self
1068                .arguments
1069                .iter()
1070                .map(|name| ScriptFunctionParameter {
1071                    meta: None,
1072                    name: name.to_owned(),
1073                    type_query: TypeQuery::of::<Reference>(),
1074                })
1075                .collect(),
1076            outputs: vec![ScriptFunctionParameter {
1077                meta: None,
1078                name: "result".to_owned(),
1079                type_query: TypeQuery::of::<Reference>(),
1080            }],
1081        };
1082        let mut registers = Vec::new();
1083        let mut operations = vec![];
1084        for name in &self.arguments {
1085            if !registers.iter().any(|n| n == name) {
1086                registers.push(name.to_owned());
1087            }
1088            operations.push(ScriptOperation::DefineRegister {
1089                query: TypeQuery::of::<Reference>(),
1090            });
1091            operations.push(ScriptOperation::PopToRegister {
1092                index: registers.iter().position(|n| n == name).unwrap(),
1093            });
1094        }
1095        for statement in &self.statements {
1096            statement.compile(&mut operations, &mut registers, closures, closures_index, 0);
1097        }
1098        operations.push(ScriptOperation::Expression {
1099            expression: SimpletonScriptExpression::Literal(SimpletonScriptLiteral::Null),
1100        });
1101        ScriptFunction {
1102            signature,
1103            script: ScriptHandle::new(operations),
1104        }
1105    }
1106}
1107
1108#[derive(Debug, Clone, Serialize, Deserialize)]
1109pub struct SimpletonStruct {
1110    pub name: String,
1111    pub fields: Vec<String>,
1112}
1113
1114impl SimpletonStruct {
1115    pub fn compile(&self, module_name: &str) -> ScriptStruct<'static> {
1116        ScriptStruct {
1117            meta: None,
1118            name: self.name.to_owned(),
1119            module_name: Some(module_name.to_owned()),
1120            visibility: Visibility::Public,
1121            fields: self
1122                .fields
1123                .iter()
1124                .map(|name| ScriptStructField {
1125                    meta: None,
1126                    name: name.to_owned(),
1127                    visibility: Visibility::Public,
1128                    type_query: TypeQuery::of::<Reference>(),
1129                })
1130                .collect(),
1131        }
1132    }
1133}
1134
1135#[derive(Debug, Clone, Serialize, Deserialize)]
1136pub struct SimpletonModule {
1137    pub name: String,
1138    pub dependencies: Vec<String>,
1139    pub structs: Vec<SimpletonStruct>,
1140    pub functions: Vec<SimpletonFunction>,
1141}
1142
1143impl SimpletonModule {
1144    pub fn parse(content: &str) -> Result<Self, String> {
1145        parser::parse(content)
1146    }
1147
1148    pub fn compile(
1149        &self,
1150        closures: &mut Vec<SimpletonFunction>,
1151        closures_index: &mut usize,
1152    ) -> ScriptModule<'static, SimpletonScriptExpression> {
1153        ScriptModule {
1154            name: self.name.to_owned(),
1155            structs: self
1156                .structs
1157                .iter()
1158                .map(|type_| type_.compile(&self.name))
1159                .collect(),
1160            enums: vec![],
1161            functions: self
1162                .functions
1163                .iter()
1164                .map(|function| function.compile(&self.name, closures, closures_index))
1165                .collect(),
1166        }
1167    }
1168}
1169
1170#[derive(Debug, Default, Clone, Serialize, Deserialize)]
1171pub struct SimpletonPackage {
1172    pub modules: HashMap<String, SimpletonModule>,
1173}
1174
1175impl SimpletonPackage {
1176    pub fn new<CP>(path: &str, content_provider: &mut CP) -> Result<Self, Box<dyn Error>>
1177    where
1178        CP: ScriptContentProvider<SimpletonModule>,
1179    {
1180        let mut result = Self::default();
1181        result.load(path, content_provider)?;
1182        Ok(result)
1183    }
1184
1185    pub fn load<CP>(&mut self, path: &str, content_provider: &mut CP) -> Result<(), Box<dyn Error>>
1186    where
1187        CP: ScriptContentProvider<SimpletonModule>,
1188    {
1189        let path = content_provider.sanitize_path(path)?;
1190        if self.modules.contains_key(&path) {
1191            return Ok(());
1192        }
1193        for content in content_provider.unpack_load(&path)? {
1194            if let Some(module) = content.data? {
1195                let dependencies = module.dependencies.to_owned();
1196                self.modules.insert(content.name, module);
1197                for relative in dependencies {
1198                    let path = content_provider.join_paths(&content.path, &relative)?;
1199                    self.load(&path, content_provider)?;
1200                }
1201            }
1202        }
1203        Ok(())
1204    }
1205
1206    pub fn compile(&self) -> ScriptPackage<'static, SimpletonScriptExpression> {
1207        let mut closures = vec![];
1208        let mut closures_index = 0;
1209        let mut modules: Vec<ScriptModule<SimpletonScriptExpression>> = self
1210            .modules
1211            .values()
1212            .map(|module| module.compile(&mut closures, &mut closures_index))
1213            .collect();
1214        let mut closure_functions = vec![];
1215        loop {
1216            let mut result = vec![];
1217            for closure in &closures {
1218                closure_functions.push(closure.compile(CLOSURES, &mut result, &mut closures_index));
1219            }
1220            if result.is_empty() {
1221                break;
1222            }
1223            closures = result;
1224        }
1225        modules.push(ScriptModule {
1226            name: CLOSURES.to_owned(),
1227            structs: vec![],
1228            enums: vec![],
1229            functions: closure_functions,
1230        });
1231        ScriptPackage { modules }
1232    }
1233
1234    #[cfg(feature = "plugins")]
1235    pub fn install_plugins(&self, registry: &mut Registry, search_paths: &[&str]) {
1236        use intuicio_core::core_version;
1237        use intuicio_plugins::install_plugin;
1238        use std::env::consts::DLL_EXTENSION;
1239
1240        for module in self.modules.values() {
1241            'plugin: for path in &module.dependencies {
1242                let mut path = PathBuf::from(path);
1243                if path
1244                    .extension()
1245                    .map(|extension| extension == "plugin")
1246                    .unwrap_or_default()
1247                {
1248                    path.set_extension(DLL_EXTENSION);
1249                    for search_path in search_paths {
1250                        let path = PathBuf::from(search_path).join(&path);
1251                        if install_plugin(
1252                            path.to_string_lossy().as_ref(),
1253                            registry,
1254                            Some(core_version()),
1255                        )
1256                        .is_ok()
1257                        {
1258                            continue 'plugin;
1259                        }
1260                    }
1261                    panic!("Could not load plugin: {:?}", path);
1262                }
1263            }
1264        }
1265    }
1266}
1267
1268pub struct SimpletonContentParser;
1269
1270impl BytesContentParser<SimpletonModule> for SimpletonContentParser {
1271    fn parse(&self, bytes: Vec<u8>) -> Result<SimpletonModule, Box<dyn Error>> {
1272        let content = String::from_utf8(bytes)?;
1273        Ok(SimpletonModule::parse(&content)?)
1274    }
1275}
1276
1277#[derive(Debug, Serialize, Deserialize)]
1278pub struct SimpletonBinary {
1279    pub version: IntuicioVersion,
1280    pub modules: Vec<SimpletonModule>,
1281}
1282
1283impl SimpletonBinary {
1284    pub fn archive(
1285        package: SimpletonPackage,
1286        dependencies_filter: impl Fn(&str) -> bool,
1287    ) -> Result<Vec<u8>, Box<dyn Error>> {
1288        let binary = SimpletonBinary {
1289            version: crate_version!(),
1290            modules: package
1291                .modules
1292                .into_values()
1293                .map(|mut module| {
1294                    module.dependencies.retain(|path| dependencies_filter(path));
1295                    module
1296                })
1297                .collect(),
1298        };
1299        let options = DefaultOptions::new()
1300            .with_fixint_encoding()
1301            .allow_trailing_bytes();
1302        Ok(options.serialize(&binary)?)
1303    }
1304}
1305
1306pub struct SimpletonBinaryFileContentProvider {
1307    extension: String,
1308}
1309
1310impl SimpletonBinaryFileContentProvider {
1311    pub fn new(extension: impl ToString) -> Self {
1312        Self {
1313            extension: extension.to_string(),
1314        }
1315    }
1316}
1317
1318impl ScriptContentProvider<SimpletonModule> for SimpletonBinaryFileContentProvider {
1319    fn load(&mut self, _: &str) -> Result<Option<SimpletonModule>, Box<dyn Error>> {
1320        Ok(None)
1321    }
1322
1323    fn unpack_load(
1324        &mut self,
1325        path: &str,
1326    ) -> Result<Vec<ScriptContent<SimpletonModule>>, Box<dyn Error>> {
1327        let options = DefaultOptions::new()
1328            .with_fixint_encoding()
1329            .allow_trailing_bytes();
1330        let bytes = std::fs::read(path)?;
1331        let binary = options.deserialize::<SimpletonBinary>(&bytes)?;
1332        let version = crate_version!();
1333        if !binary.version.is_compatible(&version) {
1334            return Err(format!(
1335                "Binary version: {} is not compatible with Simpleton version: {}",
1336                binary.version, version
1337            )
1338            .into());
1339        }
1340        Ok(binary
1341            .modules
1342            .into_iter()
1343            .enumerate()
1344            .map(|(index, module)| ScriptContent {
1345                path: path.to_owned(),
1346                name: format!("{}#{}", path, index),
1347                data: Ok(Some(module)),
1348            })
1349            .collect())
1350    }
1351
1352    fn sanitize_path(&self, path: &str) -> Result<String, Box<dyn Error>> {
1353        let mut result = PathBuf::from(path);
1354        if result.extension().is_none() {
1355            result.set_extension(&self.extension);
1356        }
1357        Ok(result.canonicalize()?.to_string_lossy().into_owned())
1358    }
1359
1360    fn join_paths(&self, parent: &str, relative: &str) -> Result<String, Box<dyn Error>> {
1361        let mut path = PathBuf::from(parent);
1362        path.pop();
1363        Ok(path.join(relative).to_string_lossy().into_owned())
1364    }
1365}