Encapsulate getters/setters.
This commit is contained in:
parent
273fc59a30
commit
9f3113b11c
20
src/api.rs
20
src/api.rs
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use crate::any::{Any, AnyExt, Dynamic};
|
use crate::any::{Any, AnyExt, Dynamic};
|
||||||
use crate::call::FuncArgs;
|
use crate::call::FuncArgs;
|
||||||
use crate::engine::{Engine, FnAny, FnSpec, FUNC_GETTER, FUNC_SETTER};
|
use crate::engine::{make_getter, make_setter, Engine, FnAny, FnSpec};
|
||||||
use crate::error::ParseError;
|
use crate::error::ParseError;
|
||||||
use crate::fn_register::RegisterFn;
|
use crate::fn_register::RegisterFn;
|
||||||
use crate::parser::{lex, parse, parse_global_expr, FnDef, Position, AST};
|
use crate::parser::{lex, parse, parse_global_expr, FnDef, Position, AST};
|
||||||
@ -15,7 +15,6 @@ use crate::optimize::optimize_into_ast;
|
|||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::{type_name, TypeId},
|
any::{type_name, TypeId},
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
format,
|
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
@ -45,7 +44,7 @@ impl<'e> Engine<'e> {
|
|||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #[derive(Clone)]
|
/// #[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
/// struct TestStruct {
|
/// struct TestStruct {
|
||||||
/// field: i64
|
/// field: i64
|
||||||
/// }
|
/// }
|
||||||
@ -69,8 +68,8 @@ impl<'e> Engine<'e> {
|
|||||||
/// engine.register_fn("update", TestStruct::update);
|
/// engine.register_fn("update", TestStruct::update);
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// engine.eval::<TestStruct>("let x = new_ts(); x.update(41); x")?.field,
|
/// engine.eval::<TestStruct>("let x = new_ts(); x.update(41); x")?,
|
||||||
/// 42
|
/// TestStruct { field: 42 }
|
||||||
/// );
|
/// );
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
@ -181,7 +180,7 @@ impl<'e> Engine<'e> {
|
|||||||
name: &str,
|
name: &str,
|
||||||
callback: impl Fn(&mut T) -> U + 'static,
|
callback: impl Fn(&mut T) -> U + 'static,
|
||||||
) {
|
) {
|
||||||
let get_fn_name = format!("{}{}", FUNC_GETTER, name);
|
let get_fn_name = make_getter(name);
|
||||||
self.register_fn(&get_fn_name, callback);
|
self.register_fn(&get_fn_name, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +189,7 @@ impl<'e> Engine<'e> {
|
|||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #[derive(Clone)]
|
/// #[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
/// struct TestStruct {
|
/// struct TestStruct {
|
||||||
/// field: i64
|
/// field: i64
|
||||||
/// }
|
/// }
|
||||||
@ -214,7 +213,10 @@ impl<'e> Engine<'e> {
|
|||||||
/// engine.register_set("xyz", TestStruct::set_field);
|
/// engine.register_set("xyz", TestStruct::set_field);
|
||||||
///
|
///
|
||||||
/// // Notice that, with a getter, there is no way to get the property value
|
/// // Notice that, with a getter, there is no way to get the property value
|
||||||
/// engine.eval("let a = new_ts(); a.xyz = 42;")?;
|
/// assert_eq!(
|
||||||
|
/// engine.eval::<TestStruct>("let a = new_ts(); a.xyz = 42; a")?,
|
||||||
|
/// TestStruct { field: 42 }
|
||||||
|
/// );
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
@ -224,7 +226,7 @@ impl<'e> Engine<'e> {
|
|||||||
name: &str,
|
name: &str,
|
||||||
callback: impl Fn(&mut T, U) -> () + 'static,
|
callback: impl Fn(&mut T, U) -> () + 'static,
|
||||||
) {
|
) {
|
||||||
let set_fn_name = format!("{}{}", FUNC_SETTER, name);
|
let set_fn_name = make_setter(name);
|
||||||
self.register_fn(&set_fn_name, callback);
|
self.register_fn(&set_fn_name, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,6 +192,34 @@ impl Default for Engine<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Make getter function
|
||||||
|
pub fn make_getter(id: &str) -> String {
|
||||||
|
format!("{}{}", FUNC_GETTER, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extract the property name from a getter function name.
|
||||||
|
fn extract_prop_from_getter(fn_name: &str) -> Option<&str> {
|
||||||
|
if fn_name.starts_with(FUNC_GETTER) {
|
||||||
|
Some(&fn_name[FUNC_GETTER.len()..])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Make setter function
|
||||||
|
pub fn make_setter(id: &str) -> String {
|
||||||
|
format!("{}{}", FUNC_SETTER, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extract the property name from a setter function name.
|
||||||
|
fn extract_prop_from_setter(fn_name: &str) -> Option<&str> {
|
||||||
|
if fn_name.starts_with(FUNC_SETTER) {
|
||||||
|
Some(&fn_name[FUNC_SETTER.len()..])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Engine<'_> {
|
impl Engine<'_> {
|
||||||
/// Create a new `Engine`
|
/// Create a new `Engine`
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
@ -296,24 +324,18 @@ impl Engine<'_> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if fn_name.starts_with(FUNC_GETTER) {
|
if let Some(prop) = extract_prop_from_getter(fn_name) {
|
||||||
// Getter function not found
|
// Getter function not found
|
||||||
return Err(EvalAltResult::ErrorDotExpr(
|
return Err(EvalAltResult::ErrorDotExpr(
|
||||||
format!(
|
format!("- property '{}' unknown or write-only", prop),
|
||||||
"- property '{}' unknown or write-only",
|
|
||||||
&fn_name[FUNC_GETTER.len()..]
|
|
||||||
),
|
|
||||||
pos,
|
pos,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if fn_name.starts_with(FUNC_SETTER) {
|
if let Some(prop) = extract_prop_from_setter(fn_name) {
|
||||||
// Setter function not found
|
// Setter function not found
|
||||||
return Err(EvalAltResult::ErrorDotExpr(
|
return Err(EvalAltResult::ErrorDotExpr(
|
||||||
format!(
|
format!("- property '{}' unknown or read-only", prop),
|
||||||
"- property '{}' unknown or read-only",
|
|
||||||
&fn_name[FUNC_SETTER.len()..]
|
|
||||||
),
|
|
||||||
pos,
|
pos,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -390,7 +412,7 @@ impl Engine<'_> {
|
|||||||
|
|
||||||
// xxx.id
|
// xxx.id
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let get_fn_name = format!("{}{}", FUNC_GETTER, id);
|
let get_fn_name = make_getter(id);
|
||||||
let this_ptr = get_this_ptr(scope, src, target);
|
let this_ptr = get_this_ptr(scope, src, target);
|
||||||
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)
|
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)
|
||||||
}
|
}
|
||||||
@ -401,7 +423,7 @@ impl Engine<'_> {
|
|||||||
let (val, _) = match idx_lhs.as_ref() {
|
let (val, _) = match idx_lhs.as_ref() {
|
||||||
// xxx.id[idx_expr]
|
// xxx.id[idx_expr]
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let get_fn_name = format!("{}{}", FUNC_GETTER, id);
|
let get_fn_name = make_getter(id);
|
||||||
let this_ptr = get_this_ptr(scope, src, target);
|
let this_ptr = get_this_ptr(scope, src, target);
|
||||||
(
|
(
|
||||||
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)?,
|
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)?,
|
||||||
@ -431,7 +453,7 @@ impl Engine<'_> {
|
|||||||
Expr::Dot(dot_lhs, rhs, _) => match dot_lhs.as_ref() {
|
Expr::Dot(dot_lhs, rhs, _) => match dot_lhs.as_ref() {
|
||||||
// xxx.id.rhs
|
// xxx.id.rhs
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let get_fn_name = format!("{}{}", FUNC_GETTER, id);
|
let get_fn_name = make_getter(id);
|
||||||
let this_ptr = get_this_ptr(scope, src, target);
|
let this_ptr = get_this_ptr(scope, src, target);
|
||||||
|
|
||||||
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)
|
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)
|
||||||
@ -445,7 +467,7 @@ impl Engine<'_> {
|
|||||||
let (val, _) = match idx_lhs.as_ref() {
|
let (val, _) = match idx_lhs.as_ref() {
|
||||||
// xxx.id[idx_expr].rhs
|
// xxx.id[idx_expr].rhs
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let get_fn_name = format!("{}{}", FUNC_GETTER, id);
|
let get_fn_name = make_getter(id);
|
||||||
let this_ptr = get_this_ptr(scope, src, target);
|
let this_ptr = get_this_ptr(scope, src, target);
|
||||||
(
|
(
|
||||||
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)?,
|
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)?,
|
||||||
@ -755,7 +777,7 @@ impl Engine<'_> {
|
|||||||
match dot_rhs {
|
match dot_rhs {
|
||||||
// xxx.id
|
// xxx.id
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let set_fn_name = format!("{}{}", FUNC_SETTER, id);
|
let set_fn_name = make_setter(id);
|
||||||
let mut args = [this_ptr, new_val.0.as_mut()];
|
let mut args = [this_ptr, new_val.0.as_mut()];
|
||||||
self.call_fn_raw(&set_fn_name, &mut args, None, *pos, 0)
|
self.call_fn_raw(&set_fn_name, &mut args, None, *pos, 0)
|
||||||
}
|
}
|
||||||
@ -766,7 +788,7 @@ impl Engine<'_> {
|
|||||||
Expr::Index(lhs, idx_expr, op_pos) => match lhs.as_ref() {
|
Expr::Index(lhs, idx_expr, op_pos) => match lhs.as_ref() {
|
||||||
// xxx.id[idx_expr]
|
// xxx.id[idx_expr]
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let get_fn_name = format!("{}{}", FUNC_GETTER, id);
|
let get_fn_name = make_getter(id);
|
||||||
|
|
||||||
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)
|
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)
|
||||||
.and_then(|v| {
|
.and_then(|v| {
|
||||||
@ -779,7 +801,7 @@ impl Engine<'_> {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
.and_then(|mut v| {
|
.and_then(|mut v| {
|
||||||
let set_fn_name = format!("{}{}", FUNC_SETTER, id);
|
let set_fn_name = make_setter(id);
|
||||||
let mut args = [this_ptr, v.as_mut()];
|
let mut args = [this_ptr, v.as_mut()];
|
||||||
self.call_fn_raw(&set_fn_name, &mut args, None, *pos, 0)
|
self.call_fn_raw(&set_fn_name, &mut args, None, *pos, 0)
|
||||||
})
|
})
|
||||||
@ -796,7 +818,7 @@ impl Engine<'_> {
|
|||||||
Expr::Dot(lhs, rhs, _) => match lhs.as_ref() {
|
Expr::Dot(lhs, rhs, _) => match lhs.as_ref() {
|
||||||
// xxx.id.rhs
|
// xxx.id.rhs
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let get_fn_name = format!("{}{}", FUNC_GETTER, id);
|
let get_fn_name = make_getter(id);
|
||||||
|
|
||||||
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)
|
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)
|
||||||
.and_then(|mut v| {
|
.and_then(|mut v| {
|
||||||
@ -804,7 +826,7 @@ impl Engine<'_> {
|
|||||||
.map(|_| v) // Discard Ok return value
|
.map(|_| v) // Discard Ok return value
|
||||||
})
|
})
|
||||||
.and_then(|mut v| {
|
.and_then(|mut v| {
|
||||||
let set_fn_name = format!("{}{}", FUNC_SETTER, id);
|
let set_fn_name = make_setter(id);
|
||||||
let mut args = [this_ptr, v.as_mut()];
|
let mut args = [this_ptr, v.as_mut()];
|
||||||
self.call_fn_raw(&set_fn_name, &mut args, None, *pos, 0)
|
self.call_fn_raw(&set_fn_name, &mut args, None, *pos, 0)
|
||||||
})
|
})
|
||||||
@ -816,7 +838,7 @@ impl Engine<'_> {
|
|||||||
Expr::Index(lhs, idx_expr, op_pos) => match lhs.as_ref() {
|
Expr::Index(lhs, idx_expr, op_pos) => match lhs.as_ref() {
|
||||||
// xxx.id[idx_expr].rhs
|
// xxx.id[idx_expr].rhs
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let get_fn_name = format!("{}{}", FUNC_GETTER, id);
|
let get_fn_name = make_getter(id);
|
||||||
|
|
||||||
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)
|
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)
|
||||||
.and_then(|v| {
|
.and_then(|v| {
|
||||||
@ -832,7 +854,7 @@ impl Engine<'_> {
|
|||||||
Self::update_indexed_value(v, idx as usize, target, val_pos)
|
Self::update_indexed_value(v, idx as usize, target, val_pos)
|
||||||
})
|
})
|
||||||
.and_then(|mut v| {
|
.and_then(|mut v| {
|
||||||
let set_fn_name = format!("{}{}", FUNC_SETTER, id);
|
let set_fn_name = make_setter(id);
|
||||||
let mut args = [this_ptr, v.as_mut()];
|
let mut args = [this_ptr, v.as_mut()];
|
||||||
self.call_fn_raw(&set_fn_name, &mut args, None, *pos, 0)
|
self.call_fn_raw(&set_fn_name, &mut args, None, *pos, 0)
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user