loft 0.0.1-alpha.22

Rusty embedded scripting language
Documentation
use super::*;

impl<'st> Interpreter {
    pub fn handle_enum_def(&mut self, name: &str, variants: Vec<EnumVariant>) -> Result<(), String> {
        let enum_def = val!(mut ValueType::EnumDef {
            name: name.to_string(),
            variants: variants.clone(),
            methods: HashMap::new(),
        });

        self.env.declare_enum(name, enum_def)?;

        for variant in variants {
            match variant {
                EnumVariant::Simple(variant_name) => {
                    let constructor = val!(ValueType::EnumConstructor {
                        fields: Vec::new(),
                        enum_name: name.to_string(),
                        variant_name: variant_name.clone(),
                    });

                    let full_path = format!("{}::{}", name, variant_name);
                    self.env.scope_resolver.declare_variable(&full_path, false);
                    self.env.set_variable(&full_path, constructor)?;
                }

                EnumVariant::Tuple(variant_name, fields) => {
                    let constructor = val!(ValueType::EnumConstructor {
                        fields,
                        enum_name: name.to_string(),
                        variant_name: variant_name.clone(),
                    });

                    let full_path = format!("{}::{}", name, variant_name);
                    self.env.scope_resolver.declare_variable(&full_path, false);
                    self.env.set_variable(&full_path, constructor)?;
                }

                EnumVariant::Struct(variant_name, fields) => {
                    let constructor = val!(ValueType::EnumStructConstructor {
                        fields,
                        enum_name: name.to_string(),
                        variant_name: variant_name.clone(),
                    });

                    let full_path = format!("{}::{}", name, variant_name);
                    self.env.scope_resolver.declare_variable(&full_path, false);
                    self.env.set_variable(&full_path, constructor)?;
                }
            }
        }

        Ok(())
    }

    pub fn handle_enum_constructor_call(&mut self, arguments: &Vec<Expr>, enum_name: String, variant_name: String, fields: Vec<Type>) -> Result<Value, String> {
        if arguments.len() != fields.len() {
            return Err(format!("Expected {} arguments for enum variant {}, got {}", fields.len(), variant_name, arguments.len()));
        }

        let mut arg_values = Vec::new();
        for arg in arguments {
            arg_values.push(self.evaluate_expression(arg)?);
        }

        Ok(val!(ValueType::Enum {
            enum_type: enum_name,
            variant: variant_name,
            data: Some(arg_values),
        }))
    }

    pub fn handle_enum_struct_call(&mut self, arguments: &Vec<Expr>, enum_name: String, variant_name: String, fields: HashMap<String, (Type, bool)>) -> Result<Value, String> {
        if arguments.len() != 1 {
            return Err(format!(
                "Expected 1 argument (field initializer) for struct-like enum variant {}, got {}",
                variant_name,
                arguments.len()
            ));
        }

        if let Expr::StructInit { fields: init_fields, .. } = &arguments[0] {
            for field_name in fields.keys() {
                if !init_fields.contains_key(field_name) {
                    return Err(format!("Missing field '{}' in struct-like enum initialization", field_name));
                }
            }

            let mut field_values = Vec::with_capacity(fields.len());
            for field_name in fields.keys() {
                let expr = &init_fields.get(field_name).expect("Expected field to exist").0;
                field_values.push(self.evaluate_expression(expr)?);
            }

            return Ok(val!(ValueType::Enum {
                enum_type: enum_name.clone(),
                variant: variant_name.clone(),
                data: Some(field_values),
            }));
        } else {
            return Err(format!("Expected struct initializer for struct-like enum variant {}", variant_name));
        }
    }
}