Minor code refactoring.
This commit is contained in:
parent
a64b01692b
commit
bedfe55005
148
src/engine.rs
148
src/engine.rs
@ -2,14 +2,12 @@ use std::any::TypeId;
|
|||||||
use std::cmp::{PartialEq, PartialOrd};
|
use std::cmp::{PartialEq, PartialOrd};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::any::{Any, AnyExt, Dynamic, Variant};
|
use crate::any::{Any, AnyExt, Dynamic, Variant};
|
||||||
use crate::call::FunArgs;
|
use crate::call::FunArgs;
|
||||||
use crate::fn_register::RegisterFn;
|
use crate::fn_register::RegisterFn;
|
||||||
use crate::parser::{lex, parse, Expr, FnDef, ParseError, Stmt, AST};
|
use crate::parser::{lex, parse, Expr, FnDef, ParseError, Stmt, AST};
|
||||||
use fmt::Debug;
|
|
||||||
|
|
||||||
pub type Array = Vec<Dynamic>;
|
pub type Array = Vec<Dynamic>;
|
||||||
pub type FnCallArgs<'a> = Vec<&'a mut Variant>;
|
pub type FnCallArgs<'a> = Vec<&'a mut Variant>;
|
||||||
@ -112,8 +110,8 @@ impl Error for EvalAltResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for EvalAltResult {
|
impl std::fmt::Display for EvalAltResult {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
if let Some(s) = self.as_str() {
|
if let Some(s) = self.as_str() {
|
||||||
write!(f, "{}: {}", self.description(), s)
|
write!(f, "{}: {}", self.description(), s)
|
||||||
} else {
|
} else {
|
||||||
@ -241,6 +239,7 @@ impl Engine {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|x| (*(&**x).into_dynamic()).type_name())
|
.map(|x| (*(&**x).into_dynamic()).type_name())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
EvalAltResult::ErrorFunctionNotFound(format!(
|
EvalAltResult::ErrorFunctionNotFound(format!(
|
||||||
"{} ({})",
|
"{} ({})",
|
||||||
ident,
|
ident,
|
||||||
@ -250,6 +249,7 @@ impl Engine {
|
|||||||
.and_then(move |f| match **f {
|
.and_then(move |f| match **f {
|
||||||
FnIntExt::Ext(ref f) => {
|
FnIntExt::Ext(ref f) => {
|
||||||
let r = f(args);
|
let r = f(args);
|
||||||
|
|
||||||
if r.is_err() {
|
if r.is_err() {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -270,6 +270,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
FnIntExt::Int(ref f) => {
|
FnIntExt::Int(ref f) => {
|
||||||
let mut scope = Scope::new();
|
let mut scope = Scope::new();
|
||||||
|
|
||||||
scope.extend(
|
scope.extend(
|
||||||
f.params
|
f.params
|
||||||
.iter()
|
.iter()
|
||||||
@ -357,17 +358,20 @@ impl Engine {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|arg| self.eval_expr(scope, arg))
|
.map(|arg| self.eval_expr(scope, arg))
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
let args = once(this_ptr)
|
let args = once(this_ptr)
|
||||||
.chain(args.iter_mut().map(|b| b.as_mut()))
|
.chain(args.iter_mut().map(|b| b.as_mut()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
self.call_fn_raw(fn_name.to_owned(), args)
|
self.call_fn_raw(fn_name.to_owned(), args)
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::Identifier(id) => {
|
Expr::Identifier(id) => {
|
||||||
let get_fn_name = "get$".to_string() + id;
|
let get_fn_name = "get$".to_string() + id;
|
||||||
|
|
||||||
self.call_fn_raw(get_fn_name, vec![this_ptr])
|
self.call_fn_raw(get_fn_name, vec![this_ptr])
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::Index(id, idx_raw) => {
|
Expr::Index(id, idx_raw) => {
|
||||||
let idx = self
|
let idx = self
|
||||||
.eval_expr(scope, idx_raw)?
|
.eval_expr(scope, idx_raw)?
|
||||||
@ -380,26 +384,27 @@ impl Engine {
|
|||||||
let mut val = self.call_fn_raw(get_fn_name, vec![this_ptr])?;
|
let mut val = self.call_fn_raw(get_fn_name, vec![this_ptr])?;
|
||||||
|
|
||||||
if let Some(arr) = (*val).downcast_mut() as Option<&mut Array> {
|
if let Some(arr) = (*val).downcast_mut() as Option<&mut Array> {
|
||||||
if idx < 0 {
|
if idx >= 0 {
|
||||||
Err(EvalAltResult::ErrorArrayBounds(arr.len(), idx))
|
|
||||||
} else {
|
|
||||||
arr.get(idx as usize)
|
arr.get(idx as usize)
|
||||||
.cloned()
|
.cloned()
|
||||||
.ok_or_else(|| EvalAltResult::ErrorArrayBounds(arr.len(), idx))
|
.ok_or_else(|| EvalAltResult::ErrorArrayBounds(arr.len(), idx))
|
||||||
|
} else {
|
||||||
|
Err(EvalAltResult::ErrorArrayBounds(arr.len(), idx))
|
||||||
}
|
}
|
||||||
} else if let Some(s) = (*val).downcast_mut() as Option<&mut String> {
|
} else if let Some(s) = (*val).downcast_mut() as Option<&mut String> {
|
||||||
if idx < 0 {
|
if idx >= 0 {
|
||||||
Err(EvalAltResult::ErrorStringBounds(s.chars().count(), idx))
|
|
||||||
} else {
|
|
||||||
s.chars()
|
s.chars()
|
||||||
.nth(idx as usize)
|
.nth(idx as usize)
|
||||||
.map(|ch| Box::new(ch) as Dynamic)
|
.map(|ch| Box::new(ch) as Dynamic)
|
||||||
.ok_or_else(|| EvalAltResult::ErrorStringBounds(s.chars().count(), idx))
|
.ok_or_else(|| EvalAltResult::ErrorStringBounds(s.chars().count(), idx))
|
||||||
|
} else {
|
||||||
|
Err(EvalAltResult::ErrorStringBounds(s.chars().count(), idx))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(EvalAltResult::ErrorIndexing)
|
Err(EvalAltResult::ErrorIndexing)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::Dot(inner_lhs, inner_rhs) => match **inner_lhs {
|
Expr::Dot(inner_lhs, inner_rhs) => match **inner_lhs {
|
||||||
Expr::Identifier(ref id) => {
|
Expr::Identifier(ref id) => {
|
||||||
let get_fn_name = "get$".to_string() + id;
|
let get_fn_name = "get$".to_string() + id;
|
||||||
@ -462,29 +467,27 @@ impl Engine {
|
|||||||
if let Some(arr) = (*val).downcast_mut() as Option<&mut Array> {
|
if let Some(arr) = (*val).downcast_mut() as Option<&mut Array> {
|
||||||
is_array = true;
|
is_array = true;
|
||||||
|
|
||||||
return if idx < 0 {
|
if idx >= 0 {
|
||||||
Err(EvalAltResult::ErrorArrayBounds(arr.len(), idx))
|
|
||||||
} else {
|
|
||||||
arr.get(idx as usize)
|
arr.get(idx as usize)
|
||||||
.cloned()
|
.cloned()
|
||||||
.ok_or_else(|| EvalAltResult::ErrorArrayBounds(arr.len(), idx))
|
.ok_or_else(|| EvalAltResult::ErrorArrayBounds(arr.len(), idx))
|
||||||
};
|
} else {
|
||||||
|
Err(EvalAltResult::ErrorArrayBounds(arr.len(), idx))
|
||||||
}
|
}
|
||||||
|
} else if let Some(s) = (*val).downcast_mut() as Option<&mut String> {
|
||||||
if let Some(s) = (*val).downcast_mut() as Option<&mut String> {
|
|
||||||
is_array = false;
|
is_array = false;
|
||||||
|
|
||||||
return if idx < 0 {
|
if idx >= 0 {
|
||||||
Err(EvalAltResult::ErrorStringBounds(s.chars().count(), idx))
|
|
||||||
} else {
|
|
||||||
s.chars()
|
s.chars()
|
||||||
.nth(idx as usize)
|
.nth(idx as usize)
|
||||||
.map(|ch| Box::new(ch) as Dynamic)
|
.map(|ch| Box::new(ch) as Dynamic)
|
||||||
.ok_or_else(|| EvalAltResult::ErrorStringBounds(s.chars().count(), idx))
|
.ok_or_else(|| EvalAltResult::ErrorStringBounds(s.chars().count(), idx))
|
||||||
};
|
} else {
|
||||||
|
Err(EvalAltResult::ErrorStringBounds(s.chars().count(), idx))
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
Err(EvalAltResult::ErrorIndexing)
|
Err(EvalAltResult::ErrorIndexing)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.map(|(idx_sc, val)| (is_array, idx_sc, idx as usize, val))
|
.map(|(idx_sc, val)| (is_array, idx_sc, idx as usize, val))
|
||||||
}
|
}
|
||||||
@ -522,6 +525,7 @@ impl Engine {
|
|||||||
|
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::Index(id, idx_raw) => {
|
Expr::Index(id, idx_raw) => {
|
||||||
let (is_array, sc_idx, idx, mut target) = self.indexed_value(scope, id, idx_raw)?;
|
let (is_array, sc_idx, idx, mut target) = self.indexed_value(scope, id, idx_raw)?;
|
||||||
let value = self.get_dot_val_helper(scope, target.as_mut(), dot_rhs);
|
let value = self.get_dot_val_helper(scope, target.as_mut(), dot_rhs);
|
||||||
@ -532,13 +536,11 @@ impl Engine {
|
|||||||
if is_array {
|
if is_array {
|
||||||
scope[sc_idx].1.downcast_mut::<Array>().unwrap()[idx] = target;
|
scope[sc_idx].1.downcast_mut::<Array>().unwrap()[idx] = target;
|
||||||
} else {
|
} else {
|
||||||
// Target should be a char
|
Self::str_replace_char(
|
||||||
let new_ch = *target.downcast::<char>().unwrap();
|
scope[sc_idx].1.downcast_mut::<String>().unwrap(), // Root is a string
|
||||||
|
idx,
|
||||||
// Root should be a String
|
*target.downcast::<char>().unwrap(), // Target should be a char
|
||||||
let s = scope[sc_idx].1.downcast_mut::<String>().unwrap();
|
);
|
||||||
|
|
||||||
Self::str_replace_char(s, idx, new_ch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
value
|
value
|
||||||
@ -556,11 +558,14 @@ impl Engine {
|
|||||||
match dot_rhs {
|
match dot_rhs {
|
||||||
Expr::Identifier(id) => {
|
Expr::Identifier(id) => {
|
||||||
let set_fn_name = "set$".to_string() + id;
|
let set_fn_name = "set$".to_string() + id;
|
||||||
|
|
||||||
self.call_fn_raw(set_fn_name, vec![this_ptr, source_val.as_mut()])
|
self.call_fn_raw(set_fn_name, vec![this_ptr, source_val.as_mut()])
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::Dot(inner_lhs, inner_rhs) => match **inner_lhs {
|
Expr::Dot(inner_lhs, inner_rhs) => match **inner_lhs {
|
||||||
Expr::Identifier(ref id) => {
|
Expr::Identifier(ref id) => {
|
||||||
let get_fn_name = "get$".to_string() + id;
|
let get_fn_name = "get$".to_string() + id;
|
||||||
|
|
||||||
self.call_fn_raw(get_fn_name, vec![this_ptr])
|
self.call_fn_raw(get_fn_name, vec![this_ptr])
|
||||||
.and_then(|mut v| {
|
.and_then(|mut v| {
|
||||||
self.set_dot_val_helper(v.as_mut(), inner_rhs, source_val)
|
self.set_dot_val_helper(v.as_mut(), inner_rhs, source_val)
|
||||||
@ -596,6 +601,7 @@ impl Engine {
|
|||||||
|
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::Index(id, idx_raw) => {
|
Expr::Index(id, idx_raw) => {
|
||||||
let (is_array, sc_idx, idx, mut target) = self.indexed_value(scope, id, idx_raw)?;
|
let (is_array, sc_idx, idx, mut target) = self.indexed_value(scope, id, idx_raw)?;
|
||||||
let value = self.set_dot_val_helper(target.as_mut(), dot_rhs, source_val);
|
let value = self.set_dot_val_helper(target.as_mut(), dot_rhs, source_val);
|
||||||
@ -605,13 +611,11 @@ impl Engine {
|
|||||||
if is_array {
|
if is_array {
|
||||||
scope[sc_idx].1.downcast_mut::<Array>().unwrap()[idx] = target;
|
scope[sc_idx].1.downcast_mut::<Array>().unwrap()[idx] = target;
|
||||||
} else {
|
} else {
|
||||||
// Target should be a char
|
Self::str_replace_char(
|
||||||
let new_ch = *target.downcast::<char>().unwrap();
|
scope[sc_idx].1.downcast_mut::<String>().unwrap(), // Root is a string
|
||||||
|
idx,
|
||||||
// Root should be a String
|
*target.downcast::<char>().unwrap(), // Target should be a char
|
||||||
let s = scope[sc_idx].1.downcast_mut::<String>().unwrap();
|
);
|
||||||
|
|
||||||
Self::str_replace_char(s, idx, new_ch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
value
|
value
|
||||||
@ -626,28 +630,34 @@ impl Engine {
|
|||||||
Expr::FloatConstant(i) => Ok(Box::new(*i)),
|
Expr::FloatConstant(i) => Ok(Box::new(*i)),
|
||||||
Expr::StringConstant(s) => Ok(Box::new(s.clone())),
|
Expr::StringConstant(s) => Ok(Box::new(s.clone())),
|
||||||
Expr::CharConstant(c) => Ok(Box::new(*c)),
|
Expr::CharConstant(c) => Ok(Box::new(*c)),
|
||||||
Expr::Identifier(id) => {
|
|
||||||
match scope.iter().rev().filter(|(name, _)| id == name).next() {
|
Expr::Identifier(id) => scope
|
||||||
Some((_, val)) => Ok(val.clone()),
|
.iter()
|
||||||
_ => Err(EvalAltResult::ErrorVariableNotFound(id.clone())),
|
.rev()
|
||||||
}
|
.filter(|(name, _)| id == name)
|
||||||
}
|
.next()
|
||||||
|
.map(|(_, val)| val.clone())
|
||||||
|
.ok_or_else(|| EvalAltResult::ErrorVariableNotFound(id.clone())),
|
||||||
|
|
||||||
Expr::Index(id, idx_raw) => {
|
Expr::Index(id, idx_raw) => {
|
||||||
self.indexed_value(scope, id, idx_raw).map(|(_, _, _, x)| x)
|
self.indexed_value(scope, id, idx_raw).map(|(_, _, _, x)| x)
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::Assignment(ref id, rhs) => {
|
Expr::Assignment(ref id, rhs) => {
|
||||||
let rhs_val = self.eval_expr(scope, rhs)?;
|
let rhs_val = self.eval_expr(scope, rhs)?;
|
||||||
|
|
||||||
match **id {
|
match **id {
|
||||||
Expr::Identifier(ref n) => {
|
Expr::Identifier(ref n) => scope
|
||||||
match scope.iter_mut().rev().filter(|(name, _)| n == name).next() {
|
.iter_mut()
|
||||||
Some((_, val)) => {
|
.rev()
|
||||||
|
.filter(|(name, _)| n == name)
|
||||||
|
.next()
|
||||||
|
.map(|(_, val)| {
|
||||||
*val = rhs_val;
|
*val = rhs_val;
|
||||||
Ok(Box::new(()))
|
Box::new(()) as Dynamic
|
||||||
}
|
})
|
||||||
_ => Err(EvalAltResult::ErrorVariableNotFound(n.clone())),
|
.ok_or_else(|| EvalAltResult::ErrorVariableNotFound(n.clone())),
|
||||||
}
|
|
||||||
}
|
|
||||||
Expr::Index(ref id, ref idx_raw) => {
|
Expr::Index(ref id, ref idx_raw) => {
|
||||||
let idx = *match self.eval_expr(scope, &idx_raw)?.downcast_ref::<i64>() {
|
let idx = *match self.eval_expr(scope, &idx_raw)?.downcast_ref::<i64>() {
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
@ -667,32 +677,32 @@ impl Engine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(arr) = val.downcast_mut() as Option<&mut Array> {
|
if let Some(arr) = val.downcast_mut() as Option<&mut Array> {
|
||||||
return if idx < 0 {
|
if idx < 0 {
|
||||||
Err(EvalAltResult::ErrorArrayBounds(arr.len(), idx))
|
Err(EvalAltResult::ErrorArrayBounds(arr.len(), idx))
|
||||||
} else if idx as usize >= arr.len() {
|
} else if idx as usize >= arr.len() {
|
||||||
Err(EvalAltResult::ErrorArrayBounds(arr.len(), idx))
|
Err(EvalAltResult::ErrorArrayBounds(arr.len(), idx))
|
||||||
} else {
|
} else {
|
||||||
arr[idx as usize] = rhs_val;
|
arr[idx as usize] = rhs_val;
|
||||||
Ok(Box::new(()))
|
Ok(Box::new(()))
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
} else if let Some(s) = val.downcast_mut() as Option<&mut String> {
|
||||||
if let Some(s) = val.downcast_mut() as Option<&mut String> {
|
|
||||||
let s_len = s.chars().count();
|
let s_len = s.chars().count();
|
||||||
|
|
||||||
return if idx < 0 {
|
if idx < 0 {
|
||||||
Err(EvalAltResult::ErrorStringBounds(s_len, idx))
|
Err(EvalAltResult::ErrorStringBounds(s_len, idx))
|
||||||
} else if idx as usize >= s_len {
|
} else if idx as usize >= s_len {
|
||||||
Err(EvalAltResult::ErrorStringBounds(s_len, idx))
|
Err(EvalAltResult::ErrorStringBounds(s_len, idx))
|
||||||
} else {
|
} else {
|
||||||
// Should be a char
|
Self::str_replace_char(
|
||||||
let new_ch = *rhs_val.downcast::<char>().unwrap();
|
s,
|
||||||
Self::str_replace_char(s, idx as usize, new_ch);
|
idx as usize,
|
||||||
|
*rhs_val.downcast::<char>().unwrap(),
|
||||||
|
);
|
||||||
Ok(Box::new(()))
|
Ok(Box::new(()))
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
return Err(EvalAltResult::ErrorIndexExpr);
|
Err(EvalAltResult::ErrorIndexExpr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Expr::Dot(ref dot_lhs, ref dot_rhs) => {
|
Expr::Dot(ref dot_lhs, ref dot_rhs) => {
|
||||||
self.set_dot_val(scope, dot_lhs, dot_rhs, rhs_val)
|
self.set_dot_val(scope, dot_lhs, dot_rhs, rhs_val)
|
||||||
@ -700,7 +710,9 @@ impl Engine {
|
|||||||
_ => Err(EvalAltResult::ErrorAssignmentToUnknownLHS),
|
_ => Err(EvalAltResult::ErrorAssignmentToUnknownLHS),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::Dot(lhs, rhs) => self.get_dot_val(scope, lhs, rhs),
|
Expr::Dot(lhs, rhs) => self.get_dot_val(scope, lhs, rhs),
|
||||||
|
|
||||||
Expr::Array(contents) => {
|
Expr::Array(contents) => {
|
||||||
let mut arr = Vec::new();
|
let mut arr = Vec::new();
|
||||||
|
|
||||||
@ -712,6 +724,7 @@ impl Engine {
|
|||||||
|
|
||||||
Ok(Box::new(arr))
|
Ok(Box::new(arr))
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::FunctionCall(fn_name, args) => self.call_fn_raw(
|
Expr::FunctionCall(fn_name, args) => self.call_fn_raw(
|
||||||
fn_name.to_owned(),
|
fn_name.to_owned(),
|
||||||
args.iter()
|
args.iter()
|
||||||
@ -721,6 +734,7 @@ impl Engine {
|
|||||||
.map(|b| b.as_mut())
|
.map(|b| b.as_mut())
|
||||||
.collect(),
|
.collect(),
|
||||||
),
|
),
|
||||||
|
|
||||||
Expr::True => Ok(Box::new(true)),
|
Expr::True => Ok(Box::new(true)),
|
||||||
Expr::False => Ok(Box::new(false)),
|
Expr::False => Ok(Box::new(false)),
|
||||||
Expr::Unit => Ok(Box::new(())),
|
Expr::Unit => Ok(Box::new(())),
|
||||||
@ -730,12 +744,14 @@ impl Engine {
|
|||||||
fn eval_stmt(&self, scope: &mut Scope, stmt: &Stmt) -> Result<Dynamic, EvalAltResult> {
|
fn eval_stmt(&self, scope: &mut Scope, stmt: &Stmt) -> Result<Dynamic, EvalAltResult> {
|
||||||
match stmt {
|
match stmt {
|
||||||
Stmt::Expr(expr) => self.eval_expr(scope, expr),
|
Stmt::Expr(expr) => self.eval_expr(scope, expr),
|
||||||
|
|
||||||
Stmt::Block(block) => {
|
Stmt::Block(block) => {
|
||||||
let prev_len = scope.len();
|
let prev_len = scope.len();
|
||||||
let mut last_result: Result<Dynamic, EvalAltResult> = Ok(Box::new(()));
|
let mut last_result: Result<Dynamic, EvalAltResult> = Ok(Box::new(()));
|
||||||
|
|
||||||
for block_stmt in block.iter() {
|
for block_stmt in block.iter() {
|
||||||
last_result = self.eval_stmt(scope, block_stmt);
|
last_result = self.eval_stmt(scope, block_stmt);
|
||||||
|
|
||||||
if let Err(x) = last_result {
|
if let Err(x) = last_result {
|
||||||
last_result = Err(x);
|
last_result = Err(x);
|
||||||
break;
|
break;
|
||||||
@ -748,6 +764,7 @@ impl Engine {
|
|||||||
|
|
||||||
last_result
|
last_result
|
||||||
}
|
}
|
||||||
|
|
||||||
Stmt::If(guard, body) => self
|
Stmt::If(guard, body) => self
|
||||||
.eval_expr(scope, guard)?
|
.eval_expr(scope, guard)?
|
||||||
.downcast::<bool>()
|
.downcast::<bool>()
|
||||||
@ -759,6 +776,7 @@ impl Engine {
|
|||||||
Ok(Box::new(()))
|
Ok(Box::new(()))
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
Stmt::IfElse(guard, body, else_body) => self
|
Stmt::IfElse(guard, body, else_body) => self
|
||||||
.eval_expr(scope, guard)?
|
.eval_expr(scope, guard)?
|
||||||
.downcast::<bool>()
|
.downcast::<bool>()
|
||||||
@ -770,6 +788,7 @@ impl Engine {
|
|||||||
self.eval_stmt(scope, else_body)
|
self.eval_stmt(scope, else_body)
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
Stmt::While(guard, body) => loop {
|
Stmt::While(guard, body) => loop {
|
||||||
match self.eval_expr(scope, guard)?.downcast::<bool>() {
|
match self.eval_expr(scope, guard)?.downcast::<bool>() {
|
||||||
Ok(guard_val) => {
|
Ok(guard_val) => {
|
||||||
@ -786,6 +805,7 @@ impl Engine {
|
|||||||
Err(_) => return Err(EvalAltResult::ErrorIfGuard),
|
Err(_) => return Err(EvalAltResult::ErrorIfGuard),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
Stmt::Loop(body) => loop {
|
Stmt::Loop(body) => loop {
|
||||||
match self.eval_stmt(scope, body) {
|
match self.eval_stmt(scope, body) {
|
||||||
Err(EvalAltResult::LoopBreak) => return Ok(Box::new(())),
|
Err(EvalAltResult::LoopBreak) => return Ok(Box::new(())),
|
||||||
@ -793,14 +813,18 @@ impl Engine {
|
|||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
Stmt::For(name, expr, body) => {
|
Stmt::For(name, expr, body) => {
|
||||||
let arr = self.eval_expr(scope, expr)?;
|
let arr = self.eval_expr(scope, expr)?;
|
||||||
let tid = Any::type_id(&*arr);
|
let tid = Any::type_id(&*arr);
|
||||||
|
|
||||||
if let Some(iter_fn) = self.type_iterators.get(&tid) {
|
if let Some(iter_fn) = self.type_iterators.get(&tid) {
|
||||||
scope.push((name.clone(), Box::new(())));
|
scope.push((name.clone(), Box::new(())));
|
||||||
let idx = scope.len() - 1;
|
let idx = scope.len() - 1;
|
||||||
|
|
||||||
for a in iter_fn(&arr) {
|
for a in iter_fn(&arr) {
|
||||||
scope[idx].1 = a;
|
scope[idx].1 = a;
|
||||||
|
|
||||||
match self.eval_stmt(scope, body) {
|
match self.eval_stmt(scope, body) {
|
||||||
Err(EvalAltResult::LoopBreak) => break,
|
Err(EvalAltResult::LoopBreak) => break,
|
||||||
Err(x) => return Err(x),
|
Err(x) => return Err(x),
|
||||||
@ -813,12 +837,16 @@ impl Engine {
|
|||||||
return Err(EvalAltResult::ErrorFor);
|
return Err(EvalAltResult::ErrorFor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Stmt::Break => Err(EvalAltResult::LoopBreak),
|
Stmt::Break => Err(EvalAltResult::LoopBreak),
|
||||||
|
|
||||||
Stmt::Return => Err(EvalAltResult::Return(Box::new(()))),
|
Stmt::Return => Err(EvalAltResult::Return(Box::new(()))),
|
||||||
|
|
||||||
Stmt::ReturnWithVal(a) => {
|
Stmt::ReturnWithVal(a) => {
|
||||||
let result = self.eval_expr(scope, a)?;
|
let result = self.eval_expr(scope, a)?;
|
||||||
Err(EvalAltResult::Return(result))
|
Err(EvalAltResult::Return(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
Stmt::Let(name, init) => {
|
Stmt::Let(name, init) => {
|
||||||
if let Some(v) = init {
|
if let Some(v) = init {
|
||||||
let i = self.eval_expr(scope, v)?;
|
let i = self.eval_expr(scope, v)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user