mirror of
https://github.com/Dummi26/mers.git
synced 2025-04-28 10:06:04 +02: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…
Reference in New Issue
Block a user