Change Dynamic::from_xxx to From<xxx> impl.

This commit is contained in:
Stephen Chung 2020-04-22 12:12:13 +08:00
parent 69733688bf
commit c69647d9fd
5 changed files with 79 additions and 98 deletions

View File

@ -492,30 +492,36 @@ impl Dynamic {
_ => Err(self.type_name()), _ => Err(self.type_name()),
} }
} }
}
/// Create a `Dynamic` from `()`. impl From<()> for Dynamic {
pub fn from_unit() -> Self { fn from(value: ()) -> Self {
Self(Union::Unit(())) Self(Union::Unit(value))
} }
/// Create a `Dynamic` from a `bool`. }
pub fn from_bool(value: bool) -> Self { impl From<bool> for Dynamic {
fn from(value: bool) -> Self {
Self(Union::Bool(value)) Self(Union::Bool(value))
} }
/// Create a `Dynamic` from an `INT`. }
pub fn from_int(value: INT) -> Self { impl From<INT> for Dynamic {
fn from(value: INT) -> Self {
Self(Union::Int(value)) Self(Union::Int(value))
} }
/// Create a `Dynamic` from a `FLOAT`. Not available under `no_float`. }
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
pub(crate) fn from_float(value: FLOAT) -> Self { impl From<FLOAT> for Dynamic {
fn from(value: FLOAT) -> Self {
Self(Union::Float(value)) Self(Union::Float(value))
} }
/// Create a `Dynamic` from a `char`. }
pub fn from_char(value: char) -> Self { impl From<char> for Dynamic {
fn from(value: char) -> Self {
Self(Union::Char(value)) Self(Union::Char(value))
} }
/// Create a `Dynamic` from a `String`. }
pub fn from_string(value: String) -> Self { impl From<String> for Dynamic {
fn from(value: String) -> Self {
Self(Union::Str(Box::new(value))) Self(Union::Str(Box::new(value)))
} }
} }

View File

@ -803,7 +803,7 @@ impl Engine {
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
ast.0 ast.0
.iter() .iter()
.try_fold(Dynamic::from_unit(), |_, stmt| { .try_fold(().into(), |_, stmt| {
self.eval_stmt(scope, Some(ast.1.as_ref()), stmt, 0) self.eval_stmt(scope, Some(ast.1.as_ref()), stmt, 0)
}) })
.or_else(|err| match *err { .or_else(|err| match *err {
@ -866,7 +866,7 @@ impl Engine {
) -> Result<(), Box<EvalAltResult>> { ) -> Result<(), Box<EvalAltResult>> {
ast.0 ast.0
.iter() .iter()
.try_fold(Dynamic::from_unit(), |_, stmt| { .try_fold(().into(), |_, stmt| {
self.eval_stmt(scope, Some(ast.1.as_ref()), stmt, 0) self.eval_stmt(scope, Some(ast.1.as_ref()), stmt, 0)
}) })
.map_or_else( .map_or_else(

View File

@ -442,7 +442,7 @@ fn update_indexed_scope_var(
_ => panic!("invalid type for indexing: {}", target.type_name()), _ => panic!("invalid type for indexing: {}", target.type_name()),
} }
Ok(Dynamic::from_unit()) Ok(().into())
} }
impl Engine { impl Engine {
@ -600,13 +600,13 @@ impl Engine {
return match fn_name { return match fn_name {
KEYWORD_PRINT if self.on_print.is_some() => { KEYWORD_PRINT if self.on_print.is_some() => {
self.on_print.as_ref().unwrap()(cast_to_string(&result, pos)?); self.on_print.as_ref().unwrap()(cast_to_string(&result, pos)?);
Ok(Dynamic::from_unit()) Ok(().into())
} }
KEYWORD_DEBUG if self.on_debug.is_some() => { KEYWORD_DEBUG if self.on_debug.is_some() => {
self.on_debug.as_ref().unwrap()(cast_to_string(&result, pos)?); self.on_debug.as_ref().unwrap()(cast_to_string(&result, pos)?);
Ok(Dynamic::from_unit()) Ok(().into())
} }
KEYWORD_PRINT | KEYWORD_DEBUG => Ok(Dynamic::from_unit()), KEYWORD_PRINT | KEYWORD_DEBUG => Ok(().into()),
_ => Ok(result), _ => Ok(result),
}; };
} }
@ -614,10 +614,7 @@ impl Engine {
if let Some(prop) = extract_prop_from_getter(fn_name) { if let Some(prop) = extract_prop_from_getter(fn_name) {
return match args[0] { return match args[0] {
// Map property access // Map property access
Dynamic(Union::Map(map)) => Ok(map Dynamic(Union::Map(map)) => Ok(map.get(prop).cloned().unwrap_or_else(|| ().into())),
.get(prop)
.cloned()
.unwrap_or_else(|| Dynamic::from_unit())),
// Getter function not found // Getter function not found
_ => Err(Box::new(EvalAltResult::ErrorDotExpr( _ => Err(Box::new(EvalAltResult::ErrorDotExpr(
@ -634,7 +631,7 @@ impl Engine {
// Map property update // Map property update
Dynamic(Union::Map(map)) => { Dynamic(Union::Map(map)) => {
map.insert(prop.to_string(), value[0].clone()); map.insert(prop.to_string(), value[0].clone());
Ok(Dynamic::from_unit()) Ok(().into())
} }
// Setter function not found // Setter function not found
@ -853,11 +850,7 @@ impl Engine {
arr.get(index as usize) arr.get(index as usize)
.map(|v| { .map(|v| {
( (
if only_index { if only_index { ().into() } else { v.clone() },
Dynamic::from_unit()
} else {
v.clone()
},
IndexValue::from_num(index), IndexValue::from_num(index),
) )
}) })
@ -880,14 +873,8 @@ impl Engine {
Ok(( Ok((
map.get(&index) map.get(&index)
.map(|v| { .map(|v| if only_index { ().into() } else { v.clone() })
if only_index { .unwrap_or_else(|| ().into()),
Dynamic::from_unit()
} else {
v.clone()
}
})
.unwrap_or_else(|| Dynamic::from_unit()),
IndexValue::from_str(index), IndexValue::from_str(index),
)) ))
} }
@ -904,7 +891,7 @@ impl Engine {
if index >= 0 { if index >= 0 {
s.chars() s.chars()
.nth(index as usize) .nth(index as usize)
.map(|ch| (Dynamic::from_char(ch), IndexValue::from_num(index))) .map(|ch| (ch.into(), IndexValue::from_num(index)))
.ok_or_else(|| { .ok_or_else(|| {
Box::new(EvalAltResult::ErrorStringBounds(num_chars, index, idx_pos)) Box::new(EvalAltResult::ErrorStringBounds(num_chars, index, idx_pos))
}) })
@ -1152,7 +1139,7 @@ impl Engine {
match rhs_value { match rhs_value {
Dynamic(Union::Array(mut rhs_value)) => { Dynamic(Union::Array(mut rhs_value)) => {
let def_value = Dynamic::from_bool(false); let def_value = false.into();
let mut result = false; let mut result = false;
// Call the '==' operator to compare each value // Call the '==' operator to compare each value
@ -1169,27 +1156,21 @@ impl Engine {
} }
} }
Ok(Dynamic::from_bool(result)) Ok(result.into())
} }
Dynamic(Union::Map(rhs_value)) => { Dynamic(Union::Map(rhs_value)) => {
// Only allows String or char // Only allows String or char
match lhs_value { match lhs_value {
Dynamic(Union::Str(s)) => { Dynamic(Union::Str(s)) => Ok(rhs_value.contains_key(s.as_ref()).into()),
Ok(Dynamic::from_bool(rhs_value.contains_key(s.as_ref()))) Dynamic(Union::Char(c)) => Ok(rhs_value.contains_key(&c.to_string()).into()),
}
Dynamic(Union::Char(c)) => {
Ok(Dynamic::from_bool(rhs_value.contains_key(&c.to_string())))
}
_ => Err(Box::new(EvalAltResult::ErrorInExpr(lhs.position()))), _ => Err(Box::new(EvalAltResult::ErrorInExpr(lhs.position()))),
} }
} }
Dynamic(Union::Str(rhs_value)) => { Dynamic(Union::Str(rhs_value)) => {
// Only allows String or char // Only allows String or char
match lhs_value { match lhs_value {
Dynamic(Union::Str(s)) => { Dynamic(Union::Str(s)) => Ok(rhs_value.contains(s.as_ref()).into()),
Ok(Dynamic::from_bool(rhs_value.contains(s.as_ref()))) Dynamic(Union::Char(c)) => Ok(rhs_value.contains(c).into()),
}
Dynamic(Union::Char(c)) => Ok(Dynamic::from_bool(rhs_value.contains(c))),
_ => Err(Box::new(EvalAltResult::ErrorInExpr(lhs.position()))), _ => Err(Box::new(EvalAltResult::ErrorInExpr(lhs.position()))),
} }
} }
@ -1206,11 +1187,11 @@ impl Engine {
level: usize, level: usize,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
match expr { match expr {
Expr::IntegerConstant(i, _) => Ok(Dynamic::from_int(*i)), Expr::IntegerConstant(i, _) => Ok((*i).into()),
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Expr::FloatConstant(f, _) => Ok(Dynamic::from_float(*f)), Expr::FloatConstant(f, _) => Ok((*f).into()),
Expr::StringConstant(s, _) => Ok(Dynamic::from_string(s.to_string())), Expr::StringConstant(s, _) => Ok(s.to_string().into()),
Expr::CharConstant(c, _) => Ok(Dynamic::from_char(*c)), Expr::CharConstant(c, _) => Ok((*c).into()),
Expr::Variable(id, pos) => 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."),
@ -1363,9 +1344,7 @@ impl Engine {
&& !has_override(self, fn_lib, KEYWORD_TYPE_OF) => && !has_override(self, fn_lib, KEYWORD_TYPE_OF) =>
{ {
let result = self.eval_expr(scope, fn_lib, &args_expr_list[0], level)?; let result = self.eval_expr(scope, fn_lib, &args_expr_list[0], level)?;
Ok(Dynamic::from_string( Ok(self.map_type_name(result.type_name()).to_string().into())
self.map_type_name(result.type_name()).to_string(),
))
} }
// eval // eval
@ -1430,8 +1409,7 @@ impl Engine {
self.eval_in_expr(scope, fn_lib, lhs.as_ref(), rhs.as_ref(), level) self.eval_in_expr(scope, fn_lib, lhs.as_ref(), rhs.as_ref(), level)
} }
Expr::And(lhs, rhs, _) => Ok(Dynamic::from_bool( Expr::And(lhs, rhs, _) => Ok((self
self
.eval_expr(scope, fn_lib,lhs.as_ref(), level)? .eval_expr(scope, fn_lib,lhs.as_ref(), level)?
.as_bool() .as_bool()
.map_err(|_| { .map_err(|_| {
@ -1443,11 +1421,10 @@ impl Engine {
.as_bool() .as_bool()
.map_err(|_| { .map_err(|_| {
EvalAltResult::ErrorBooleanArgMismatch("AND".into(), rhs.position()) EvalAltResult::ErrorBooleanArgMismatch("AND".into(), rhs.position())
})?, })?)
)), .into()),
Expr::Or(lhs, rhs, _) => Ok(Dynamic::from_bool( Expr::Or(lhs, rhs, _) => Ok((self
self
.eval_expr(scope,fn_lib, lhs.as_ref(), level)? .eval_expr(scope,fn_lib, lhs.as_ref(), level)?
.as_bool() .as_bool()
.map_err(|_| { .map_err(|_| {
@ -1459,12 +1436,12 @@ impl Engine {
.as_bool() .as_bool()
.map_err(|_| { .map_err(|_| {
EvalAltResult::ErrorBooleanArgMismatch("OR".into(), rhs.position()) EvalAltResult::ErrorBooleanArgMismatch("OR".into(), rhs.position())
})?, })?)
)), .into()),
Expr::True(_) => Ok(Dynamic::from_bool(true)), Expr::True(_) => Ok(true.into()),
Expr::False(_) => Ok(Dynamic::from_bool(false)), Expr::False(_) => Ok(false.into()),
Expr::Unit(_) => Ok(Dynamic::from_unit()), Expr::Unit(_) => Ok(().into()),
_ => panic!("should not appear: {:?}", expr), _ => panic!("should not appear: {:?}", expr),
} }
@ -1480,7 +1457,7 @@ impl Engine {
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
match stmt { match stmt {
// No-op // No-op
Stmt::Noop(_) => Ok(Dynamic::from_unit()), Stmt::Noop(_) => Ok(().into()),
// Expression as statement // Expression as statement
Stmt::Expr(expr) => { Stmt::Expr(expr) => {
@ -1490,7 +1467,7 @@ impl Engine {
result result
} else { } else {
// If it is an assignment, erase the result at the root // If it is an assignment, erase the result at the root
Dynamic::from_unit() ().into()
}) })
} }
@ -1498,7 +1475,7 @@ impl Engine {
Stmt::Block(block, _) => { Stmt::Block(block, _) => {
let prev_len = scope.len(); let prev_len = scope.len();
let result = block.iter().try_fold(Dynamic::from_unit(), |_, stmt| { let result = block.iter().try_fold(().into(), |_, stmt| {
self.eval_stmt(scope, fn_lib, stmt, level) self.eval_stmt(scope, fn_lib, stmt, level)
}); });
@ -1518,7 +1495,7 @@ impl Engine {
} else if let Some(stmt) = else_body { } else if let Some(stmt) = else_body {
self.eval_stmt(scope, fn_lib, stmt.as_ref(), level) self.eval_stmt(scope, fn_lib, stmt.as_ref(), level)
} else { } else {
Ok(Dynamic::from_unit()) Ok(().into())
} }
}), }),
@ -1529,13 +1506,11 @@ impl Engine {
Ok(_) => (), Ok(_) => (),
Err(err) => match *err { Err(err) => match *err {
EvalAltResult::ErrorLoopBreak(false, _) => (), EvalAltResult::ErrorLoopBreak(false, _) => (),
EvalAltResult::ErrorLoopBreak(true, _) => { EvalAltResult::ErrorLoopBreak(true, _) => return Ok(().into()),
return Ok(Dynamic::from_unit())
}
_ => return Err(err), _ => return Err(err),
}, },
}, },
Ok(false) => return Ok(Dynamic::from_unit()), Ok(false) => return Ok(().into()),
Err(_) => { Err(_) => {
return Err(Box::new(EvalAltResult::ErrorLogicGuard(guard.position()))) return Err(Box::new(EvalAltResult::ErrorLogicGuard(guard.position())))
} }
@ -1548,7 +1523,7 @@ impl Engine {
Ok(_) => (), Ok(_) => (),
Err(err) => match *err { Err(err) => match *err {
EvalAltResult::ErrorLoopBreak(false, _) => (), EvalAltResult::ErrorLoopBreak(false, _) => (),
EvalAltResult::ErrorLoopBreak(true, _) => return Ok(Dynamic::from_unit()), EvalAltResult::ErrorLoopBreak(true, _) => return Ok(().into()),
_ => return Err(err), _ => return Err(err),
}, },
} }
@ -1589,7 +1564,7 @@ impl Engine {
} }
scope.rewind(scope.len() - 1); scope.rewind(scope.len() - 1);
Ok(Dynamic::from_unit()) Ok(().into())
} else { } else {
Err(Box::new(EvalAltResult::ErrorFor(expr.position()))) Err(Box::new(EvalAltResult::ErrorFor(expr.position())))
} }
@ -1603,7 +1578,7 @@ impl Engine {
// Empty return // Empty return
Stmt::ReturnWithVal(None, ReturnType::Return, pos) => { Stmt::ReturnWithVal(None, ReturnType::Return, pos) => {
Err(Box::new(EvalAltResult::Return(Dynamic::from_unit(), *pos))) Err(Box::new(EvalAltResult::Return(().into(), *pos)))
} }
// Return value // Return value
@ -1630,13 +1605,13 @@ impl Engine {
let val = self.eval_expr(scope, fn_lib, expr, level)?; let val = self.eval_expr(scope, fn_lib, expr, level)?;
// TODO - avoid copying variable name in inner block? // TODO - avoid copying variable name in inner block?
scope.push_dynamic_value(name.clone(), ScopeEntryType::Normal, val, false); scope.push_dynamic_value(name.clone(), ScopeEntryType::Normal, val, false);
Ok(Dynamic::from_unit()) Ok(().into())
} }
Stmt::Let(name, None, _) => { Stmt::Let(name, None, _) => {
// TODO - avoid copying variable name in inner block? // TODO - avoid copying variable name in inner block?
scope.push(name.clone(), ()); scope.push(name.clone(), ());
Ok(Dynamic::from_unit()) Ok(().into())
} }
// Const statement // Const statement
@ -1644,7 +1619,7 @@ impl Engine {
let val = self.eval_expr(scope, fn_lib, expr, level)?; let val = self.eval_expr(scope, fn_lib, expr, level)?;
// TODO - avoid copying variable name in inner block? // TODO - avoid copying variable name in inner block?
scope.push_dynamic_value(name.clone(), ScopeEntryType::Constant, val, true); scope.push_dynamic_value(name.clone(), ScopeEntryType::Constant, val, true);
Ok(Dynamic::from_unit()) Ok(().into())
} }
Stmt::Const(_, _, _) => panic!("constant expression not constant!"), Stmt::Const(_, _, _) => panic!("constant expression not constant!"),

View File

@ -592,7 +592,7 @@ fn optimize_expr<'a>(expr: Expr, state: &mut State<'a>) -> Expr {
result.or_else(|| { result.or_else(|| {
if !arg_for_type_of.is_empty() { if !arg_for_type_of.is_empty() {
// Handle `type_of()` // Handle `type_of()`
Some(Dynamic::from_string(arg_for_type_of.to_string())) Some(arg_for_type_of.to_string().into())
} else { } else {
// Otherwise use the default value, if any // Otherwise use the default value, if any
def_value.clone() def_value.clone()

View File

@ -321,14 +321,14 @@ impl Expr {
/// Panics when the expression is not constant. /// Panics when the expression is not constant.
pub fn get_constant_value(&self) -> Dynamic { pub fn get_constant_value(&self) -> Dynamic {
match self { match self {
Self::IntegerConstant(i, _) => Dynamic::from_int(*i), Self::IntegerConstant(i, _) => (*i).into(),
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
Self::FloatConstant(f, _) => Dynamic::from_float(*f), Self::FloatConstant(f, _) => (*f).into(),
Self::CharConstant(c, _) => Dynamic::from_char(*c), Self::CharConstant(c, _) => (*c).into(),
Self::StringConstant(s, _) => Dynamic::from_string(s.to_string()), Self::StringConstant(s, _) => s.to_string().into(),
Self::True(_) => Dynamic::from_bool(true), Self::True(_) => true.into(),
Self::False(_) => Dynamic::from_bool(false), Self::False(_) => false.into(),
Self::Unit(_) => Dynamic::from_unit(), Self::Unit(_) => ().into(),
Self::Array(items, _) if items.iter().all(Self::is_constant) => { Self::Array(items, _) if items.iter().all(Self::is_constant) => {
Dynamic(Union::Array(Box::new( Dynamic(Union::Array(Box::new(
@ -996,7 +996,7 @@ fn parse_unary<'a>(
Ok(Expr::FunctionCall( Ok(Expr::FunctionCall(
"!".into(), "!".into(),
vec![parse_primary(input, allow_stmt_expr)?], vec![parse_primary(input, allow_stmt_expr)?],
Some(Dynamic::from_bool(false)), // NOT operator, when operating on invalid operand, defaults to false Some(false.into()), // NOT operator, when operating on invalid operand, defaults to false
pos, pos,
)) ))
} }
@ -1304,37 +1304,37 @@ fn parse_binary_op<'a>(
Token::EqualsTo => Expr::FunctionCall( Token::EqualsTo => Expr::FunctionCall(
"==".into(), "==".into(),
vec![current_lhs, rhs], vec![current_lhs, rhs],
Some(Dynamic::from_bool(false)), Some(false.into()),
pos, pos,
), ),
Token::NotEqualsTo => Expr::FunctionCall( Token::NotEqualsTo => Expr::FunctionCall(
"!=".into(), "!=".into(),
vec![current_lhs, rhs], vec![current_lhs, rhs],
Some(Dynamic::from_bool(false)), Some(false.into()),
pos, pos,
), ),
Token::LessThan => Expr::FunctionCall( Token::LessThan => Expr::FunctionCall(
"<".into(), "<".into(),
vec![current_lhs, rhs], vec![current_lhs, rhs],
Some(Dynamic::from_bool(false)), Some(false.into()),
pos, pos,
), ),
Token::LessThanEqualsTo => Expr::FunctionCall( Token::LessThanEqualsTo => Expr::FunctionCall(
"<=".into(), "<=".into(),
vec![current_lhs, rhs], vec![current_lhs, rhs],
Some(Dynamic::from_bool(false)), Some(false.into()),
pos, pos,
), ),
Token::GreaterThan => Expr::FunctionCall( Token::GreaterThan => Expr::FunctionCall(
">".into(), ">".into(),
vec![current_lhs, rhs], vec![current_lhs, rhs],
Some(Dynamic::from_bool(false)), Some(false.into()),
pos, pos,
), ),
Token::GreaterThanEqualsTo => Expr::FunctionCall( Token::GreaterThanEqualsTo => Expr::FunctionCall(
">=".into(), ">=".into(),
vec![current_lhs, rhs], vec![current_lhs, rhs],
Some(Dynamic::from_bool(false)), Some(false.into()),
pos, pos,
), ),