Skip to content

Commit 5748185

Browse files
committed
FromDynVal-trait
1 parent 7539dda commit 5748185

File tree

2 files changed

+52
-23
lines changed

2 files changed

+52
-23
lines changed

src/dynval.rs

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::ast::Span;
22
use itertools::Itertools;
33
use serde::{Deserialize, Serialize};
4-
use std::{convert::TryFrom, fmt, iter::FromIterator};
4+
use std::{fmt, iter::FromIterator, str::FromStr};
55

66
pub type Result<T> = std::result::Result<T, ConversionError>;
77

@@ -34,7 +34,7 @@ impl From<String> for DynVal {
3434

3535
impl fmt::Display for DynVal {
3636
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
37-
write!(f, "\"{}\"", self.0)
37+
write!(f, "{}", self.0)
3838
}
3939
}
4040
impl fmt::Debug for DynVal {
@@ -70,32 +70,46 @@ impl std::str::FromStr for DynVal {
7070
}
7171
}
7272

73-
macro_rules! impl_try_from {
74-
(impl From<$typ:ty> {
75-
$(for $for:ty => |$arg:ident| $code:expr);*;
76-
}) => {
77-
$(impl TryFrom<$typ> for $for {
78-
type Error = ConversionError;
79-
fn try_from($arg: $typ) -> std::result::Result<Self, Self::Error> { $code }
73+
pub trait FromDynVal: Sized {
74+
type Err;
75+
fn from_dynval(x: &DynVal) -> std::result::Result<Self, Self::Err>;
76+
}
77+
78+
impl<E, T: FromStr<Err = E>> FromDynVal for T {
79+
type Err = E;
80+
81+
fn from_dynval(x: &DynVal) -> std::result::Result<Self, Self::Err> {
82+
x.0.parse()
83+
}
84+
}
85+
86+
macro_rules! impl_from_dynval {
87+
(
88+
$(for $for:ty => |$name:ident| $code:expr);*;
89+
) => {
90+
$(impl FromDynVal for $for {
91+
type Err = ConversionError;
92+
fn from_dynval($name: DynVal) -> std::result::Result<Self, Self::Err> { $code }
8093
})*
8194
};
8295
}
83-
macro_rules! impl_primval_from {
96+
macro_rules! impl_dynval_from {
8497
($($t:ty),*) => {
8598
$(impl From<$t> for DynVal {
8699
fn from(x: $t) -> Self { DynVal(x.to_string(), None) }
87100
})*
88101
};
89102
}
90-
impl_try_from!(impl From<DynVal> {
91-
for String => |x| x.as_string();
92-
for f64 => |x| x.as_f64();
93-
for i32 => |x| x.as_i32();
94-
for bool => |x| x.as_bool();
95-
//for Vec<String> => |x| x.as_vec();
96-
});
97103

98-
impl_primval_from!(bool, i32, u32, f32, u8, f64, &str);
104+
// impl_from_dynval! {
105+
// for String => |x| x.as_string();
106+
// for f64 => |x| x.as_f64();
107+
// for i32 => |x| x.as_i32();
108+
// for bool => |x| x.as_bool();
109+
////for Vec<String> => |x| x.as_vec();
110+
//}
111+
112+
impl_dynval_from!(bool, i32, u32, f32, u8, f64, &str);
99113

100114
impl From<&serde_json::Value> for DynVal {
101115
fn from(v: &serde_json::Value) -> Self {
@@ -118,6 +132,10 @@ impl DynVal {
118132
DynVal(s, None)
119133
}
120134

135+
pub fn read_as<E, T: FromDynVal<Err = E>>(&self) -> std::result::Result<T, E> {
136+
T::from_dynval(self)
137+
}
138+
121139
pub fn into_inner(self) -> String {
122140
self.0
123141
}

src/eval.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ use std::collections::HashMap;
88

99
#[derive(Debug, thiserror::Error)]
1010
pub enum EvalError {
11+
#[error("Tried to reference variable `{0}`, but we cannot access variables here")]
12+
NoVariablesAllowed(String),
13+
1114
#[error("Invalid regex: {0}")]
1215
InvalidRegex(#[from] regex::Error),
1316

@@ -114,12 +117,20 @@ impl SimplExpr {
114117
}
115118
}
116119

117-
pub fn eval(self, values: &HashMap<VarName, DynVal>) -> Result<DynVal, EvalError> {
120+
pub fn eval_no_vars(&self) -> Result<DynVal, EvalError> {
121+
match self.eval(&HashMap::new()) {
122+
Ok(x) => Ok(x),
123+
Err(EvalError::UnknownVariable(name)) => Err(EvalError::NoVariablesAllowed(name)),
124+
Err(x) => Err(x),
125+
}
126+
}
127+
128+
pub fn eval(&self, values: &HashMap<VarName, DynVal>) -> Result<DynVal, EvalError> {
118129
let span = self.span();
119130
let value = match self {
120-
SimplExpr::Literal(_, x) => Ok(x),
131+
SimplExpr::Literal(_, x) => Ok(x.clone()),
121132
SimplExpr::VarRef(span, ref name) => {
122-
Ok(values.get(name).cloned().ok_or_else(|| EvalError::UnresolvedVariable(name.to_string()).at(span))?.at(span))
133+
Ok(values.get(name).cloned().ok_or_else(|| EvalError::UnresolvedVariable(name.to_string()).at(*span))?.at(*span))
123134
}
124135
SimplExpr::BinOp(_, a, op, b) => {
125136
let a = a.eval(values)?;
@@ -176,12 +187,12 @@ impl SimplExpr {
176187
.unwrap_or(&serde_json::Value::Null);
177188
Ok(DynVal::from(indexed_value))
178189
}
179-
_ => Err(EvalError::CannotIndex(format!("{}", val)).at(span)),
190+
_ => Err(EvalError::CannotIndex(format!("{}", val)).at(*span)),
180191
}
181192
}
182193
SimplExpr::FunctionCall(span, function_name, args) => {
183194
let args = args.into_iter().map(|a| a.eval(values)).collect::<Result<_, EvalError>>()?;
184-
call_expr_function(&function_name, args).map_err(|e| e.at(span))
195+
call_expr_function(&function_name, args).map_err(|e| e.at(*span))
185196
}
186197
};
187198
Ok(value?.at(span))

0 commit comments

Comments
 (0)