mirror of
				https://github.com/Dummi26/mers.git
				synced 2025-11-04 05:16:17 +01:00 
			
		
		
		
	add object field getting syntax obj:field
This commit is contained in:
		
							parent
							
								
									3cd8dc02d2
								
							
						
					
					
						commit
						e07010dcfc
					
				@ -1,6 +1,6 @@
 | 
			
		||||
[package]
 | 
			
		||||
name = "mers"
 | 
			
		||||
version = "0.9.20"
 | 
			
		||||
version = "0.9.21"
 | 
			
		||||
edition = "2021"
 | 
			
		||||
license = "MIT OR Apache-2.0"
 | 
			
		||||
description = "dynamically typed but type-checked programming language"
 | 
			
		||||
@ -15,7 +15,7 @@ default = ["colored-output"]
 | 
			
		||||
colored-output = ["mers_lib/ecolor-term", "mers_lib/pretty-print", "dep:colored"]
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
mers_lib = "0.9.20"
 | 
			
		||||
mers_lib = "0.9.21"
 | 
			
		||||
# mers_lib = { path = "../mers_lib" }
 | 
			
		||||
clap = { version = "4.3.19", features = ["derive"] }
 | 
			
		||||
colored = { version = "2.1.0", optional = true }
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
[package]
 | 
			
		||||
name = "mers_lib"
 | 
			
		||||
version = "0.9.20"
 | 
			
		||||
version = "0.9.21"
 | 
			
		||||
edition = "2021"
 | 
			
		||||
license = "MIT OR Apache-2.0"
 | 
			
		||||
description = "library to use the mers language in other projects"
 | 
			
		||||
 | 
			
		||||
