git.delta.rocks / jrsonnet / refs/commits / 6bf55d21bf51

difftreelog

feat default params in function description

Yaroslav Bolyukin2024-06-18parent: #b5d51b9.patch.diff
in: master

5 files changed

modifiedcrates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth
11use thiserror::Error;11use thiserror::Error;
1212
13use crate::{function::CallLocation, stdlib::format::FormatError, typed::TypeLocError, ObjValue};13use crate::{
14 function::{builtin::ParamDefault, CallLocation},
15 stdlib::format::FormatError,
16 typed::TypeLocError,
17 ObjValue,
18};
1419
15pub(crate) fn format_found(list: &[IStr], what: &str) -> String {20pub(crate) fn format_found(list: &[IStr], what: &str) -> String {
43 if sig.is_empty() {48 if sig.is_empty() {
44 out.push_str("/*no arguments*/");49 out.push_str("/*no arguments*/");
45 } else {50 } else {
46 for (i, (name, has_default)) in sig.iter().enumerate() {51 for (i, (name, default)) in sig.iter().enumerate() {
47 if i != 0 {52 if i != 0 {
48 out.push_str(", ");53 out.push_str(", ");
49 }54 }
52 } else {57 } else {
53 out.push_str("<unnamed>");58 out.push_str("<unnamed>");
54 }59 }
60 match default {
61 ParamDefault::None => {}
62 ParamDefault::Exists => out.push_str(" = <default>"),
55 if *has_default {63 ParamDefault::Literal(lit) => {
56 out.push_str(" = <default>");64 out.push_str(" = ");
65 out.push_str(lit);
57 }66 }
67 }
58 }68 }
59 }69 }
60 out.push(')');70 out.push(')');
88 heap.into_iter().map(|v| v.1).collect()98 heap.into_iter().map(|v| v.1).collect()
89}99}
90100
91type FunctionSignature = Vec<(Option<IStr>, bool)>;101type FunctionSignature = Vec<(Option<IStr>, ParamDefault)>;
92102
93/// Possible errors103/// Possible errors
94#[allow(missing_docs)]104#[allow(missing_docs)]
modifiedcrates/jrsonnet-evaluator/src/function/builtin.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/function/builtin.rs
+++ b/crates/jrsonnet-evaluator/src/function/builtin.rs
@@ -33,22 +33,40 @@
 	}
 }
 
+#[derive(Clone, Copy, Debug, Trace)]
+pub enum ParamDefault {
+	None,
+	Exists,
+	Literal(&'static str),
+}
+impl ParamDefault {
+	pub const fn exists(is_exists: bool) -> Self {
+		if is_exists {
+			Self::Exists
+		} else {
+			Self::None
+		}
+	}
+}
+
 #[derive(Clone, Trace)]
 pub struct BuiltinParam {
 	name: ParamName,
-	has_default: bool,
+	default: ParamDefault,
 }
 impl BuiltinParam {
-	pub const fn new(name: ParamName, has_default: bool) -> Self {
-		Self { name, has_default }
+	pub const fn new(name: ParamName, default: ParamDefault) -> Self {
+		Self { name, default }
 	}
 	/// Parameter name for named call parsing
 	pub fn name(&self) -> &ParamName {
 		&self.name
 	}
-	/// Is implementation allowed to return empty value
+	pub fn default(&self) -> ParamDefault {
+		self.default
+	}
 	pub fn has_default(&self) -> bool {
-		self.has_default
+		!matches!(self.default, ParamDefault::None)
 	}
 }
 
@@ -87,7 +105,7 @@
 				.into_iter()
 				.map(|n| BuiltinParam {
 					name: ParamName::new_dynamic(n),
-					has_default: false,
+					default: ParamDefault::Exists,
 				})
 				.collect(),
 			handler: tb!(handler),
modifiedcrates/jrsonnet-evaluator/src/function/mod.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/function/mod.rs
+++ b/crates/jrsonnet-evaluator/src/function/mod.rs
@@ -8,7 +8,7 @@
 
 use self::{
 	arglike::OptionalContext,
-	builtin::{Builtin, BuiltinParam, ParamName, StaticBuiltin},
+	builtin::{Builtin, BuiltinParam, ParamDefault, ParamName, StaticBuiltin},
 	native::NativeDesc,
 	parse::{parse_default_function_call, parse_function_call},
 };
@@ -142,7 +142,7 @@
 							.as_ref()
 							.map(IStr::to_string)
 							.map_or(ParamName::ANONYMOUS, ParamName::new_dynamic),
-						p.1.is_some(),
+						ParamDefault::exists(p.1.is_some()),
 					)
 				})
 				.collect(),
