intuicio_frontend_simpleton/
script.rs

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