Reshuffle code sections.
This commit is contained in:
parent
dd09dbf79e
commit
b23fd6e20a
238
src/engine.rs
238
src/engine.rs
@ -344,6 +344,98 @@ pub(crate) fn calc_fn_def(fn_name: &str, params: usize) -> u64 {
|
|||||||
s.finish()
|
s.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Print/debug to stdout
|
||||||
|
fn default_print(s: &str) {
|
||||||
|
#[cfg(not(feature = "no_std"))]
|
||||||
|
println!("{}", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Search for a variable within the scope, returning its value and index inside the Scope
|
||||||
|
fn search_scope<'a>(
|
||||||
|
scope: &'a Scope,
|
||||||
|
id: &str,
|
||||||
|
begin: Position,
|
||||||
|
) -> Result<(ScopeSource<'a>, Dynamic), Box<EvalAltResult>> {
|
||||||
|
scope
|
||||||
|
.get(id)
|
||||||
|
.ok_or_else(|| Box::new(EvalAltResult::ErrorVariableNotFound(id.into(), begin)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Replace a character at an index position in a mutable string
|
||||||
|
fn str_replace_char(s: &mut String, idx: usize, new_ch: char) {
|
||||||
|
let mut chars: Vec<char> = s.chars().collect();
|
||||||
|
let ch = *chars.get(idx).expect("string index out of bounds");
|
||||||
|
|
||||||
|
// See if changed - if so, update the String
|
||||||
|
if ch != new_ch {
|
||||||
|
chars[idx] = new_ch;
|
||||||
|
s.clear();
|
||||||
|
chars.iter().for_each(|&ch| s.push(ch));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update the value at an index position
|
||||||
|
fn update_indexed_val(
|
||||||
|
mut target: Dynamic,
|
||||||
|
idx: IndexValue,
|
||||||
|
new_val: Dynamic,
|
||||||
|
pos: Position,
|
||||||
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
|
match target.get_mut() {
|
||||||
|
Union::Array(arr) => {
|
||||||
|
arr[idx.as_num()] = new_val;
|
||||||
|
}
|
||||||
|
Union::Map(map) => {
|
||||||
|
map.insert(idx.as_str(), new_val);
|
||||||
|
}
|
||||||
|
Union::Str(s) => {
|
||||||
|
// Value must be a character
|
||||||
|
let ch = new_val
|
||||||
|
.as_char()
|
||||||
|
.map_err(|_| EvalAltResult::ErrorCharMismatch(pos))?;
|
||||||
|
str_replace_char(s, idx.as_num(), ch);
|
||||||
|
}
|
||||||
|
// All other variable types should be an error
|
||||||
|
_ => panic!("invalid type for indexing: {}", target.type_name()),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update the value at an index position in a variable inside the scope
|
||||||
|
fn update_indexed_scope_var(
|
||||||
|
scope: &mut Scope,
|
||||||
|
src: ScopeSource,
|
||||||
|
idx: IndexValue,
|
||||||
|
new_val: Dynamic,
|
||||||
|
pos: Position,
|
||||||
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
|
let target = scope.get_mut(src);
|
||||||
|
|
||||||
|
match target.get_mut() {
|
||||||
|
// array_id[idx] = val
|
||||||
|
Union::Array(arr) => {
|
||||||
|
arr[idx.as_num()] = new_val;
|
||||||
|
}
|
||||||
|
// map_id[idx] = val
|
||||||
|
Union::Map(map) => {
|
||||||
|
map.insert(idx.as_str(), new_val);
|
||||||
|
}
|
||||||
|
// string_id[idx] = val
|
||||||
|
Union::Str(s) => {
|
||||||
|
// Value must be a character
|
||||||
|
let ch = new_val
|
||||||
|
.as_char()
|
||||||
|
.map_err(|_| EvalAltResult::ErrorCharMismatch(pos))?;
|
||||||
|
str_replace_char(s, idx.as_num(), ch);
|
||||||
|
}
|
||||||
|
// All other variable types should be an error
|
||||||
|
_ => panic!("invalid type for indexing: {}", target.type_name()),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Dynamic::from_unit())
|
||||||
|
}
|
||||||
|
|
||||||
impl Engine {
|
impl Engine {
|
||||||
/// Create a new `Engine`
|
/// Create a new `Engine`
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
@ -669,7 +761,7 @@ impl Engine {
|
|||||||
match dot_lhs {
|
match dot_lhs {
|
||||||
// id.???
|
// id.???
|
||||||
Expr::Variable(id, pos) => {
|
Expr::Variable(id, pos) => {
|
||||||
let (entry, _) = Self::search_scope(scope, id, *pos)?;
|
let (entry, _) = search_scope(scope, id, *pos)?;
|
||||||
|
|
||||||
// Avoid referencing scope which is used below as mut
|
// Avoid referencing scope which is used below as mut
|
||||||
let entry = ScopeSource { name: id, ..entry };
|
let entry = ScopeSource { name: id, ..entry };
|
||||||
@ -696,8 +788,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ScopeEntryType::Normal => {
|
ScopeEntryType::Normal => {
|
||||||
let pos = dot_rhs.position();
|
update_indexed_scope_var(scope, src, index, val, dot_rhs.position())?;
|
||||||
Self::update_indexed_scope_var(scope, src, index, val, pos)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -713,17 +804,6 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Search for a variable within the scope, returning its value and index inside the Scope
|
|
||||||
fn search_scope<'a>(
|
|
||||||
scope: &'a Scope,
|
|
||||||
id: &str,
|
|
||||||
begin: Position,
|
|
||||||
) -> Result<(ScopeSource<'a>, Dynamic), Box<EvalAltResult>> {
|
|
||||||
scope
|
|
||||||
.get(id)
|
|
||||||
.ok_or_else(|| Box::new(EvalAltResult::ErrorVariableNotFound(id.into(), begin)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the value at the indexed position of a base type
|
/// Get the value at the indexed position of a base type
|
||||||
fn get_indexed_val(
|
fn get_indexed_val(
|
||||||
&self,
|
&self,
|
||||||
@ -746,6 +826,8 @@ impl Engine {
|
|||||||
.as_int()
|
.as_int()
|
||||||
.map_err(|_| EvalAltResult::ErrorNumericIndexExpr(idx_expr.position()))?;
|
.map_err(|_| EvalAltResult::ErrorNumericIndexExpr(idx_expr.position()))?;
|
||||||
|
|
||||||
|
let arr_len = arr.len();
|
||||||
|
|
||||||
if index >= 0 {
|
if index >= 0 {
|
||||||
arr.get(index as usize)
|
arr.get(index as usize)
|
||||||
.map(|v| {
|
.map(|v| {
|
||||||
@ -759,13 +841,11 @@ impl Engine {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
Box::new(EvalAltResult::ErrorArrayBounds(arr.len(), index, idx_pos))
|
Box::new(EvalAltResult::ErrorArrayBounds(arr_len, index, idx_pos))
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(Box::new(EvalAltResult::ErrorArrayBounds(
|
Err(Box::new(EvalAltResult::ErrorArrayBounds(
|
||||||
arr.len(),
|
arr_len, index, idx_pos,
|
||||||
index,
|
|
||||||
idx_pos,
|
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -834,21 +914,13 @@ impl Engine {
|
|||||||
) -> Result<(Option<ScopeSource<'a>>, IndexValue, Dynamic), Box<EvalAltResult>> {
|
) -> Result<(Option<ScopeSource<'a>>, IndexValue, Dynamic), Box<EvalAltResult>> {
|
||||||
match lhs {
|
match lhs {
|
||||||
// id[idx_expr]
|
// id[idx_expr]
|
||||||
Expr::Variable(id, _) => {
|
Expr::Variable(name, _) => {
|
||||||
let (ScopeSource { typ, index, .. }, val) =
|
let (ScopeSource { typ, index, .. }, val) =
|
||||||
Self::search_scope(scope, &id, lhs.position())?;
|
search_scope(scope, &name, lhs.position())?;
|
||||||
let (val, idx) =
|
let (val, idx) =
|
||||||
self.get_indexed_val(scope, fn_lib, &val, idx_expr, op_pos, level, false)?;
|
self.get_indexed_val(scope, fn_lib, &val, idx_expr, op_pos, level, false)?;
|
||||||
|
|
||||||
Ok((
|
Ok((Some(ScopeSource { name, typ, index }), idx, val))
|
||||||
Some(ScopeSource {
|
|
||||||
name: &id,
|
|
||||||
typ,
|
|
||||||
index,
|
|
||||||
}),
|
|
||||||
idx,
|
|
||||||
val,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// (expr)[idx_expr]
|
// (expr)[idx_expr]
|
||||||
@ -860,81 +932,6 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replace a character at an index position in a mutable string
|
|
||||||
fn str_replace_char(s: &mut String, idx: usize, new_ch: char) {
|
|
||||||
let mut chars: Vec<char> = s.chars().collect();
|
|
||||||
let ch = *chars.get(idx).expect("string index out of bounds");
|
|
||||||
|
|
||||||
// See if changed - if so, update the String
|
|
||||||
if ch != new_ch {
|
|
||||||
chars[idx] = new_ch;
|
|
||||||
s.clear();
|
|
||||||
chars.iter().for_each(|&ch| s.push(ch));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update the value at an index position in a variable inside the scope
|
|
||||||
fn update_indexed_scope_var(
|
|
||||||
scope: &mut Scope,
|
|
||||||
src: ScopeSource,
|
|
||||||
idx: IndexValue,
|
|
||||||
new_val: Dynamic,
|
|
||||||
pos: Position,
|
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
||||||
let target = scope.get_mut(src);
|
|
||||||
|
|
||||||
match target.get_mut() {
|
|
||||||
// array_id[idx] = val
|
|
||||||
Union::Array(arr) => {
|
|
||||||
arr[idx.as_num()] = new_val;
|
|
||||||
}
|
|
||||||
// map_id[idx] = val
|
|
||||||
Union::Map(map) => {
|
|
||||||
map.insert(idx.as_str(), new_val);
|
|
||||||
}
|
|
||||||
// string_id[idx] = val
|
|
||||||
Union::Str(s) => {
|
|
||||||
// Value must be a character
|
|
||||||
let ch = new_val
|
|
||||||
.as_char()
|
|
||||||
.map_err(|_| EvalAltResult::ErrorCharMismatch(pos))?;
|
|
||||||
Self::str_replace_char(s, idx.as_num(), ch);
|
|
||||||
}
|
|
||||||
// All other variable types should be an error
|
|
||||||
_ => panic!("invalid type for indexing: {}", target.type_name()),
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Dynamic::from_unit())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update the value at an index position
|
|
||||||
fn update_indexed_val(
|
|
||||||
mut target: Dynamic,
|
|
||||||
idx: IndexValue,
|
|
||||||
new_val: Dynamic,
|
|
||||||
pos: Position,
|
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
||||||
match target.get_mut() {
|
|
||||||
Union::Array(arr) => {
|
|
||||||
arr[idx.as_num()] = new_val;
|
|
||||||
}
|
|
||||||
Union::Map(map) => {
|
|
||||||
map.insert(idx.as_str(), new_val);
|
|
||||||
}
|
|
||||||
Union::Str(s) => {
|
|
||||||
// Value must be a character
|
|
||||||
let ch = new_val
|
|
||||||
.as_char()
|
|
||||||
.map_err(|_| EvalAltResult::ErrorCharMismatch(pos))?;
|
|
||||||
Self::str_replace_char(s, idx.as_num(), ch);
|
|
||||||
}
|
|
||||||
// All other variable types should be an error
|
|
||||||
_ => panic!("invalid type for indexing: {}", target.type_name()),
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(target)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Chain-evaluate a dot setter
|
/// Chain-evaluate a dot setter
|
||||||
fn dot_set_helper(
|
fn dot_set_helper(
|
||||||
&self,
|
&self,
|
||||||
@ -965,7 +962,7 @@ impl Engine {
|
|||||||
scope, fn_lib, &val, idx_expr, *op_pos, level, true,
|
scope, fn_lib, &val, idx_expr, *op_pos, level, true,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Self::update_indexed_val(val, index, new_val.clone(), val_pos)
|
update_indexed_val(val, index, new_val.clone(), val_pos)
|
||||||
})
|
})
|
||||||
.and_then(|mut val| {
|
.and_then(|mut val| {
|
||||||
let fn_name = make_setter(id);
|
let fn_name = make_setter(id);
|
||||||
@ -990,8 +987,8 @@ impl Engine {
|
|||||||
.and_then(|mut val| {
|
.and_then(|mut val| {
|
||||||
self.dot_set_helper(
|
self.dot_set_helper(
|
||||||
scope, fn_lib, &mut val, rhs, new_val, val_pos, level,
|
scope, fn_lib, &mut val, rhs, new_val, val_pos, level,
|
||||||
)
|
)?;
|
||||||
.map(|_| val) // Discard Ok return value
|
Ok(val)
|
||||||
})
|
})
|
||||||
.and_then(|mut val| {
|
.and_then(|mut val| {
|
||||||
let fn_name = make_setter(id);
|
let fn_name = make_setter(id);
|
||||||
@ -1017,7 +1014,7 @@ impl Engine {
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
// In case the expression mutated `target`, we need to update it back into the scope because it is cloned.
|
// In case the expression mutated `target`, we need to update it back into the scope because it is cloned.
|
||||||
Self::update_indexed_val(v, index, value, val_pos)
|
update_indexed_val(v, index, value, val_pos)
|
||||||
})
|
})
|
||||||
.and_then(|mut v| {
|
.and_then(|mut v| {
|
||||||
let fn_name = make_setter(id);
|
let fn_name = make_setter(id);
|
||||||
@ -1063,7 +1060,7 @@ impl Engine {
|
|||||||
match dot_lhs {
|
match dot_lhs {
|
||||||
// id.???
|
// id.???
|
||||||
Expr::Variable(id, pos) => {
|
Expr::Variable(id, pos) => {
|
||||||
let (src, mut target) = Self::search_scope(scope, id, *pos)?;
|
let (src, mut target) = search_scope(scope, id, *pos)?;
|
||||||
|
|
||||||
match src.typ {
|
match src.typ {
|
||||||
ScopeEntryType::Constant => Err(Box::new(
|
ScopeEntryType::Constant => Err(Box::new(
|
||||||
@ -1072,14 +1069,9 @@ impl Engine {
|
|||||||
_ => {
|
_ => {
|
||||||
// Avoid referencing scope which is used below as mut
|
// Avoid referencing scope which is used below as mut
|
||||||
let entry = ScopeSource { name: id, ..src };
|
let entry = ScopeSource { name: id, ..src };
|
||||||
|
let this_ptr = &mut target;
|
||||||
let value = self.dot_set_helper(
|
let value = self.dot_set_helper(
|
||||||
scope,
|
scope, fn_lib, this_ptr, dot_rhs, new_val, val_pos, level,
|
||||||
fn_lib,
|
|
||||||
&mut target,
|
|
||||||
dot_rhs,
|
|
||||||
new_val,
|
|
||||||
val_pos,
|
|
||||||
level,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// In case the expression mutated `target`, we need to update it back into the scope because it is cloned.
|
// In case the expression mutated `target`, we need to update it back into the scope because it is cloned.
|
||||||
@ -1109,7 +1101,7 @@ impl Engine {
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
ScopeEntryType::Normal => {
|
ScopeEntryType::Normal => {
|
||||||
Self::update_indexed_scope_var(scope, src, index, target, val_pos)?;
|
update_indexed_scope_var(scope, src, index, target, val_pos)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1198,7 +1190,7 @@ impl Engine {
|
|||||||
Expr::FloatConstant(f, _) => Ok(Dynamic::from_float(*f)),
|
Expr::FloatConstant(f, _) => Ok(Dynamic::from_float(*f)),
|
||||||
Expr::StringConstant(s, _) => Ok(Dynamic::from_string(s.to_string())),
|
Expr::StringConstant(s, _) => Ok(Dynamic::from_string(s.to_string())),
|
||||||
Expr::CharConstant(c, _) => Ok(Dynamic::from_char(*c)),
|
Expr::CharConstant(c, _) => Ok(Dynamic::from_char(*c)),
|
||||||
Expr::Variable(id, pos) => Self::search_scope(scope, id, *pos).map(|(_, val)| val),
|
Expr::Variable(id, pos) => search_scope(scope, id, *pos).map(|(_, val)| val),
|
||||||
Expr::Property(_, _) => panic!("unexpected property."),
|
Expr::Property(_, _) => panic!("unexpected property."),
|
||||||
|
|
||||||
// Statement block
|
// Statement block
|
||||||
@ -1261,9 +1253,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
ScopeEntryType::Normal => {
|
ScopeEntryType::Normal => {
|
||||||
let pos = rhs.position();
|
let pos = rhs.position();
|
||||||
Ok(Self::update_indexed_scope_var(
|
Ok(update_indexed_scope_var(scope, src, index, rhs_val, pos)?)
|
||||||
scope, src, index, rhs_val, pos,
|
|
||||||
)?)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1645,9 +1635,3 @@ impl Engine {
|
|||||||
.unwrap_or(name)
|
.unwrap_or(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print/debug to stdout
|
|
||||||
fn default_print(s: &str) {
|
|
||||||
#[cfg(not(feature = "no_std"))]
|
|
||||||
println!("{}", s);
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user