modifiedcrates/jrsonnet-evaluator/src/function/parse.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/function/parse.rs
+++ b/crates/jrsonnet-evaluator/src/function/parse.rs
@@ -10,6 +10,7 @@
 	destructure::destruct,
 	error::{ErrorKind::*, Result},
 	evaluate_named,
+	function::builtin::ParamDefault,
 	gc::GcHashMap,
 	val::ThunkValue,
 	Context, Pending, Thunk, Val,
@@ -49,7 +50,10 @@
 	if args.unnamed_len() > params.len() {
 		bail!(TooManyArgsFunctionHas(
 			params.len(),
-			params.iter().map(|p| (p.0.name(), p.1.is_some())).collect()
+			params
+				.iter()
+				.map(|p| (p.0.name(), ParamDefault::exists(p.1.is_some())))
+				.collect()
 		))
 	}
 
@@ -127,7 +131,10 @@
 				if !found {
 					bail!(FunctionParameterNotBoundInCall(
 						param.0.clone().name(),
-						params.iter().map(|p| (p.0.name(), p.1.is_some())).collect()
+						params
+							.iter()
+							.map(|p| (p.0.name(), ParamDefault::exists(p.1.is_some())))
+							.collect()
 					));
 				}
 			}
@@ -163,7 +170,7 @@
 			params.len(),
 			params
 				.iter()
-				.map(|p| (p.name().as_str().map(IStr::from), p.has_default()))
+				.map(|p| (p.name().as_str().map(IStr::from), p.default()))
 				.collect()
 		))
 	}
@@ -211,7 +218,7 @@
 						param.name().as_str().map(IStr::from),
 						params
 							.iter()
-							.map(|p| (p.name().as_str().map(IStr::from), p.has_default()))
+							.map(|p| (p.name().as_str().map(IStr::from), p.default()))
 							.collect()
 					));
 				}
@@ -232,7 +239,10 @@
 		fn get(self: Box<Self>) -> Result<Val> {
 			Err(FunctionParameterNotBoundInCall(
 				Some(self.0.clone()),
-				self.1.iter().map(|p| (p.0.name(), p.1.is_some())).collect(),
+				self.1
+					.iter()
+					.map(|p| (p.0.name(), ParamDefault::exists(p.1.is_some())))
+					.collect(),
 			)
 			.into())
 		}
modifiedcrates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-macros/src/lib.rs
+++ b/crates/jrsonnet-macros/src/lib.rs
@@ -253,10 +253,14 @@
 			let name = name
 				.as_ref()
 				.map_or_else(|| quote! {None}, |n| quote! {ParamName::new_static(#n)});
-			let is_optional = optionality.is_optional();
+			let default = match optionality {
+				Optionality::Required => quote!(ParamDefault::None),
+				Optionality::Optional => quote!(ParamDefault::Exists),
+				Optionality::Default(e) => quote!(ParamDefault::Literal(stringify!(#e))),
+			};
 			Some(quote! {
 				#(#cfg_attrs)*
-				BuiltinParam::new(#name, #is_optional),
+				BuiltinParam::new(#name, #default),
 			})
 		}
 		ArgInfo::Lazy { is_option, name } => {
@@ -264,7 +268,7 @@
 				.as_ref()
 				.map_or_else(|| quote! {None}, |n| quote! {ParamName::new_static(#n)});
 			Some(quote! {
-				BuiltinParam::new(#name, #is_option),
+				BuiltinParam::new(#name, ParamDefault::exists(#is_option)),
 			})
 		}
 		ArgInfo::Context | ArgInfo::Location | ArgInfo::This => None,
@@ -375,7 +379,7 @@
 		const _: () = {
 			use ::jrsonnet_evaluator::{
 				State, Val,
-				function::{builtin::{Builtin, StaticBuiltin, BuiltinParam, ParamName}, CallLocation, ArgsLike, parse::parse_builtin_call},
+				function::{builtin::{Builtin, StaticBuiltin, BuiltinParam, ParamName, ParamDefault}, CallLocation, ArgsLike, parse::parse_builtin_call},
 				Result, Context, typed::Typed,
 				parser::ExprLocation,
 			};