@ -72,6 +72,7 @@ pub enum EColor {
 | 
			
		||||
    ChainWithNonFunction,
 | 
			
		||||
    Function,
 | 
			
		||||
    FunctionArgument,
 | 
			
		||||
    ObjectField,
 | 
			
		||||
    InitFrom,
 | 
			
		||||
    InitTo,
 | 
			
		||||
    AssignFrom,
 | 
			
		||||
 | 
			
		||||
@ -50,7 +50,7 @@ pub fn default_theme<C>(
 | 
			
		||||
    let type_right = blue;
 | 
			
		||||
    let type_wrong = magenta;
 | 
			
		||||
    let type_wrong_b = magenta_bright;
 | 
			
		||||
    let function = blue_bright; // used in combination with TYPE_WRONG
 | 
			
		||||
    let function_and_field = blue_bright; // used in combination with TYPE_WRONG
 | 
			
		||||
    let missing = cyan;
 | 
			
		||||
    let runtime = yellow;
 | 
			
		||||
    let runtime_b = yellow_bright;
 | 
			
		||||
@ -93,8 +93,9 @@ pub fn default_theme<C>(
 | 
			
		||||
 | 
			
		||||
        AssignTargetNonReference => type_wrong,
 | 
			
		||||
 | 
			
		||||
        Function => function,
 | 
			
		||||
        Function => function_and_field,
 | 
			
		||||
        FunctionArgument => type_wrong,
 | 
			
		||||
        ObjectField => function_and_field,
 | 
			
		||||
 | 
			
		||||
        InitFrom | AssignFrom | AsTypeStatementWithTooBroadType => type_wrong,
 | 
			
		||||
        InitTo | AssignTo | AsTypeTypeAnnotation => type_right,
 | 
			
		||||
 | 
			
		||||
@ -218,6 +218,15 @@ pub fn parse(
 | 
			
		||||
                });
 | 
			
		||||
                pos_after_first = src.get_pos();
 | 
			
		||||
            }
 | 
			
		||||
        } else if let Some(':') = src.peek_char() {
 | 
			
		||||
            src.next_char();
 | 
			
		||||
            let field = src.next_word().to_owned();
 | 
			
		||||
            first = Box::new(program::parsed::field::Field {
 | 
			
		||||
                pos_in_src: (first.source_range().start(), src.get_pos(), srca).into(),
 | 
			
		||||
                object: first,
 | 
			
		||||
                field,
 | 
			
		||||
            });
 | 
			
		||||
            pos_after_first = src.get_pos();
 | 
			
		||||
        } else {
 | 
			
		||||
            src.set_pos(pos_after_first);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										41
									
								
								mers_lib/src/program/parsed/field.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								mers_lib/src/program/parsed/field.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
			
		||||
use crate::{
 | 
			
		||||
    data::object::ObjectFieldsMap,
 | 
			
		||||
    errors::{CheckError, SourceRange},
 | 
			
		||||
    info, program,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use super::{CompInfo, MersStatement};
 | 
			
		||||
 | 
			
		||||
/// Extracts a property with the given name from the object
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct Field {
 | 
			
		||||
    pub pos_in_src: SourceRange,
 | 
			
		||||
    pub object: Box<dyn MersStatement>,
 | 
			
		||||
    pub field: String,
 | 
			
		||||
}
 | 
			
		||||
impl MersStatement for Field {
 | 
			
		||||
    fn has_scope(&self) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
    fn compile_custom(
 | 
			
		||||
        &self,
 | 
			
		||||
        info: &mut info::Info<super::Local>,
 | 
			
		||||
        comp: CompInfo,
 | 
			
		||||
    ) -> Result<Box<dyn program::run::MersStatement>, CheckError> {
 | 
			
		||||
        Ok(Box::new(program::run::field::Field {
 | 
			
		||||
            pos_in_src: self.pos_in_src.clone(),
 | 
			
		||||
            object: self.object.compile(info, comp)?,
 | 
			
		||||
            field_str: self.field.clone(),
 | 
			
		||||
            field: info.global.object_fields.get_or_add_field(&self.field),
 | 
			
		||||
        }))
 | 
			
		||||
    }
 | 
			
		||||
    fn source_range(&self) -> SourceRange {
 | 
			
		||||
        self.pos_in_src.clone()
 | 
			
		||||
    }
 | 
			
		||||
    fn inner_statements(&self) -> Vec<&dyn MersStatement> {
 | 
			
		||||
        vec![&*self.object]
 | 
			
		||||
    }
 | 
			
		||||
    fn as_any(&self) -> &dyn std::any::Any {
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -20,6 +20,8 @@ pub mod chain;
 | 
			
		||||
#[cfg(feature = "parse")]
 | 
			
		||||
pub mod custom_type;
 | 
			
		||||
#[cfg(feature = "parse")]
 | 
			
		||||
pub mod field;
 | 
			
		||||
#[cfg(feature = "parse")]
 | 
			
		||||
pub mod function;
 | 
			
		||||
#[cfg(feature = "parse")]
 | 
			
		||||
pub mod r#if;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										85
									
								
								mers_lib/src/program/run/field.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								mers_lib/src/program/run/field.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,85 @@
 | 
			
		||||
use crate::{
 | 
			
		||||
    data::{self, object::ObjectT, Data, MersDataWInfo, MersTypeWInfo, Type},
 | 
			
		||||
    errors::{CheckError, EColor, SourceRange},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use super::MersStatement;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct Field {
 | 
			
		||||
    pub pos_in_src: SourceRange,
 | 
			
		||||
    pub object: Box<dyn MersStatement>,
 | 
			
		||||
    pub field_str: String,
 | 
			
		||||
    pub field: usize,
 | 
			
		||||
}
 | 
			
		||||
impl MersStatement for Field {
 | 
			
		||||
    fn check_custom(
 | 
			
		||||
        &self,
 | 
			
		||||
        info: &mut super::CheckInfo,
 | 
			
		||||
        init_to: Option<&Type>,
 | 
			
		||||
    ) -> Result<data::Type, super::CheckError> {
 | 
			
		||||
        if init_to.is_some() {
 | 
			
		||||
            return Err("can't init to statement type Field".to_string().into());
 | 
			
		||||
        }
 | 
			
		||||
        let object = self.object.check(info, init_to)?;
 | 
			
		||||
        let mut o = Type::empty();
 | 
			
		||||
        for t in object.types.iter() {
 | 
			
		||||
            if let Some(t) = t.as_any().downcast_ref::<ObjectT>() {
 | 
			
		||||
                if let Some(t) = t.get(self.field) {
 | 
			
		||||
                    o.add_all(t);
 | 
			
		||||
                } else {
 | 
			
		||||
                    return Err(CheckError::new().msg(vec![
 | 
			
		||||
                        ("can't get field ".to_owned(), None),
 | 
			
		||||
                        (self.field_str.clone(), Some(EColor::ObjectField)),
 | 
			
		||||
                        (" of object ".to_owned(), None),
 | 
			
		||||
                        (t.with_info(info).to_string(), Some(EColor::InitFrom)),
 | 
			
		||||
                    ]));
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                return Err(CheckError::new().msg(vec![
 | 
			
		||||
                    ("can't get field ".to_owned(), None),
 | 
			
		||||
                    (self.field_str.clone(), Some(EColor::ObjectField)),
 | 
			
		||||
                    (" of non-object type ".to_owned(), None),
 | 
			
		||||
                    (t.with_info(info).to_string(), Some(EColor::InitFrom)),
 | 
			
		||||
                ]));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        Ok(o)
 | 
			
		||||
    }
 | 
			
		||||
    fn run_custom(&self, info: &mut super::Info) -> Result<Data, CheckError> {
 | 
			
		||||
        let object = self.object.run(info)?;
 | 
			
		||||
        let object = object.get();
 | 
			
		||||
        let object = object
 | 
			
		||||
            .as_any()
 | 
			
		||||
            .downcast_ref::<data::object::Object>()
 | 
			
		||||
            .ok_or_else(|| {
 | 
			
		||||
                format!(
 | 
			
		||||
                    "couldn't extract field {} from non-object value {}",
 | 
			
		||||
                    self.field_str,
 | 
			
		||||
                    object.with_info(info)
 | 
			
		||||
                )
 | 
			
		||||
            })?;
 | 
			
		||||
        Ok(object
 | 
			
		||||
            .get(self.field)
 | 
			
		||||
            .ok_or_else(|| {
 | 
			
		||||
                format!(
 | 
			
		||||
                    "couldn't extract field {} from object {}",
 | 
			
		||||
                    self.field_str,
 | 
			
		||||
                    object.with_info(info)
 | 
			
		||||
                )
 | 
			
		||||
            })?
 | 
			
		||||
            .clone())
 | 
			
		||||
    }
 | 
			
		||||
    fn has_scope(&self) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
    fn source_range(&self) -> SourceRange {
 | 
			
		||||
        self.pos_in_src.clone()
 | 
			
		||||
    }
 | 
			
		||||
    fn inner_statements(&self) -> Vec<&dyn MersStatement> {
 | 
			
		||||
        vec![&*self.object]
 | 
			
		||||
    }
 | 
			
		||||
    fn as_any(&self) -> &dyn std::any::Any {
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -23,6 +23,8 @@ pub mod chain;
 | 
			
		||||
#[cfg(feature = "run")]
 | 
			
		||||
pub mod custom_type;
 | 
			
		||||
#[cfg(feature = "run")]
 | 
			
		||||
pub mod field;
 | 
			
		||||
#[cfg(feature = "run")]
 | 
			
		||||
pub mod function;
 | 
			
		||||
#[cfg(feature = "run")]
 | 
			
		||||
pub mod r#if;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user