difftreelog
perf lesser and cheaper clones
in: master
11 files changed
cmds/jrsonnet/src/main.rsdiffbeforeafterboth--- a/cmds/jrsonnet/src/main.rs
+++ b/cmds/jrsonnet/src/main.rs
@@ -5,7 +5,7 @@
use jsonnet_parser::{el, Arg, ArgsDesc, Expr, LocExpr, ParserSettings};
use location::{offset_to_location, CodeLocation};
use std::env::current_dir;
-use std::{collections::HashMap, path::PathBuf, str::FromStr};
+use std::{collections::HashMap, path::PathBuf, str::FromStr, rc::Rc};
enum Format {
None,
@@ -128,10 +128,10 @@
evaluator.with_stdlib();
}
for ExtStr { name, value } in opts.ext_str.iter().cloned() {
- evaluator.add_ext_var(name, Val::Str(value));
+ evaluator.add_ext_var(name.into(), Val::Str(value.into()));
}
for ExtStr { name, value } in opts.ext_code.iter().cloned() {
- evaluator.add_ext_var(name, evaluator.parse_evaluate_raw(&value).unwrap());
+ evaluator.add_ext_var(name.into(), evaluator.parse_evaluate_raw(&value).unwrap());
}
let mut input = current_dir().unwrap();
input.push(opts.input.clone());
@@ -147,7 +147,7 @@
Val::Func(f) => {
let mut desc_map = HashMap::new();
for ExtStr { name, value } in opts.tla_str.iter().cloned() {
- desc_map.insert(name, el!(Expr::Str(value)));
+ desc_map.insert(name, el!(Expr::Str(value.into())));
}
for ExtStr { name, value } in opts.tla_code.iter().cloned() {
desc_map.insert(
@@ -155,17 +155,17 @@
jsonnet_parser::parse(
&value,
&ParserSettings {
- file_name: PathBuf::new(),
+ file_name: Rc::new(PathBuf::new()),
loc_data: false,
},
)
.unwrap(),
);
}
- evaluator.add_global("__tmp__tlf__".to_owned(), Val::Func(f));
+ evaluator.add_global("__tmp__tlf__".into(), Val::Func(f));
evaluator
.evaluate_raw(el!(Expr::Apply(
- el!(Expr::Var("__tmp__tlf__".to_owned())),
+ el!(Expr::Var("__tmp__tlf__".into())),
ArgsDesc(desc_map.into_iter().map(|(k, v)| Arg(Some(k), v)).collect()),
false,
)))
@@ -178,7 +178,7 @@
if opts.no_stdlib {
evaluator.with_stdlib();
}
- evaluator.add_global("__tmp__to_json__".to_owned(), v);
+ evaluator.add_global("__tmp__to_json__".into(), v);
let v = evaluator.parse_evaluate_raw(&format!(
"std.manifestJsonEx(__tmp__to_json__, \"{}\")",
" ".repeat(opts.line_padding),
@@ -195,7 +195,7 @@
if opts.no_stdlib {
evaluator.with_stdlib();
}
- evaluator.add_global("__tmp__to_yaml__".to_owned(), v);
+ evaluator.add_global("__tmp__to_yaml__".into(), v);
let v = evaluator
.parse_evaluate_raw("std.manifestYamlDoc(__tmp__to_yaml__, \" \")");
match v {
crates/jsonnet-evaluator/build.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/build.rs
+++ b/crates/jsonnet-evaluator/build.rs
@@ -34,7 +34,7 @@
Member::Field(FieldMember {
name: FieldName::Fixed(name),
..
- }) if name == "join"
+ }) if **name == *"join"
)
})
.collect(),
crates/jsonnet-evaluator/src/ctx.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/ctx.rs
+++ b/crates/jsonnet-evaluator/src/ctx.rs
@@ -16,7 +16,7 @@
dollar: Option<ObjValue>,
this: Option<ObjValue>,
super_obj: Option<ObjValue>,
- bindings: LayeredHashMap<String, LazyVal>,
+ bindings: LayeredHashMap<Rc<str>, LazyVal>,
}
pub struct Context(Rc<ContextInternals>);
impl Debug for Context {
@@ -53,9 +53,9 @@
}))
}
- pub fn binding(&self, name: &str) -> Result<LazyVal> {
- self.0.bindings.get(name).cloned().ok_or_else(|| {
- create_error::<()>(Error::UnknownVariable(name.to_owned()))
+ pub fn binding(&self, name: Rc<str>) -> Result<LazyVal> {
+ self.0.bindings.get(&name).cloned().ok_or_else(|| {
+ create_error::<()>(Error::UnknownVariable(name))
.err()
.unwrap()
})
@@ -67,7 +67,7 @@
ctx.unwrap()
}
- pub fn with_var(&self, name: String, value: Val) -> Result<Context> {
+ pub fn with_var(&self, name: Rc<str>, value: Val) -> Result<Context> {
let mut new_bindings = HashMap::with_capacity(1);
new_bindings.insert(name, resolved_lazy_val!(value));
self.extend(new_bindings, None, None, None)
@@ -75,7 +75,7 @@
pub fn extend(
&self,
- new_bindings: HashMap<String, LazyVal>,
+ new_bindings: HashMap<Rc<str>, LazyVal>,
new_dollar: Option<ObjValue>,
new_this: Option<ObjValue>,
new_super_obj: Option<ObjValue>,
@@ -97,7 +97,7 @@
}
pub fn extend_unbound(
&self,
- new_bindings: HashMap<String, LazyBinding>,
+ new_bindings: HashMap<Rc<str>, LazyBinding>,
new_dollar: Option<ObjValue>,
new_this: Option<ObjValue>,
new_super_obj: Option<ObjValue>,
crates/jsonnet-evaluator/src/error.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/error.rs
+++ b/crates/jsonnet-evaluator/src/error.rs
@@ -6,20 +6,20 @@
pub enum Error {
VariableIsNotDefined(String),
TypeMismatch(&'static str, Vec<ValType>, ValType),
- NoSuchField(String),
+ NoSuchField(Rc<str>),
- UnknownVariable(String),
+ UnknownVariable(Rc<str>),
UnknownFunctionParameter(String),
- BindingParameterASecondTime(String),
+ BindingParameterASecondTime(Rc<str>),
TooManyArgsFunctionHas(usize),
- FunctionParameterNotBoundInCall(String),
+ FunctionParameterNotBoundInCall(Rc<str>),
- UndefinedExternalVariable(String),
+ UndefinedExternalVariable(Rc<str>),
FieldMustBeStringGot(ValType),
- AttemptedIndexAnArrayWithString(String),
+ AttemptedIndexAnArrayWithString(Rc<str>),
ValueIndexMustBeTypeGot(ValType, ValType, ValType),
CantIndexInto(ValType),
@@ -31,7 +31,7 @@
ImportNotSupported(PathBuf, PathBuf),
ImportSyntaxError(jsonnet_parser::ParseError),
- RuntimeError(String),
+ RuntimeError(Rc<str>),
StackOverflow,
FractionalIndex,
DivisionByZero,
crates/jsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/evaluate.rs
+++ b/crates/jsonnet-evaluator/src/evaluate.rs
@@ -14,7 +14,7 @@
rc::Rc,
};
-pub fn evaluate_binding(b: &BindSpec, context_creator: ContextCreator) -> (String, LazyBinding) {
+pub fn evaluate_binding(b: &BindSpec, context_creator: ContextCreator) -> (Rc<str>, LazyBinding) {
let b = b.clone();
if let Some(params) = &b.params {
let params = params.clone();
@@ -54,11 +54,12 @@
pub fn evaluate_field_name(
context: Context,
field_name: &jsonnet_parser::FieldName,
-) -> Result<Option<String>> {
+) -> Result<Option<Rc<str>>> {
Ok(match field_name {
jsonnet_parser::FieldName::Fixed(n) => Some(n.clone()),
jsonnet_parser::FieldName::Dyn(expr) => {
- let value = evaluate(context, expr)?.unwrap_if_lazy()?;
+ let lazy = evaluate(context, expr)?;
+ let value = lazy.unwrap_if_lazy()?;
if matches!(value, Val::Null) {
None
} else {
@@ -80,17 +81,17 @@
pub(crate) fn evaluate_add_op(a: &Val, b: &Val) -> Result<Val> {
Ok(match (a, b) {
- (Val::Str(v1), Val::Str(v2)) => Val::Str(v1.to_owned() + &v2),
+ (Val::Str(v1), Val::Str(v2)) => Val::Str(((**v1).to_owned() + &v2).into()),
// Can't use generic json serialization way, because it depends on number to string concatenation (std.jsonnet:890)
- (Val::Num(n), Val::Str(o)) => Val::Str(format!("{}{}", n, o)),
- (Val::Str(o), Val::Num(n)) => Val::Str(format!("{}{}", o, n)),
+ (Val::Num(n), Val::Str(o)) => Val::Str(format!("{}{}", n, o).into()),
+ (Val::Str(o), Val::Num(n)) => Val::Str(format!("{}{}", o, n).into()),
- (Val::Str(s), o) => Val::Str(format!("{}{}", s, o.clone().into_json(0)?)),
- (o, Val::Str(s)) => Val::Str(format!("{}{}", o.clone().into_json(0)?, s)),
+ (Val::Str(s), o) => Val::Str(format!("{}{}", s, o.clone().into_json(0)?).into()),
+ (o, Val::Str(s)) => Val::Str(format!("{}{}", o.clone().into_json(0)?, s).into()),
(Val::Obj(v1), Val::Obj(v2)) => Val::Obj(v2.with_super(v1.clone())),
- (Val::Arr(a), Val::Arr(b)) => Val::Arr([&a[..], &b[..]].concat()),
+ (Val::Arr(a), Val::Arr(b)) => Val::Arr(Rc::new([&a[..], &b[..]].concat())),
(Val::Num(v1), Val::Num(v2)) => Val::Num(v1 + v2),
_ => panic!("can't add: {:?} and {:?}", a, b),
})
@@ -117,7 +118,7 @@
Ok(match (a, op, b) {
(a, BinaryOpType::Add, b) => evaluate_add_op(a, b)?,
- (Val::Str(v1), BinaryOpType::Mul, Val::Num(v2)) => Val::Str(v1.repeat(*v2 as usize)),
+ (Val::Str(v1), BinaryOpType::Mul, Val::Num(v2)) => Val::Str(v1.repeat(*v2 as usize).into()),
// Bool X Bool
(Val::Bool(a), BinaryOpType::And, Val::Bool(b)) => Val::Bool(*a && *b),
@@ -165,7 +166,7 @@
})
}
-future_wrapper!(HashMap<String, LazyBinding>, FutureNewBindings);
+future_wrapper!(HashMap<Rc<str>, LazyBinding>, FutureNewBindings);
future_wrapper!(ObjValue, FutureObjValue);
pub fn evaluate_comp<T>(
@@ -186,10 +187,10 @@
match evaluate(context.clone(), &expr)?.unwrap_if_lazy()? {
Val::Arr(list) => {
let mut out = Vec::new();
- for item in list {
- let item = item.clone().unwrap_if_lazy()?;
+ for item in list.iter() {
+ let item = item.unwrap_if_lazy()?;
out.push(evaluate_comp(
- context.with_var(var.clone(), item)?,
+ context.with_var(var.clone(), item.clone())?,
value,
&specs[1..],
)?);
@@ -202,113 +203,108 @@
})
}
-// TODO: Asserts
-pub fn evaluate_object(context: Context, object: ObjBody) -> Result<ObjValue> {
- Ok(match object {
- ObjBody::MemberList(members) => {
- let new_bindings = FutureNewBindings::new();
- let future_this = FutureObjValue::new();
- let context_creator = context_creator!(
- closure!(clone context, clone new_bindings, |this: Option<ObjValue>, super_obj: Option<ObjValue>| {
- Ok(context.extend_unbound(
- new_bindings.clone().unwrap(),
- context.dollar().clone().or_else(||this.clone()),
- Some(this.unwrap()),
- super_obj
- )?)
- })
- );
- {
- let mut bindings: HashMap<String, LazyBinding> = HashMap::new();
- for (n, b) in members
- .iter()
- .filter_map(|m| match m {
- Member::BindStmt(b) => Some(b.clone()),
- _ => None,
- })
- .map(|b| evaluate_binding(&b, context_creator.clone()))
- {
- bindings.insert(n, b);
+pub fn evaluate_member_list_object(context: Context, members: &Vec<Member>) -> Result<ObjValue> {
+ let new_bindings = FutureNewBindings::new();
+ let future_this = FutureObjValue::new();
+ let context_creator = context_creator!(
+ closure!(clone context, clone new_bindings, |this: Option<ObjValue>, super_obj: Option<ObjValue>| {
+ Ok(context.extend_unbound(
+ new_bindings.clone().unwrap(),
+ context.dollar().clone().or_else(||this.clone()),
+ Some(this.unwrap()),
+ super_obj
+ )?)
+ })
+ );
+ {
+ let mut bindings: HashMap<Rc<str>, LazyBinding> = HashMap::new();
+ for (n, b) in members
+ .iter()
+ .filter_map(|m| match m {
+ Member::BindStmt(b) => Some(b.clone()),
+ _ => None,
+ })
+ .map(|b| evaluate_binding(&b, context_creator.clone()))
+ {
+ bindings.insert(n, b);
+ }
+ new_bindings.fill(bindings);
+ }
+
+ let mut new_members = BTreeMap::new();
+ for member in members.iter() {
+ match member {
+ Member::Field(FieldMember {
+ name,
+ plus,
+ params: None,
+ visibility,
+ value,
+ }) => {
+ let name = evaluate_field_name(context.clone(), &name)?;
+ if name.is_none() {
+ continue;
}
- new_bindings.fill(bindings);
+ let name = name.unwrap();
+ new_members.insert(
+ name.clone(),
+ ObjMember {
+ add: *plus,
+ visibility: *visibility,
+ invoke: LazyBinding::Bindable(Rc::new(
+ closure!(clone name, clone value, clone context_creator, |this, super_obj| {
+ Ok(LazyVal::new_resolved(push(&value.1, "object field", ||{
+ let context = context_creator.0(this, super_obj)?;
+ evaluate(
+ context,
+ &value,
+ )
+ })?))
+ }),
+ )),
+ },
+ );
}
-
- let mut new_members = BTreeMap::new();
- for member in members.into_iter() {
- match member {
- Member::Field(FieldMember {
- name,
- plus,
- params: None,
- visibility,
- value,
- }) => {
- let name = evaluate_field_name(context.clone(), &name)?;
- if name.is_none() {
- continue;
- }
- let name = name.unwrap();
- new_members.insert(
- name.clone(),
- ObjMember {
- add: plus,
- visibility: visibility.clone(),
- invoke: LazyBinding::Bindable(Rc::new(
- closure!(clone name, clone value, clone context_creator, |this, super_obj| {
- Ok(LazyVal::new_resolved(push(&value.1, "object field", ||{
- let context = context_creator.0(this, super_obj)?;
- evaluate(
- context,
- &value,
- )?.unwrap_if_lazy()
- })?))
- }),
- )),
- },
- );
- }
- Member::Field(FieldMember {
- name,
- params: Some(params),
- value,
- ..
- }) => {
- let name = evaluate_field_name(context.clone(), &name)?;
- if name.is_none() {
- continue;
- }
- let name = name.unwrap();
- new_members.insert(
- name,
- ObjMember {
- add: false,
- visibility: Visibility::Hidden,
- invoke: LazyBinding::Bindable(Rc::new(
- closure!(clone value, clone context_creator, |this, super_obj| {
- // TODO: Assert
- Ok(LazyVal::new_resolved(evaluate_method(
- context_creator.0(this, super_obj)?,
- params.clone(),
- value.clone(),
- )))
- }),
- )),
- },
- );
- }
- Member::BindStmt(_) => {}
- Member::AssertStmt(_) => {}
+ Member::Field(FieldMember {
+ name,
+ params: Some(params),
+ value,
+ ..
+ }) => {
+ let name = evaluate_field_name(context.clone(), &name)?;
+ if name.is_none() {
+ continue;
}
+ let name = name.unwrap();
+ new_members.insert(
+ name,
+ ObjMember {
+ add: false,
+ visibility: Visibility::Hidden,
+ invoke: LazyBinding::Bindable(Rc::new(
+ closure!(clone value, clone context_creator, clone params, |this, super_obj| {
+ // TODO: Assert
+ Ok(LazyVal::new_resolved(evaluate_method(
+ context_creator.0(this, super_obj)?,
+ params.clone(),
+ value.clone(),
+ )))
+ }),
+ )),
+ },
+ );
}
- future_this.fill(ObjValue::new(None, Rc::new(new_members)))
+ Member::BindStmt(_) => {}
+ Member::AssertStmt(_) => {}
}
- ObjBody::ObjComp {
- pre_locals,
- key,
- value,
- post_locals,
- compspecs,
- } => {
+ }
+ Ok(future_this.fill(ObjValue::new(None, Rc::new(new_members))))
+}
+
+pub fn evaluate_object(context: Context, object: &ObjBody) -> Result<ObjValue> {
+ Ok(match object {
+ ObjBody::MemberList(members) => evaluate_member_list_object(context, &members)?,
+ ObjBody::ObjComp(obj) => {
let future_this = FutureObjValue::new();
let mut new_members = BTreeMap::new();
for (k, v) in evaluate_comp(
@@ -325,26 +321,27 @@
)?)
})
);
- let mut bindings: HashMap<String, LazyBinding> = HashMap::new();
- for (n, b) in pre_locals
+ let mut bindings: HashMap<Rc<str>, LazyBinding> = HashMap::new();
+ for (n, b) in obj
+ .pre_locals
.iter()
- .chain(post_locals.iter())
+ .chain(obj.post_locals.iter())
.map(|b| evaluate_binding(b, context_creator.clone()))
{
bindings.insert(n, b);
}
let bindings = new_bindings.fill(bindings);
let ctx = ctx.extend_unbound(bindings, None, None, None)?;
- let key = evaluate(ctx.clone(), &key)?;
+ let key = evaluate(ctx.clone(), &obj.key)?;
let value = LazyBinding::Bindable(Rc::new(
- closure!(clone ctx, clone value, |this, _super_obj| {
+ closure!(clone ctx, clone obj.value, |this, _super_obj| {
Ok(LazyVal::new_resolved(evaluate(ctx.extend(HashMap::new(), None, this, None)?, &value)?))
}),
));
Ok((key, value))
},
- &compspecs,
+ &obj.compspecs,
)?
.unwrap()
{
@@ -394,7 +391,7 @@
BinaryOp(v1, o, v2) => evaluate_binary_op_special(context, &v1, *o, &v2)?,
UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(context, v)?)?,
Var(name) => push(loc, "var", || {
- Val::Lazy(context.binding(&name)?).unwrap_if_lazy()
+ Ok(Val::Lazy(context.binding(name.clone())?).unwrap_if_lazy()?)
})?,
Index(LocExpr(v, _), index) if matches!(&**v, Expr::Literal(LiteralType::Super)) => {
let name = evaluate(context.clone(), index)?.try_cast_str("object index")?;
@@ -411,9 +408,9 @@
evaluate(context, index)?,
) {
(Val::Obj(v), Val::Str(s)) => {
- if let Some(v) = v.get(&s)? {
+ if let Some(v) = v.get(s.clone())? {
v.unwrap_if_lazy()?
- } else if let Some(Val::Str(n)) = v.get("__intristic_namespace__")? {
+ } else if let Some(Val::Str(n)) = v.get("__intristic_namespace__".into())? {
Val::Intristic(n, s)
} else {
create_error(crate::Error::NoSuchField(s))?
@@ -443,9 +440,13 @@
n.value_type()?,
))?,
- (Val::Str(s), Val::Num(n)) => {
- Val::Str(s.chars().skip(n as usize).take(1).collect())
- }
+ (Val::Str(s), Val::Num(n)) => Val::Str(
+ s.chars()
+ .skip(n as usize)
+ .take(1)
+ .collect::<String>()
+ .into(),
+ ),
(Val::Str(_), n) => create_error(crate::Error::ValueIndexMustBeTypeGot(
ValType::Str,
ValType::Num,
@@ -456,7 +457,7 @@
}
}
LocalExpr(bindings, returned) => {
- let mut new_bindings: HashMap<String, LazyBinding> = HashMap::new();
+ let mut new_bindings: HashMap<Rc<str>, LazyBinding> = HashMap::new();
let future_context = Context::new_future();
let context_creator = context_creator!(
@@ -484,19 +485,20 @@
})
)));
}
- Val::Arr(out)
+ Val::Arr(Rc::new(out))
}
ArrComp(expr, compspecs) => Val::Arr(
// First compspec should be forspec, so no "None" possible here
- evaluate_comp(context, &|ctx| evaluate(ctx, expr), compspecs)?.unwrap(),
+ Rc::new(evaluate_comp(context, &|ctx| evaluate(ctx, expr), compspecs)?.unwrap()),
),
- Obj(body) => Val::Obj(evaluate_object(context, body.clone())?),
+ Obj(body) => Val::Obj(evaluate_object(context, body)?),
ObjExtend(s, t) => evaluate_add_op(
&evaluate(context.clone(), s)?,
- &Val::Obj(evaluate_object(context, t.clone())?),
+ &Val::Obj(evaluate_object(context, t)?),
)?,
Apply(value, args, tailstrict) => {
- let value = evaluate(context.clone(), value)?.unwrap_if_lazy()?;
+ let lazy = evaluate(context.clone(), value)?;
+ let value = lazy.unwrap_if_lazy()?;
match value {
Val::Intristic(ns, name) => match (&ns as &str, &name as &str) {
// arr/string/function
@@ -519,7 +521,7 @@
("std", "type") => {
assert_eq!(args.len(), 1);
let expr = &args.get(0).unwrap().1;
- Val::Str(evaluate(context, expr)?.value_type()?.name().to_owned())
+ Val::Str(evaluate(context, expr)?.value_type()?.name().into())
}
// length, idx=>any
("std", "makeArray") => {
@@ -532,14 +534,14 @@
let mut out = Vec::with_capacity(v as usize);
for i in 0..v as usize {
let call_ctx =
- Context::new().with_var("v".to_owned(), Val::Num(i as f64))?;
+ Context::new().with_var("v".into(), Val::Num(i as f64))?;
out.push(d.evaluate(
call_ctx,
- &ArgsDesc(vec![Arg(None, el!(Expr::Var("v".to_owned())))]),
+ &ArgsDesc(vec![Arg(None, el!(Expr::Var("v".into())))]),
true,
)?)
}
- Val::Arr(out)
+ Val::Arr(Rc::new(out))
} else {
panic!("bad makeArray call");
}
@@ -564,13 +566,13 @@
evaluate(context.clone(), &args[0].1)?,
evaluate(context, &args[1].1)?,
) {
- Val::Arr(
+ Val::Arr(Rc::new(
body.fields_visibility()
.into_iter()
.filter(|(_k, v)| *v || include_hidden)
.map(|(k, _v)| Val::Str(k))
.collect(),
- )
+ ))
} else {
panic!("bad objectFieldsEx call");
}
@@ -587,7 +589,7 @@
body.fields_visibility()
.into_iter()
.filter(|(_k, v)| *v || include_hidden)
- .any(|(k, _v)| k == name),
+ .any(|(k, _v)| *k == *name),
)
} else {
panic!("bad objectHasEx call");
@@ -664,8 +666,8 @@
evaluate(context.clone(), &args[0].1)?,
evaluate(context.clone(), &args[1].1)?,
) {
- Val::Arr(
- arr.into_iter()
+ Val::Arr(Rc::new(
+ arr.iter()
.filter(|e| {
predicate
.evaluate_values(context.clone(), &[e.clone()])
@@ -673,8 +675,9 @@
.try_cast_bool("filter predicate")
.unwrap()
})
+ .cloned()
.collect(),
- )
+ ))
} else {
panic!("bad filter call");
}
@@ -682,33 +685,35 @@
// faster
("std", "join") => {
assert_eq!(args.len(), 2);
- let joiner = evaluate(context.clone(), &args[0].1)?.unwrap_if_lazy()?;
- let items = evaluate(context, &args[1].1)?.unwrap_if_lazy()?;
- match (joiner, items) {
+ let joiner = evaluate(context.clone(), &args[0].1)?;
+ let items = evaluate(context, &args[1].1)?;
+ match (joiner.unwrap_if_lazy()?, items.unwrap_if_lazy()?) {
(Val::Arr(joiner_items), Val::Arr(items)) => {
// TODO: Minimal size should be known
let mut out = Vec::new();
let mut first = true;
- for item in items {
+ for item in items.iter().cloned() {
if let Val::Arr(items) = item.unwrap_if_lazy()? {
if !first {
+ out.reserve(joiner_items.len());
out.extend(joiner_items.iter().cloned());
}
first = false;
- out.extend(items);
+ out.reserve(items.len());
+ out.extend(items.iter().cloned());
} else {
panic!("all array items should be arrays")
}
}
- Val::Arr(out)
+ Val::Arr(Rc::new(out))
}
(Val::Str(joiner), Val::Arr(items)) => {
let mut out = String::new();
let mut first = true;
- for item in items {
+ for item in items.iter().cloned() {
if let Val::Str(item) = item.unwrap_if_lazy()? {
if !first {
out += &joiner;
@@ -720,7 +725,7 @@
}
}
- Val::Str(out)
+ Val::Str(out.into())
}
(joiner, items) => panic!("bad join call: {:?} {:?}", joiner, items),
}
@@ -776,20 +781,20 @@
}
}
Import(path) => {
- let mut import_location = loc
+ let mut tmp = loc
.clone()
.expect("imports can't be used without loc_data")
- .0
- .clone();
+ .0;
+ let import_location = Rc::make_mut(&mut tmp);
import_location.pop();
with_state(|s| s.import_file(&import_location, path))?
}
ImportStr(path) => {
- let mut import_location = loc
+ let mut tmp = loc
.clone()
.expect("imports can't be used without loc_data")
- .0
- .clone();
+ .0;
+ let import_location = Rc::make_mut(&mut tmp);
import_location.pop();
Val::Str(with_state(|s| s.import_file_str(&import_location, path))?)
}
crates/jsonnet-evaluator/src/function.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/function.rs
+++ b/crates/jsonnet-evaluator/src/function.rs
@@ -35,7 +35,7 @@
let mut positioned_args = vec![None; params.0.len()];
for (id, arg) in args.iter().enumerate() {
let idx = if let Some(name) = &arg.0 {
- params.iter().position(|p| &p.0 == name).ok_or_else(|| {
+ params.iter().position(|p| *p.0 == *name).ok_or_else(|| {
create_error::<()>(Error::UnknownFunctionParameter(name.clone()))
.err()
.unwrap()
crates/jsonnet-evaluator/src/lib.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/lib.rs
+++ b/crates/jsonnet-evaluator/src/lib.rs
@@ -65,11 +65,11 @@
/// Contains file source codes and evaluated results for imports and pretty
/// printing stacktraces
files: RefCell<HashMap<PathBuf, FileData>>,
- str_files: RefCell<HashMap<PathBuf, String>>,
- globals: RefCell<HashMap<String, Val>>,
+ str_files: RefCell<HashMap<PathBuf, Rc<str>>>,
+ globals: RefCell<HashMap<Rc<str>, Val>>,
/// Values to use with std.extVar
- ext_vars: RefCell<HashMap<String, Val>>,
+ ext_vars: RefCell<HashMap<Rc<str>, Val>>,
settings: EvaluationSettings,
import_resolver: Box<dyn ImportResolver>,
@@ -87,7 +87,7 @@
with_state(|s| s.error(err))
}
pub(crate) fn push<T>(
- e: &Option<Rc<ExprLocation>>,
+ e: &Option<ExprLocation>,
comment: &str,
f: impl FnOnce() -> Result<T>,
) -> Result<T> {
@@ -185,11 +185,14 @@
})?;
self.evaluate_file(&file_path)
}
- pub(crate) fn import_file_str(&self, from: &PathBuf, path: &PathBuf) -> Result<String> {
+ pub(crate) fn import_file_str(&self, from: &PathBuf, path: &PathBuf) -> Result<Rc<str>> {
let path = self.0.import_resolver.resolve_file(from, path)?;
if !self.0.str_files.borrow().contains_key(&path) {
let file_str = self.0.import_resolver.load_file_contents(&path)?;
- self.0.str_files.borrow_mut().insert(path.clone(), file_str);
+ self.0
+ .str_files
+ .borrow_mut()
+ .insert(path.clone(), file_str.into());
}
Ok(self.0.str_files.borrow().get(&path).cloned().unwrap())
}
@@ -210,10 +213,10 @@
self.run_in_state(|| evaluate(self.create_default_context()?, &code))
}
- pub fn add_global(&self, name: String, value: Val) {
+ pub fn add_global(&self, name: Rc<str>, value: Val) {
self.0.globals.borrow_mut().insert(name, value);
}
- pub fn add_ext_var(&self, name: String, value: Val) {
+ pub fn add_ext_var(&self, name: Rc<str>, value: Val) {
self.0.ext_vars.borrow_mut().insert(name, value);
}
@@ -236,14 +239,14 @@
.unwrap();
}
let val = self.evaluate_file(&PathBuf::from("std.jsonnet")).unwrap();
- self.add_global("std".to_owned(), val);
+ self.add_global("std".into(), val);
});
self
}
pub fn create_default_context(&self) -> Result<Context> {
let globals = self.0.globals.borrow();
- let mut new_bindings: HashMap<String, LazyBinding> = HashMap::new();
+ let mut new_bindings: HashMap<Rc<str>, LazyBinding> = HashMap::new();
for (name, value) in globals.iter() {
new_bindings.insert(
name.clone(),
@@ -255,7 +258,7 @@
pub fn push<T>(
&self,
- e: Rc<ExprLocation>,
+ e: ExprLocation,
comment: String,
f: impl FnOnce() -> Result<T>,
) -> Result<T> {
@@ -362,7 +365,7 @@
let evaluator = EvaluationState::default();
evaluator.with_stdlib();
let val = evaluator.parse_evaluate_raw($str).unwrap();
- evaluator.add_global("__tmp__to_yaml__".to_owned(), val);
+ evaluator.add_global("__tmp__to_yaml__".into(), val);
evaluator
.parse_evaluate_raw("std.manifestJsonEx(__tmp__to_yaml__, \"\")")
.unwrap()
crates/jsonnet-evaluator/src/obj.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/obj.rs
+++ b/crates/jsonnet-evaluator/src/obj.rs
@@ -18,9 +18,10 @@
#[derive(Debug)]
pub struct ObjValueInternals {
super_obj: Option<ObjValue>,
- this_entries: Rc<BTreeMap<String, ObjMember>>,
- value_cache: RefCell<HashMap<String, Val>>,
+ this_entries: Rc<BTreeMap<Rc<str>, ObjMember>>,
+ value_cache: RefCell<HashMap<Rc<str>, Val>>,
}
+#[derive(Clone)]
pub struct ObjValue(pub(crate) Rc<ObjValueInternals>);
impl Debug for ObjValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -43,7 +44,7 @@
impl ObjValue {
pub fn new(
super_obj: Option<ObjValue>,
- this_entries: Rc<BTreeMap<String, ObjMember>>,
+ this_entries: Rc<BTreeMap<Rc<str>, ObjMember>>,
) -> ObjValue {
ObjValue(Rc::new(ObjValueInternals {
super_obj,
@@ -57,7 +58,7 @@
Some(v) => ObjValue::new(Some(v.with_super(super_obj)), self.0.this_entries.clone()),
}
}
- pub fn enum_fields(&self, handler: &impl Fn(&str, &Visibility)) {
+ pub fn enum_fields(&self, handler: &impl Fn(&Rc<str>, &Visibility)) {
if let Some(s) = &self.0.super_obj {
s.enum_fields(handler);
}
@@ -65,7 +66,7 @@
handler(&name, &member.visibility);
}
}
- pub fn fields_visibility(&self) -> IndexMap<String, bool> {
+ pub fn fields_visibility(&self) -> IndexMap<Rc<str>, bool> {
let out = Rc::new(RefCell::new(IndexMap::new()));
self.enum_fields(&|name, visibility| {
let mut out = out.borrow_mut();
@@ -85,16 +86,20 @@
});
Rc::try_unwrap(out).unwrap().into_inner()
}
- pub fn get(&self, key: &str) -> Result<Option<Val>> {
- if let Some(v) = self.0.value_cache.borrow().get(key) {
+ pub fn visible_fields(&self) -> Vec<Rc<str>> {
+ self.fields_visibility()
+ .into_iter()
+ .filter(|(_k, v)| *v)
+ .map(|(k, _)| k)
+ .collect()
+ }
+ pub fn get(&self, key: Rc<str>) -> Result<Option<Val>> {
+ if let Some(v) = self.0.value_cache.borrow().get(&key) {
return Ok(Some(v.clone()));
}
- if let Some(v) = self.get_raw(key, self)? {
+ if let Some(v) = self.get_raw(&key, self)? {
let v = v.unwrap_if_lazy()?;
- self.0
- .value_cache
- .borrow_mut()
- .insert(key.to_owned(), v.clone());
+ self.0.value_cache.borrow_mut().insert(key, v.clone());
Ok(Some(v))
} else {
Ok(None)
@@ -108,10 +113,10 @@
.evaluate()?,
)),
(Some(k), Some(s)) => {
- let our = k
+ let lazy = k
.invoke
- .evaluate(Some(real_this.clone()), self.0.super_obj.clone())?
- .evaluate()?;
+ .evaluate(Some(real_this.clone()), self.0.super_obj.clone())?;
+ let our = lazy.evaluate()?;
if k.add {
s.get_raw(key, real_this)?
.map_or(Ok(Some(our.clone())), |v| {
@@ -124,11 +129,6 @@
(None, Some(s)) => s.get_raw(key, real_this),
(None, None) => Ok(None),
}
- }
-}
-impl Clone for ObjValue {
- fn clone(&self) -> Self {
- ObjValue(self.0.clone())
}
}
impl PartialEq for ObjValue {
crates/jsonnet-evaluator/src/val.rsdiffbeforeafterboth--- a/crates/jsonnet-evaluator/src/val.rs
+++ b/crates/jsonnet-evaluator/src/val.rs
@@ -81,7 +81,7 @@
}
}
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ValType {
Bool,
Null,
@@ -115,42 +115,46 @@
pub enum Val {
Bool(bool),
Null,
- Str(String),
+ Str(Rc<str>),
Num(f64),
Lazy(LazyVal),
- Arr(Vec<Val>),
+ Arr(Rc<Vec<Val>>),
Obj(ObjValue),
Func(FuncDesc),
// Library functions implemented in native
- Intristic(String, String),
+ Intristic(Rc<str>, Rc<str>),
+}
+macro_rules! matches_unwrap {
+ ($e: expr, $p: pat, $r: expr) => {
+ match $e {
+ $p => $r,
+ _ => panic!("no match"),
+ }
+ };
}
impl Val {
+ pub fn assert_type(&self, context: &'static str, val_type: ValType) -> Result<()> {
+ let this_type = self.value_type()?;
+ if this_type != val_type {
+ create_error(Error::TypeMismatch(context, vec![val_type], this_type))
+ } else {
+ Ok(())
+ }
+ }
pub fn try_cast_bool(self, context: &'static str) -> Result<bool> {
- match self.unwrap_if_lazy()? {
- Val::Bool(v) => Ok(v),
- v => create_error(Error::TypeMismatch(
- context,
- vec![ValType::Bool],
- v.value_type()?,
- )),
- }
+ self.assert_type(context, ValType::Bool)?;
+ Ok(matches_unwrap!(self.unwrap_if_lazy()?, Val::Bool(v), v))
}
- pub fn try_cast_str(self, context: &'static str) -> Result<String> {
- match self.unwrap_if_lazy()? {
- Val::Str(v) => Ok(v),
- v => create_error(Error::TypeMismatch(
- context,
- vec![ValType::Str],
- v.value_type()?,
- )),
- }
+ pub fn try_cast_str(self, context: &'static str) -> Result<Rc<str>> {
+ self.assert_type(context, ValType::Str)?;
+ Ok(matches_unwrap!(self.unwrap_if_lazy()?, Val::Str(v), v))
}
- pub fn unwrap_if_lazy(self) -> Result<Self> {
+ pub fn unwrap_if_lazy(&self) -> Result<Self> {
Ok(if let Val::Lazy(v) = self {
v.evaluate()?.unwrap_if_lazy()?
} else {
- self
+ self.clone()
})
}
pub fn value_type(&self) -> Result<ValType> {
@@ -166,26 +170,30 @@
Val::Lazy(_) => self.clone().unwrap_if_lazy()?.value_type()?,
})
}
- pub fn into_json(self, padding: usize) -> Result<String> {
+ pub fn into_json(self, padding: usize) -> Result<Rc<str>> {
with_state(|s| {
let ctx = s
.create_default_context()?
- .with_var("__tmp__to_json__".to_owned(), self)?;
- if let Val::Str(result) = evaluate(
+ .with_var("__tmp__to_json__".into(), self)?;
+ Ok(evaluate(
ctx,
&el!(Expr::Apply(
el!(Expr::Index(
- el!(Expr::Var("std".to_owned())),
- el!(Expr::Str("manifestJsonEx".to_owned()))
+ el!(Expr::Var("std".into())),
+ el!(Expr::Str("manifestJsonEx".into()))
)),
ArgsDesc(vec![
- Arg(None, el!(Expr::Var("__tmp__to_json__".to_owned()))),
- Arg(None, el!(Expr::Str(" ".repeat(padding))))
+ Arg(None, el!(Expr::Var("__tmp__to_json__".into()))),
+ Arg(None, el!(Expr::Str(" ".repeat(padding).into())))
]),
false
)),
- )? {
- Ok(result)
+ )?
+ .try_cast_str("to json")?)
+ })
+ }
+}
+
} else {
unreachable!()
}
crates/jsonnet-parser/src/expr.rsdiffbeforeafterboth1use serde::{Deserialize, Serialize};1use serde::{Deserialize, Serialize};2use std::{fmt::Debug, ops::Deref, path::PathBuf, rc::Rc};2use std::{fmt::Debug, ops::Deref, path::PathBuf, rc::Rc};334#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]4#[derive(Debug, PartialEq, Serialize, Deserialize)]5pub enum FieldName {5pub enum FieldName {6 /// {fixed: 2}6 /// {fixed: 2}7 Fixed(String),7 Fixed(Rc<str>),8 /// {["dyn"+"amic"]: 3}8 /// {["dyn"+"amic"]: 3}9 Dyn(LocExpr),9 Dyn(LocExpr),10}10}111112#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]12#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]13pub enum Visibility {13pub enum Visibility {14 /// :14 /// :15 Normal,15 Normal,19 Unhide,19 Unhide,20}20}212122#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]22#[derive(Debug, PartialEq, Serialize, Deserialize)]23pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);23pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);242425#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]25#[derive(Debug, PartialEq, Serialize, Deserialize)]26pub struct FieldMember {26pub struct FieldMember {27 pub name: FieldName,27 pub name: FieldName,28 pub plus: bool,28 pub plus: bool,31 pub value: LocExpr,31 pub value: LocExpr,32}32}333334#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]34#[derive(Debug, PartialEq, Serialize, Deserialize)]35pub enum Member {35pub enum Member {36 Field(FieldMember),36 Field(FieldMember),37 BindStmt(BindSpec),37 BindStmt(BindSpec),71}71}727273/// name, default value73/// name, default value74#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]74#[derive(Debug, PartialEq, Serialize, Deserialize)]75pub struct Param(pub String, pub Option<LocExpr>);75pub struct Param(pub Rc<str>, pub Option<LocExpr>);76/// Defined function parameters76/// Defined function parameters77#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]77#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]78pub struct ParamsDesc(pub Vec<Param>);78pub struct ParamsDesc(pub Rc<Vec<Param>>);79impl Deref for ParamsDesc {79impl Deref for ParamsDesc {80 type Target = Vec<Param>;80 type Target = Vec<Param>;81 fn deref(&self) -> &Self::Target {81 fn deref(&self) -> &Self::Target {82 &self.082 &self.083 }83 }84}84}858586#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]86#[derive(Debug, PartialEq, Serialize, Deserialize)]87pub struct Arg(pub Option<String>, pub LocExpr);87pub struct Arg(pub Option<String>, pub LocExpr);88#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]88#[derive(Debug, PartialEq, Serialize, Deserialize)]89pub struct ArgsDesc(pub Vec<Arg>);89pub struct ArgsDesc(pub Vec<Arg>);90impl Deref for ArgsDesc {90impl Deref for ArgsDesc {91 type Target = Vec<Arg>;91 type Target = Vec<Arg>;969697#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]97#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]98pub struct BindSpec {98pub struct BindSpec {99 pub name: String,99 pub name: Rc<str>,100 pub params: Option<ParamsDesc>,100 pub params: Option<ParamsDesc>,101 pub value: LocExpr,101 pub value: LocExpr,102}102}103103104#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]104#[derive(Debug, PartialEq, Serialize, Deserialize)]105pub struct IfSpecData(pub LocExpr);105pub struct IfSpecData(pub LocExpr);106#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]106#[derive(Debug, PartialEq, Serialize, Deserialize)]107pub struct ForSpecData(pub String, pub LocExpr);107pub struct ForSpecData(pub Rc<str>, pub LocExpr);108108109#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]109#[derive(Debug, PartialEq, Serialize, Deserialize)]110pub enum CompSpec {110pub enum CompSpec {111 IfSpec(IfSpecData),111 IfSpec(IfSpecData),112 ForSpec(ForSpecData),112 ForSpec(ForSpecData),113}113}114114115#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]115#[derive(Debug, PartialEq, Serialize, Deserialize)]116pub enum ObjBody {116pub struct ObjComp {117 MemberList(Vec<Member>),118 ObjComp {119 pre_locals: Vec<BindSpec>,117 pub pre_locals: Vec<BindSpec>,120 key: LocExpr,118 pub key: LocExpr,121 value: LocExpr,119 pub value: LocExpr,122 post_locals: Vec<BindSpec>,120 pub post_locals: Vec<BindSpec>,123 compspecs: Vec<CompSpec>,121 pub compspecs: Vec<CompSpec>,124 },122}125}123124#[derive(Debug, PartialEq, Serialize, Deserialize)]125pub enum ObjBody {126 MemberList(Vec<Member>),127 ObjComp(ObjComp),128}126129127#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]130#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Copy)]128pub enum LiteralType {131pub enum LiteralType {129 This,132 This,130 Super,133 Super,134 False,137 False,135}138}136139137#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]140#[derive(Debug, PartialEq, Serialize, Deserialize)]138pub struct SliceDesc {141pub struct SliceDesc {139 pub start: Option<LocExpr>,142 pub start: Option<LocExpr>,140 pub end: Option<LocExpr>,143 pub end: Option<LocExpr>,141 pub step: Option<LocExpr>,144 pub step: Option<LocExpr>,142}145}143146144/// Syntax base147/// Syntax base145#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]148#[derive(Debug, PartialEq, Serialize, Deserialize)]146pub enum Expr {149pub enum Expr {147 Literal(LiteralType),150 Literal(LiteralType),148151149 /// String value: "hello"152 /// String value: "hello"150 Str(String),153 Str(Rc<str>),151 /// Number: 1, 2.0, 2e+20154 /// Number: 1, 2.0, 2e+20152 Num(f64),155 Num(f64),153 /// Variable name: test156 /// Variable name: test154 Var(String),157 Var(Rc<str>),155158156 /// Array of expressions: [1, 2, "Hello"]159 /// Array of expressions: [1, 2, "Hello"]157 Arr(Vec<LocExpr>),160 Arr(Vec<LocExpr>),crates/jsonnet-parser/src/lib.rsdiffbeforeafterboth--- a/crates/jsonnet-parser/src/lib.rs
+++ b/crates/jsonnet-parser/src/lib.rs
@@ -39,7 +39,7 @@
/// Reserved word followed by any non-alphanumberic
rule reserved() = ("assert" / "else" / "error" / "false" / "for" / "function" / "if" / "import" / "importstr" / "in" / "local" / "null" / "tailstrict" / "then" / "self" / "super" / "true") end_of_ident()
- rule id() -> String = quiet!{ !reserved() s:$(alpha() (alpha() / digit())*) {s.to_owned()}} / expected!("<identifier>")
+ rule id() = quiet!{ !reserved() alpha() (alpha() / digit())*} / expected!("<identifier>")
rule keyword(id: &'static str)
= ##parse_string_literal(id) end_of_ident()
@@ -47,7 +47,7 @@
rule l(s: &ParserSettings, x: rule<Expr>) -> LocExpr
= start:position!() v:x() end:position!() {loc_expr!(v, s.loc_data, (s.file_name.clone(), start, end))}
- pub rule param(s: &ParserSettings) -> expr::Param = name:id() expr:(_ "=" _ expr:expr(s){expr})? { expr::Param(name, expr) }
+ pub rule param(s: &ParserSettings) -> expr::Param = name:$(id()) expr:(_ "=" _ expr:expr(s){expr})? { expr::Param(name.into(), expr) }
pub rule params(s: &ParserSettings) -> expr::ParamsDesc
= params:(param(s) ** comma()) {
let mut defaults_started = false;
@@ -55,12 +55,12 @@
defaults_started = defaults_started || param.1.is_some();
assert_eq!(defaults_started, param.1.is_some(), "defauld parameters should be used after all positionals");
}
- expr::ParamsDesc(params)
+ expr::ParamsDesc(Rc::new(params))
}
- / { expr::ParamsDesc(Vec::new()) }
+ / { expr::ParamsDesc(Rc::new(Vec::new())) }
pub rule arg(s: &ParserSettings) -> expr::Arg
- = name:id() _ "=" _ expr:expr(s) {expr::Arg(Some(name), expr)}
+ = name:$(id()) _ "=" _ expr:expr(s) {expr::Arg(Some(name.into()), expr)}
/ expr:expr(s) {expr::Arg(None, expr)}
pub rule args(s: &ParserSettings) -> expr::ArgsDesc
= args:arg(s) ** comma() comma()? {
@@ -74,8 +74,8 @@
/ { expr::ArgsDesc(Vec::new()) }
pub rule bind(s: &ParserSettings) -> expr::BindSpec
- = name:id() _ "=" _ expr:expr(s) {expr::BindSpec{name, params: None, value: expr}}
- / name:id() _ "(" _ params:params(s) _ ")" _ "=" _ expr:expr(s) {expr::BindSpec{name, params: Some(params), value: expr}}
+ = name:$(id()) _ "=" _ expr:expr(s) {expr::BindSpec{name:name.into(), params: None, value: expr}}
+ / name:$(id()) _ "(" _ params:params(s) _ ")" _ "=" _ expr:expr(s) {expr::BindSpec{name:name.into(), params: Some(params), value: expr}}
pub rule assertion(s: &ParserSettings) -> expr::AssertStmt
= keyword("assert") _ cond:expr(s) msg:(_ ":" _ e:expr(s) {e})? { expr::AssertStmt(cond, msg) }
@@ -95,8 +95,8 @@
/ string_block()
pub rule field_name(s: &ParserSettings) -> expr::FieldName
- = name:id() {expr::FieldName::Fixed(name)}
- / name:string() {expr::FieldName::Fixed(name)}
+ = name:$(id()) {expr::FieldName::Fixed(name.into())}
+ / name:string() {expr::FieldName::Fixed(name.into())}
/ "[" _ expr:expr(s) _ "]" {expr::FieldName::Dyn(expr)}
pub rule visibility() -> expr::Visibility
= ":::" {expr::Visibility::Unhide}
@@ -125,35 +125,41 @@
/ field:field(s) {expr::Member::Field(field)}
pub rule objinside(s: &ParserSettings) -> expr::ObjBody
= pre_locals:(b: obj_local(s) comma() {b})* "[" _ key:expr(s) _ "]" _ ":" _ value:expr(s) post_locals:(comma() b:obj_local(s) {b})* _ forspec:forspec(s) others:(_ rest:compspec(s) {rest})? {
- expr::ObjBody::ObjComp {
+ let mut compspecs = vec![CompSpec::ForSpec(forspec)];
+ compspecs.extend(others.unwrap_or_default());
+ expr::ObjBody::ObjComp(expr::ObjComp{
pre_locals,
key,
value,
post_locals,
- compspecs: [vec![CompSpec::ForSpec(forspec)], others.unwrap_or_default()].concat(),
- }
+ compspecs,
+ })
}
/ members:(member(s) ** comma()) comma()? {expr::ObjBody::MemberList(members)}
pub rule ifspec(s: &ParserSettings) -> IfSpecData
= keyword("if") _ expr:expr(s) {IfSpecData(expr)}
pub rule forspec(s: &ParserSettings) -> ForSpecData
- = keyword("for") _ id:id() _ keyword("in") _ cond:expr(s) {ForSpecData(id, cond)}
+ = keyword("for") _ id:$(id()) _ keyword("in") _ cond:expr(s) {ForSpecData(id.into(), cond)}
pub rule compspec(s: &ParserSettings) -> Vec<expr::CompSpec>
= s:(i:ifspec(s) { expr::CompSpec::IfSpec(i) } / f:forspec(s) {expr::CompSpec::ForSpec(f)} ) ** _ {s}
pub rule local_expr(s: &ParserSettings) -> LocExpr
= l(s,<keyword("local") _ binds:bind(s) ** comma() _ ";" _ expr:expr(s) { Expr::LocalExpr(binds, expr) }>)
pub rule string_expr(s: &ParserSettings) -> LocExpr
- = l(s, <s:string() {Expr::Str(s)}>)
+ = l(s, <s:string() {Expr::Str(s.into())}>)
pub rule obj_expr(s: &ParserSettings) -> LocExpr
= l(s,<"{" _ body:objinside(s) _ "}" {Expr::Obj(body)}>)
pub rule array_expr(s: &ParserSettings) -> LocExpr
= l(s,<"[" _ elems:(expr(s) ** comma()) _ comma()? "]" {Expr::Arr(elems)}>)
pub rule array_comp_expr(s: &ParserSettings) -> LocExpr
- = l(s,<"[" _ expr:expr(s) _ comma()? _ forspec:forspec(s) _ others:(others: compspec(s) _ {others})? "]" {Expr::ArrComp(expr, [vec![CompSpec::ForSpec(forspec)], others.unwrap_or_default()].concat())}>)
+ = l(s,<"[" _ expr:expr(s) _ comma()? _ forspec:forspec(s) _ others:(others: compspec(s) _ {others})? "]" {
+ let mut specs = vec![CompSpec::ForSpec(forspec)];
+ specs.extend(others.unwrap_or_default());
+ Expr::ArrComp(expr, specs)
+ }>)
pub rule number_expr(s: &ParserSettings) -> LocExpr
= l(s,<n:number() { expr::Expr::Num(n) }>)
pub rule var_expr(s: &ParserSettings) -> LocExpr
- = l(s,<n:id() { expr::Expr::Var(n) }>)
+ = l(s,<n:$(id()) { expr::Expr::Var(n.into()) }>)
pub rule if_then_else_expr(s: &ParserSettings) -> LocExpr
= l(s,<cond:ifspec(s) _ keyword("then") _ cond_then:expr(s) cond_else:(_ keyword("else") _ e:expr(s) {e})? {Expr::IfElse{
cond,
@@ -219,16 +225,16 @@
--
a:(@) _ "==" _ b:@ {loc_expr_todo!(Expr::Apply(
el!(Expr::Index(
- el!(Expr::Var("std".to_owned())),
- el!(Expr::Str("equals".to_owned()))
+ el!(Expr::Var("std".into())),
+ el!(Expr::Str("equals".into()))
)),
ArgsDesc(vec![Arg(None, a), Arg(None, b)]),
true
))}
a:(@) _ "!=" _ b:@ {loc_expr_todo!(Expr::UnaryOp(UnaryOpType::Not, el!(Expr::Apply(
el!(Expr::Index(
- el!(Expr::Var("std".to_owned())),
- el!(Expr::Str("equals".to_owned()))
+ el!(Expr::Var("std".into())),
+ el!(Expr::Str("equals".into()))
)),
ArgsDesc(vec![Arg(None, a), Arg(None, b)]),
true
@@ -240,8 +246,8 @@
a:(@) _ ">=" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Gte, b))}
a:(@) _ keyword("in") _ b:@ {loc_expr_todo!(Expr::Apply(
el!(Expr::Index(
- el!(Expr::Var("std".to_owned())),
- el!(Expr::Str("objectHasEx".to_owned()))
+ el!(Expr::Var("std".into())),
+ el!(Expr::Str("objectHasEx".into()))
)), ArgsDesc(vec![Arg(None, b), Arg(None, a), Arg(None, el!(Expr::Literal(LiteralType::True)))]),
true
))}
@@ -256,8 +262,8 @@
a:(@) _ "/" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Div, b))}
a:(@) _ "%" _ b:@ {loc_expr_todo!(Expr::Apply(
el!(Expr::Index(
- el!(Expr::Var("std".to_owned())),
- el!(Expr::Str("mod".to_owned()))
+ el!(Expr::Var("std".into())),
+ el!(Expr::Str("mod".into()))
)), ArgsDesc(vec![Arg(None, a), Arg(None, b)]),
true
))}
@@ -268,8 +274,8 @@
--
a:(@) _ "[" _ s:slice_desc(s) _ "]" {loc_expr_todo!(Expr::Apply(
el!(Expr::Index(
- el!(Expr::Var("std".to_owned())),
- el!(Expr::Str("slice".to_owned())),
+ el!(Expr::Var("std".into())),
+ el!(Expr::Str("slice".into())),
)),
ArgsDesc(vec![
Arg(None, a),
@@ -279,7 +285,7 @@
]),
true,
))}
- a:(@) _ "." _ s:id() {loc_expr_todo!(Expr::Index(a, el!(Expr::Str(s))))}
+ a:(@) _ "." _ s:$(id()) {loc_expr_todo!(Expr::Index(a, el!(Expr::Str(s.into()))))}
a:(@) _ "[" _ s:expr(s) _ "]" {loc_expr_todo!(Expr::Index(a, s))}
a:(@) _ "(" _ args:args(s) _ ")" ts:(_ keyword("tailstrict"))? {loc_expr_todo!(Expr::Apply(a, args, ts.is_some()))}
a:(@) _ "{" _ body:objinside(s) _ "}" {loc_expr_todo!(Expr::ObjExtend(a, body))}
@@ -352,7 +358,7 @@
fn multiline_string() {
assert_eq!(
parse!("|||\n Hello world!\n a\n|||"),
- el!(Expr::Str("Hello world!\n a\n".to_owned())),
+ el!(Expr::Str("Hello world!\n a\n".into())),
)
}
@@ -369,20 +375,20 @@
fn string_escaping() {
assert_eq!(
parse!(r#""Hello, \"world\"!""#),
- el!(Expr::Str(r#"Hello, "world"!"#.to_owned())),
+ el!(Expr::Str(r#"Hello, "world"!"#.into())),
);
assert_eq!(
parse!(r#"'Hello \'world\'!'"#),
- el!(Expr::Str("Hello 'world'!".to_owned())),
+ el!(Expr::Str("Hello 'world'!".into())),
);
- assert_eq!(parse!(r#"'\\\\'"#), el!(Expr::Str("\\\\".to_owned())),);
+ assert_eq!(parse!(r#"'\\\\'"#), el!(Expr::Str("\\\\".into())),);
}
#[test]
fn string_unescaping() {
assert_eq!(
parse!(r#""Hello\nWorld""#),
- el!(Expr::Str("Hello\nWorld".to_owned())),
+ el!(Expr::Str("Hello\nWorld".into())),
);
}
@@ -390,7 +396,7 @@
fn string_verbantim() {
assert_eq!(
parse!(r#"@"Hello\n""World""""#),
- el!(Expr::Str("Hello\\n\"World\"".to_owned())),
+ el!(Expr::Str("Hello\\n\"World\"".into())),
);
}
@@ -489,16 +495,13 @@
parse!("[std.deepJoin(x) for x in arr]"),
el!(ArrComp(
el!(Apply(
- el!(Index(
- el!(Var("std".to_owned())),
- el!(Str("deepJoin".to_owned()))
- )),
- ArgsDesc(vec![Arg(None, el!(Var("x".to_owned())))]),
+ el!(Index(el!(Var("std".into())), el!(Str("deepJoin".into())))),
+ ArgsDesc(vec![Arg(None, el!(Var("x".into())))]),
false,
)),
vec![CompSpec::ForSpec(ForSpecData(
- "x".to_owned(),
- el!(Var("arr".to_owned()))
+ "x".into(),
+ el!(Var("arr".into()))
))]
)),
)
@@ -508,7 +511,7 @@
fn reserved() {
use Expr::*;
assert_eq!(parse!("null"), el!(Literal(LiteralType::Null)));
- assert_eq!(parse!("nulla"), el!(Var("nulla".to_owned())));
+ assert_eq!(parse!("nulla"), el!(Var("nulla".into())));
}
#[test]
@@ -522,9 +525,9 @@
assert_eq!(
parse!("!a && !b"),
el!(BinaryOp(
- el!(UnaryOp(UnaryOpType::Not, el!(Var("a".to_owned())))),
+ el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into())))),
BinaryOpType::And,
- el!(UnaryOp(UnaryOpType::Not, el!(Var("b".to_owned()))))
+ el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()))))
))
);
}
@@ -535,9 +538,9 @@
assert_eq!(
parse!("!a / !b"),
el!(BinaryOp(
- el!(UnaryOp(UnaryOpType::Not, el!(Var("a".to_owned())))),
+ el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into())))),
BinaryOpType::Div,
- el!(UnaryOp(UnaryOpType::Not, el!(Var("b".to_owned()))))
+ el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()))))
))
);
}
@@ -549,7 +552,7 @@
parse!("!!a"),
el!(UnaryOp(
UnaryOpType::Not,
- el!(UnaryOp(UnaryOpType::Not, el!(Var("a".to_owned()))))
+ el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into()))))
))
)
}