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

difftreelog

refactor(evaluator) use argument parsing macro

Лач2020-06-27parent: #6435abe.patch.diff
in: master

2 files changed

modifiedcrates/jsonnet-evaluator/src/error.rsdiffbeforeafterboth
--- a/crates/jsonnet-evaluator/src/error.rs
+++ b/crates/jsonnet-evaluator/src/error.rs
@@ -4,13 +4,16 @@
 
 #[derive(Debug, Clone)]
 pub enum Error {
+	IntristicNotFound(Rc<str>, Rc<str>),
+	IntristicArgumentReorderingIsNotSupportedYet,
+
 	VariableIsNotDefined(String),
 	TypeMismatch(&'static str, Vec<ValType>, ValType),
-	IntristicArgumentReorderingIsNotSupportedYet,
 	NoSuchField(Rc<str>),
 
 	UnknownVariable(Rc<str>),
 
+	OnlyFunctionsCanBeCalledGot(ValType),
 	UnknownFunctionParameter(String),
 	BindingParameterASecondTime(Rc<str>),
 	TooManyArgsFunctionHas(usize),
modifiedcrates/jsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth
1use crate::{1use crate::{
2 context_creator, create_error, escape_string_json, future_wrapper, lazy_val, manifest_json_ex,2 context_creator, create_error, escape_string_json, future_wrapper, lazy_val, manifest_json_ex,
3 push, with_state, Context, ContextCreator, Error, FuncDesc, LazyBinding, LazyVal, ObjMember,3 parse_args, push, with_state, Context, ContextCreator, Error, FuncDesc, LazyBinding, LazyVal,
4 ObjValue, Result, Val, ValType,4 ObjMember, ObjValue, Result, Val, ValType,
5};5};
6use closure::closure;6use closure::closure;
7use jsonnet_parser::{7use jsonnet_parser::{
502 match value {502 match value {
503 Val::Intristic(ns, name) => match (&ns as &str, &name as &str) {503 Val::Intristic(ns, name) => match (&ns as &str, &name as &str) {
504 // arr/string/function504 // arr/string/function
505 ("std", "length") => {505 ("std", "length") => parse_args!(context, "std.length", args, 1, [
506 assert_eq!(args.len(), 1);506 0, x: [Val::Str|Val::Arr|Val::Obj], vec![ValType::Str, ValType::Arr, ValType::Obj];
507 let expr = &args.get(0).unwrap().1;507 ], {
508 match evaluate(context, expr)? {508 match x {
509 Val::Str(n) => Val::Num(n.chars().count() as f64),509 Val::Str(n) => Val::Num(n.chars().count() as f64),
510 Val::Arr(i) => Val::Num(i.len() as f64),510 Val::Arr(i) => Val::Num(i.len() as f64),
511 Val::Obj(o) => Val::Num(511 Val::Obj(o) => Val::Num(
514 .filter(|(_k, v)| *v)514 .filter(|(_k, v)| *v)
515 .count() as f64,515 .count() as f64,
516 ),516 ),
517 v => panic!("can't get length of {:?}", v),517 _ => unreachable!(),
518 }518 }
519 }519 }),
520 // any520 // any
521 ("std", "type") => {521 ("std", "type") => parse_args!(context, "std.type", args, 1, [
522 assert_eq!(args.len(), 1);522 0, x, vec![];
523 let expr = &args.get(0).unwrap().1;523 ], {
524 Val::Str(evaluate(context, expr)?.value_type()?.name().into())524 Val::Str(x.value_type()?.name().into())
525 }525 }),
526 // length, idx=>any526 // length, idx=>any
527 ("std", "makeArray") => {527 ("std", "makeArray") => parse_args!(context, "std.makeArray", args, 2, [
528 assert_eq!(args.len(), 2);
529 if let (Val::Num(v), Val::Func(d)) = (528 0, sz: [Val::Num]!!Val::Num, vec![ValType::Num];
530 evaluate(context.clone(), &args[0].1)?,
531 evaluate(context, &args[1].1)?,529 1, func: [Val::Func]!!Val::Func, vec![ValType::Func];
532 ) {530 ], {
533 assert!(v >= 0.0);531 assert!(sz >= 0.0);
534 let mut out = Vec::with_capacity(v as usize);532 let mut out = Vec::with_capacity(sz as usize);
535 for i in 0..v as usize {533 for i in 0..sz as usize {
536 let call_ctx =534 out.push(func.evaluate_values(
537 Context::new().with_var("v".into(), Val::Num(i as f64))?;
538 out.push(d.evaluate(
539 call_ctx,535 Context::new(),
540 &ArgsDesc(vec![Arg(None, el!(Expr::Var("v".into())))]),
541 true,536 &[Val::Num(i as f64)]
542 )?)
543 }
544 Val::Arr(Rc::new(out))
545 } else {
546 panic!("bad makeArray call");537 )?)
547 }538 }
548 }539 Val::Arr(Rc::new(out))
540 }),
549 // string541 // string
550 ("std", "codepoint") => {542 ("std", "codepoint") => parse_args!(context, "std.codepoint", args, 1, [
551 assert_eq!(args.len(), 1);
552 if let Val::Str(s) = evaluate(context, &args[0].1)? {543 0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
544 ], {
553 assert!(545 assert!(
554 s.chars().count() == 1,546 str.chars().count() == 1,
555 "std.codepoint should receive single char string"547 "std.codepoint should receive single char string"
556 );548 );
557 Val::Num(s.chars().take(1).next().unwrap() as u32 as f64)549 Val::Num(str.chars().take(1).next().unwrap() as u32 as f64)
558 } else {550 }),
559 panic!("bad codepoint call");
560 }
561 }
562 // object, includeHidden551 // object, includeHidden
563 ("std", "objectFieldsEx") => {552 ("std", "objectFieldsEx") => {
564 assert_eq!(args.len(), 2);553 parse_args!(context, "std.objectFieldsEx",args, 2, [
565 if let (Val::Obj(body), Val::Bool(include_hidden)) = (554 0, obj: [Val::Obj]!!Val::Obj, vec![ValType::Obj];
566 evaluate(context.clone(), &args[0].1)?,555 1, inc_hidden: [Val::Bool]!!Val::Bool, vec![ValType::Bool];
567 evaluate(context, &args[1].1)?,
568 ) {556 ], {
569 Val::Arr(Rc::new(557 Val::Arr(Rc::new(
570 body.fields_visibility()558 obj.fields_visibility()
571 .into_iter()559 .into_iter()
572 .filter(|(_k, v)| *v || include_hidden)560 .filter(|(_k, v)| *v || inc_hidden)
573 .map(|(k, _v)| Val::Str(k))561 .map(|(k, _v)| Val::Str(k))
574 .collect(),562 .collect(),
575 ))563 ))
576 } else {564 })
577 panic!("bad objectFieldsEx call");
578 }
579 }565 }
580 // object, field, includeHidden566 // object, field, includeHidden
581 ("std", "objectHasEx") => {567 ("std", "objectHasEx") => parse_args!(context, "std.objectHasEx", args, 3, [
582 assert_eq!(args.len(), 3);
583 if let (Val::Obj(body), Val::Str(name), Val::Bool(include_hidden)) = (568 0, obj: [Val::Obj]!!Val::Obj, vec![ValType::Obj];
584 evaluate(context.clone(), &args[0].1)?,569 1, f: [Val::Str]!!Val::Str, vec![ValType::Str];
585 evaluate(context.clone(), &args[1].1)?,
586 evaluate(context, &args[2].1)?,570 2, inc_hidden: [Val::Bool]!!Val::Bool, vec![ValType::Bool];
587 ) {571 ], {
588 Val::Bool(572 Val::Bool(
589 body.fields_visibility()573 obj.fields_visibility()
590 .into_iter()574 .into_iter()
591 .filter(|(_k, v)| *v || include_hidden)575 .filter(|(_k, v)| *v || inc_hidden)
592 .any(|(k, _v)| *k == *name),576 .any(|(k, _v)| *k == *f),
593 )577 )
594 } else {578 }),
595 panic!("bad objectHasEx call");
596 }
597 }
598 ("std", "primitiveEquals") => {579 ("std", "primitiveEquals") => {
599 assert_eq!(args.len(), 2);580 parse_args!(context, "std.primitiveEquals", args, 2, [
600 let (a, b) = (
601 evaluate(context.clone(), &args[0].1)?,581 0, a, vec![];
602 evaluate(context, &args[1].1)?,582 1, b, vec![];
603 );583 ], {
604 Val::Bool(a == b)584 Val::Bool(a == b)
585 })
605 }586 }
606 ("std", "modulo") => {587 ("std", "modulo") => parse_args!(context, "std.modulo", args, 2, [
607 assert_eq!(args.len(), 2);588 0, a: [Val::Num]!!Val::Num, vec![ValType::Num];
608 if let (Val::Num(a), Val::Num(b)) = (589 1, b: [Val::Num]!!Val::Num, vec![ValType::Num];
609 evaluate(context.clone(), &args[0].1)?,590 ], {
610 evaluate(context, &args[1].1)?,591 Val::Num(a % b)
611 ) {592 }),
612 Val::Num(a % b)593 ("std", "floor") => parse_args!(context, "std.floor", args, 1, [
613 } else {594 0, x: [Val::Num]!!Val::Num, vec![ValType::Num];
614 panic!("bad modulo call");595 ], {
615 }596 Val::Num(x.floor())
616 }597 }),
617 ("std", "floor") => {598 ("std", "trace") => parse_args!(context, "std.trace", args, 2, [
618 assert_eq!(args.len(), 1);599 0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
619 if let Val::Num(a) = evaluate(context, &args[0].1)? {600 1, rest, vec![];
620 Val::Num(a.floor())601 ], {
621 } else {602 // TODO: Line numbers as in original jsonnet
622 panic!("bad floor call");603 println!("TRACE: {}", str);
623 }604 rest
624 }605 }),
625 ("std", "trace") => {606 ("std", "pow") => parse_args!(context, "std.modulo", args, 2, [
626 assert_eq!(args.len(), 2);607 0, x: [Val::Num]!!Val::Num, vec![ValType::Num];
627 if let (Val::Str(a), b) = (608 1, n: [Val::Num]!!Val::Num, vec![ValType::Num];
628 evaluate(context.clone(), &args[0].1)?,609 ], {
629 evaluate(context, &args[1].1)?,610 Val::Num(x.powf(n))
630 ) {611 }),
631 // TODO: Line numbers as in original jsonnet612 ("std", "extVar") => parse_args!(context, "std.extVar", args, 2, [
632 println!("TRACE: {}", a);613 0, x: [Val::Str]!!Val::Str, vec![ValType::Str];
633 b614 ], {
634 } else {615 with_state(|s| s.0.ext_vars.borrow().get(&x).cloned()).ok_or_else(
635 panic!("bad trace call");616 || {
636 }617 create_error::<()>(crate::Error::UndefinedExternalVariable(x))
637 }618 .err()
638 ("std", "pow") => {619 .unwrap()
639 assert_eq!(args.len(), 2);620 },
640 if let (Val::Num(a), Val::Num(b)) = (621 )?
641 evaluate(context.clone(), &args[0].1)?,622 }),
642 evaluate(context, &args[1].1)?,623 ("std", "filter") => parse_args!(context, "std.filter", args, 2, [
643 ) {624 0, func: [Val::Func]!!Val::Func, vec![ValType::Func];
644 Val::Num(a.powf(b))625 1, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
645 } else {626 ], {
646 panic!("bad pow call");627 Val::Arr(Rc::new(
647 }628 arr.iter()
648 }629 .cloned()
649 ("std", "extVar") => {630 .filter(|e| {
650 assert_eq!(args.len(), 1);631 func
651 if let Val::Str(a) = evaluate(context, &args[0].1)? {632 .evaluate_values(context.clone(), &[e.clone()])
652 with_state(|s| s.0.ext_vars.borrow().get(&a).cloned()).ok_or_else(
653 || {
654 create_error::<()>(crate::Error::UndefinedExternalVariable(a))
655 .err()
656 .unwrap()633 .unwrap()
657 },634 .try_cast_bool("filter predicate")
658 )?
659 } else {
660 panic!("bad extVar call");
661 }
662 }
663 ("std", "filter") => {
664 assert_eq!(args.len(), 2);
665 if let (Val::Func(predicate), Val::Arr(arr)) = (
666 evaluate(context.clone(), &args[0].1)?,
667 evaluate(context.clone(), &args[1].1)?,
668 ) {
669 Val::Arr(Rc::new(
670 arr.iter()
671 .cloned()
672 .filter(|e| {
673 predicate
674 .evaluate_values(context.clone(), &[e.clone()])
675 .unwrap()
676 .try_cast_bool("filter predicate")
677 .unwrap()635 .unwrap()
678 })636 })
679 .collect(),637 .collect(),
680 ))638 ))
681 } else {639 }),
682 panic!("bad filter call");
683 }640 ("std", "char") => parse_args!(context, "std.char", args, 1, [
684 }
685 ("std", "char") => {
686 assert_eq!(args.len(), 1);
687 let ch = evaluate(context, &args[0].1)?641 0, n: [Val::Num]!!Val::Num, vec![ValType::Num];
688 .unwrap_if_lazy()?642 ], {
689 .try_cast_num("std.char first argument")?;
690 let mut out = String::new();643 let mut out = String::new();
691 out.push(std::char::from_u32(ch as u32).unwrap());644 out.push(std::char::from_u32(n as u32).unwrap());
692 Val::Str(out.into())645 Val::Str(out.into())
693 }646 }),
694 ("std", "encodeUTF8") => {647 ("std", "encodeUTF8") => parse_args!(context, "std.encodeUtf8", args, 1, [
695 assert_eq!(args.len(), 1);
696 let s = evaluate(context, &args[0].1)?648 0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
697 .unwrap_if_lazy()?649 ], {
698 .try_cast_str("std.encodeUTF8 first argument")?;
699 Val::Arr(Rc::new(s.bytes().map(|b| Val::Num(b as f64)).collect()))650 Val::Arr(Rc::new(str.bytes().map(|b| Val::Num(b as f64)).collect()))
700 }651 }),
701 ("std", "md5") => {652 ("std", "md5") => parse_args!(context, "std.md5", args, 1, [
702 assert_eq!(args.len(), 1);
703 let s = evaluate(context, &args[0].1)?653 0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
704 .unwrap_if_lazy()?654 ], {
705 .try_cast_str("std.md5 first argument")?;
706 Val::Str(format!("{:x}", md5::compute(s.as_bytes())).into())655 Val::Str(format!("{:x}", md5::compute(str.as_bytes())).into())
707 }656 }),
708 // faster657 // faster
709 ("std", "join") => {658 ("std", "join") => parse_args!(context, "std.join", args, 2, [
710 assert_eq!(args.len(), 2);
711 let joiner = evaluate(context.clone(), &args[0].1)?;659 0, sep: [Val::Str|Val::Arr], vec![ValType::Str, ValType::Arr];
712 let items = evaluate(context, &args[1].1)?;660 1, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
713 match (joiner.unwrap_if_lazy()?, items.unwrap_if_lazy()?) {661 ], {
662 match sep {
714 (Val::Arr(joiner_items), Val::Arr(items)) => {663 Val::Arr(joiner_items) => {
715 // TODO: Minimal size should be known
716 let mut out = Vec::new();664 let mut out = Vec::new();
717665
718 let mut first = true;666 let mut first = true;
719 for item in items.iter().cloned() {667 for item in arr.iter().cloned() {
720 if let Val::Arr(items) = item.unwrap_if_lazy()? {668 if let Val::Arr(items) = item.unwrap_if_lazy()? {
721 if !first {669 if !first {
722 out.reserve(joiner_items.len());670 out.reserve(joiner_items.len());
731 }679 }
732680
733 Val::Arr(Rc::new(out))681 Val::Arr(Rc::new(out))
734 }682 },
735 (Val::Str(joiner), Val::Arr(items)) => {683 Val::Str(sep) => {
736 let mut out = String::new();684 let mut out = String::new();
737685
738 let mut first = true;686 let mut first = true;
739 for item in items.iter().cloned() {687 for item in arr.iter().cloned() {
740 if let Val::Str(item) = item.unwrap_if_lazy()? {688 if let Val::Str(item) = item.unwrap_if_lazy()? {
741 if !first {689 if !first {
742 out += &joiner;690 out += &sep;
743 }691 }
744 first = false;692 first = false;
745 out += &item;693 out += &item;
749 }697 }
750698
751 Val::Str(out.into())699 Val::Str(out.into())
752 }700 },
753 (joiner, items) => panic!("bad join call: {:?} {:?}", joiner, items),701 _ => unreachable!()
754 }702 }
755 }703 }),
756 // Faster704 // Faster
757 ("std", "escapeStringJson") => {705 ("std", "escapeStringJson") => {
758 assert_eq!(args.len(), 1);706 parse_args!(context, "std.escapeStringJson", args, 1, [
759 match evaluate(context, &args[0].1)?.unwrap_if_lazy()? {707 0, str_: [Val::Str]!!Val::Str, vec![ValType::Str];
708 ], {
760 Val::Str(s) => Val::Str(escape_string_json(&s).into()),709 Val::Str(escape_string_json(&str_).into())
761 _ => panic!("bad escapeStringJson call"),710 })
762 }
763 }711 }
764 // Faster712 // Faster
765 ("std", "manifestJsonEx") => {713 ("std", "manifestJsonEx") => {
766 assert_eq!(args.len(), 2);714 parse_args!(context, "std.manifestJsonEx", args, 2, [
767 let value = evaluate(context.clone(), &args[0].1)?.unwrap_if_lazy()?;715 0, value, vec![];
768 let ident = evaluate(context, &args[1].1)?.unwrap_if_lazy()?;716 1, indent: [Val::Str]!!Val::Str, vec![ValType::Str];
769 match (value, ident) {717 ], {
770 (o, Val::Str(s)) => Val::Str(manifest_json_ex(&o, &s)?.into()),718 Val::Str(manifest_json_ex(&value, &indent)?.into())
771 _ => panic!("bad escapeStringJson call"),719 })
772 }
773 }720 }
774 (ns, name) => panic!("Intristic not found: {}.{}", ns, name),721 (ns, name) => panic!("Intristic not found: {}.{}", ns, name),
775 },722 },