mirror of
https://github.com/Dummi26/mers.git
synced 2025-04-28 18:16:05 +02:00
add object field getting syntax obj:field
This commit is contained in:
parent
3cd8dc02d2
commit
e07010dcfc
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "mers"
|
name = "mers"
|
||||||
version = "0.9.20"
|
version = "0.9.21"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
description = "dynamically typed but type-checked programming language"
|
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"]
|
colored-output = ["mers_lib/ecolor-term", "mers_lib/pretty-print", "dep:colored"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
mers_lib = "0.9.20"
|
mers_lib = "0.9.21"
|
||||||
# mers_lib = { path = "../mers_lib" }
|
# mers_lib = { path = "../mers_lib" }
|
||||||
clap = { version = "4.3.19", features = ["derive"] }
|
clap = { version = "4.3.19", features = ["derive"] }
|
||||||
colored = { version = "2.1.0", optional = true }
|
colored = { version = "2.1.0", optional = true }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "mers_lib"
|
name = "mers_lib"
|
||||||
version = "0.9.20"
|
version = "0.9.21"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
description = "library to use the mers language in other projects"
|
description = "library to use the mers language in other projects"
|
||||||
|
@ -72,6 +72,7 @@ pub enum EColor {
|
|||||||
ChainWithNonFunction,
|
ChainWithNonFunction,
|
||||||
Function,
|
Function,
|
||||||
FunctionArgument,
|
FunctionArgument,
|
||||||
|
ObjectField,
|
||||||
InitFrom,
|
InitFrom,
|
||||||
InitTo,
|
InitTo,
|
||||||
AssignFrom,
|
AssignFrom,
|
||||||
|
@ -50,7 +50,7 @@ pub fn default_theme<C>(
|
|||||||
let type_right = blue;
|
let type_right = blue;
|
||||||
let type_wrong = magenta;
|
let type_wrong = magenta;
|
||||||
let type_wrong_b = magenta_bright;
|
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 missing = cyan;
|
||||||
let runtime = yellow;
|
let runtime = yellow;
|
||||||
let runtime_b = yellow_bright;
|
let runtime_b = yellow_bright;
|
||||||
@ -93,8 +93,9 @@ pub fn default_theme<C>(
|
|||||||
|
|
||||||
AssignTargetNonReference => type_wrong,
|
AssignTargetNonReference => type_wrong,
|
||||||
|
|
||||||
Function => function,
|
Function => function_and_field,
|
||||||
FunctionArgument => type_wrong,
|
FunctionArgument => type_wrong,
|
||||||
|
ObjectField => function_and_field,
|
||||||
|
|
||||||
InitFrom | AssignFrom | AsTypeStatementWithTooBroadType => type_wrong,
|
InitFrom | AssignFrom | AsTypeStatementWithTooBroadType => type_wrong,
|
||||||
InitTo | AssignTo | AsTypeTypeAnnotation => type_right,
|
InitTo | AssignTo | AsTypeTypeAnnotation => type_right,
|
||||||
|
@ -218,6 +218,15 @@ pub fn parse(
|
|||||||
});
|
});
|
||||||
pos_after_first = src.get_pos();
|
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 {
|
} else {
|
||||||
src.set_pos(pos_after_first);
|
src.set_pos(pos_after_first);
|
||||||
break;
|
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")]
|
#[cfg(feature = "parse")]
|
||||||
pub mod custom_type;
|
pub mod custom_type;
|
||||||
#[cfg(feature = "parse")]
|
#[cfg(feature = "parse")]
|
||||||
|
pub mod field;
|
||||||
|
#[cfg(feature = "parse")]
|
||||||
pub mod function;
|
pub mod function;
|
||||||
#[cfg(feature = "parse")]
|
#[cfg(feature = "parse")]
|
||||||
pub mod r#if;
|
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")]
|
#[cfg(feature = "run")]
|
||||||
pub mod custom_type;
|
pub mod custom_type;
|
||||||
#[cfg(feature = "run")]
|
#[cfg(feature = "run")]
|
||||||
|
pub mod field;
|
||||||
|
#[cfg(feature = "run")]
|
||||||
pub mod function;
|
pub mod function;
|
||||||
#[cfg(feature = "run")]
|
#[cfg(feature = "run")]
|
||||||
pub mod r#if;
|
pub mod r#if;
|
||||||
|
Loading…
Reference in New Issue
Block a user