difftreelog
feat make type descriptions look more js-like
in: master
2 files changed
crates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/mod.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs
@@ -79,7 +79,7 @@
fn builtin_length(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "length", args, 1, [
- 0, x: ty!((str | obj | [any]));
+ 0, x: ty!((string | object | array));
], {
Ok(match x {
Val::Str(n) => Val::Num(n.chars().count() as f64),
@@ -109,8 +109,8 @@
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "makeArray", args, 2, [
- 0, sz: ty!(number((Some(0.0))..(None))) => Val::Num;
- 1, func: ty!(fn.any) => Val::Func;
+ 0, sz: ty!(BoundedNumber<(Some(0.0)), (None)>) => Val::Num;
+ 1, func: ty!(function) => Val::Func;
], {
let mut out = Vec::with_capacity(sz as usize);
for i in 0..sz as usize {
@@ -141,8 +141,8 @@
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "objectFieldsEx", args, 2, [
- 0, obj: ty!(obj) => Val::Obj;
- 1, inc_hidden: ty!(bool) => Val::Bool;
+ 0, obj: ty!(object) => Val::Obj;
+ 1, inc_hidden: ty!(boolean) => Val::Bool;
], {
let mut out = obj.fields_visibility()
.into_iter()
@@ -160,9 +160,9 @@
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "objectHasEx", args, 3, [
- 0, obj: ty!(obj) => Val::Obj;
- 1, f: ty!(str) => Val::Str;
- 2, inc_hidden: ty!(bool) => Val::Bool;
+ 0, obj: ty!(object) => Val::Obj;
+ 1, f: ty!(string) => Val::Str;
+ 2, inc_hidden: ty!(boolean) => Val::Bool;
], {
Ok(Val::Bool(
obj.fields_visibility()
@@ -176,10 +176,10 @@
// faster
fn builtin_slice(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "slice", args, 4, [
- 0, indexable: ty!((str | [any]));
- 1, index: ty!((num | null));
- 2, end: ty!((num | null));
- 3, step: ty!((num | null));
+ 0, indexable: ty!((string | array));
+ 1, index: ty!((number | null));
+ 2, end: ty!((number | null));
+ 3, step: ty!((number | null));
], {
let index = match index {
Val::Num(v) => v as usize,
@@ -238,8 +238,8 @@
fn builtin_modulo(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "modulo", args, 2, [
- 0, a: ty!(num) => Val::Num;
- 1, b: ty!(num) => Val::Num;
+ 0, a: ty!(number) => Val::Num;
+ 1, b: ty!(number) => Val::Num;
], {
Ok(Val::Num(a % b))
})
@@ -247,7 +247,7 @@
fn builtin_mod(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "mod", args, 2, [
- 0, a: ty!((num | str));
+ 0, a: ty!((number | string));
1, b: ty!(any);
], {
match (a, b) {
@@ -260,7 +260,7 @@
fn builtin_floor(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "floor", args, 1, [
- 0, x: ty!(num) => Val::Num;
+ 0, x: ty!(number) => Val::Num;
], {
Ok(Val::Num(x.floor()))
})
@@ -268,7 +268,7 @@
fn builtin_log(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "log", args, 1, [
- 0, n: ty!(num) => Val::Num;
+ 0, n: ty!(number) => Val::Num;
], {
Ok(Val::Num(n.ln()))
})
@@ -276,8 +276,8 @@
fn builtin_pow(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "pow", args, 2, [
- 0, x: ty!(num) => Val::Num;
- 1, n: ty!(num) => Val::Num;
+ 0, x: ty!(number) => Val::Num;
+ 1, n: ty!(number) => Val::Num;
], {
Ok(Val::Num(x.powf(n)))
})
@@ -285,7 +285,7 @@
fn builtin_ext_var(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "extVar", args, 1, [
- 0, x: ty!(str) => Val::Str;
+ 0, x: ty!(string) => Val::Str;
], {
Ok(with_state(|s| s.settings().ext_vars.get(&x).cloned()).ok_or(UndefinedExternalVariable(x))?)
})
@@ -293,7 +293,7 @@
fn builtin_native(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "native", args, 1, [
- 0, x: ty!(str) => Val::Str;
+ 0, x: ty!(string) => Val::Str;
], {
Ok(with_state(|s| s.settings().ext_natives.get(&x).cloned()).map(|v| Val::Func(Rc::new(FuncVal::NativeExt(x.clone(), v)))).ok_or(UndefinedExternalFunction(x))?)
})
@@ -301,8 +301,8 @@
fn builtin_filter(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "filter", args, 2, [
- 0, func: ty!(fn.any) => Val::Func;
- 1, arr: ty!([any]) => Val::Arr;
+ 0, func: ty!(function) => Val::Func;
+ 1, arr: ty!(array) => Val::Arr;
], {
let mut out = Vec::new();
for item in arr.iter() {
@@ -319,8 +319,8 @@
fn builtin_foldl(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "foldl", args, 3, [
- 0, func: ty!(fn.any) => Val::Func;
- 1, arr: ty!([any]) => Val::Arr;
+ 0, func: ty!(function) => Val::Func;
+ 1, arr: ty!(array) => Val::Arr;
2, init: ty!(any);
], {
let mut acc = init;
@@ -333,8 +333,8 @@
fn builtin_foldr(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "foldr", args, 3, [
- 0, func: ty!(fn.any) => Val::Func;
- 1, arr: ty!([any]) => Val::Arr;
+ 0, func: ty!(function) => Val::Func;
+ 1, arr: ty!(array) => Val::Arr;
2, init: ty!(any);
], {
let mut acc = init;
@@ -352,8 +352,8 @@
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "sort", args, 2, [
- 0, arr: ty!([any]) => Val::Arr;
- 1, keyF: ty!(fn.any) => Val::Func;
+ 0, arr: ty!(array) => Val::Arr;
+ 1, keyF: ty!(function) => Val::Func;
], {
if arr.len() <= 1 {
return Ok(Val::Arr(arr))
@@ -365,7 +365,7 @@
// faster
fn builtin_format(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "format", args, 2, [
- 0, str: ty!(str) => Val::Str;
+ 0, str: ty!(string) => Val::Str;
1, vals: ty!(any)
], {
std_format(str, vals)
@@ -374,8 +374,8 @@
fn builtin_range(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "range", args, 2, [
- 0, from: ty!(num) => Val::Num;
- 1, to: ty!(num) => Val::Num;
+ 0, from: ty!(number) => Val::Num;
+ 1, to: ty!(number) => Val::Num;
], {
let mut out = Vec::with_capacity((1+to as usize-from as usize).max(0));
for i in from as usize..=to as usize {
@@ -387,7 +387,7 @@
fn builtin_char(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "char", args, 1, [
- 0, n: ty!(num) => Val::Num;
+ 0, n: ty!(number) => Val::Num;
], {
let mut out = String::new();
out.push(std::char::from_u32(n as u32).ok_or_else(||
@@ -403,7 +403,7 @@
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "encodeUTF8", args, 1, [
- 0, str: ty!(str) => Val::Str;
+ 0, str: ty!(string) => Val::Str;
], {
Ok(Val::Arr((str.bytes().map(|b| Val::Num(b as f64)).collect::<Vec<Val>>()).into()))
})
@@ -411,7 +411,7 @@
fn builtin_md5(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "md5", args, 1, [
- 0, str: ty!(str) => Val::Str;
+ 0, str: ty!(string) => Val::Str;
], {
Ok(Val::Str(format!("{:x}", md5::compute(&str.as_bytes())).into()))
})
@@ -419,7 +419,7 @@
fn builtin_trace(context: Context, loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "trace", args, 2, [
- 0, str: ty!(str) => Val::Str;
+ 0, str: ty!(string) => Val::Str;
1, rest: ty!(any);
], {
eprint!("TRACE:");
@@ -436,7 +436,7 @@
fn builtin_base64(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "base64", args, 1, [
- 0, input: ty!((str | [num]));
+ 0, input: ty!((string | (Array<number>)));
], {
Ok(Val::Str(match input {
Val::Str(s) => {
@@ -452,10 +452,11 @@
})
}
+
fn builtin_join(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "join", args, 2, [
- 0, sep: ty!((str | [any]));
- 1, arr: ty!([any]) => Val::Arr;
+ 0, sep: ty!((string | array));
+ 1, arr: ty!(array) => Val::Arr;
], {
Ok(match sep {
Val::Arr(joiner_items) => {
@@ -516,7 +517,7 @@
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "escapeStringJson", args, 1, [
- 0, str_: ty!(str) => Val::Str;
+ 0, str_: ty!(string) => Val::Str;
], {
Ok(Val::Str(escape_string_json(&str_).into()))
})
@@ -530,7 +531,7 @@
) -> Result<Val> {
parse_args!(context, "manifestJsonEx", args, 2, [
0, value: ty!(any);
- 1, indent: ty!(str) => Val::Str;
+ 1, indent: ty!(string) => Val::Str;
], {
Ok(Val::Str(manifest_json_ex(&value, &ManifestJsonOptions {
padding: &indent,
@@ -542,7 +543,7 @@
// faster
fn builtin_reverse(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "reverse", args, 1, [
- 0, value: ty!([any]) => Val::Arr;
+ 0, value: ty!(array) => Val::Arr;
], {
Ok(Val::Arr(value.reversed()))
})
crates/jrsonnet-types/src/lib.rsdiffbeforeafterboth1use std::fmt::Display;23#[macro_export]4macro_rules! ty {5 ([$inner:tt]) => {{6 use $crate::{ComplexValType, ValType, ty};7 static VAL: &'static ComplexValType = &ty!($inner);8 match VAL {9 ComplexValType::Any => ComplexValType::Simple(ValType::Arr),10 _ => ComplexValType::ArrayRef(&VAL),11 }12 }};13 (bool) => {14 $crate::ComplexValType::Simple($crate::ValType::Bool)15 };16 (null) => {17 $crate::ComplexValType::Simple($crate::ValType::Null)18 };19 (str) => {20 $crate::ComplexValType::Simple($crate::ValType::Str)21 };22 (char) => {23 $crate::ComplexValType::Char24 };25 (num) => {26 $crate::ComplexValType::Simple($crate::ValType::Num)27 };28 (number(($min:expr)..($max:expr))) => {{29 $crate::ComplexValType::BoundedNumber($min, $max)30 }};31 (obj) => {32 $crate::ComplexValType::Simple($crate::ValType::Obj)33 };34 (any) => {35 $crate::ComplexValType::Any36 };37 (fn.any) => {38 $crate::ComplexValType::Simple($crate::ValType::Func)39 };40 (($($a:tt) |+)) => {{41 static CONTENTS: &'static [$crate::ComplexValType] = &[42 $(ty!($a)),+43 ];44 $crate::ComplexValType::UnionRef(CONTENTS)45 }};46 (($($a:tt) &+)) => {{47 static CONTENTS: &'static [$crate::ComplexValType] = &[48 $(ty!($a)),+49 ];50 $crate::ComplexValType::SumRef(CONTENTS)51 }};52}5354#[test]55fn test() {56 assert_eq!(57 ty!([num]),58 ComplexValType::ArrayRef(&ComplexValType::Simple(ValType::Num))59 );60 assert_eq!(ty!([any]), ComplexValType::Simple(ValType::Arr));61 assert_eq!(ty!(any), ComplexValType::Any);62 assert_eq!(63 ty!((str | num)),64 ComplexValType::UnionRef(&[65 ComplexValType::Simple(ValType::Str),66 ComplexValType::Simple(ValType::Num)67 ])68 );69 assert_eq!(70 format!("{}", ty!(((str & num) | (obj & null)))),71 "string & number | object & null"72 );73 assert_eq!(format!("{}", ty!((str | [any]))), "string | array");74 assert_eq!(format!("{}", ty!(((str & num) | [any]))), "string & number | array");75}7677#[derive(Debug, Clone, Copy, PartialEq, Eq)]78pub enum ValType {79 Bool,80 Null,81 Str,82 Num,83 Arr,84 Obj,85 Func,86}8788impl ValType {89 pub const fn name(&self) -> &'static str {90 use ValType::*;91 match self {92 Bool => "boolean",93 Null => "null",94 Str => "string",95 Num => "number",96 Arr => "array",97 Obj => "object",98 Func => "function",99 }100 }101}102103impl Display for ValType {104 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {105 write!(f, "{}", self.name())106 }107}108109#[derive(Debug, Clone, PartialEq)]110pub enum ComplexValType {111 Any,112 Char,113 Simple(ValType),114 BoundedNumber(Option<f64>, Option<f64>),115 ArrayRef(&'static ComplexValType),116 ObjectRef(&'static [(&'static str, ComplexValType)]),117 UnionRef(&'static [ComplexValType]),118 SumRef(&'static [ComplexValType]),119}120impl From<ValType> for ComplexValType {121 fn from(s: ValType) -> Self {122 Self::Simple(s)123 }124}125126fn write_union(127 f: &mut std::fmt::Formatter<'_>,128 is_union: bool,129 union: &[ComplexValType],130) -> std::fmt::Result {131 for (i, v) in union.iter().enumerate() {132 let should_add_braces = match v {133 ComplexValType::UnionRef(_) if !is_union => true,134 _ => false,135 };136 if i != 0 {137 write!(f, " {} ", if is_union { '|' } else { '&' })?;138 }139 if should_add_braces {140 write!(f, "(")?;141 }142 write!(f, "{}", v)?;143 if should_add_braces {144 write!(f, ")")?;145 }146 }147 Ok(())148}149150impl Display for ComplexValType {151 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {152 match self {153 ComplexValType::Any => write!(f, "any")?,154 ComplexValType::Simple(s) => write!(f, "{}", s)?,155 ComplexValType::Char => write!(f, "char")?,156 ComplexValType::BoundedNumber(a, b) => write!(157 f,158 "BoundedNumber<{}, {}>",159 a.map(|e| e.to_string()).unwrap_or_else(|| "".into()),160 b.map(|e| e.to_string()).unwrap_or_else(|| "".into())161 )?,162 ComplexValType::ArrayRef(a) => {163 if **a == ComplexValType::Any {164 write!(f, "array")?165 } else {166 write!(f, "Array<{}>", a)?167 }168 }169 ComplexValType::ObjectRef(fields) => {170 write!(f, "{{")?;171 for (i, (k, v)) in fields.iter().enumerate() {172 if i != 0 {173 write!(f, ", ")?;174 }175 write!(f, "{}: {}", k, v)?;176 }177 write!(f, "}}")?;178 }179 ComplexValType::UnionRef(v) => write_union(f, true, v)?,180 ComplexValType::SumRef(v) => write_union(f, false, v)?,181 };182 Ok(())183 }184}1use std::fmt::Display;23#[macro_export]4macro_rules! ty {5 ((Array<number>)) => {{6 $crate::ComplexValType::ArrayRef(&$crate::ComplexValType::Simple($crate::ValType::Num))7 }};8 (array) => {9 $crate::ComplexValType::Simple($crate::ValType::Arr)10 };11 (boolean) => {12 $crate::ComplexValType::Simple($crate::ValType::Bool)13 };14 (null) => {15 $crate::ComplexValType::Simple($crate::ValType::Null)16 };17 (string) => {18 $crate::ComplexValType::Simple($crate::ValType::Str)19 };20 (char) => {21 $crate::ComplexValType::Char22 };23 (number) => {24 $crate::ComplexValType::Simple($crate::ValType::Num)25 };26 (BoundedNumber<($min:expr), ($max:expr)>) => {{27 $crate::ComplexValType::BoundedNumber($min, $max)28 }};29 (object) => {30 $crate::ComplexValType::Simple($crate::ValType::Obj)31 };32 (any) => {33 $crate::ComplexValType::Any34 };35 (function) => {36 $crate::ComplexValType::Simple($crate::ValType::Func)37 };38 (($($a:tt) |+)) => {{39 static CONTENTS: &'static [$crate::ComplexValType] = &[40 $(ty!($a)),+41 ];42 $crate::ComplexValType::UnionRef(CONTENTS)43 }};44 (($($a:tt) &+)) => {{45 static CONTENTS: &'static [$crate::ComplexValType] = &[46 $(ty!($a)),+47 ];48 $crate::ComplexValType::SumRef(CONTENTS)49 }};50}5152#[test]53fn test() {54 assert_eq!(55 ty!((Array<number>)),56 ComplexValType::ArrayRef(&ComplexValType::Simple(ValType::Num))57 );58 assert_eq!(ty!(array), ComplexValType::Simple(ValType::Arr));59 assert_eq!(ty!(any), ComplexValType::Any);60 assert_eq!(61 ty!((string | number)),62 ComplexValType::UnionRef(&[63 ComplexValType::Simple(ValType::Str),64 ComplexValType::Simple(ValType::Num)65 ])66 );67 assert_eq!(68 format!("{}", ty!(((string & number) | (object & null)))),69 "string & number | object & null"70 );71 assert_eq!(format!("{}", ty!((string | array))), "string | array");72 assert_eq!(format!("{}", ty!(((string & number) | array))), "string & number | array");73}7475#[derive(Debug, Clone, Copy, PartialEq, Eq)]76pub enum ValType {77 Bool,78 Null,79 Str,80 Num,81 Arr,82 Obj,83 Func,84}8586impl ValType {87 pub const fn name(&self) -> &'static str {88 use ValType::*;89 match self {90 Bool => "boolean",91 Null => "null",92 Str => "string",93 Num => "number",94 Arr => "array",95 Obj => "object",96 Func => "function",97 }98 }99}100101impl Display for ValType {102 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {103 write!(f, "{}", self.name())104 }105}106107#[derive(Debug, Clone, PartialEq)]108pub enum ComplexValType {109 Any,110 Char,111 Simple(ValType),112 BoundedNumber(Option<f64>, Option<f64>),113 ArrayRef(&'static ComplexValType),114 ObjectRef(&'static [(&'static str, ComplexValType)]),115 UnionRef(&'static [ComplexValType]),116 SumRef(&'static [ComplexValType]),117}118impl From<ValType> for ComplexValType {119 fn from(s: ValType) -> Self {120 Self::Simple(s)121 }122}123124fn write_union(125 f: &mut std::fmt::Formatter<'_>,126 is_union: bool,127 union: &[ComplexValType],128) -> std::fmt::Result {129 for (i, v) in union.iter().enumerate() {130 let should_add_braces = match v {131 ComplexValType::UnionRef(_) if !is_union => true,132 _ => false,133 };134 if i != 0 {135 write!(f, " {} ", if is_union { '|' } else { '&' })?;136 }137 if should_add_braces {138 write!(f, "(")?;139 }140 write!(f, "{}", v)?;141 if should_add_braces {142 write!(f, ")")?;143 }144 }145 Ok(())146}147148impl Display for ComplexValType {149 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {150 match self {151 ComplexValType::Any => write!(f, "any")?,152 ComplexValType::Simple(s) => write!(f, "{}", s)?,153 ComplexValType::Char => write!(f, "char")?,154 ComplexValType::BoundedNumber(a, b) => write!(155 f,156 "BoundedNumber<{}, {}>",157 a.map(|e| e.to_string()).unwrap_or_else(|| "".into()),158 b.map(|e| e.to_string()).unwrap_or_else(|| "".into())159 )?,160 ComplexValType::ArrayRef(a) => {161 if **a == ComplexValType::Any {162 write!(f, "array")?163 } else {164 write!(f, "Array<{}>", a)?165 }166 }167 ComplexValType::ObjectRef(fields) => {168 write!(f, "{{")?;169 for (i, (k, v)) in fields.iter().enumerate() {170 if i != 0 {171 write!(f, ", ")?;172 }173 write!(f, "{}: {}", k, v)?;174 }175 write!(f, "}}")?;176 }177 ComplexValType::UnionRef(v) => write_union(f, true, v)?,178 ComplexValType::SumRef(v) => write_union(f, false, v)?,179 };180 Ok(())181 }182}