git.delta.rocks / jrsonnet / refs/commits / a0455123d694

difftreelog

perf lesser and cheaper clones

Лач2020-06-26parent: #c1a6c6a.patch.diff
in: master

11 files changed

modifiedcmds/jrsonnet/src/main.rsdiffbeforeafterboth
5use jsonnet_parser::{el, Arg, ArgsDesc, Expr, LocExpr, ParserSettings};5use jsonnet_parser::{el, Arg, ArgsDesc, Expr, LocExpr, ParserSettings};
6use location::{offset_to_location, CodeLocation};6use location::{offset_to_location, CodeLocation};
7use std::env::current_dir;7use std::env::current_dir;
8use std::{collections::HashMap, path::PathBuf, str::FromStr};8use std::{collections::HashMap, path::PathBuf, str::FromStr, rc::Rc};
99
10enum Format {10enum Format {
11 None,11 None,
128 evaluator.with_stdlib();128 evaluator.with_stdlib();
129 }129 }
130 for ExtStr { name, value } in opts.ext_str.iter().cloned() {130 for ExtStr { name, value } in opts.ext_str.iter().cloned() {
131 evaluator.add_ext_var(name, Val::Str(value));131 evaluator.add_ext_var(name.into(), Val::Str(value.into()));
132 }132 }
133 for ExtStr { name, value } in opts.ext_code.iter().cloned() {133 for ExtStr { name, value } in opts.ext_code.iter().cloned() {
134 evaluator.add_ext_var(name, evaluator.parse_evaluate_raw(&value).unwrap());134 evaluator.add_ext_var(name.into(), evaluator.parse_evaluate_raw(&value).unwrap());
135 }135 }
136 let mut input = current_dir().unwrap();136 let mut input = current_dir().unwrap();
137 input.push(opts.input.clone());137 input.push(opts.input.clone());
147 Val::Func(f) => {147 Val::Func(f) => {
148 let mut desc_map = HashMap::new();148 let mut desc_map = HashMap::new();
149 for ExtStr { name, value } in opts.tla_str.iter().cloned() {149 for ExtStr { name, value } in opts.tla_str.iter().cloned() {
150 desc_map.insert(name, el!(Expr::Str(value)));150 desc_map.insert(name, el!(Expr::Str(value.into())));
151 }151 }
152 for ExtStr { name, value } in opts.tla_code.iter().cloned() {152 for ExtStr { name, value } in opts.tla_code.iter().cloned() {
153 desc_map.insert(153 desc_map.insert(
154 name,154 name,
155 jsonnet_parser::parse(155 jsonnet_parser::parse(
156 &value,156 &value,
157 &ParserSettings {157 &ParserSettings {
158 file_name: PathBuf::new(),158 file_name: Rc::new(PathBuf::new()),
159 loc_data: false,159 loc_data: false,
160 },160 },
161 )161 )
162 .unwrap(),162 .unwrap(),
163 );163 );
164 }164 }
165 evaluator.add_global("__tmp__tlf__".to_owned(), Val::Func(f));165 evaluator.add_global("__tmp__tlf__".into(), Val::Func(f));
166 evaluator166 evaluator
167 .evaluate_raw(el!(Expr::Apply(167 .evaluate_raw(el!(Expr::Apply(
168 el!(Expr::Var("__tmp__tlf__".to_owned())),168 el!(Expr::Var("__tmp__tlf__".into())),
169 ArgsDesc(desc_map.into_iter().map(|(k, v)| Arg(Some(k), v)).collect()),169 ArgsDesc(desc_map.into_iter().map(|(k, v)| Arg(Some(k), v)).collect()),
170 false,170 false,
171 )))171 )))
178 if opts.no_stdlib {178 if opts.no_stdlib {
179 evaluator.with_stdlib();179 evaluator.with_stdlib();
180 }180 }
181 evaluator.add_global("__tmp__to_json__".to_owned(), v);181 evaluator.add_global("__tmp__to_json__".into(), v);
182 let v = evaluator.parse_evaluate_raw(&format!(182 let v = evaluator.parse_evaluate_raw(&format!(
183 "std.manifestJsonEx(__tmp__to_json__, \"{}\")",183 "std.manifestJsonEx(__tmp__to_json__, \"{}\")",
184 " ".repeat(opts.line_padding),184 " ".repeat(opts.line_padding),
195 if opts.no_stdlib {195 if opts.no_stdlib {
196 evaluator.with_stdlib();196 evaluator.with_stdlib();
197 }197 }
198 evaluator.add_global("__tmp__to_yaml__".to_owned(), v);198 evaluator.add_global("__tmp__to_yaml__".into(), v);
199 let v = evaluator199 let v = evaluator
200 .parse_evaluate_raw("std.manifestYamlDoc(__tmp__to_yaml__, \" \")");200 .parse_evaluate_raw("std.manifestYamlDoc(__tmp__to_yaml__, \" \")");
201 match v {201 match v {
modifiedcrates/jsonnet-evaluator/build.rsdiffbeforeafterboth
34 Member::Field(FieldMember {34 Member::Field(FieldMember {
35 name: FieldName::Fixed(name),35 name: FieldName::Fixed(name),
36 ..36 ..
37 }) if name == "join"37 }) if **name == *"join"
38 )38 )
39 })39 })
40 .collect(),40 .collect(),
modifiedcrates/jsonnet-evaluator/src/ctx.rsdiffbeforeafterboth
16 dollar: Option<ObjValue>,16 dollar: Option<ObjValue>,
17 this: Option<ObjValue>,17 this: Option<ObjValue>,
18 super_obj: Option<ObjValue>,18 super_obj: Option<ObjValue>,
19 bindings: LayeredHashMap<String, LazyVal>,19 bindings: LayeredHashMap<Rc<str>, LazyVal>,
20}20}
21pub struct Context(Rc<ContextInternals>);21pub struct Context(Rc<ContextInternals>);
22impl Debug for Context {22impl Debug for Context {
53 }))53 }))
54 }54 }
5555
56 pub fn binding(&self, name: &str) -> Result<LazyVal> {56 pub fn binding(&self, name: Rc<str>) -> Result<LazyVal> {
57 self.0.bindings.get(name).cloned().ok_or_else(|| {57 self.0.bindings.get(&name).cloned().ok_or_else(|| {
58 create_error::<()>(Error::UnknownVariable(name.to_owned()))58 create_error::<()>(Error::UnknownVariable(name))
59 .err()59 .err()
60 .unwrap()60 .unwrap()
61 })61 })
67 ctx.unwrap()67 ctx.unwrap()
68 }68 }
6969
70 pub fn with_var(&self, name: String, value: Val) -> Result<Context> {70 pub fn with_var(&self, name: Rc<str>, value: Val) -> Result<Context> {
71 let mut new_bindings = HashMap::with_capacity(1);71 let mut new_bindings = HashMap::with_capacity(1);
72 new_bindings.insert(name, resolved_lazy_val!(value));72 new_bindings.insert(name, resolved_lazy_val!(value));
73 self.extend(new_bindings, None, None, None)73 self.extend(new_bindings, None, None, None)
74 }74 }
7575
76 pub fn extend(76 pub fn extend(
77 &self,77 &self,
78 new_bindings: HashMap<String, LazyVal>,78 new_bindings: HashMap<Rc<str>, LazyVal>,
79 new_dollar: Option<ObjValue>,79 new_dollar: Option<ObjValue>,
80 new_this: Option<ObjValue>,80 new_this: Option<ObjValue>,
81 new_super_obj: Option<ObjValue>,81 new_super_obj: Option<ObjValue>,
97 }97 }
98 pub fn extend_unbound(98 pub fn extend_unbound(
99 &self,99 &self,
100 new_bindings: HashMap<String, LazyBinding>,100 new_bindings: HashMap<Rc<str>, LazyBinding>,
101 new_dollar: Option<ObjValue>,101 new_dollar: Option<ObjValue>,
102 new_this: Option<ObjValue>,102 new_this: Option<ObjValue>,
103 new_super_obj: Option<ObjValue>,103 new_super_obj: Option<ObjValue>,
modifiedcrates/jsonnet-evaluator/src/error.rsdiffbeforeafterboth
6pub enum Error {6pub enum Error {
7 VariableIsNotDefined(String),7 VariableIsNotDefined(String),
8 TypeMismatch(&'static str, Vec<ValType>, ValType),8 TypeMismatch(&'static str, Vec<ValType>, ValType),
9 NoSuchField(String),9 NoSuchField(Rc<str>),
1010
11 UnknownVariable(String),11 UnknownVariable(Rc<str>),
1212
13 UnknownFunctionParameter(String),13 UnknownFunctionParameter(String),
14 BindingParameterASecondTime(String),14 BindingParameterASecondTime(Rc<str>),
15 TooManyArgsFunctionHas(usize),15 TooManyArgsFunctionHas(usize),
16 FunctionParameterNotBoundInCall(String),16 FunctionParameterNotBoundInCall(Rc<str>),
1717
18 UndefinedExternalVariable(String),18 UndefinedExternalVariable(Rc<str>),
1919
20 FieldMustBeStringGot(ValType),20 FieldMustBeStringGot(ValType),
2121
22 AttemptedIndexAnArrayWithString(String),22 AttemptedIndexAnArrayWithString(Rc<str>),
23 ValueIndexMustBeTypeGot(ValType, ValType, ValType),23 ValueIndexMustBeTypeGot(ValType, ValType, ValType),
24 CantIndexInto(ValType),24 CantIndexInto(ValType),
2525
31 ImportNotSupported(PathBuf, PathBuf),31 ImportNotSupported(PathBuf, PathBuf),
32 ImportSyntaxError(jsonnet_parser::ParseError),32 ImportSyntaxError(jsonnet_parser::ParseError),
3333
34 RuntimeError(String),34 RuntimeError(Rc<str>),
35 StackOverflow,35 StackOverflow,
36 FractionalIndex,36 FractionalIndex,
37 DivisionByZero,37 DivisionByZero,
modifiedcrates/jsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth
14 rc::Rc,14 rc::Rc,
15};15};
1616
17pub fn evaluate_binding(b: &BindSpec, context_creator: ContextCreator) -> (String, LazyBinding) {17pub fn evaluate_binding(b: &BindSpec, context_creator: ContextCreator) -> (Rc<str>, LazyBinding) {
18 let b = b.clone();18 let b = b.clone();
19 if let Some(params) = &b.params {19 if let Some(params) = &b.params {
20 let params = params.clone();20 let params = params.clone();
54pub fn evaluate_field_name(54pub fn evaluate_field_name(
55 context: Context,55 context: Context,
56 field_name: &jsonnet_parser::FieldName,56 field_name: &jsonnet_parser::FieldName,
57) -> Result<Option<String>> {57) -> Result<Option<Rc<str>>> {
58 Ok(match field_name {58 Ok(match field_name {
59 jsonnet_parser::FieldName::Fixed(n) => Some(n.clone()),59 jsonnet_parser::FieldName::Fixed(n) => Some(n.clone()),
60 jsonnet_parser::FieldName::Dyn(expr) => {60 jsonnet_parser::FieldName::Dyn(expr) => {
61 let value = evaluate(context, expr)?.unwrap_if_lazy()?;61 let lazy = evaluate(context, expr)?;
62 let value = lazy.unwrap_if_lazy()?;
62 if matches!(value, Val::Null) {63 if matches!(value, Val::Null) {
63 None64 None
64 } else {65 } else {
8081
81pub(crate) fn evaluate_add_op(a: &Val, b: &Val) -> Result<Val> {82pub(crate) fn evaluate_add_op(a: &Val, b: &Val) -> Result<Val> {
82 Ok(match (a, b) {83 Ok(match (a, b) {
83 (Val::Str(v1), Val::Str(v2)) => Val::Str(v1.to_owned() + &v2),84 (Val::Str(v1), Val::Str(v2)) => Val::Str(((**v1).to_owned() + &v2).into()),
8485
85 // Can't use generic json serialization way, because it depends on number to string concatenation (std.jsonnet:890)86 // Can't use generic json serialization way, because it depends on number to string concatenation (std.jsonnet:890)
86 (Val::Num(n), Val::Str(o)) => Val::Str(format!("{}{}", n, o)),87 (Val::Num(n), Val::Str(o)) => Val::Str(format!("{}{}", n, o).into()),
87 (Val::Str(o), Val::Num(n)) => Val::Str(format!("{}{}", o, n)),88 (Val::Str(o), Val::Num(n)) => Val::Str(format!("{}{}", o, n).into()),
8889
89 (Val::Str(s), o) => Val::Str(format!("{}{}", s, o.clone().into_json(0)?)),90 (Val::Str(s), o) => Val::Str(format!("{}{}", s, o.clone().into_json(0)?).into()),
90 (o, Val::Str(s)) => Val::Str(format!("{}{}", o.clone().into_json(0)?, s)),91 (o, Val::Str(s)) => Val::Str(format!("{}{}", o.clone().into_json(0)?, s).into()),
9192
92 (Val::Obj(v1), Val::Obj(v2)) => Val::Obj(v2.with_super(v1.clone())),93 (Val::Obj(v1), Val::Obj(v2)) => Val::Obj(v2.with_super(v1.clone())),
93 (Val::Arr(a), Val::Arr(b)) => Val::Arr([&a[..], &b[..]].concat()),94 (Val::Arr(a), Val::Arr(b)) => Val::Arr(Rc::new([&a[..], &b[..]].concat())),
94 (Val::Num(v1), Val::Num(v2)) => Val::Num(v1 + v2),95 (Val::Num(v1), Val::Num(v2)) => Val::Num(v1 + v2),
95 _ => panic!("can't add: {:?} and {:?}", a, b),96 _ => panic!("can't add: {:?} and {:?}", a, b),
96 })97 })
117 Ok(match (a, op, b) {118 Ok(match (a, op, b) {
118 (a, BinaryOpType::Add, b) => evaluate_add_op(a, b)?,119 (a, BinaryOpType::Add, b) => evaluate_add_op(a, b)?,
119120
120 (Val::Str(v1), BinaryOpType::Mul, Val::Num(v2)) => Val::Str(v1.repeat(*v2 as usize)),121 (Val::Str(v1), BinaryOpType::Mul, Val::Num(v2)) => Val::Str(v1.repeat(*v2 as usize).into()),
121122
122 // Bool X Bool123 // Bool X Bool
123 (Val::Bool(a), BinaryOpType::And, Val::Bool(b)) => Val::Bool(*a && *b),124 (Val::Bool(a), BinaryOpType::And, Val::Bool(b)) => Val::Bool(*a && *b),
165 })166 })
166}167}
167168
168future_wrapper!(HashMap<String, LazyBinding>, FutureNewBindings);169future_wrapper!(HashMap<Rc<str>, LazyBinding>, FutureNewBindings);
169future_wrapper!(ObjValue, FutureObjValue);170future_wrapper!(ObjValue, FutureObjValue);
170171
171pub fn evaluate_comp<T>(172pub fn evaluate_comp<T>(
186 match evaluate(context.clone(), &expr)?.unwrap_if_lazy()? {187 match evaluate(context.clone(), &expr)?.unwrap_if_lazy()? {
187 Val::Arr(list) => {188 Val::Arr(list) => {
188 let mut out = Vec::new();189 let mut out = Vec::new();
189 for item in list {190 for item in list.iter() {
190 let item = item.clone().unwrap_if_lazy()?;191 let item = item.unwrap_if_lazy()?;
191 out.push(evaluate_comp(192 out.push(evaluate_comp(
192 context.with_var(var.clone(), item)?,193 context.with_var(var.clone(), item.clone())?,
193 value,194 value,
194 &specs[1..],195 &specs[1..],
195 )?);196 )?);
202 })203 })
203}204}
204205
206pub fn evaluate_member_list_object(context: Context, members: &Vec<Member>) -> Result<ObjValue> {
207 let new_bindings = FutureNewBindings::new();
208 let future_this = FutureObjValue::new();
209 let context_creator = context_creator!(
210 closure!(clone context, clone new_bindings, |this: Option<ObjValue>, super_obj: Option<ObjValue>| {
211 Ok(context.extend_unbound(
212 new_bindings.clone().unwrap(),
213 context.dollar().clone().or_else(||this.clone()),
214 Some(this.unwrap()),
215 super_obj
216 )?)
217 })
218 );
219 {
220 let mut bindings: HashMap<Rc<str>, LazyBinding> = HashMap::new();
221 for (n, b) in members
222 .iter()
223 .filter_map(|m| match m {
224 Member::BindStmt(b) => Some(b.clone()),
225 _ => None,
226 })
227 .map(|b| evaluate_binding(&b, context_creator.clone()))
228 {
229 bindings.insert(n, b);
230 }
231 new_bindings.fill(bindings);
232 }
233
234 let mut new_members = BTreeMap::new();
235 for member in members.iter() {
236 match member {
237 Member::Field(FieldMember {
238 name,
239 plus,
240 params: None,
241 visibility,
242 value,
243 }) => {
244 let name = evaluate_field_name(context.clone(), &name)?;
245 if name.is_none() {
246 continue;
247 }
248 let name = name.unwrap();
249 new_members.insert(
250 name.clone(),
251 ObjMember {
252 add: *plus,
253 visibility: *visibility,
254 invoke: LazyBinding::Bindable(Rc::new(
255 closure!(clone name, clone value, clone context_creator, |this, super_obj| {
256 Ok(LazyVal::new_resolved(push(&value.1, "object field", ||{
257 let context = context_creator.0(this, super_obj)?;
258 evaluate(
259 context,
260 &value,
261 )
262 })?))
263 }),
264 )),
265 },
266 );
267 }
268 Member::Field(FieldMember {
269 name,
270 params: Some(params),
271 value,
272 ..
273 }) => {
274 let name = evaluate_field_name(context.clone(), &name)?;
275 if name.is_none() {
276 continue;
277 }
278 let name = name.unwrap();
279 new_members.insert(
280 name,
281 ObjMember {
282 add: false,
283 visibility: Visibility::Hidden,
284 invoke: LazyBinding::Bindable(Rc::new(
285 closure!(clone value, clone context_creator, clone params, |this, super_obj| {
205// TODO: Asserts286 // TODO: Assert
287 Ok(LazyVal::new_resolved(evaluate_method(
288 context_creator.0(this, super_obj)?,
289 params.clone(),
290 value.clone(),
291 )))
292 }),
293 )),
294 },
295 );
296 }
297 Member::BindStmt(_) => {}
298 Member::AssertStmt(_) => {}
299 }
300 }
301 Ok(future_this.fill(ObjValue::new(None, Rc::new(new_members))))
302}
303
206pub fn evaluate_object(context: Context, object: ObjBody) -> Result<ObjValue> {304pub fn evaluate_object(context: Context, object: &ObjBody) -> Result<ObjValue> {
207 Ok(match object {305 Ok(match object {
208 ObjBody::MemberList(members) => {306 ObjBody::MemberList(members) => evaluate_member_list_object(context, &members)?,
209 let new_bindings = FutureNewBindings::new();
210 let future_this = FutureObjValue::new();
211 let context_creator = context_creator!(
212 closure!(clone context, clone new_bindings, |this: Option<ObjValue>, super_obj: Option<ObjValue>| {
213 Ok(context.extend_unbound(
214 new_bindings.clone().unwrap(),
215 context.dollar().clone().or_else(||this.clone()),
216 Some(this.unwrap()),
217 super_obj
218 )?)
219 })
220 );
221 {
222 let mut bindings: HashMap<String, LazyBinding> = HashMap::new();
223 for (n, b) in members
224 .iter()
225 .filter_map(|m| match m {
226 Member::BindStmt(b) => Some(b.clone()),
227 _ => None,
228 })
229 .map(|b| evaluate_binding(&b, context_creator.clone()))
230 {
231 bindings.insert(n, b);
232 }
233 new_bindings.fill(bindings);
234 }
235
236 let mut new_members = BTreeMap::new();
237 for member in members.into_iter() {
238 match member {
239 Member::Field(FieldMember {
240 name,
241 plus,
242 params: None,
243 visibility,
244 value,
245 }) => {
246 let name = evaluate_field_name(context.clone(), &name)?;
247 if name.is_none() {
248 continue;
249 }
250 let name = name.unwrap();
251 new_members.insert(
252 name.clone(),
253 ObjMember {
254 add: plus,
255 visibility: visibility.clone(),
256 invoke: LazyBinding::Bindable(Rc::new(
257 closure!(clone name, clone value, clone context_creator, |this, super_obj| {
258 Ok(LazyVal::new_resolved(push(&value.1, "object field", ||{
259 let context = context_creator.0(this, super_obj)?;
260 evaluate(
261 context,
262 &value,
263 )?.unwrap_if_lazy()
264 })?))
265 }),
266 )),
267 },
268 );
269 }
270 Member::Field(FieldMember {
271 name,
272 params: Some(params),
273 value,
274 ..
275 }) => {
276 let name = evaluate_field_name(context.clone(), &name)?;
277 if name.is_none() {
278 continue;
279 }
280 let name = name.unwrap();
281 new_members.insert(
282 name,
283 ObjMember {
284 add: false,
285 visibility: Visibility::Hidden,
286 invoke: LazyBinding::Bindable(Rc::new(
287 closure!(clone value, clone context_creator, |this, super_obj| {
288 // TODO: Assert
289 Ok(LazyVal::new_resolved(evaluate_method(
290 context_creator.0(this, super_obj)?,
291 params.clone(),
292 value.clone(),
293 )))
294 }),
295 )),
296 },
297 );
298 }
299 Member::BindStmt(_) => {}
300 Member::AssertStmt(_) => {}
301 }
302 }
303 future_this.fill(ObjValue::new(None, Rc::new(new_members)))
304 }
305 ObjBody::ObjComp {307 ObjBody::ObjComp(obj) => {
306 pre_locals,
307 key,
308 value,
309 post_locals,
310 compspecs,
311 } => {
312 let future_this = FutureObjValue::new();308 let future_this = FutureObjValue::new();
313 let mut new_members = BTreeMap::new();309 let mut new_members = BTreeMap::new();
314 for (k, v) in evaluate_comp(310 for (k, v) in evaluate_comp(
325 )?)321 )?)
326 })322 })
327 );323 );
328 let mut bindings: HashMap<String, LazyBinding> = HashMap::new();324 let mut bindings: HashMap<Rc<str>, LazyBinding> = HashMap::new();
329 for (n, b) in pre_locals325 for (n, b) in obj
326 .pre_locals
330 .iter()327 .iter()
331 .chain(post_locals.iter())328 .chain(obj.post_locals.iter())
332 .map(|b| evaluate_binding(b, context_creator.clone()))329 .map(|b| evaluate_binding(b, context_creator.clone()))
333 {330 {
334 bindings.insert(n, b);331 bindings.insert(n, b);
335 }332 }
336 let bindings = new_bindings.fill(bindings);333 let bindings = new_bindings.fill(bindings);
337 let ctx = ctx.extend_unbound(bindings, None, None, None)?;334 let ctx = ctx.extend_unbound(bindings, None, None, None)?;
338 let key = evaluate(ctx.clone(), &key)?;335 let key = evaluate(ctx.clone(), &obj.key)?;
339 let value = LazyBinding::Bindable(Rc::new(336 let value = LazyBinding::Bindable(Rc::new(
340 closure!(clone ctx, clone value, |this, _super_obj| {337 closure!(clone ctx, clone obj.value, |this, _super_obj| {
341 Ok(LazyVal::new_resolved(evaluate(ctx.extend(HashMap::new(), None, this, None)?, &value)?))338 Ok(LazyVal::new_resolved(evaluate(ctx.extend(HashMap::new(), None, this, None)?, &value)?))
342 }),339 }),
343 ));340 ));
344341
345 Ok((key, value))342 Ok((key, value))
346 },343 },
347 &compspecs,344 &obj.compspecs,
348 )?345 )?
349 .unwrap()346 .unwrap()
350 {347 {
394 BinaryOp(v1, o, v2) => evaluate_binary_op_special(context, &v1, *o, &v2)?,391 BinaryOp(v1, o, v2) => evaluate_binary_op_special(context, &v1, *o, &v2)?,
395 UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(context, v)?)?,392 UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(context, v)?)?,
396 Var(name) => push(loc, "var", || {393 Var(name) => push(loc, "var", || {
397 Val::Lazy(context.binding(&name)?).unwrap_if_lazy()394 Ok(Val::Lazy(context.binding(name.clone())?).unwrap_if_lazy()?)
398 })?,395 })?,
399 Index(LocExpr(v, _), index) if matches!(&**v, Expr::Literal(LiteralType::Super)) => {396 Index(LocExpr(v, _), index) if matches!(&**v, Expr::Literal(LiteralType::Super)) => {
400 let name = evaluate(context.clone(), index)?.try_cast_str("object index")?;397 let name = evaluate(context.clone(), index)?.try_cast_str("object index")?;
411 evaluate(context, index)?,408 evaluate(context, index)?,
412 ) {409 ) {
413 (Val::Obj(v), Val::Str(s)) => {410 (Val::Obj(v), Val::Str(s)) => {
414 if let Some(v) = v.get(&s)? {411 if let Some(v) = v.get(s.clone())? {
415 v.unwrap_if_lazy()?412 v.unwrap_if_lazy()?
416 } else if let Some(Val::Str(n)) = v.get("__intristic_namespace__")? {413 } else if let Some(Val::Str(n)) = v.get("__intristic_namespace__".into())? {
417 Val::Intristic(n, s)414 Val::Intristic(n, s)
418 } else {415 } else {
419 create_error(crate::Error::NoSuchField(s))?416 create_error(crate::Error::NoSuchField(s))?
443 n.value_type()?,440 n.value_type()?,
444 ))?,441 ))?,
445442
446 (Val::Str(s), Val::Num(n)) => {443 (Val::Str(s), Val::Num(n)) => Val::Str(
447 Val::Str(s.chars().skip(n as usize).take(1).collect())444 s.chars()
448 }445 .skip(n as usize)
446 .take(1)
447 .collect::<String>()
448 .into(),
449 ),
449 (Val::Str(_), n) => create_error(crate::Error::ValueIndexMustBeTypeGot(450 (Val::Str(_), n) => create_error(crate::Error::ValueIndexMustBeTypeGot(
450 ValType::Str,451 ValType::Str,
451 ValType::Num,452 ValType::Num,
456 }457 }
457 }458 }
458 LocalExpr(bindings, returned) => {459 LocalExpr(bindings, returned) => {
459 let mut new_bindings: HashMap<String, LazyBinding> = HashMap::new();460 let mut new_bindings: HashMap<Rc<str>, LazyBinding> = HashMap::new();
460 let future_context = Context::new_future();461 let future_context = Context::new_future();
461462
462 let context_creator = context_creator!(463 let context_creator = context_creator!(
484 })485 })
485 )));486 )));
486 }487 }
487 Val::Arr(out)488 Val::Arr(Rc::new(out))
488 }489 }
489 ArrComp(expr, compspecs) => Val::Arr(490 ArrComp(expr, compspecs) => Val::Arr(
490 // First compspec should be forspec, so no "None" possible here491 // First compspec should be forspec, so no "None" possible here
491 evaluate_comp(context, &|ctx| evaluate(ctx, expr), compspecs)?.unwrap(),492 Rc::new(evaluate_comp(context, &|ctx| evaluate(ctx, expr), compspecs)?.unwrap()),
492 ),493 ),
493 Obj(body) => Val::Obj(evaluate_object(context, body.clone())?),494 Obj(body) => Val::Obj(evaluate_object(context, body)?),
494 ObjExtend(s, t) => evaluate_add_op(495 ObjExtend(s, t) => evaluate_add_op(
495 &evaluate(context.clone(), s)?,496 &evaluate(context.clone(), s)?,
496 &Val::Obj(evaluate_object(context, t.clone())?),497 &Val::Obj(evaluate_object(context, t)?),
497 )?,498 )?,
498 Apply(value, args, tailstrict) => {499 Apply(value, args, tailstrict) => {
499 let value = evaluate(context.clone(), value)?.unwrap_if_lazy()?;500 let lazy = evaluate(context.clone(), value)?;
501 let value = lazy.unwrap_if_lazy()?;
500 match value {502 match value {
501 Val::Intristic(ns, name) => match (&ns as &str, &name as &str) {503 Val::Intristic(ns, name) => match (&ns as &str, &name as &str) {
502 // arr/string/function504 // arr/string/function
519 ("std", "type") => {521 ("std", "type") => {
520 assert_eq!(args.len(), 1);522 assert_eq!(args.len(), 1);
521 let expr = &args.get(0).unwrap().1;523 let expr = &args.get(0).unwrap().1;
522 Val::Str(evaluate(context, expr)?.value_type()?.name().to_owned())524 Val::Str(evaluate(context, expr)?.value_type()?.name().into())
523 }525 }
524 // length, idx=>any526 // length, idx=>any
525 ("std", "makeArray") => {527 ("std", "makeArray") => {
532 let mut out = Vec::with_capacity(v as usize);534 let mut out = Vec::with_capacity(v as usize);
533 for i in 0..v as usize {535 for i in 0..v as usize {
534 let call_ctx =536 let call_ctx =
535 Context::new().with_var("v".to_owned(), Val::Num(i as f64))?;537 Context::new().with_var("v".into(), Val::Num(i as f64))?;
536 out.push(d.evaluate(538 out.push(d.evaluate(
537 call_ctx,539 call_ctx,
538 &ArgsDesc(vec![Arg(None, el!(Expr::Var("v".to_owned())))]),540 &ArgsDesc(vec![Arg(None, el!(Expr::Var("v".into())))]),
539 true,541 true,
540 )?)542 )?)
541 }543 }
542 Val::Arr(out)544 Val::Arr(Rc::new(out))
543 } else {545 } else {
544 panic!("bad makeArray call");546 panic!("bad makeArray call");
545 }547 }
564 evaluate(context.clone(), &args[0].1)?,566 evaluate(context.clone(), &args[0].1)?,
565 evaluate(context, &args[1].1)?,567 evaluate(context, &args[1].1)?,
566 ) {568 ) {
567 Val::Arr(569 Val::Arr(Rc::new(
568 body.fields_visibility()570 body.fields_visibility()
569 .into_iter()571 .into_iter()
570 .filter(|(_k, v)| *v || include_hidden)572 .filter(|(_k, v)| *v || include_hidden)
571 .map(|(k, _v)| Val::Str(k))573 .map(|(k, _v)| Val::Str(k))
572 .collect(),574 .collect(),
573 )575 ))
574 } else {576 } else {
575 panic!("bad objectFieldsEx call");577 panic!("bad objectFieldsEx call");
576 }578 }
587 body.fields_visibility()589 body.fields_visibility()
588 .into_iter()590 .into_iter()
589 .filter(|(_k, v)| *v || include_hidden)591 .filter(|(_k, v)| *v || include_hidden)
590 .any(|(k, _v)| k == name),592 .any(|(k, _v)| *k == *name),
591 )593 )
592 } else {594 } else {
593 panic!("bad objectHasEx call");595 panic!("bad objectHasEx call");
664 evaluate(context.clone(), &args[0].1)?,666 evaluate(context.clone(), &args[0].1)?,
665 evaluate(context.clone(), &args[1].1)?,667 evaluate(context.clone(), &args[1].1)?,
666 ) {668 ) {
667 Val::Arr(669 Val::Arr(Rc::new(
668 arr.into_iter()670 arr.iter()
669 .filter(|e| {671 .filter(|e| {
670 predicate672 predicate
671 .evaluate_values(context.clone(), &[e.clone()])673 .evaluate_values(context.clone(), &[e.clone()])
672 .unwrap()674 .unwrap()
673 .try_cast_bool("filter predicate")675 .try_cast_bool("filter predicate")
674 .unwrap()676 .unwrap()
675 })677 })
678 .cloned()
676 .collect(),679 .collect(),
677 )680 ))
678 } else {681 } else {
679 panic!("bad filter call");682 panic!("bad filter call");
680 }683 }
681 }684 }
682 // faster685 // faster
683 ("std", "join") => {686 ("std", "join") => {
684 assert_eq!(args.len(), 2);687 assert_eq!(args.len(), 2);
685 let joiner = evaluate(context.clone(), &args[0].1)?.unwrap_if_lazy()?;688 let joiner = evaluate(context.clone(), &args[0].1)?;
686 let items = evaluate(context, &args[1].1)?.unwrap_if_lazy()?;689 let items = evaluate(context, &args[1].1)?;
687 match (joiner, items) {690 match (joiner.unwrap_if_lazy()?, items.unwrap_if_lazy()?) {
688 (Val::Arr(joiner_items), Val::Arr(items)) => {691 (Val::Arr(joiner_items), Val::Arr(items)) => {
689 // TODO: Minimal size should be known692 // TODO: Minimal size should be known
690 let mut out = Vec::new();693 let mut out = Vec::new();
691694
692 let mut first = true;695 let mut first = true;
693 for item in items {696 for item in items.iter().cloned() {
694 if let Val::Arr(items) = item.unwrap_if_lazy()? {697 if let Val::Arr(items) = item.unwrap_if_lazy()? {
695 if !first {698 if !first {
699 out.reserve(joiner_items.len());
696 out.extend(joiner_items.iter().cloned());700 out.extend(joiner_items.iter().cloned());
697 }701 }
698 first = false;702 first = false;
703 out.reserve(items.len());
699 out.extend(items);704 out.extend(items.iter().cloned());
700 } else {705 } else {
701 panic!("all array items should be arrays")706 panic!("all array items should be arrays")
702 }707 }
703 }708 }
704709
705 Val::Arr(out)710 Val::Arr(Rc::new(out))
706 }711 }
707 (Val::Str(joiner), Val::Arr(items)) => {712 (Val::Str(joiner), Val::Arr(items)) => {
708 let mut out = String::new();713 let mut out = String::new();
709714
710 let mut first = true;715 let mut first = true;
711 for item in items {716 for item in items.iter().cloned() {
712 if let Val::Str(item) = item.unwrap_if_lazy()? {717 if let Val::Str(item) = item.unwrap_if_lazy()? {
713 if !first {718 if !first {
714 out += &joiner;719 out += &joiner;
720 }725 }
721 }726 }
722727
723 Val::Str(out)728 Val::Str(out.into())
724 }729 }
725 (joiner, items) => panic!("bad join call: {:?} {:?}", joiner, items),730 (joiner, items) => panic!("bad join call: {:?} {:?}", joiner, items),
726 }731 }
776 }781 }
777 }782 }
778 Import(path) => {783 Import(path) => {
779 let mut import_location = loc784 let mut tmp = loc
780 .clone()785 .clone()
781 .expect("imports can't be used without loc_data")786 .expect("imports can't be used without loc_data")
782 .0787 .0;
783 .clone();788 let import_location = Rc::make_mut(&mut tmp);
784 import_location.pop();789 import_location.pop();
785 with_state(|s| s.import_file(&import_location, path))?790 with_state(|s| s.import_file(&import_location, path))?
786 }791 }
787 ImportStr(path) => {792 ImportStr(path) => {
788 let mut import_location = loc793 let mut tmp = loc
789 .clone()794 .clone()
790 .expect("imports can't be used without loc_data")795 .expect("imports can't be used without loc_data")
791 .0796 .0;
792 .clone();797 let import_location = Rc::make_mut(&mut tmp);
793 import_location.pop();798 import_location.pop();
794 Val::Str(with_state(|s| s.import_file_str(&import_location, path))?)799 Val::Str(with_state(|s| s.import_file_str(&import_location, path))?)
795 }800 }
modifiedcrates/jsonnet-evaluator/src/function.rsdiffbeforeafterboth
35 let mut positioned_args = vec![None; params.0.len()];35 let mut positioned_args = vec![None; params.0.len()];
36 for (id, arg) in args.iter().enumerate() {36 for (id, arg) in args.iter().enumerate() {
37 let idx = if let Some(name) = &arg.0 {37 let idx = if let Some(name) = &arg.0 {
38 params.iter().position(|p| &p.0 == name).ok_or_else(|| {38 params.iter().position(|p| *p.0 == *name).ok_or_else(|| {
39 create_error::<()>(Error::UnknownFunctionParameter(name.clone()))39 create_error::<()>(Error::UnknownFunctionParameter(name.clone()))
40 .err()40 .err()
41 .unwrap()41 .unwrap()
modifiedcrates/jsonnet-evaluator/src/lib.rsdiffbeforeafterboth
65 /// Contains file source codes and evaluated results for imports and pretty65 /// Contains file source codes and evaluated results for imports and pretty
66 /// printing stacktraces66 /// printing stacktraces
67 files: RefCell<HashMap<PathBuf, FileData>>,67 files: RefCell<HashMap<PathBuf, FileData>>,
68 str_files: RefCell<HashMap<PathBuf, String>>,68 str_files: RefCell<HashMap<PathBuf, Rc<str>>>,
69 globals: RefCell<HashMap<String, Val>>,69 globals: RefCell<HashMap<Rc<str>, Val>>,
7070
71 /// Values to use with std.extVar71 /// Values to use with std.extVar
72 ext_vars: RefCell<HashMap<String, Val>>,72 ext_vars: RefCell<HashMap<Rc<str>, Val>>,
7373
74 settings: EvaluationSettings,74 settings: EvaluationSettings,
75 import_resolver: Box<dyn ImportResolver>,75 import_resolver: Box<dyn ImportResolver>,
87 with_state(|s| s.error(err))87 with_state(|s| s.error(err))
88}88}
89pub(crate) fn push<T>(89pub(crate) fn push<T>(
90 e: &Option<Rc<ExprLocation>>,90 e: &Option<ExprLocation>,
91 comment: &str,91 comment: &str,
92 f: impl FnOnce() -> Result<T>,92 f: impl FnOnce() -> Result<T>,
93) -> Result<T> {93) -> Result<T> {
185 })?;185 })?;
186 self.evaluate_file(&file_path)186 self.evaluate_file(&file_path)
187 }187 }
188 pub(crate) fn import_file_str(&self, from: &PathBuf, path: &PathBuf) -> Result<String> {188 pub(crate) fn import_file_str(&self, from: &PathBuf, path: &PathBuf) -> Result<Rc<str>> {
189 let path = self.0.import_resolver.resolve_file(from, path)?;189 let path = self.0.import_resolver.resolve_file(from, path)?;
190 if !self.0.str_files.borrow().contains_key(&path) {190 if !self.0.str_files.borrow().contains_key(&path) {
191 let file_str = self.0.import_resolver.load_file_contents(&path)?;191 let file_str = self.0.import_resolver.load_file_contents(&path)?;
192 self.0.str_files.borrow_mut().insert(path.clone(), file_str);192 self.0
193 .str_files
194 .borrow_mut()
195 .insert(path.clone(), file_str.into());
193 }196 }
194 Ok(self.0.str_files.borrow().get(&path).cloned().unwrap())197 Ok(self.0.str_files.borrow().get(&path).cloned().unwrap())
195 }198 }
210 self.run_in_state(|| evaluate(self.create_default_context()?, &code))213 self.run_in_state(|| evaluate(self.create_default_context()?, &code))
211 }214 }
212215
213 pub fn add_global(&self, name: String, value: Val) {216 pub fn add_global(&self, name: Rc<str>, value: Val) {
214 self.0.globals.borrow_mut().insert(name, value);217 self.0.globals.borrow_mut().insert(name, value);
215 }218 }
216 pub fn add_ext_var(&self, name: String, value: Val) {219 pub fn add_ext_var(&self, name: Rc<str>, value: Val) {
217 self.0.ext_vars.borrow_mut().insert(name, value);220 self.0.ext_vars.borrow_mut().insert(name, value);
218 }221 }
219222
236 .unwrap();239 .unwrap();
237 }240 }
238 let val = self.evaluate_file(&PathBuf::from("std.jsonnet")).unwrap();241 let val = self.evaluate_file(&PathBuf::from("std.jsonnet")).unwrap();
239 self.add_global("std".to_owned(), val);242 self.add_global("std".into(), val);
240 });243 });
241 self244 self
242 }245 }
243246
244 pub fn create_default_context(&self) -> Result<Context> {247 pub fn create_default_context(&self) -> Result<Context> {
245 let globals = self.0.globals.borrow();248 let globals = self.0.globals.borrow();
246 let mut new_bindings: HashMap<String, LazyBinding> = HashMap::new();249 let mut new_bindings: HashMap<Rc<str>, LazyBinding> = HashMap::new();
247 for (name, value) in globals.iter() {250 for (name, value) in globals.iter() {
248 new_bindings.insert(251 new_bindings.insert(
249 name.clone(),252 name.clone(),
255258
256 pub fn push<T>(259 pub fn push<T>(
257 &self,260 &self,
258 e: Rc<ExprLocation>,261 e: ExprLocation,
259 comment: String,262 comment: String,
260 f: impl FnOnce() -> Result<T>,263 f: impl FnOnce() -> Result<T>,
261 ) -> Result<T> {264 ) -> Result<T> {
362 let evaluator = EvaluationState::default();365 let evaluator = EvaluationState::default();
363 evaluator.with_stdlib();366 evaluator.with_stdlib();
364 let val = evaluator.parse_evaluate_raw($str).unwrap();367 let val = evaluator.parse_evaluate_raw($str).unwrap();
365 evaluator.add_global("__tmp__to_yaml__".to_owned(), val);368 evaluator.add_global("__tmp__to_yaml__".into(), val);
366 evaluator369 evaluator
367 .parse_evaluate_raw("std.manifestJsonEx(__tmp__to_yaml__, \"\")")370 .parse_evaluate_raw("std.manifestJsonEx(__tmp__to_yaml__, \"\")")
368 .unwrap()371 .unwrap()
modifiedcrates/jsonnet-evaluator/src/obj.rsdiffbeforeafterboth
18#[derive(Debug)]18#[derive(Debug)]
19pub struct ObjValueInternals {19pub struct ObjValueInternals {
20 super_obj: Option<ObjValue>,20 super_obj: Option<ObjValue>,
21 this_entries: Rc<BTreeMap<String, ObjMember>>,21 this_entries: Rc<BTreeMap<Rc<str>, ObjMember>>,
22 value_cache: RefCell<HashMap<String, Val>>,22 value_cache: RefCell<HashMap<Rc<str>, Val>>,
23}23}
24#[derive(Clone)]
24pub struct ObjValue(pub(crate) Rc<ObjValueInternals>);25pub struct ObjValue(pub(crate) Rc<ObjValueInternals>);
25impl Debug for ObjValue {26impl Debug for ObjValue {
26 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43impl ObjValue {44impl ObjValue {
44 pub fn new(45 pub fn new(
45 super_obj: Option<ObjValue>,46 super_obj: Option<ObjValue>,
46 this_entries: Rc<BTreeMap<String, ObjMember>>,47 this_entries: Rc<BTreeMap<Rc<str>, ObjMember>>,
47 ) -> ObjValue {48 ) -> ObjValue {
48 ObjValue(Rc::new(ObjValueInternals {49 ObjValue(Rc::new(ObjValueInternals {
49 super_obj,50 super_obj,
57 Some(v) => ObjValue::new(Some(v.with_super(super_obj)), self.0.this_entries.clone()),58 Some(v) => ObjValue::new(Some(v.with_super(super_obj)), self.0.this_entries.clone()),
58 }59 }
59 }60 }
60 pub fn enum_fields(&self, handler: &impl Fn(&str, &Visibility)) {61 pub fn enum_fields(&self, handler: &impl Fn(&Rc<str>, &Visibility)) {
61 if let Some(s) = &self.0.super_obj {62 if let Some(s) = &self.0.super_obj {
62 s.enum_fields(handler);63 s.enum_fields(handler);
63 }64 }
64 for (name, member) in self.0.this_entries.iter() {65 for (name, member) in self.0.this_entries.iter() {
65 handler(&name, &member.visibility);66 handler(&name, &member.visibility);
66 }67 }
67 }68 }
68 pub fn fields_visibility(&self) -> IndexMap<String, bool> {69 pub fn fields_visibility(&self) -> IndexMap<Rc<str>, bool> {
69 let out = Rc::new(RefCell::new(IndexMap::new()));70 let out = Rc::new(RefCell::new(IndexMap::new()));
70 self.enum_fields(&|name, visibility| {71 self.enum_fields(&|name, visibility| {
71 let mut out = out.borrow_mut();72 let mut out = out.borrow_mut();
85 });86 });
86 Rc::try_unwrap(out).unwrap().into_inner()87 Rc::try_unwrap(out).unwrap().into_inner()
87 }88 }
89 pub fn visible_fields(&self) -> Vec<Rc<str>> {
90 self.fields_visibility()
91 .into_iter()
92 .filter(|(_k, v)| *v)
93 .map(|(k, _)| k)
94 .collect()
95 }
88 pub fn get(&self, key: &str) -> Result<Option<Val>> {96 pub fn get(&self, key: Rc<str>) -> Result<Option<Val>> {
89 if let Some(v) = self.0.value_cache.borrow().get(key) {97 if let Some(v) = self.0.value_cache.borrow().get(&key) {
90 return Ok(Some(v.clone()));98 return Ok(Some(v.clone()));
91 }99 }
92 if let Some(v) = self.get_raw(key, self)? {100 if let Some(v) = self.get_raw(&key, self)? {
93 let v = v.unwrap_if_lazy()?;101 let v = v.unwrap_if_lazy()?;
94 self.0102 self.0.value_cache.borrow_mut().insert(key, v.clone());
95 .value_cache
96 .borrow_mut()
97 .insert(key.to_owned(), v.clone());
98 Ok(Some(v))103 Ok(Some(v))
99 } else {104 } else {
100 Ok(None)105 Ok(None)
108 .evaluate()?,113 .evaluate()?,
109 )),114 )),
110 (Some(k), Some(s)) => {115 (Some(k), Some(s)) => {
111 let our = k116 let lazy = k
112 .invoke117 .invoke
113 .evaluate(Some(real_this.clone()), self.0.super_obj.clone())?118 .evaluate(Some(real_this.clone()), self.0.super_obj.clone())?;
114 .evaluate()?;119 let our = lazy.evaluate()?;
115 if k.add {120 if k.add {
116 s.get_raw(key, real_this)?121 s.get_raw(key, real_this)?
117 .map_or(Ok(Some(our.clone())), |v| {122 .map_or(Ok(Some(our.clone())), |v| {
126 }131 }
127 }132 }
128}133}
129impl Clone for ObjValue {
130 fn clone(&self) -> Self {
131 ObjValue(self.0.clone())
132 }
133}
134impl PartialEq for ObjValue {134impl PartialEq for ObjValue {
135 fn eq(&self, other: &Self) -> bool {135 fn eq(&self, other: &Self) -> bool {
136 Rc::ptr_eq(&self.0, &other.0)136 Rc::ptr_eq(&self.0, &other.0)
modifiedcrates/jsonnet-evaluator/src/val.rsdiffbeforeafterboth
81 }81 }
82}82}
8383
84#[derive(Debug, Clone)]84#[derive(Debug, Clone, Copy, PartialEq)]
85pub enum ValType {85pub enum ValType {
86 Bool,86 Bool,
87 Null,87 Null,
115pub enum Val {115pub enum Val {
116 Bool(bool),116 Bool(bool),
117 Null,117 Null,
118 Str(String),118 Str(Rc<str>),
119 Num(f64),119 Num(f64),
120 Lazy(LazyVal),120 Lazy(LazyVal),
121 Arr(Vec<Val>),121 Arr(Rc<Vec<Val>>),
122 Obj(ObjValue),122 Obj(ObjValue),
123 Func(FuncDesc),123 Func(FuncDesc),
124124
125 // Library functions implemented in native125 // Library functions implemented in native
126 Intristic(String, String),126 Intristic(Rc<str>, Rc<str>),
127}127}
128macro_rules! matches_unwrap {
129 ($e: expr, $p: pat, $r: expr) => {
130 match $e {
131 $p => $r,
132 _ => panic!("no match"),
133 }
134 };
135}
128impl Val {136impl Val {
129 pub fn try_cast_bool(self, context: &'static str) -> Result<bool> {137 pub fn assert_type(&self, context: &'static str, val_type: ValType) -> Result<()> {
130 match self.unwrap_if_lazy()? {138 let this_type = self.value_type()?;
131 Val::Bool(v) => Ok(v),139 if this_type != val_type {
132 v => create_error(Error::TypeMismatch(140 create_error(Error::TypeMismatch(context, vec![val_type], this_type))
133 context,
134 vec![ValType::Bool],
135 v.value_type()?,141 } else {
136 )),142 Ok(())
137 }143 }
138 }144 }
139 pub fn try_cast_str(self, context: &'static str) -> Result<String> {145 pub fn try_cast_bool(self, context: &'static str) -> Result<bool> {
140 match self.unwrap_if_lazy()? {146 self.assert_type(context, ValType::Bool)?;
141 Val::Str(v) => Ok(v),147 Ok(matches_unwrap!(self.unwrap_if_lazy()?, Val::Bool(v), v))
142 v => create_error(Error::TypeMismatch(
143 context,
144 vec![ValType::Str],
145 v.value_type()?,
146 )),
147 }
148 }148 }
149 pub fn unwrap_if_lazy(self) -> Result<Self> {149 pub fn try_cast_str(self, context: &'static str) -> Result<Rc<str>> {
150 self.assert_type(context, ValType::Str)?;
151 Ok(matches_unwrap!(self.unwrap_if_lazy()?, Val::Str(v), v))
152 }
153 pub fn unwrap_if_lazy(&self) -> Result<Self> {
150 Ok(if let Val::Lazy(v) = self {154 Ok(if let Val::Lazy(v) = self {
151 v.evaluate()?.unwrap_if_lazy()?155 v.evaluate()?.unwrap_if_lazy()?
152 } else {156 } else {
153 self157 self.clone()
154 })158 })
155 }159 }
156 pub fn value_type(&self) -> Result<ValType> {160 pub fn value_type(&self) -> Result<ValType> {
166 Val::Lazy(_) => self.clone().unwrap_if_lazy()?.value_type()?,170 Val::Lazy(_) => self.clone().unwrap_if_lazy()?.value_type()?,
167 })171 })
168 }172 }
169 pub fn into_json(self, padding: usize) -> Result<String> {173 pub fn into_json(self, padding: usize) -> Result<Rc<str>> {
170 with_state(|s| {174 with_state(|s| {
171 let ctx = s175 let ctx = s
172 .create_default_context()?176 .create_default_context()?
173 .with_var("__tmp__to_json__".to_owned(), self)?;177 .with_var("__tmp__to_json__".into(), self)?;
174 if let Val::Str(result) = evaluate(178 Ok(evaluate(
175 ctx,179 ctx,
176 &el!(Expr::Apply(180 &el!(Expr::Apply(
177 el!(Expr::Index(181 el!(Expr::Index(
178 el!(Expr::Var("std".to_owned())),182 el!(Expr::Var("std".into())),
179 el!(Expr::Str("manifestJsonEx".to_owned()))183 el!(Expr::Str("manifestJsonEx".into()))
180 )),184 )),
181 ArgsDesc(vec![185 ArgsDesc(vec![
182 Arg(None, el!(Expr::Var("__tmp__to_json__".to_owned()))),186 Arg(None, el!(Expr::Var("__tmp__to_json__".into()))),
183 Arg(None, el!(Expr::Str(" ".repeat(padding))))187 Arg(None, el!(Expr::Str(" ".repeat(padding).into())))
184 ]),188 ]),
185 false189 false
186 )),190 )),
187 )? {191 )?
188 Ok(result)192 .try_cast_str("to json")?)
193 })
194 }
195}
196
189 } else {197 } else {
190 unreachable!()198 unreachable!()
modifiedcrates/jsonnet-parser/src/expr.rsdiffbeforeafterboth
1use 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};
33
4#[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}
1111
12#[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}
2121
22#[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>);
2424
25#[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}
3333
34#[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}
7272
73/// name, default value73/// name, default value
74#[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 parameters
77#[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.0
83 }83 }
84}84}
8585
86#[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>;
9696
97#[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}
103103
104#[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);
108108
109#[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}
114114
115#[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}123
124#[derive(Debug, PartialEq, Serialize, Deserialize)]
125pub enum ObjBody {
126 MemberList(Vec<Member>),
127 ObjComp(ObjComp),
128}
126129
127#[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}
136139
137#[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}
143146
144/// Syntax base147/// Syntax base
145#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]148#[derive(Debug, PartialEq, Serialize, Deserialize)]
146pub enum Expr {149pub enum Expr {
147 Literal(LiteralType),150 Literal(LiteralType),
148151
149 /// 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+20
152 Num(f64),155 Num(f64),
153 /// Variable name: test156 /// Variable name: test
154 Var(String),157 Var(Rc<str>),
155158
156 /// Array of expressions: [1, 2, "Hello"]159 /// Array of expressions: [1, 2, "Hello"]
157 Arr(Vec<LocExpr>),160 Arr(Vec<LocExpr>),
modifiedcrates/jsonnet-parser/src/lib.rsdiffbeforeafterboth
3939
40 /// Reserved word followed by any non-alphanumberic40 /// Reserved word followed by any non-alphanumberic
41 rule reserved() = ("assert" / "else" / "error" / "false" / "for" / "function" / "if" / "import" / "importstr" / "in" / "local" / "null" / "tailstrict" / "then" / "self" / "super" / "true") end_of_ident()41 rule reserved() = ("assert" / "else" / "error" / "false" / "for" / "function" / "if" / "import" / "importstr" / "in" / "local" / "null" / "tailstrict" / "then" / "self" / "super" / "true") end_of_ident()
42 rule id() -> String = quiet!{ !reserved() s:$(alpha() (alpha() / digit())*) {s.to_owned()}} / expected!("<identifier>")42 rule id() = quiet!{ !reserved() alpha() (alpha() / digit())*} / expected!("<identifier>")
4343
44 rule keyword(id: &'static str)44 rule keyword(id: &'static str)
45 = ##parse_string_literal(id) end_of_ident()45 = ##parse_string_literal(id) end_of_ident()
46 // Adds location data information to existing expression46 // Adds location data information to existing expression
47 rule l(s: &ParserSettings, x: rule<Expr>) -> LocExpr47 rule l(s: &ParserSettings, x: rule<Expr>) -> LocExpr
48 = start:position!() v:x() end:position!() {loc_expr!(v, s.loc_data, (s.file_name.clone(), start, end))}48 = start:position!() v:x() end:position!() {loc_expr!(v, s.loc_data, (s.file_name.clone(), start, end))}
4949
50 pub rule param(s: &ParserSettings) -> expr::Param = name:id() expr:(_ "=" _ expr:expr(s){expr})? { expr::Param(name, expr) }50 pub rule param(s: &ParserSettings) -> expr::Param = name:$(id()) expr:(_ "=" _ expr:expr(s){expr})? { expr::Param(name.into(), expr) }
51 pub rule params(s: &ParserSettings) -> expr::ParamsDesc51 pub rule params(s: &ParserSettings) -> expr::ParamsDesc
52 = params:(param(s) ** comma()) {52 = params:(param(s) ** comma()) {
53 let mut defaults_started = false;53 let mut defaults_started = false;
54 for param in &params {54 for param in &params {
55 defaults_started = defaults_started || param.1.is_some();55 defaults_started = defaults_started || param.1.is_some();
56 assert_eq!(defaults_started, param.1.is_some(), "defauld parameters should be used after all positionals");56 assert_eq!(defaults_started, param.1.is_some(), "defauld parameters should be used after all positionals");
57 }57 }
58 expr::ParamsDesc(params)58 expr::ParamsDesc(Rc::new(params))
59 }59 }
60 / { expr::ParamsDesc(Vec::new()) }60 / { expr::ParamsDesc(Rc::new(Vec::new())) }
6161
62 pub rule arg(s: &ParserSettings) -> expr::Arg62 pub rule arg(s: &ParserSettings) -> expr::Arg
63 = name:id() _ "=" _ expr:expr(s) {expr::Arg(Some(name), expr)}63 = name:$(id()) _ "=" _ expr:expr(s) {expr::Arg(Some(name.into()), expr)}
64 / expr:expr(s) {expr::Arg(None, expr)}64 / expr:expr(s) {expr::Arg(None, expr)}
65 pub rule args(s: &ParserSettings) -> expr::ArgsDesc65 pub rule args(s: &ParserSettings) -> expr::ArgsDesc
66 = args:arg(s) ** comma() comma()? {66 = args:arg(s) ** comma() comma()? {
74 / { expr::ArgsDesc(Vec::new()) }74 / { expr::ArgsDesc(Vec::new()) }
7575
76 pub rule bind(s: &ParserSettings) -> expr::BindSpec76 pub rule bind(s: &ParserSettings) -> expr::BindSpec
77 = name:id() _ "=" _ expr:expr(s) {expr::BindSpec{name, params: None, value: expr}}77 = name:$(id()) _ "=" _ expr:expr(s) {expr::BindSpec{name:name.into(), params: None, value: expr}}
78 / name:id() _ "(" _ params:params(s) _ ")" _ "=" _ expr:expr(s) {expr::BindSpec{name, params: Some(params), value: expr}}78 / name:$(id()) _ "(" _ params:params(s) _ ")" _ "=" _ expr:expr(s) {expr::BindSpec{name:name.into(), params: Some(params), value: expr}}
79 pub rule assertion(s: &ParserSettings) -> expr::AssertStmt79 pub rule assertion(s: &ParserSettings) -> expr::AssertStmt
80 = keyword("assert") _ cond:expr(s) msg:(_ ":" _ e:expr(s) {e})? { expr::AssertStmt(cond, msg) }80 = keyword("assert") _ cond:expr(s) msg:(_ ":" _ e:expr(s) {e})? { expr::AssertStmt(cond, msg) }
8181
95 / string_block()95 / string_block()
9696
97 pub rule field_name(s: &ParserSettings) -> expr::FieldName97 pub rule field_name(s: &ParserSettings) -> expr::FieldName
98 = name:id() {expr::FieldName::Fixed(name)}98 = name:$(id()) {expr::FieldName::Fixed(name.into())}
99 / name:string() {expr::FieldName::Fixed(name)}99 / name:string() {expr::FieldName::Fixed(name.into())}
100 / "[" _ expr:expr(s) _ "]" {expr::FieldName::Dyn(expr)}100 / "[" _ expr:expr(s) _ "]" {expr::FieldName::Dyn(expr)}
101 pub rule visibility() -> expr::Visibility101 pub rule visibility() -> expr::Visibility
102 = ":::" {expr::Visibility::Unhide}102 = ":::" {expr::Visibility::Unhide}
125 / field:field(s) {expr::Member::Field(field)}125 / field:field(s) {expr::Member::Field(field)}
126 pub rule objinside(s: &ParserSettings) -> expr::ObjBody126 pub rule objinside(s: &ParserSettings) -> expr::ObjBody
127 = 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})? {127 = 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})? {
128 let mut compspecs = vec![CompSpec::ForSpec(forspec)];
129 compspecs.extend(others.unwrap_or_default());
128 expr::ObjBody::ObjComp {130 expr::ObjBody::ObjComp(expr::ObjComp{
129 pre_locals,131 pre_locals,
130 key,132 key,
131 value,133 value,
132 post_locals,134 post_locals,
133 compspecs: [vec![CompSpec::ForSpec(forspec)], others.unwrap_or_default()].concat(),135 compspecs,
134 }136 })
135 }137 }
136 / members:(member(s) ** comma()) comma()? {expr::ObjBody::MemberList(members)}138 / members:(member(s) ** comma()) comma()? {expr::ObjBody::MemberList(members)}
137 pub rule ifspec(s: &ParserSettings) -> IfSpecData139 pub rule ifspec(s: &ParserSettings) -> IfSpecData
138 = keyword("if") _ expr:expr(s) {IfSpecData(expr)}140 = keyword("if") _ expr:expr(s) {IfSpecData(expr)}
139 pub rule forspec(s: &ParserSettings) -> ForSpecData141 pub rule forspec(s: &ParserSettings) -> ForSpecData
140 = keyword("for") _ id:id() _ keyword("in") _ cond:expr(s) {ForSpecData(id, cond)}142 = keyword("for") _ id:$(id()) _ keyword("in") _ cond:expr(s) {ForSpecData(id.into(), cond)}
141 pub rule compspec(s: &ParserSettings) -> Vec<expr::CompSpec>143 pub rule compspec(s: &ParserSettings) -> Vec<expr::CompSpec>
142 = s:(i:ifspec(s) { expr::CompSpec::IfSpec(i) } / f:forspec(s) {expr::CompSpec::ForSpec(f)} ) ** _ {s}144 = s:(i:ifspec(s) { expr::CompSpec::IfSpec(i) } / f:forspec(s) {expr::CompSpec::ForSpec(f)} ) ** _ {s}
143 pub rule local_expr(s: &ParserSettings) -> LocExpr145 pub rule local_expr(s: &ParserSettings) -> LocExpr
144 = l(s,<keyword("local") _ binds:bind(s) ** comma() _ ";" _ expr:expr(s) { Expr::LocalExpr(binds, expr) }>)146 = l(s,<keyword("local") _ binds:bind(s) ** comma() _ ";" _ expr:expr(s) { Expr::LocalExpr(binds, expr) }>)
145 pub rule string_expr(s: &ParserSettings) -> LocExpr147 pub rule string_expr(s: &ParserSettings) -> LocExpr
146 = l(s, <s:string() {Expr::Str(s)}>)148 = l(s, <s:string() {Expr::Str(s.into())}>)
147 pub rule obj_expr(s: &ParserSettings) -> LocExpr149 pub rule obj_expr(s: &ParserSettings) -> LocExpr
148 = l(s,<"{" _ body:objinside(s) _ "}" {Expr::Obj(body)}>)150 = l(s,<"{" _ body:objinside(s) _ "}" {Expr::Obj(body)}>)
149 pub rule array_expr(s: &ParserSettings) -> LocExpr151 pub rule array_expr(s: &ParserSettings) -> LocExpr
150 = l(s,<"[" _ elems:(expr(s) ** comma()) _ comma()? "]" {Expr::Arr(elems)}>)152 = l(s,<"[" _ elems:(expr(s) ** comma()) _ comma()? "]" {Expr::Arr(elems)}>)
151 pub rule array_comp_expr(s: &ParserSettings) -> LocExpr153 pub rule array_comp_expr(s: &ParserSettings) -> LocExpr
152 = 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())}>)154 = l(s,<"[" _ expr:expr(s) _ comma()? _ forspec:forspec(s) _ others:(others: compspec(s) _ {others})? "]" {
155 let mut specs = vec![CompSpec::ForSpec(forspec)];
156 specs.extend(others.unwrap_or_default());
157 Expr::ArrComp(expr, specs)
158 }>)
153 pub rule number_expr(s: &ParserSettings) -> LocExpr159 pub rule number_expr(s: &ParserSettings) -> LocExpr
154 = l(s,<n:number() { expr::Expr::Num(n) }>)160 = l(s,<n:number() { expr::Expr::Num(n) }>)
155 pub rule var_expr(s: &ParserSettings) -> LocExpr161 pub rule var_expr(s: &ParserSettings) -> LocExpr
156 = l(s,<n:id() { expr::Expr::Var(n) }>)162 = l(s,<n:$(id()) { expr::Expr::Var(n.into()) }>)
157 pub rule if_then_else_expr(s: &ParserSettings) -> LocExpr163 pub rule if_then_else_expr(s: &ParserSettings) -> LocExpr
158 = l(s,<cond:ifspec(s) _ keyword("then") _ cond_then:expr(s) cond_else:(_ keyword("else") _ e:expr(s) {e})? {Expr::IfElse{164 = l(s,<cond:ifspec(s) _ keyword("then") _ cond_then:expr(s) cond_else:(_ keyword("else") _ e:expr(s) {e})? {Expr::IfElse{
159 cond,165 cond,
219 --225 --
220 a:(@) _ "==" _ b:@ {loc_expr_todo!(Expr::Apply(226 a:(@) _ "==" _ b:@ {loc_expr_todo!(Expr::Apply(
221 el!(Expr::Index(227 el!(Expr::Index(
222 el!(Expr::Var("std".to_owned())),228 el!(Expr::Var("std".into())),
223 el!(Expr::Str("equals".to_owned()))229 el!(Expr::Str("equals".into()))
224 )),230 )),
225 ArgsDesc(vec![Arg(None, a), Arg(None, b)]),231 ArgsDesc(vec![Arg(None, a), Arg(None, b)]),
226 true232 true
227 ))}233 ))}
228 a:(@) _ "!=" _ b:@ {loc_expr_todo!(Expr::UnaryOp(UnaryOpType::Not, el!(Expr::Apply(234 a:(@) _ "!=" _ b:@ {loc_expr_todo!(Expr::UnaryOp(UnaryOpType::Not, el!(Expr::Apply(
229 el!(Expr::Index(235 el!(Expr::Index(
230 el!(Expr::Var("std".to_owned())),236 el!(Expr::Var("std".into())),
231 el!(Expr::Str("equals".to_owned()))237 el!(Expr::Str("equals".into()))
232 )),238 )),
233 ArgsDesc(vec![Arg(None, a), Arg(None, b)]),239 ArgsDesc(vec![Arg(None, a), Arg(None, b)]),
234 true240 true
240 a:(@) _ ">=" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Gte, b))}246 a:(@) _ ">=" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Gte, b))}
241 a:(@) _ keyword("in") _ b:@ {loc_expr_todo!(Expr::Apply(247 a:(@) _ keyword("in") _ b:@ {loc_expr_todo!(Expr::Apply(
242 el!(Expr::Index(248 el!(Expr::Index(
243 el!(Expr::Var("std".to_owned())),249 el!(Expr::Var("std".into())),
244 el!(Expr::Str("objectHasEx".to_owned()))250 el!(Expr::Str("objectHasEx".into()))
245 )), ArgsDesc(vec![Arg(None, b), Arg(None, a), Arg(None, el!(Expr::Literal(LiteralType::True)))]),251 )), ArgsDesc(vec![Arg(None, b), Arg(None, a), Arg(None, el!(Expr::Literal(LiteralType::True)))]),
246 true252 true
247 ))}253 ))}
256 a:(@) _ "/" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Div, b))}262 a:(@) _ "/" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Div, b))}
257 a:(@) _ "%" _ b:@ {loc_expr_todo!(Expr::Apply(263 a:(@) _ "%" _ b:@ {loc_expr_todo!(Expr::Apply(
258 el!(Expr::Index(264 el!(Expr::Index(
259 el!(Expr::Var("std".to_owned())),265 el!(Expr::Var("std".into())),
260 el!(Expr::Str("mod".to_owned()))266 el!(Expr::Str("mod".into()))
261 )), ArgsDesc(vec![Arg(None, a), Arg(None, b)]),267 )), ArgsDesc(vec![Arg(None, a), Arg(None, b)]),
262 true268 true
263 ))}269 ))}
268 --274 --
269 a:(@) _ "[" _ s:slice_desc(s) _ "]" {loc_expr_todo!(Expr::Apply(275 a:(@) _ "[" _ s:slice_desc(s) _ "]" {loc_expr_todo!(Expr::Apply(
270 el!(Expr::Index(276 el!(Expr::Index(
271 el!(Expr::Var("std".to_owned())),277 el!(Expr::Var("std".into())),
272 el!(Expr::Str("slice".to_owned())),278 el!(Expr::Str("slice".into())),
273 )),279 )),
274 ArgsDesc(vec![280 ArgsDesc(vec![
275 Arg(None, a),281 Arg(None, a),
279 ]),285 ]),
280 true,286 true,
281 ))}287 ))}
282 a:(@) _ "." _ s:id() {loc_expr_todo!(Expr::Index(a, el!(Expr::Str(s))))}288 a:(@) _ "." _ s:$(id()) {loc_expr_todo!(Expr::Index(a, el!(Expr::Str(s.into()))))}
283 a:(@) _ "[" _ s:expr(s) _ "]" {loc_expr_todo!(Expr::Index(a, s))}289 a:(@) _ "[" _ s:expr(s) _ "]" {loc_expr_todo!(Expr::Index(a, s))}
284 a:(@) _ "(" _ args:args(s) _ ")" ts:(_ keyword("tailstrict"))? {loc_expr_todo!(Expr::Apply(a, args, ts.is_some()))}290 a:(@) _ "(" _ args:args(s) _ ")" ts:(_ keyword("tailstrict"))? {loc_expr_todo!(Expr::Apply(a, args, ts.is_some()))}
285 a:(@) _ "{" _ body:objinside(s) _ "}" {loc_expr_todo!(Expr::ObjExtend(a, body))}291 a:(@) _ "{" _ body:objinside(s) _ "}" {loc_expr_todo!(Expr::ObjExtend(a, body))}
352 fn multiline_string() {358 fn multiline_string() {
353 assert_eq!(359 assert_eq!(
354 parse!("|||\n Hello world!\n a\n|||"),360 parse!("|||\n Hello world!\n a\n|||"),
355 el!(Expr::Str("Hello world!\n a\n".to_owned())),361 el!(Expr::Str("Hello world!\n a\n".into())),
356 )362 )
357 }363 }
358364
369 fn string_escaping() {375 fn string_escaping() {
370 assert_eq!(376 assert_eq!(
371 parse!(r#""Hello, \"world\"!""#),377 parse!(r#""Hello, \"world\"!""#),
372 el!(Expr::Str(r#"Hello, "world"!"#.to_owned())),378 el!(Expr::Str(r#"Hello, "world"!"#.into())),
373 );379 );
374 assert_eq!(380 assert_eq!(
375 parse!(r#"'Hello \'world\'!'"#),381 parse!(r#"'Hello \'world\'!'"#),
376 el!(Expr::Str("Hello 'world'!".to_owned())),382 el!(Expr::Str("Hello 'world'!".into())),
377 );383 );
378 assert_eq!(parse!(r#"'\\\\'"#), el!(Expr::Str("\\\\".to_owned())),);384 assert_eq!(parse!(r#"'\\\\'"#), el!(Expr::Str("\\\\".into())),);
379 }385 }
380386
381 #[test]387 #[test]
382 fn string_unescaping() {388 fn string_unescaping() {
383 assert_eq!(389 assert_eq!(
384 parse!(r#""Hello\nWorld""#),390 parse!(r#""Hello\nWorld""#),
385 el!(Expr::Str("Hello\nWorld".to_owned())),391 el!(Expr::Str("Hello\nWorld".into())),
386 );392 );
387 }393 }
388394
389 #[test]395 #[test]
390 fn string_verbantim() {396 fn string_verbantim() {
391 assert_eq!(397 assert_eq!(
392 parse!(r#"@"Hello\n""World""""#),398 parse!(r#"@"Hello\n""World""""#),
393 el!(Expr::Str("Hello\\n\"World\"".to_owned())),399 el!(Expr::Str("Hello\\n\"World\"".into())),
394 );400 );
395 }401 }
396402
489 parse!("[std.deepJoin(x) for x in arr]"),495 parse!("[std.deepJoin(x) for x in arr]"),
490 el!(ArrComp(496 el!(ArrComp(
491 el!(Apply(497 el!(Apply(
492 el!(Index(498 el!(Index(el!(Var("std".into())), el!(Str("deepJoin".into())))),
493 el!(Var("std".to_owned())),
494 el!(Str("deepJoin".to_owned()))
495 )),
496 ArgsDesc(vec![Arg(None, el!(Var("x".to_owned())))]),499 ArgsDesc(vec![Arg(None, el!(Var("x".into())))]),
497 false,500 false,
498 )),501 )),
499 vec![CompSpec::ForSpec(ForSpecData(502 vec![CompSpec::ForSpec(ForSpecData(
500 "x".to_owned(),503 "x".into(),
501 el!(Var("arr".to_owned()))504 el!(Var("arr".into()))
502 ))]505 ))]
503 )),506 )),
504 )507 )
508 fn reserved() {511 fn reserved() {
509 use Expr::*;512 use Expr::*;
510 assert_eq!(parse!("null"), el!(Literal(LiteralType::Null)));513 assert_eq!(parse!("null"), el!(Literal(LiteralType::Null)));
511 assert_eq!(parse!("nulla"), el!(Var("nulla".to_owned())));514 assert_eq!(parse!("nulla"), el!(Var("nulla".into())));
512 }515 }
513516
514 #[test]517 #[test]
522 assert_eq!(525 assert_eq!(
523 parse!("!a && !b"),526 parse!("!a && !b"),
524 el!(BinaryOp(527 el!(BinaryOp(
525 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".to_owned())))),528 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into())))),
526 BinaryOpType::And,529 BinaryOpType::And,
527 el!(UnaryOp(UnaryOpType::Not, el!(Var("b".to_owned()))))530 el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()))))
528 ))531 ))
529 );532 );
530 }533 }
535 assert_eq!(538 assert_eq!(
536 parse!("!a / !b"),539 parse!("!a / !b"),
537 el!(BinaryOp(540 el!(BinaryOp(
538 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".to_owned())))),541 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into())))),
539 BinaryOpType::Div,542 BinaryOpType::Div,
540 el!(UnaryOp(UnaryOpType::Not, el!(Var("b".to_owned()))))543 el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()))))
541 ))544 ))
542 );545 );
543 }546 }
549 parse!("!!a"),552 parse!("!!a"),
550 el!(UnaryOp(553 el!(UnaryOp(
551 UnaryOpType::Not,554 UnaryOpType::Not,
552 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".to_owned()))))555 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into()))))
553 ))556 ))
554 )557 )
555 }558 }