difftreelog
style fix clippy warnings
in: master
35 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -68,6 +68,15 @@
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
+name = "block-buffer"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -141,6 +150,45 @@
]
[[package]]
+name = "cpufeatures"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "digest"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c"
+dependencies = [
+ "block-buffer",
+ "crypto-common",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
name = "getrandom"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -304,6 +352,7 @@
"serde",
"serde_json",
"serde_yaml_with_quirks",
+ "sha2",
"structdump",
]
@@ -550,6 +599,17 @@
]
[[package]]
+name = "sha2"
+version = "0.10.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
+dependencies = [
+ "cfg-if 1.0.0",
+ "cpufeatures",
+ "digest",
+]
+
+[[package]]
name = "smallvec"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -640,6 +700,12 @@
]
[[package]]
+name = "typenum"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
+
+[[package]]
name = "unicode-ident"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
bindings/jsonnet/src/import.rsdiffbeforeafterboth--- a/bindings/jsonnet/src/import.rs
+++ b/bindings/jsonnet/src/import.rs
@@ -12,7 +12,7 @@
};
use jrsonnet_evaluator::{
- error::{Error::*, Result},
+ error::{ErrorKind::*, Result},
throw, FileImportResolver, ImportResolver,
};
use jrsonnet_gcmodule::Trace;
bindings/jsonnet/src/lib.rsdiffbeforeafterboth--- a/bindings/jsonnet/src/lib.rs
+++ b/bindings/jsonnet/src/lib.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::box_default)]
+
#[cfg(feature = "interop")]
pub mod interop;
@@ -20,11 +22,11 @@
apply_tla,
function::TlaArg,
gc::GcHashMap,
+ manifest::{JsonFormat, ManifestFormat, ToStringFormat},
stack::set_stack_depth_limit,
- stdlib::manifest::{JsonFormat, ToStringFormat},
tb, throw,
trace::{CompactFormat, PathResolver, TraceFormat},
- FileImportResolver, IStr, ManifestFormat, Result, State, Val,
+ FileImportResolver, IStr, Result, State, Val,
};
/// WASM stub
@@ -193,7 +195,7 @@
let filename = parse_path(CStr::from_ptr(filename));
match vm
.state
- .import(&filename)
+ .import(filename)
.and_then(|val| apply_tla(vm.state.clone(), &vm.tla_args, val))
.and_then(|val| val.manifest(&vm.manifest_format))
{
@@ -286,7 +288,7 @@
let filename = parse_path(CStr::from_ptr(filename));
match vm
.state
- .import(&filename)
+ .import(filename)
.and_then(|val| apply_tla(vm.state.clone(), &vm.tla_args, val))
.and_then(|val| val_to_multi(val, &vm.manifest_format))
{
bindings/jsonnet/src/native.rsdiffbeforeafterboth--- a/bindings/jsonnet/src/native.rs
+++ b/bindings/jsonnet/src/native.rs
@@ -5,7 +5,7 @@
};
use jrsonnet_evaluator::{
- error::{Error, LocError},
+ error::{Error, ErrorKind},
function::builtin::{NativeCallback, NativeCallbackHandler},
tb,
typed::Typed,
@@ -38,7 +38,7 @@
cb: JsonnetNativeCallback,
}
impl NativeCallbackHandler for JsonnetNativeCallbackHandler {
- fn call(&self, args: &[Val]) -> Result<Val, LocError> {
+ fn call(&self, args: &[Val]) -> Result<Val, Error> {
let mut n_args = Vec::new();
for a in args {
n_args.push(Some(Box::new(a.clone())));
@@ -57,7 +57,7 @@
Ok(v)
} else {
let e = IStr::from_untyped(v).expect("error msg should be a string");
- Err(Error::RuntimeError(e).into())
+ Err(ErrorKind::RuntimeError(e).into())
}
}
}
cmds/jrsonnet/src/main.rsdiffbeforeafterboth--- a/cmds/jrsonnet/src/main.rs
+++ b/cmds/jrsonnet/src/main.rs
@@ -6,7 +6,11 @@
use clap::{CommandFactory, Parser};
use clap_complete::Shell;
use jrsonnet_cli::{ConfigureState, GeneralOpts, ManifestOpts, OutputOpts, TraceOpts};
-use jrsonnet_evaluator::{apply_tla, error::LocError, throw, ResultExt, State, Val};
+use jrsonnet_evaluator::{
+ apply_tla,
+ error::{Error as JrError, ErrorKind},
+ throw, ResultExt, State, Val,
+};
#[cfg(feature = "mimalloc")]
#[global_allocator]
@@ -96,7 +100,7 @@
enum Error {
// Handled differently
#[error("evaluation error")]
- Evaluation(LocError),
+ Evaluation(JrError),
#[error("io error")]
Io(#[from] std::io::Error),
#[error("input is not utf8 encoded")]
@@ -104,14 +108,14 @@
#[error("missing input argument")]
MissingInputArgument,
}
-impl From<LocError> for Error {
- fn from(e: LocError) -> Self {
+impl From<JrError> for Error {
+ fn from(e: JrError) -> Self {
Self::Evaluation(e)
}
}
-impl From<jrsonnet_evaluator::error::Error> for Error {
- fn from(e: jrsonnet_evaluator::error::Error) -> Self {
- Self::from(LocError::from(e))
+impl From<ErrorKind> for Error {
+ fn from(e: ErrorKind) -> Self {
+ Self::from(JrError::from(e))
}
}
crates/jrsonnet-cli/src/manifest.rsdiffbeforeafterboth--- a/crates/jrsonnet-cli/src/manifest.rs
+++ b/crates/jrsonnet-cli/src/manifest.rs
@@ -3,9 +3,10 @@
use clap::{Parser, ValueEnum};
use jrsonnet_evaluator::{
error::Result,
- stdlib::manifest::{JsonFormat, StringFormat, ToStringFormat, YamlFormat, YamlStreamFormat},
- ManifestFormat, State,
+ manifest::{JsonFormat, ManifestFormat, StringFormat, ToStringFormat, YamlStreamFormat},
+ State,
};
+use jrsonnet_stdlib::YamlFormat;
use crate::ConfigureState;
crates/jrsonnet-cli/src/tla.rsdiffbeforeafterboth--- a/crates/jrsonnet-cli/src/tla.rs
+++ b/crates/jrsonnet-cli/src/tla.rs
@@ -1,6 +1,6 @@
use clap::Parser;
use jrsonnet_evaluator::{
- error::{Error, Result},
+ error::{ErrorKind, Result},
function::TlaArg,
gc::GcHashMap,
IStr, State,
@@ -51,15 +51,15 @@
{
let source = Source::new_virtual(format!("<top-level-arg:{name}>").into(), code.into());
out.insert(
- (&name as &str).into(),
+ (name as &str).into(),
TlaArg::Code(
jrsonnet_parser::parse(
- &code,
+ code,
&ParserSettings {
source: source.clone(),
},
)
- .map_err(|e| Error::ImportSyntaxError {
+ .map_err(|e| ErrorKind::ImportSyntaxError {
path: source,
error: Box::new(e),
})?,
crates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/ctx.rs
+++ b/crates/jrsonnet-evaluator/src/ctx.rs
@@ -4,8 +4,8 @@
use jrsonnet_interner::IStr;
use crate::{
- error::Error::*, gc::GcHashMap, map::LayeredHashMap, ObjValue, Pending, Result, State, Thunk,
- Val,
+ error::ErrorKind::*, gc::GcHashMap, map::LayeredHashMap, ObjValue, Pending, Result, State,
+ Thunk, Val,
};
#[derive(Trace)]
crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/error.rs
+++ b/crates/jrsonnet-evaluator/src/error.rs
@@ -74,7 +74,7 @@
#[allow(missing_docs)]
#[derive(Error, Debug, Clone, Trace)]
#[non_exhaustive]
-pub enum Error {
+pub enum ErrorKind {
#[error("intrinsic not found: {0}")]
IntrinsicNotFound(IStr),
@@ -211,14 +211,14 @@
}
#[cfg(feature = "anyhow-error")]
-impl From<anyhow::Error> for LocError {
+impl From<anyhow::Error> for Error {
fn from(e: anyhow::Error) -> Self {
- Self::new(Error::Other(Rc::new(e)))
+ Self::new(ErrorKind::Other(Rc::new(e)))
}
}
-impl From<Error> for LocError {
- fn from(e: Error) -> Self {
+impl From<ErrorKind> for Error {
+ fn from(e: ErrorKind) -> Self {
Self::new(e)
}
}
@@ -236,16 +236,16 @@
pub struct StackTrace(pub Vec<StackTraceElement>);
#[derive(Clone, Trace)]
-pub struct LocError(Box<(Error, StackTrace)>);
-impl LocError {
- pub fn new(e: Error) -> Self {
+pub struct Error(Box<(ErrorKind, StackTrace)>);
+impl Error {
+ pub fn new(e: ErrorKind) -> Self {
Self(Box::new((e, StackTrace(vec![]))))
}
- pub const fn error(&self) -> &Error {
+ pub const fn error(&self) -> &ErrorKind {
&(self.0).0
}
- pub fn error_mut(&mut self) -> &mut Error {
+ pub fn error_mut(&mut self) -> &mut ErrorKind {
&mut (self.0).0
}
pub const fn trace(&self) -> &StackTrace {
@@ -255,7 +255,7 @@
&mut (self.0).1
}
}
-impl Display for LocError {
+impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "{}", self.0 .0)?;
for el in &self.0 .1 .0 {
@@ -269,7 +269,7 @@
Ok(())
}
}
-impl Debug for LocError {
+impl Debug for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("LocError").field(&self.0).finish()
}
@@ -294,7 +294,7 @@
}
}
-pub type Result<V, E = LocError> = std::result::Result<V, E>;
+pub type Result<V, E = Error> = std::result::Result<V, E>;
pub trait ResultExt: Sized {
#[must_use]
fn with_description<O: Into<String>>(self, msg: impl FnOnce() -> O) -> Self;
@@ -314,7 +314,7 @@
self.with_description_src(src, || msg)
}
}
-impl<T> ResultExt for Result<T, LocError> {
+impl<T> ResultExt for Result<T, Error> {
fn with_description<O: Into<String>>(mut self, msg: impl FnOnce() -> O) -> Self {
if let Err(e) = &mut self {
let trace = e.trace_mut();
@@ -348,9 +348,9 @@
return Err($w$(::$i)*$(($($tt)*))?.into())
};
($l:literal) => {
- return Err($crate::error::Error::RuntimeError($l.into()).into())
+ return Err($crate::error::ErrorKind::RuntimeError($l.into()).into())
};
($l:literal, $($tt:tt)*) => {
- return Err($crate::error::Error::RuntimeError(format!($l, $($tt)*).into()).into())
+ return Err($crate::error::ErrorKind::RuntimeError(format!($l, $($tt)*).into()).into())
};
}
crates/jrsonnet-evaluator/src/evaluate/destructure.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/destructure.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/destructure.rs
@@ -3,7 +3,7 @@
use jrsonnet_parser::{BindSpec, Destruct, LocExpr, ParamsDesc};
use crate::{
- error::{Error::*, Result},
+ error::{ErrorKind::*, Result},
evaluate, evaluate_method, evaluate_named,
gc::GcHashMap,
tb, throw,
crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs
@@ -11,14 +11,14 @@
use self::destructure::destruct;
use crate::{
destructure::evaluate_dest,
- error::Error::*,
+ error::ErrorKind::*,
evaluate::operator::{evaluate_add_op, evaluate_binary_op_special, evaluate_unary_op},
function::{CallLocation, FuncDesc, FuncVal},
tb, throw,
typed::Typed,
val::{ArrValue, CachedUnbound, IndexableVal, Thunk, ThunkValue},
- Context, GcHashMap, LocError, ObjValue, ObjValueBuilder, ObjectAssertion, Pending, Result,
- ResultExt, State, Unbound, Val,
+ Context, GcHashMap, ObjValue, ObjValueBuilder, ObjectAssertion, Pending, Result, State,
+ Unbound, Val,
};
pub mod destructure;
pub mod operator;
@@ -165,7 +165,7 @@
uctx: B,
field: &FieldMember,
) -> Result<()> {
- let name = evaluate_field_name(ctx.clone(), &field.name)?;
+ let name = evaluate_field_name(ctx, &field.name)?;
let Some(name) = name else {
return Ok(());
};
@@ -187,11 +187,7 @@
impl<B: Unbound<Bound = Context>> Unbound for UnboundValue<B> {
type Bound = Val;
fn bind(&self, sup: Option<ObjValue>, this: Option<ObjValue>) -> Result<Val> {
- Ok(evaluate_named(
- self.uctx.bind(sup, this)?,
- &self.value,
- self.name.clone(),
- )?)
+ evaluate_named(self.uctx.bind(sup, this)?, &self.value, self.name.clone())
}
}
@@ -201,9 +197,9 @@
.with_visibility(*visibility)
.with_location(value.1.clone())
.bindable(tb!(UnboundValue {
- uctx: uctx.clone(),
+ uctx,
value: value.clone(),
- name: name.clone()
+ name,
}))?;
}
FieldMember {
@@ -236,10 +232,10 @@
.with_visibility(*visibility)
.with_location(value.1.clone())
.bindable(tb!(UnboundMethod {
- uctx: uctx.clone(),
+ uctx,
value: value.clone(),
params: params.clone(),
- name: name.clone()
+ name,
}))?;
}
}
@@ -267,7 +263,7 @@
for member in members.iter() {
match member {
Member::Field(field) => {
- evaluate_field_member(&mut builder, ctx.clone(), uctx.clone(), &field)?
+ evaluate_field_member(&mut builder, ctx.clone(), uctx.clone(), field)?;
}
Member::AssertStmt(stmt) => {
#[derive(Trace)]
crates/jrsonnet-evaluator/src/evaluate/operator.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/operator.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/operator.rs
@@ -3,7 +3,7 @@
use jrsonnet_parser::{BinaryOpType, LocExpr, UnaryOpType};
use crate::{
- error::Error::*, evaluate, stdlib::std_format, throw, typed::Typed, val::equals, Context,
+ error::ErrorKind::*, evaluate, stdlib::std_format, throw, typed::Typed, val::equals, Context,
Result, Val,
};
crates/jrsonnet-evaluator/src/function/arglike.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function/arglike.rs
+++ b/crates/jrsonnet-evaluator/src/function/arglike.rs
@@ -180,8 +180,8 @@
}
}
-impl<A: ArgLike, S> sealed::Named for HashMap<IStr, A, S> {}
-impl<A: ArgLike, S> ArgsLike for HashMap<IStr, A, S> {
+impl<V: ArgLike, S> sealed::Named for HashMap<IStr, V, S> {}
+impl<V: ArgLike, S> ArgsLike for HashMap<IStr, V, S> {
fn unnamed_len(&self) -> usize {
0
}
@@ -213,7 +213,7 @@
}
}
}
-impl<A, S> OptionalContext for HashMap<IStr, A, S> where A: ArgLike + OptionalContext {}
+impl<V, S> OptionalContext for HashMap<IStr, V, S> where V: ArgLike + OptionalContext {}
impl<A: ArgLike> ArgsLike for GcHashMap<IStr, A> {
fn unnamed_len(&self) -> usize {
@@ -239,7 +239,7 @@
}
fn named_names(&self, handler: &mut dyn FnMut(&IStr)) {
- self.0.named_names(handler)
+ self.0.named_names(handler);
}
}
crates/jrsonnet-evaluator/src/function/parse.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function/parse.rs
+++ b/crates/jrsonnet-evaluator/src/function/parse.rs
@@ -7,7 +7,7 @@
use super::{arglike::ArgsLike, builtin::BuiltinParam};
use crate::{
destructure::destruct,
- error::{Error::*, Result},
+ error::{ErrorKind::*, Result},
evaluate_named,
gc::GcHashMap,
tb, throw,
crates/jrsonnet-evaluator/src/import.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/import.rs
+++ b/crates/jrsonnet-evaluator/src/import.rs
@@ -12,10 +12,7 @@
use jrsonnet_parser::{SourceDirectory, SourceFile, SourcePath};
use crate::{
- error::{
- Error::{self, *},
- Result,
- },
+ error::{ErrorKind::*, Result},
throw,
};
@@ -94,7 +91,7 @@
} else if let Some(d) = from.downcast_ref::<SourceDirectory>() {
d.path().to_owned()
} else if from.is_default() {
- current_dir().map_err(|e| Error::ImportIo(e.to_string()))?
+ current_dir().map_err(|e| ImportIo(e.to_string()))?
} else {
unreachable!("resolver can't return this path")
};
@@ -122,7 +119,7 @@
Err(e) if e.kind() == ErrorKind::NotFound => {
throw!(AbsoluteImportFileNotFound(path.to_owned()))
}
- Err(e) => throw!(Error::ImportIo(e.to_string())),
+ Err(e) => throw!(ImportIo(e.to_string())),
};
if meta.is_file() {
Ok(SourcePath::new(SourceFile::new(
@@ -141,7 +138,7 @@
let path = if let Some(f) = id.downcast_ref::<SourceFile>() {
f.path()
} else if id.downcast_ref::<SourceDirectory>().is_some() || id.is_default() {
- throw!(Error::ImportIsADirectory(id.clone()))
+ throw!(ImportIsADirectory(id.clone()))
} else {
unreachable!("other types are not supported in resolve");
};
crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/lib.rs
+++ b/crates/jrsonnet-evaluator/src/lib.rs
@@ -51,6 +51,7 @@
pub mod gc;
mod import;
mod integrations;
+pub mod manifest;
mod map;
mod obj;
pub mod stack;
@@ -69,7 +70,7 @@
pub use ctx::*;
pub use dynamic::*;
-pub use error::{Error::*, LocError, Result, ResultExt};
+pub use error::{Error, ErrorKind::*, Result, ResultExt};
pub use evaluate::*;
use function::CallLocation;
use gc::{GcHashMap, TraceBox};
@@ -82,7 +83,7 @@
pub use obj::*;
use stack::check_depth;
pub use tla::apply_tla;
-pub use val::{ManifestFormat, Thunk, Val};
+pub use val::{Thunk, Val};
/// Thunk without bound `super`/`this`
/// object inheritance may be overriden multiple times, and will be fixed only on field read
crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/obj.rs
+++ b/crates/jrsonnet-evaluator/src/obj.rs
@@ -11,7 +11,7 @@
use rustc_hash::FxHashMap;
use crate::{
- error::{Error::*, LocError},
+ error::{Error, ErrorKind::*},
function::CallLocation,
gc::{GcHashMap, GcHashSet, TraceBox},
operator::evaluate_add_op,
@@ -115,7 +115,7 @@
Cached(Val),
NotFound,
Pending,
- Errored(LocError),
+ Errored(Error),
}
#[allow(clippy::module_name_repetitions)]
crates/jrsonnet-evaluator/src/stack.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/stack.rs
+++ b/crates/jrsonnet-evaluator/src/stack.rs
@@ -1,6 +1,6 @@
use std::{cell::Cell, marker::PhantomData};
-use crate::error::{Error, LocError};
+use crate::error::{Error, ErrorKind};
struct StackLimit {
max_stack_size: Cell<usize>,
@@ -22,14 +22,14 @@
}
pub struct StackOverflowError;
-impl From<StackOverflowError> for Error {
+impl From<StackOverflowError> for ErrorKind {
fn from(_: StackOverflowError) -> Self {
- Error::StackOverflow
+ ErrorKind::StackOverflow
}
}
-impl From<StackOverflowError> for LocError {
+impl From<StackOverflowError> for Error {
fn from(_: StackOverflowError) -> Self {
- Error::StackOverflow.into()
+ ErrorKind::StackOverflow.into()
}
}
crates/jrsonnet-evaluator/src/stdlib/format.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/stdlib/format.rs
+++ b/crates/jrsonnet-evaluator/src/stdlib/format.rs
@@ -6,7 +6,7 @@
use jrsonnet_types::ValType;
use thiserror::Error;
-use crate::{error::Error::*, throw, typed::Typed, LocError, ObjValue, Result, Val};
+use crate::{error::ErrorKind::*, throw, typed::Typed, Error, ObjValue, Result, Val};
#[derive(Debug, Clone, Error, Trace)]
pub enum FormatError {
@@ -26,7 +26,7 @@
NoSuchFormatField(IStr),
}
-impl From<FormatError> for LocError {
+impl From<FormatError> for Error {
fn from(e: FormatError) -> Self {
Self::new(Format(e))
}
crates/jrsonnet-evaluator/src/stdlib/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/stdlib/mod.rs
+++ b/crates/jrsonnet-evaluator/src/stdlib/mod.rs
@@ -7,7 +7,6 @@
use crate::{error::Result, function::CallLocation, State, Val};
pub mod format;
-pub mod manifest;
pub fn std_format(str: IStr, vals: Val) -> Result<String> {
State::push(
crates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/trace/mod.rs
+++ b/crates/jrsonnet-evaluator/src/trace/mod.rs
@@ -6,7 +6,7 @@
use jrsonnet_gcmodule::Trace;
use jrsonnet_parser::{CodeLocation, Source};
-use crate::{error::Error, LocError};
+use crate::{error::ErrorKind, Error};
/// The way paths should be displayed
#[derive(Clone, Trace)]
@@ -51,9 +51,9 @@
fn write_trace(
&self,
out: &mut dyn std::fmt::Write,
- error: &LocError,
+ error: &Error,
) -> Result<(), std::fmt::Error>;
- fn format(&self, error: &LocError) -> Result<String, std::fmt::Error> {
+ fn format(&self, error: &Error) -> Result<String, std::fmt::Error> {
let mut out = String::new();
self.write_trace(&mut out, error)?;
Ok(out)
@@ -107,10 +107,10 @@
fn write_trace(
&self,
out: &mut dyn std::fmt::Write,
- error: &LocError,
+ error: &Error,
) -> Result<(), std::fmt::Error> {
write!(out, "{}", error.error())?;
- if let Error::ImportSyntaxError { path, error } = error.error() {
+ if let ErrorKind::ImportSyntaxError { path, error } = error.error() {
use std::fmt::Write;
writeln!(out)?;
@@ -204,7 +204,7 @@
fn write_trace(
&self,
out: &mut dyn std::fmt::Write,
- error: &LocError,
+ error: &Error,
) -> Result<(), std::fmt::Error> {
write!(out, "{}", error.error())?;
for item in &error.trace().0 {
@@ -250,10 +250,10 @@
fn write_trace(
&self,
out: &mut dyn std::fmt::Write,
- error: &LocError,
+ error: &Error,
) -> Result<(), std::fmt::Error> {
write!(out, "{}", error.error())?;
- if let Error::ImportSyntaxError { path, error } = error.error() {
+ if let ErrorKind::ImportSyntaxError { path, error } = error.error() {
writeln!(out)?;
let offset = error.location.offset;
let location = path
crates/jrsonnet-evaluator/src/typed/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/typed/mod.rs
+++ b/crates/jrsonnet-evaluator/src/typed/mod.rs
@@ -7,7 +7,7 @@
use thiserror::Error;
use crate::{
- error::{Error, LocError, Result},
+ error::{Error, ErrorKind, Result},
State, Val,
};
@@ -26,9 +26,9 @@
)]
BoundsFailed(f64, Option<f64>, Option<f64>),
}
-impl From<TypeError> for LocError {
+impl From<TypeError> for Error {
fn from(e: TypeError) -> Self {
- Error::TypeError(e.into()).into()
+ ErrorKind::TypeError(e.into()).into()
}
}
@@ -39,9 +39,9 @@
Self(Box::new(e), ValuePathStack(Vec::new()))
}
}
-impl From<TypeLocError> for LocError {
+impl From<TypeLocError> for Error {
fn from(e: TypeLocError) -> Self {
- Error::TypeError(e).into()
+ ErrorKind::TypeError(e).into()
}
}
impl Display for TypeLocError {
@@ -92,7 +92,7 @@
State::push_description(error_reason, || match item() {
Ok(_) => Ok(()),
Err(mut e) => {
- if let Error::TypeError(e) = &mut e.error_mut() {
+ if let ErrorKind::TypeError(e) = &mut e.error_mut() {
(e.1).0.push(path());
}
Err(e)
@@ -218,7 +218,7 @@
return Ok(());
}
Err(e) => match e.error() {
- Error::TypeError(e) => errors.push(e.clone()),
+ ErrorKind::TypeError(e) => errors.push(e.clone()),
_ => return Err(e),
},
}
@@ -233,7 +233,7 @@
return Ok(());
}
Err(e) => match e.error() {
- Error::TypeError(e) => errors.push(e.clone()),
+ ErrorKind::TypeError(e) => errors.push(e.clone()),
_ => return Err(e),
},
}
crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -5,9 +5,10 @@
use jrsonnet_types::ValType;
use crate::{
- error::{Error::*, LocError},
+ error::{Error, ErrorKind::*},
function::FuncVal,
gc::{GcHashMap, TraceBox},
+ manifest::{ManifestFormat, ToStringFormat},
throw,
typed::BoundedUsize,
ObjValue, Result, Unbound, WeakObjValue,
@@ -21,7 +22,7 @@
#[derive(Trace)]
enum ThunkInner<T: Trace> {
Computed(T),
- Errored(LocError),
+ Errored(Error),
Waiting(TraceBox<dyn ThunkValue<Output = T>>),
Pending,
}
@@ -116,33 +117,6 @@
impl<T: Trace> PartialEq for Thunk<T> {
fn eq(&self, other: &Self) -> bool {
Cc::ptr_eq(&self.0, &other.0)
- }
-}
-
-pub trait ManifestFormat {
- fn manifest_buf(&self, val: Val, buf: &mut String) -> Result<()>;
- fn manifest(&self, val: Val) -> Result<String> {
- let mut out = String::new();
- self.manifest_buf(val, &mut out)?;
- Ok(out)
- }
-}
-impl<T> ManifestFormat for Box<T>
-where
- T: ManifestFormat + ?Sized,
-{
- fn manifest_buf(&self, val: Val, buf: &mut String) -> Result<()> {
- let inner = &**self;
- inner.manifest_buf(val, buf)
- }
-}
-impl<T> ManifestFormat for &'_ T
-where
- T: ManifestFormat + ?Sized,
-{
- fn manifest_buf(&self, val: Val, buf: &mut String) -> Result<()> {
- let inner = &**self;
- inner.manifest_buf(val, buf)
}
}
@@ -649,9 +623,7 @@
Self::Bool(false) => "false".into(),
Self::Null => "null".into(),
Self::Str(s) => s.clone(),
- _ => self
- .manifest(crate::stdlib::manifest::ToStringFormat)
- .map(IStr::from)?,
+ _ => self.manifest(ToStringFormat).map(IStr::from)?,
})
}
crates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-macros/src/lib.rs
+++ b/crates/jrsonnet-macros/src/lib.rs
@@ -540,7 +540,7 @@
}
} else {
quote! {
- <#ty>::from_untyped(obj.get(#name.into())?.ok_or_else(|| Error::NoSuchField(#name.into(), vec![]))?)?
+ <#ty>::from_untyped(obj.get(#name.into())?.ok_or_else(|| ErrorKind::NoSuchField(#name.into(), vec![]))?)?
}
};
@@ -638,19 +638,19 @@
use ::jrsonnet_evaluator::{
typed::{ComplexValType, Typed, TypedObj, CheckType},
Val, State,
- error::{LocError, Error, Result},
+ error::{ErrorKind, Result as JrResult},
ObjValueBuilder, ObjValue,
};
#typed
impl TypedObj for #ident {
- fn serialize(self, out: &mut ObjValueBuilder) -> Result<(), LocError> {
+ fn serialize(self, out: &mut ObjValueBuilder) -> JrResult<()> {
#(#fields_serialize)*
Ok(())
}
- fn parse(obj: &ObjValue) -> Result<Self, LocError> {
+ fn parse(obj: &ObjValue) -> JrResult<Self> {
Ok(Self {
#(#fields_parse)*
})
crates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth1#![allow(clippy::redundant_closure_call, clippy::derive_partial_eq_without_eq)]23use std::rc::Rc;45use peg::parser;6mod expr;7pub use expr::*;8pub use jrsonnet_interner::IStr;9pub use peg;10mod location;11mod source;12mod unescape;13pub use location::CodeLocation;14pub use source::{Source, SourceDirectory, SourceFile, SourcePath, SourcePathT, SourceVirtual};1516pub struct ParserSettings {17 pub source: Source,18}1920macro_rules! expr_bin {21 ($a:ident $op:ident $b:ident) => {22 Expr::BinaryOp($a, $op, $b)23 };24}25macro_rules! expr_un {26 ($op:ident $a:ident) => {27 Expr::UnaryOp($op, $a)28 };29}3031parser! {32 grammar jsonnet_parser() for str {33 use peg::ParseLiteral;3435 rule eof() = quiet!{![_]} / expected!("<eof>")36 rule eol() = "\n" / eof()3738 /// Standard C-like comments39 rule comment()40 = "//" (!eol()[_])* eol()41 / "/*" ("\\*/" / "\\\\" / (!("*/")[_]))* "*/"42 / "#" (!eol()[_])* eol()4344 rule single_whitespace() = quiet!{([' ' | '\r' | '\n' | '\t'] / comment())} / expected!("<whitespace>")45 rule _() = quiet!{([' ' | '\r' | '\n' | '\t']+) / comment()}* / expected!("<whitespace>")4647 /// For comma-delimited elements48 rule comma() = quiet!{_ "," _} / expected!("<comma>")49 rule alpha() -> char = c:$(['_' | 'a'..='z' | 'A'..='Z']) {c.chars().next().unwrap()}50 rule digit() -> char = d:$(['0'..='9']) {d.chars().next().unwrap()}51 rule end_of_ident() = !['0'..='9' | '_' | 'a'..='z' | 'A'..='Z']52 /// Sequence of digits53 rule uint_str() -> &'input str = a:$(digit()+) { a }54 /// Number in scientific notation format55 rule number() -> f64 = quiet!{a:$(uint_str() ("." uint_str())? (['e'|'E'] (s:['+'|'-'])? uint_str())?) {? a.parse().map_err(|_| "<number>") }} / expected!("<number>")5657 /// Reserved word followed by any non-alphanumberic58 rule reserved() = ("assert" / "else" / "error" / "false" / "for" / "function" / "if" / "import" / "importstr" / "importbin" / "in" / "local" / "null" / "tailstrict" / "then" / "self" / "super" / "true") end_of_ident()59 rule id() -> IStr = v:$(quiet!{ !reserved() alpha() (alpha() / digit())*} / expected!("<identifier>")) { v.into() }6061 rule keyword(id: &'static str) -> ()62 = ##parse_string_literal(id) end_of_ident()6364 pub rule param(s: &ParserSettings) -> expr::Param = name:destruct(s) expr:(_ "=" _ expr:expr(s){expr})? { expr::Param(name, expr) }65 pub rule params(s: &ParserSettings) -> expr::ParamsDesc66 = params:param(s) ** comma() comma()? { expr::ParamsDesc(Rc::new(params)) }67 / { expr::ParamsDesc(Rc::new(Vec::new())) }6869 pub rule arg(s: &ParserSettings) -> (Option<IStr>, LocExpr)70 = name:(quiet! { (s:id() _ "=" !['='] _ {s})? } / expected!("<argument name>")) expr:expr(s) {(name, expr)}7172 pub rule args(s: &ParserSettings) -> expr::ArgsDesc73 = args:arg(s)**comma() comma()? {?74 let unnamed_count = args.iter().take_while(|(n, _)| n.is_none()).count();75 let mut unnamed = Vec::with_capacity(unnamed_count);76 let mut named = Vec::with_capacity(args.len() - unnamed_count);77 let mut named_started = false;78 for (name, value) in args {79 if let Some(name) = name {80 named_started = true;81 named.push((name, value));82 } else {83 if named_started {84 return Err("<named argument>")85 }86 unnamed.push(value);87 }88 }89 Ok(expr::ArgsDesc::new(unnamed, named))90 }9192 pub rule destruct_rest() -> expr::DestructRest93 = "..." into:(_ into:id() {into})? {if let Some(into) = into {94 expr::DestructRest::Keep(into)95 } else {expr::DestructRest::Drop}}96 pub rule destruct_array(s: &ParserSettings) -> expr::Destruct97 = "[" _ start:destruct(s)**comma() rest:(98 comma() _ rest:destruct_rest()? end:(99 comma() end:destruct(s)**comma() (_ comma())? {end}100 / comma()? {Vec::new()}101 ) {(rest, end)}102 / comma()? {(None, Vec::new())}103 ) _ "]" {?104 #[cfg(feature = "exp-destruct")] return Ok(expr::Destruct::Array {105 start,106 rest: rest.0,107 end: rest.1,108 });109 #[cfg(not(feature = "exp-destruct"))] Err("experimental destructuring was not enabled")110 }111 pub rule destruct_object(s: &ParserSettings) -> expr::Destruct112 = "{" _113 fields:(name:id() into:(_ ":" _ into:destruct(s) {into})? default:(_ "=" _ v:expr(s) {v})? {(name, into, default)})**comma()114 rest:(115 comma() rest:destruct_rest()? {rest}116 / comma()? {None}117 )118 _ "}" {?119 #[cfg(feature = "exp-destruct")] return Ok(expr::Destruct::Object {120 fields,121 rest,122 });123 #[cfg(not(feature = "exp-destruct"))] Err("experimental destructuring was not enabled")124 }125 pub rule destruct(s: &ParserSettings) -> expr::Destruct126 = v:id() {expr::Destruct::Full(v)}127 / "?" {?128 #[cfg(feature = "exp-destruct")] return Ok(expr::Destruct::Skip);129 #[cfg(not(feature = "exp-destruct"))] Err("experimental destructuring was not enabled")130 }131 / arr:destruct_array(s) {arr}132 / obj:destruct_object(s) {obj}133134 pub rule bind(s: &ParserSettings) -> expr::BindSpec135 = into:destruct(s) _ "=" _ expr:expr(s) {expr::BindSpec::Field{into, value: expr}}136 / name:id() _ "(" _ params:params(s) _ ")" _ "=" _ expr:expr(s) {expr::BindSpec::Function{name, params, value: expr}}137138 pub rule assertion(s: &ParserSettings) -> expr::AssertStmt139 = keyword("assert") _ cond:expr(s) msg:(_ ":" _ e:expr(s) {e})? { expr::AssertStmt(cond, msg) }140141 pub rule whole_line() -> &'input str142 = str:$((!['\n'][_])* "\n") {str}143 pub rule string_block() -> String144 = "|||" (!['\n']single_whitespace())* "\n"145 empty_lines:$(['\n']*)146 prefix:[' ' | '\t']+ first_line:whole_line()147 lines:("\n" {"\n"} / [' ' | '\t']*<{prefix.len()}> s:whole_line() {s})*148 [' ' | '\t']*<, {prefix.len() - 1}> "|||"149 {let mut l = empty_lines.to_owned(); l.push_str(first_line); l.extend(lines); l}150151 rule hex_char()152 = quiet! { ['0'..='9' | 'a'..='f' | 'A'..='F'] } / expected!("<hex char>")153154 rule string_char(c: rule<()>)155 = (!['\\']!c()[_])+156 / "\\\\"157 / "\\u" hex_char() hex_char() hex_char() hex_char()158 / "\\x" hex_char() hex_char()159 / ['\\'] (quiet! { ['b' | 'f' | 'n' | 'r' | 't' | '"' | '\''] } / expected!("<escape character>"))160 pub rule string() -> String161 = ['"'] str:$(string_char(<"\"">)*) ['"'] {? unescape::unescape(str).ok_or("<escaped string>")}162 / ['\''] str:$(string_char(<"\'">)*) ['\''] {? unescape::unescape(str).ok_or("<escaped string>")}163 / quiet!{ "@'" str:$(("''" / (!['\''][_]))*) "'" {str.replace("''", "'")}164 / "@\"" str:$(("\"\"" / (!['"'][_]))*) "\"" {str.replace("\"\"", "\"")}165 / string_block() } / expected!("<string>")166167 pub rule field_name(s: &ParserSettings) -> expr::FieldName168 = name:id() {expr::FieldName::Fixed(name)}169 / name:string() {expr::FieldName::Fixed(name.into())}170 / "[" _ expr:expr(s) _ "]" {expr::FieldName::Dyn(expr)}171 pub rule visibility() -> expr::Visibility172 = ":::" {expr::Visibility::Unhide}173 / "::" {expr::Visibility::Hidden}174 / ":" {expr::Visibility::Normal}175 pub rule field(s: &ParserSettings) -> expr::FieldMember176 = name:field_name(s) _ plus:"+"? _ visibility:visibility() _ value:expr(s) {expr::FieldMember{177 name,178 plus: plus.is_some(),179 params: None,180 visibility,181 value,182 }}183 / name:field_name(s) _ "(" _ params:params(s) _ ")" _ visibility:visibility() _ value:expr(s) {expr::FieldMember{184 name,185 plus: false,186 params: Some(params),187 visibility,188 value,189 }}190 pub rule obj_local(s: &ParserSettings) -> BindSpec191 = keyword("local") _ bind:bind(s) {bind}192 pub rule member(s: &ParserSettings) -> expr::Member193 = bind:obj_local(s) {expr::Member::BindStmt(bind)}194 / assertion:assertion(s) {expr::Member::AssertStmt(assertion)}195 / field:field(s) {expr::Member::Field(field)}196 pub rule objinside(s: &ParserSettings) -> expr::ObjBody197 = pre_locals:(b: obj_local(s) comma() {b})* &"[" field:field(s) post_locals:(comma() b:obj_local(s) {b})* _ ("," _)? forspec:forspec(s) others:(_ rest:compspec(s) {rest})? {198 let mut compspecs = vec![CompSpec::ForSpec(forspec)];199 compspecs.extend(others.unwrap_or_default());200 expr::ObjBody::ObjComp(expr::ObjComp{201 pre_locals,202 field,203 post_locals,204 compspecs,205 })206 }207 / members:(member(s) ** comma()) comma()? {expr::ObjBody::MemberList(members)}208 pub rule ifspec(s: &ParserSettings) -> IfSpecData209 = keyword("if") _ expr:expr(s) {IfSpecData(expr)}210 pub rule forspec(s: &ParserSettings) -> ForSpecData211 = keyword("for") _ id:destruct(s) _ keyword("in") _ cond:expr(s) {ForSpecData(id, cond)}212 pub rule compspec(s: &ParserSettings) -> Vec<expr::CompSpec>213 = s:(i:ifspec(s) { expr::CompSpec::IfSpec(i) } / f:forspec(s) {expr::CompSpec::ForSpec(f)} ) ** _ {s}214 pub rule local_expr(s: &ParserSettings) -> Expr215 = keyword("local") _ binds:bind(s) ** comma() (_ ",")? _ ";" _ expr:expr(s) { Expr::LocalExpr(binds, expr) }216 pub rule string_expr(s: &ParserSettings) -> Expr217 = s:string() {Expr::Str(s.into())}218 pub rule obj_expr(s: &ParserSettings) -> Expr219 = "{" _ body:objinside(s) _ "}" {Expr::Obj(body)}220 pub rule array_expr(s: &ParserSettings) -> Expr221 = "[" _ elems:(expr(s) ** comma()) _ comma()? "]" {Expr::Arr(elems)}222 pub rule array_comp_expr(s: &ParserSettings) -> Expr223 = "[" _ expr:expr(s) _ comma()? _ forspec:forspec(s) _ others:(others: compspec(s) _ {others})? "]" {224 let mut specs = vec![CompSpec::ForSpec(forspec)];225 specs.extend(others.unwrap_or_default());226 Expr::ArrComp(expr, specs)227 }228 pub rule number_expr(s: &ParserSettings) -> Expr229 = n:number() { expr::Expr::Num(n) }230 pub rule var_expr(s: &ParserSettings) -> Expr231 = n:id() { expr::Expr::Var(n) }232 pub rule id_loc(s: &ParserSettings) -> LocExpr233 = a:position!() n:id() b:position!() { LocExpr(Rc::new(expr::Expr::Str(n)), ExprLocation(s.source.clone(), a as u32,b as u32)) }234 pub rule if_then_else_expr(s: &ParserSettings) -> Expr235 = cond:ifspec(s) _ keyword("then") _ cond_then:expr(s) cond_else:(_ keyword("else") _ e:expr(s) {e})? {Expr::IfElse{236 cond,237 cond_then,238 cond_else,239 }}240241 pub rule literal(s: &ParserSettings) -> Expr242 = v:(243 keyword("null") {LiteralType::Null}244 / keyword("true") {LiteralType::True}245 / keyword("false") {LiteralType::False}246 / keyword("self") {LiteralType::This}247 / keyword("$") {LiteralType::Dollar}248 / keyword("super") {LiteralType::Super}249 ) {Expr::Literal(v)}250251 pub rule expr_basic(s: &ParserSettings) -> Expr252 = literal(s)253254 / string_expr(s) / number_expr(s)255 / array_expr(s)256 / obj_expr(s)257 / array_expr(s)258 / array_comp_expr(s)259260 / keyword("importstr") _ path:expr(s) {Expr::ImportStr(path)}261 / keyword("importbin") _ path:expr(s) {Expr::ImportBin(path)}262 / keyword("import") _ path:expr(s) {Expr::Import(path)}263264 / var_expr(s)265 / local_expr(s)266 / if_then_else_expr(s)267268 / keyword("function") _ "(" _ params:params(s) _ ")" _ expr:expr(s) {Expr::Function(params, expr)}269 / assertion:assertion(s) _ ";" _ expr:expr(s) { Expr::AssertExpr(assertion, expr) }270271 / keyword("error") _ expr:expr(s) { Expr::ErrorStmt(expr) }272273 rule slice_part(s: &ParserSettings) -> Option<LocExpr>274 = _ e:(e:expr(s) _{e})? {e}275 pub rule slice_desc(s: &ParserSettings) -> SliceDesc276 = start:slice_part(s) ":" pair:(end:slice_part(s) step:(":" e:slice_part(s){e})? {(end, step.flatten())})? {277 let (end, step) = if let Some((end, step)) = pair {278 (end, step)279 }else{280 (None, None)281 };282283 SliceDesc { start, end, step }284 }285286 rule binop(x: rule<()>) -> ()287 = quiet!{ x() } / expected!("<binary op>")288 rule unaryop(x: rule<()>) -> ()289 = quiet!{ x() } / expected!("<unary op>")290291292 use BinaryOpType::*;293 use UnaryOpType::*;294 rule expr(s: &ParserSettings) -> LocExpr295 = precedence! {296 start:position!() v:@ end:position!() { LocExpr(Rc::new(v), ExprLocation(s.source.clone(), start as u32, end as u32)) }297 --298 a:(@) _ binop(<"||">) _ b:@ {expr_bin!(a Or b)}299 --300 a:(@) _ binop(<"&&">) _ b:@ {expr_bin!(a And b)}301 --302 a:(@) _ binop(<"|">) _ b:@ {expr_bin!(a BitOr b)}303 --304 a:@ _ binop(<"^">) _ b:(@) {expr_bin!(a BitXor b)}305 --306 a:(@) _ binop(<"&">) _ b:@ {expr_bin!(a BitAnd b)}307 --308 a:(@) _ binop(<"==">) _ b:@ {expr_bin!(a Eq b)}309 a:(@) _ binop(<"!=">) _ b:@ {expr_bin!(a Neq b)}310 --311 a:(@) _ binop(<"<">) _ b:@ {expr_bin!(a Lt b)}312 a:(@) _ binop(<">">) _ b:@ {expr_bin!(a Gt b)}313 a:(@) _ binop(<"<=">) _ b:@ {expr_bin!(a Lte b)}314 a:(@) _ binop(<">=">) _ b:@ {expr_bin!(a Gte b)}315 a:(@) _ binop(<keyword("in")>) _ b:@ {expr_bin!(a In b)}316 --317 a:(@) _ binop(<"<<">) _ b:@ {expr_bin!(a Lhs b)}318 a:(@) _ binop(<">>">) _ b:@ {expr_bin!(a Rhs b)}319 --320 a:(@) _ binop(<"+">) _ b:@ {expr_bin!(a Add b)}321 a:(@) _ binop(<"-">) _ b:@ {expr_bin!(a Sub b)}322 --323 a:(@) _ binop(<"*">) _ b:@ {expr_bin!(a Mul b)}324 a:(@) _ binop(<"/">) _ b:@ {expr_bin!(a Div b)}325 a:(@) _ binop(<"%">) _ b:@ {expr_bin!(a Mod b)}326 --327 unaryop(<"-">) _ b:@ {expr_un!(Minus b)}328 unaryop(<"!">) _ b:@ {expr_un!(Not b)}329 unaryop(<"~">) _ b:@ {expr_un!(BitNot b)}330 --331 a:(@) _ "[" _ e:slice_desc(s) _ "]" {Expr::Slice(a, e)}332 a:(@) _ "." _ a:position!() e:id_loc(s) b:position!() {Expr::Index(a, e)}333 a:(@) _ "[" _ e:expr(s) _ "]" {Expr::Index(a, e)}334 a:(@) _ "(" _ args:args(s) _ ")" ts:(_ keyword("tailstrict"))? {Expr::Apply(a, args, ts.is_some())}335 a:(@) _ "{" _ body:objinside(s) _ "}" {Expr::ObjExtend(a, body)}336 --337 e:expr_basic(s) {e}338 "(" _ e:expr(s) _ ")" {Expr::Parened(e)}339 }340341 pub rule jsonnet(s: &ParserSettings) -> LocExpr = _ e:expr(s) _ {e}342 }343}344345pub type ParseError = peg::error::ParseError<peg::str::LineCol>;346pub fn parse(str: &str, settings: &ParserSettings) -> Result<LocExpr, ParseError> {347 jsonnet_parser::jsonnet(str, settings)348}349/// Used for importstr values350pub fn string_to_expr(str: IStr, settings: &ParserSettings) -> LocExpr {351 let len = str.len();352 LocExpr(353 Rc::new(Expr::Str(str)),354 ExprLocation(settings.source.clone(), 0, len as u32),355 )356}357358#[cfg(test)]359pub mod tests {360 use jrsonnet_interner::IStr;361 use BinaryOpType::*;362363 use super::{expr::*, parse};364 use crate::{source::Source, ParserSettings};365366 macro_rules! parse {367 ($s:expr) => {368 parse(369 $s,370 &ParserSettings {371 source: Source::new_virtual("<test>".into(), IStr::empty()),372 },373 )374 .unwrap()375 };376 }377378 macro_rules! el {379 ($expr:expr, $from:expr, $to:expr$(,)?) => {380 LocExpr(381 std::rc::Rc::new($expr),382 ExprLocation(383 Source::new_virtual("<test>".into(), IStr::empty()),384 $from,385 $to,386 ),387 )388 };389 }390391 #[test]392 fn multiline_string() {393 assert_eq!(394 parse!("|||\n Hello world!\n a\n|||"),395 el!(Expr::Str("Hello world!\n a\n".into()), 0, 31),396 );397 assert_eq!(398 parse!("|||\n Hello world!\n a\n|||"),399 el!(Expr::Str("Hello world!\n a\n".into()), 0, 27),400 );401 assert_eq!(402 parse!("|||\n\t\tHello world!\n\t\t\ta\n|||"),403 el!(Expr::Str("Hello world!\n\ta\n".into()), 0, 27),404 );405 assert_eq!(406 parse!("|||\n Hello world!\n a\n |||"),407 el!(Expr::Str("Hello world!\n a\n".into()), 0, 30),408 );409 }410411 #[test]412 fn slice() {413 parse!("a[1:]");414 parse!("a[1::]");415 parse!("a[:1:]");416 parse!("a[::1]");417 parse!("str[:len - 1]");418 }419420 #[test]421 fn string_escaping() {422 assert_eq!(423 parse!(r#""Hello, \"world\"!""#),424 el!(Expr::Str(r#"Hello, "world"!"#.into()), 0, 19),425 );426 assert_eq!(427 parse!(r#"'Hello \'world\'!'"#),428 el!(Expr::Str("Hello 'world'!".into()), 0, 18),429 );430 assert_eq!(parse!(r#"'\\\\'"#), el!(Expr::Str("\\\\".into()), 0, 6));431 }432433 #[test]434 fn string_unescaping() {435 assert_eq!(436 parse!(r#""Hello\nWorld""#),437 el!(Expr::Str("Hello\nWorld".into()), 0, 14),438 );439 }440441 #[test]442 fn string_verbantim() {443 assert_eq!(444 parse!(r#"@"Hello\n""World""""#),445 el!(Expr::Str("Hello\\n\"World\"".into()), 0, 19),446 );447 }448449 #[test]450 fn imports() {451 assert_eq!(452 parse!("import \"hello\""),453 el!(Expr::Import("hello".into()), 0, 14),454 );455 assert_eq!(456 parse!("importstr \"garnish.txt\""),457 el!(Expr::ImportStr("garnish.txt".into()), 0, 23)458 );459 assert_eq!(460 parse!("importbin \"garnish.bin\""),461 el!(Expr::ImportBin("garnish.bin".into()), 0, 23)462 );463 }464465 #[test]466 fn empty_object() {467 assert_eq!(468 parse!("{}"),469 el!(Expr::Obj(ObjBody::MemberList(vec![])), 0, 2)470 );471 }472473 #[test]474 fn basic_math() {475 assert_eq!(476 parse!("2+2*2"),477 el!(478 Expr::BinaryOp(479 el!(Expr::Num(2.0), 0, 1),480 Add,481 el!(482 Expr::BinaryOp(el!(Expr::Num(2.0), 2, 3), Mul, el!(Expr::Num(2.0), 4, 5)),483 2,484 5485 )486 ),487 0,488 5489 )490 );491 }492493 #[test]494 fn basic_math_with_indents() {495 assert_eq!(496 parse!("2 + 2 * 2 "),497 el!(498 Expr::BinaryOp(499 el!(Expr::Num(2.0), 0, 1),500 Add,501 el!(502 Expr::BinaryOp(el!(Expr::Num(2.0), 7, 8), Mul, el!(Expr::Num(2.0), 13, 14),),503 7,504 14505 ),506 ),507 0,508 14509 )510 );511 }512513 #[test]514 fn basic_math_parened() {515 assert_eq!(516 parse!("2+(2+2*2)"),517 el!(518 Expr::BinaryOp(519 el!(Expr::Num(2.0), 0, 1),520 Add,521 el!(522 Expr::Parened(el!(523 Expr::BinaryOp(524 el!(Expr::Num(2.0), 3, 4),525 Add,526 el!(527 Expr::BinaryOp(528 el!(Expr::Num(2.0), 5, 6),529 Mul,530 el!(Expr::Num(2.0), 7, 8),531 ),532 5,533 8534 ),535 ),536 3,537 8538 )),539 2,540 9541 ),542 ),543 0,544 9545 )546 );547 }548549 /// Comments should not affect parsing550 #[test]551 fn comments() {552 assert_eq!(553 parse!("2//comment\n+//comment\n3/*test*/*/*test*/4"),554 el!(555 Expr::BinaryOp(556 el!(Expr::Num(2.0), 0, 1),557 Add,558 el!(559 Expr::BinaryOp(560 el!(Expr::Num(3.0), 22, 23),561 Mul,562 el!(Expr::Num(4.0), 40, 41)563 ),564 22,565 41566 )567 ),568 0,569 41570 )571 );572 }573574 /// Comments should be able to be escaped575 #[test]576 fn comment_escaping() {577 assert_eq!(578 parse!("2/*\\*/+*/ - 22"),579 el!(580 Expr::BinaryOp(el!(Expr::Num(2.0), 0, 1), Sub, el!(Expr::Num(22.0), 12, 14)),581 0,582 14583 )584 );585 }586587 #[test]588 fn suffix() {589 // assert_eq!(parse!("std.test"), el!(Expr::Num(2.2)));590 // assert_eq!(parse!("std(2)"), el!(Expr::Num(2.2)));591 // assert_eq!(parse!("std.test(2)"), el!(Expr::Num(2.2)));592 // assert_eq!(parse!("a[b]"), el!(Expr::Num(2.2)))593 }594595 #[test]596 fn array_comp() {597 use Expr::*;598 /*599 `ArrComp(Apply(Index(Var("std") from "test.jsonnet":1-4, Var("deepJoin") from "test.jsonnet":5-13) from "test.jsonnet":1-13, ArgsDesc { unnamed: [Var("x") from "test.jsonnet":14-15], named: [] }, false) from "test.jsonnet":1-16, [ForSpec(ForSpecData("x", Var("arr") from "test.jsonnet":26-29))]) from "test.jsonnet":0-30`,600 `ArrComp(Apply(Index(Var("std") from "test.jsonnet":1-4, Str("deepJoin") from "test.jsonnet":5-13) from "test.jsonnet":1-13, ArgsDesc { unnamed: [Var("x") from "test.jsonnet":14-15], named: [] }, false) from "test.jsonnet":1-16, [ForSpec(ForSpecData("x", Var("arr") from "test.jsonnet":26-29))]) from "test.jsonnet":0-30`601 */602 assert_eq!(603 parse!("[std.deepJoin(x) for x in arr]"),604 el!(605 ArrComp(606 el!(607 Apply(608 el!(609 Index(610 el!(Var("std".into()), 1, 4),611 el!(Str("deepJoin".into()), 5, 13)612 ),613 1,614 13615 ),616 ArgsDesc::new(vec![el!(Var("x".into()), 14, 15)], vec![]),617 false,618 ),619 1,620 16621 ),622 vec![CompSpec::ForSpec(ForSpecData(623 Destruct::Full("x".into()),624 el!(Var("arr".into()), 26, 29)625 ))]626 ),627 0,628 30629 ),630 )631 }632633 #[test]634 fn reserved() {635 use Expr::*;636 assert_eq!(parse!("null"), el!(Literal(LiteralType::Null), 0, 4));637 assert_eq!(parse!("nulla"), el!(Var("nulla".into()), 0, 5));638 }639640 #[test]641 fn multiple_args_buf() {642 parse!("a(b, null_fields)");643 }644645 #[test]646 fn infix_precedence() {647 use Expr::*;648 assert_eq!(649 parse!("!a && !b"),650 el!(651 BinaryOp(652 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into()), 1, 2)), 0, 2),653 And,654 el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()), 7, 8)), 6, 8)655 ),656 0,657 8658 )659 );660 }661662 #[test]663 fn infix_precedence_division() {664 use Expr::*;665 assert_eq!(666 parse!("!a / !b"),667 el!(668 BinaryOp(669 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into()), 1, 2)), 0, 2),670 Div,671 el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()), 6, 7)), 5, 7)672 ),673 0,674 7675 )676 );677 }678679 #[test]680 fn double_negation() {681 use Expr::*;682 assert_eq!(683 parse!("!!a"),684 el!(685 UnaryOp(686 UnaryOpType::Not,687 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into()), 2, 3)), 1, 3)688 ),689 0,690 3691 )692 )693 }694695 #[test]696 fn array_test_error() {697 parse!("[a for a in b if c for e in f]");698 // ^^^^ failed code699 }700701 #[test]702 fn missing_newline_between_comment_and_eof() {703 parse!(704 "{a:1}705706 //+213"707 );708 }709710 #[test]711 fn default_param_before_nondefault() {712 parse!("local x(foo = 'foo', bar) = null; null");713 }714715 #[test]716 fn add_location_info_to_all_sub_expressions() {717 use Expr::*;718719 let file_name = Source::new_virtual("<test>".into(), IStr::empty());720 let expr = parse(721 "{} { local x = 1, x: x } + {}",722 &ParserSettings { source: file_name },723 )724 .unwrap();725 assert_eq!(726 expr,727 el!(728 BinaryOp(729 el!(730 ObjExtend(731 el!(Obj(ObjBody::MemberList(vec![])), 0, 2),732 ObjBody::MemberList(vec![733 Member::BindStmt(BindSpec::Field {734 into: Destruct::Full("x".into()),735 value: el!(Num(1.0), 15, 16)736 }),737 Member::Field(FieldMember {738 name: FieldName::Fixed("x".into()),739 plus: false,740 params: None,741 visibility: Visibility::Normal,742 value: el!(Var("x".into()), 21, 22),743 })744 ])745 ),746 0,747 24748 ),749 BinaryOpType::Add,750 el!(Obj(ObjBody::MemberList(vec![])), 27, 29),751 ),752 0,753 29754 ),755 );756 }757}1#![allow(clippy::redundant_closure_call, clippy::derive_partial_eq_without_eq)]23use std::rc::Rc;45use peg::parser;6mod expr;7pub use expr::*;8pub use jrsonnet_interner::IStr;9pub use peg;10mod location;11mod source;12mod unescape;13pub use location::CodeLocation;14pub use source::{Source, SourceDirectory, SourceFile, SourcePath, SourcePathT, SourceVirtual};1516pub struct ParserSettings {17 pub source: Source,18}1920macro_rules! expr_bin {21 ($a:ident $op:ident $b:ident) => {22 Expr::BinaryOp($a, $op, $b)23 };24}25macro_rules! expr_un {26 ($op:ident $a:ident) => {27 Expr::UnaryOp($op, $a)28 };29}3031parser! {32 grammar jsonnet_parser() for str {33 use peg::ParseLiteral;3435 rule eof() = quiet!{![_]} / expected!("<eof>")36 rule eol() = "\n" / eof()3738 /// Standard C-like comments39 rule comment()40 = "//" (!eol()[_])* eol()41 / "/*" ("\\*/" / "\\\\" / (!("*/")[_]))* "*/"42 / "#" (!eol()[_])* eol()4344 rule single_whitespace() = quiet!{([' ' | '\r' | '\n' | '\t'] / comment())} / expected!("<whitespace>")45 rule _() = quiet!{([' ' | '\r' | '\n' | '\t']+) / comment()}* / expected!("<whitespace>")4647 /// For comma-delimited elements48 rule comma() = quiet!{_ "," _} / expected!("<comma>")49 rule alpha() -> char = c:$(['_' | 'a'..='z' | 'A'..='Z']) {c.chars().next().unwrap()}50 rule digit() -> char = d:$(['0'..='9']) {d.chars().next().unwrap()}51 rule end_of_ident() = !['0'..='9' | '_' | 'a'..='z' | 'A'..='Z']52 /// Sequence of digits53 rule uint_str() -> &'input str = a:$(digit()+) { a }54 /// Number in scientific notation format55 rule number() -> f64 = quiet!{a:$(uint_str() ("." uint_str())? (['e'|'E'] (s:['+'|'-'])? uint_str())?) {? a.parse().map_err(|_| "<number>") }} / expected!("<number>")5657 /// Reserved word followed by any non-alphanumberic58 rule reserved() = ("assert" / "else" / "error" / "false" / "for" / "function" / "if" / "import" / "importstr" / "importbin" / "in" / "local" / "null" / "tailstrict" / "then" / "self" / "super" / "true") end_of_ident()59 rule id() -> IStr = v:$(quiet!{ !reserved() alpha() (alpha() / digit())*} / expected!("<identifier>")) { v.into() }6061 rule keyword(id: &'static str) -> ()62 = ##parse_string_literal(id) end_of_ident()6364 pub rule param(s: &ParserSettings) -> expr::Param = name:destruct(s) expr:(_ "=" _ expr:expr(s){expr})? { expr::Param(name, expr) }65 pub rule params(s: &ParserSettings) -> expr::ParamsDesc66 = params:param(s) ** comma() comma()? { expr::ParamsDesc(Rc::new(params)) }67 / { expr::ParamsDesc(Rc::new(Vec::new())) }6869 pub rule arg(s: &ParserSettings) -> (Option<IStr>, LocExpr)70 = name:(quiet! { (s:id() _ "=" !['='] _ {s})? } / expected!("<argument name>")) expr:expr(s) {(name, expr)}7172 pub rule args(s: &ParserSettings) -> expr::ArgsDesc73 = args:arg(s)**comma() comma()? {?74 let unnamed_count = args.iter().take_while(|(n, _)| n.is_none()).count();75 let mut unnamed = Vec::with_capacity(unnamed_count);76 let mut named = Vec::with_capacity(args.len() - unnamed_count);77 let mut named_started = false;78 for (name, value) in args {79 if let Some(name) = name {80 named_started = true;81 named.push((name, value));82 } else {83 if named_started {84 return Err("<named argument>")85 }86 unnamed.push(value);87 }88 }89 Ok(expr::ArgsDesc::new(unnamed, named))90 }9192 pub rule destruct_rest() -> expr::DestructRest93 = "..." into:(_ into:id() {into})? {if let Some(into) = into {94 expr::DestructRest::Keep(into)95 } else {expr::DestructRest::Drop}}96 pub rule destruct_array(s: &ParserSettings) -> expr::Destruct97 = "[" _ start:destruct(s)**comma() rest:(98 comma() _ rest:destruct_rest()? end:(99 comma() end:destruct(s)**comma() (_ comma())? {end}100 / comma()? {Vec::new()}101 ) {(rest, end)}102 / comma()? {(None, Vec::new())}103 ) _ "]" {?104 #[cfg(feature = "exp-destruct")] return Ok(expr::Destruct::Array {105 start,106 rest: rest.0,107 end: rest.1,108 });109 #[cfg(not(feature = "exp-destruct"))] Err("experimental destructuring was not enabled")110 }111 pub rule destruct_object(s: &ParserSettings) -> expr::Destruct112 = "{" _113 fields:(name:id() into:(_ ":" _ into:destruct(s) {into})? default:(_ "=" _ v:expr(s) {v})? {(name, into, default)})**comma()114 rest:(115 comma() rest:destruct_rest()? {rest}116 / comma()? {None}117 )118 _ "}" {?119 #[cfg(feature = "exp-destruct")] return Ok(expr::Destruct::Object {120 fields,121 rest,122 });123 #[cfg(not(feature = "exp-destruct"))] Err("experimental destructuring was not enabled")124 }125 pub rule destruct(s: &ParserSettings) -> expr::Destruct126 = v:id() {expr::Destruct::Full(v)}127 / "?" {?128 #[cfg(feature = "exp-destruct")] return Ok(expr::Destruct::Skip);129 #[cfg(not(feature = "exp-destruct"))] Err("experimental destructuring was not enabled")130 }131 / arr:destruct_array(s) {arr}132 / obj:destruct_object(s) {obj}133134 pub rule bind(s: &ParserSettings) -> expr::BindSpec135 = into:destruct(s) _ "=" _ expr:expr(s) {expr::BindSpec::Field{into, value: expr}}136 / name:id() _ "(" _ params:params(s) _ ")" _ "=" _ expr:expr(s) {expr::BindSpec::Function{name, params, value: expr}}137138 pub rule assertion(s: &ParserSettings) -> expr::AssertStmt139 = keyword("assert") _ cond:expr(s) msg:(_ ":" _ e:expr(s) {e})? { expr::AssertStmt(cond, msg) }140141 pub rule whole_line() -> &'input str142 = str:$((!['\n'][_])* "\n") {str}143 pub rule string_block() -> String144 = "|||" (!['\n']single_whitespace())* "\n"145 empty_lines:$(['\n']*)146 prefix:[' ' | '\t']+ first_line:whole_line()147 lines:("\n" {"\n"} / [' ' | '\t']*<{prefix.len()}> s:whole_line() {s})*148 [' ' | '\t']*<, {prefix.len() - 1}> "|||"149 {let mut l = empty_lines.to_owned(); l.push_str(first_line); l.extend(lines); l}150151 rule hex_char()152 = quiet! { ['0'..='9' | 'a'..='f' | 'A'..='F'] } / expected!("<hex char>")153154 rule string_char(c: rule<()>)155 = (!['\\']!c()[_])+156 / "\\\\"157 / "\\u" hex_char() hex_char() hex_char() hex_char()158 / "\\x" hex_char() hex_char()159 / ['\\'] (quiet! { ['b' | 'f' | 'n' | 'r' | 't' | '"' | '\''] } / expected!("<escape character>"))160 pub rule string() -> String161 = ['"'] str:$(string_char(<"\"">)*) ['"'] {? unescape::unescape(str).ok_or("<escaped string>")}162 / ['\''] str:$(string_char(<"\'">)*) ['\''] {? unescape::unescape(str).ok_or("<escaped string>")}163 / quiet!{ "@'" str:$(("''" / (!['\''][_]))*) "'" {str.replace("''", "'")}164 / "@\"" str:$(("\"\"" / (!['"'][_]))*) "\"" {str.replace("\"\"", "\"")}165 / string_block() } / expected!("<string>")166167 pub rule field_name(s: &ParserSettings) -> expr::FieldName168 = name:id() {expr::FieldName::Fixed(name)}169 / name:string() {expr::FieldName::Fixed(name.into())}170 / "[" _ expr:expr(s) _ "]" {expr::FieldName::Dyn(expr)}171 pub rule visibility() -> expr::Visibility172 = ":::" {expr::Visibility::Unhide}173 / "::" {expr::Visibility::Hidden}174 / ":" {expr::Visibility::Normal}175 pub rule field(s: &ParserSettings) -> expr::FieldMember176 = name:field_name(s) _ plus:"+"? _ visibility:visibility() _ value:expr(s) {expr::FieldMember{177 name,178 plus: plus.is_some(),179 params: None,180 visibility,181 value,182 }}183 / name:field_name(s) _ "(" _ params:params(s) _ ")" _ visibility:visibility() _ value:expr(s) {expr::FieldMember{184 name,185 plus: false,186 params: Some(params),187 visibility,188 value,189 }}190 pub rule obj_local(s: &ParserSettings) -> BindSpec191 = keyword("local") _ bind:bind(s) {bind}192 pub rule member(s: &ParserSettings) -> expr::Member193 = bind:obj_local(s) {expr::Member::BindStmt(bind)}194 / assertion:assertion(s) {expr::Member::AssertStmt(assertion)}195 / field:field(s) {expr::Member::Field(field)}196 pub rule objinside(s: &ParserSettings) -> expr::ObjBody197 = pre_locals:(b: obj_local(s) comma() {b})* &"[" field:field(s) post_locals:(comma() b:obj_local(s) {b})* _ ("," _)? forspec:forspec(s) others:(_ rest:compspec(s) {rest})? {198 let mut compspecs = vec![CompSpec::ForSpec(forspec)];199 compspecs.extend(others.unwrap_or_default());200 expr::ObjBody::ObjComp(expr::ObjComp{201 pre_locals,202 field,203 post_locals,204 compspecs,205 })206 }207 / members:(member(s) ** comma()) comma()? {expr::ObjBody::MemberList(members)}208 pub rule ifspec(s: &ParserSettings) -> IfSpecData209 = keyword("if") _ expr:expr(s) {IfSpecData(expr)}210 pub rule forspec(s: &ParserSettings) -> ForSpecData211 = keyword("for") _ id:destruct(s) _ keyword("in") _ cond:expr(s) {ForSpecData(id, cond)}212 pub rule compspec(s: &ParserSettings) -> Vec<expr::CompSpec>213 = s:(i:ifspec(s) { expr::CompSpec::IfSpec(i) } / f:forspec(s) {expr::CompSpec::ForSpec(f)} ) ** _ {s}214 pub rule local_expr(s: &ParserSettings) -> Expr215 = keyword("local") _ binds:bind(s) ** comma() (_ ",")? _ ";" _ expr:expr(s) { Expr::LocalExpr(binds, expr) }216 pub rule string_expr(s: &ParserSettings) -> Expr217 = s:string() {Expr::Str(s.into())}218 pub rule obj_expr(s: &ParserSettings) -> Expr219 = "{" _ body:objinside(s) _ "}" {Expr::Obj(body)}220 pub rule array_expr(s: &ParserSettings) -> Expr221 = "[" _ elems:(expr(s) ** comma()) _ comma()? "]" {Expr::Arr(elems)}222 pub rule array_comp_expr(s: &ParserSettings) -> Expr223 = "[" _ expr:expr(s) _ comma()? _ forspec:forspec(s) _ others:(others: compspec(s) _ {others})? "]" {224 let mut specs = vec![CompSpec::ForSpec(forspec)];225 specs.extend(others.unwrap_or_default());226 Expr::ArrComp(expr, specs)227 }228 pub rule number_expr(s: &ParserSettings) -> Expr229 = n:number() { expr::Expr::Num(n) }230 pub rule var_expr(s: &ParserSettings) -> Expr231 = n:id() { expr::Expr::Var(n) }232 pub rule id_loc(s: &ParserSettings) -> LocExpr233 = a:position!() n:id() b:position!() { LocExpr(Rc::new(expr::Expr::Str(n)), ExprLocation(s.source.clone(), a as u32,b as u32)) }234 pub rule if_then_else_expr(s: &ParserSettings) -> Expr235 = cond:ifspec(s) _ keyword("then") _ cond_then:expr(s) cond_else:(_ keyword("else") _ e:expr(s) {e})? {Expr::IfElse{236 cond,237 cond_then,238 cond_else,239 }}240241 pub rule literal(s: &ParserSettings) -> Expr242 = v:(243 keyword("null") {LiteralType::Null}244 / keyword("true") {LiteralType::True}245 / keyword("false") {LiteralType::False}246 / keyword("self") {LiteralType::This}247 / keyword("$") {LiteralType::Dollar}248 / keyword("super") {LiteralType::Super}249 ) {Expr::Literal(v)}250251 pub rule expr_basic(s: &ParserSettings) -> Expr252 = literal(s)253254 / string_expr(s) / number_expr(s)255 / array_expr(s)256 / obj_expr(s)257 / array_expr(s)258 / array_comp_expr(s)259260 / keyword("importstr") _ path:expr(s) {Expr::ImportStr(path)}261 / keyword("importbin") _ path:expr(s) {Expr::ImportBin(path)}262 / keyword("import") _ path:expr(s) {Expr::Import(path)}263264 / var_expr(s)265 / local_expr(s)266 / if_then_else_expr(s)267268 / keyword("function") _ "(" _ params:params(s) _ ")" _ expr:expr(s) {Expr::Function(params, expr)}269 / assertion:assertion(s) _ ";" _ expr:expr(s) { Expr::AssertExpr(assertion, expr) }270271 / keyword("error") _ expr:expr(s) { Expr::ErrorStmt(expr) }272273 rule slice_part(s: &ParserSettings) -> Option<LocExpr>274 = _ e:(e:expr(s) _{e})? {e}275 pub rule slice_desc(s: &ParserSettings) -> SliceDesc276 = start:slice_part(s) ":" pair:(end:slice_part(s) step:(":" e:slice_part(s){e})? {(end, step.flatten())})? {277 let (end, step) = if let Some((end, step)) = pair {278 (end, step)279 }else{280 (None, None)281 };282283 SliceDesc { start, end, step }284 }285286 rule binop(x: rule<()>) -> ()287 = quiet!{ x() } / expected!("<binary op>")288 rule unaryop(x: rule<()>) -> ()289 = quiet!{ x() } / expected!("<unary op>")290291292 use BinaryOpType::*;293 use UnaryOpType::*;294 rule expr(s: &ParserSettings) -> LocExpr295 = precedence! {296 start:position!() v:@ end:position!() { LocExpr(Rc::new(v), ExprLocation(s.source.clone(), start as u32, end as u32)) }297 --298 a:(@) _ binop(<"||">) _ b:@ {expr_bin!(a Or b)}299 --300 a:(@) _ binop(<"&&">) _ b:@ {expr_bin!(a And b)}301 --302 a:(@) _ binop(<"|">) _ b:@ {expr_bin!(a BitOr b)}303 --304 a:@ _ binop(<"^">) _ b:(@) {expr_bin!(a BitXor b)}305 --306 a:(@) _ binop(<"&">) _ b:@ {expr_bin!(a BitAnd b)}307 --308 a:(@) _ binop(<"==">) _ b:@ {expr_bin!(a Eq b)}309 a:(@) _ binop(<"!=">) _ b:@ {expr_bin!(a Neq b)}310 --311 a:(@) _ binop(<"<">) _ b:@ {expr_bin!(a Lt b)}312 a:(@) _ binop(<">">) _ b:@ {expr_bin!(a Gt b)}313 a:(@) _ binop(<"<=">) _ b:@ {expr_bin!(a Lte b)}314 a:(@) _ binop(<">=">) _ b:@ {expr_bin!(a Gte b)}315 a:(@) _ binop(<keyword("in")>) _ b:@ {expr_bin!(a In b)}316 --317 a:(@) _ binop(<"<<">) _ b:@ {expr_bin!(a Lhs b)}318 a:(@) _ binop(<">>">) _ b:@ {expr_bin!(a Rhs b)}319 --320 a:(@) _ binop(<"+">) _ b:@ {expr_bin!(a Add b)}321 a:(@) _ binop(<"-">) _ b:@ {expr_bin!(a Sub b)}322 --323 a:(@) _ binop(<"*">) _ b:@ {expr_bin!(a Mul b)}324 a:(@) _ binop(<"/">) _ b:@ {expr_bin!(a Div b)}325 a:(@) _ binop(<"%">) _ b:@ {expr_bin!(a Mod b)}326 --327 unaryop(<"-">) _ b:@ {expr_un!(Minus b)}328 unaryop(<"!">) _ b:@ {expr_un!(Not b)}329 unaryop(<"~">) _ b:@ {expr_un!(BitNot b)}330 --331 a:(@) _ "[" _ e:slice_desc(s) _ "]" {Expr::Slice(a, e)}332 a:(@) _ "." _ a:position!() e:id_loc(s) b:position!() {Expr::Index(a, e)}333 a:(@) _ "[" _ e:expr(s) _ "]" {Expr::Index(a, e)}334 a:(@) _ "(" _ args:args(s) _ ")" ts:(_ keyword("tailstrict"))? {Expr::Apply(a, args, ts.is_some())}335 a:(@) _ "{" _ body:objinside(s) _ "}" {Expr::ObjExtend(a, body)}336 --337 e:expr_basic(s) {e}338 "(" _ e:expr(s) _ ")" {Expr::Parened(e)}339 }340341 pub rule jsonnet(s: &ParserSettings) -> LocExpr = _ e:expr(s) _ {e}342 }343}344345pub type ParseError = peg::error::ParseError<peg::str::LineCol>;346pub fn parse(str: &str, settings: &ParserSettings) -> Result<LocExpr, ParseError> {347 jsonnet_parser::jsonnet(str, settings)348}349/// Used for importstr values350pub fn string_to_expr(str: IStr, settings: &ParserSettings) -> LocExpr {351 let len = str.len();352 LocExpr(353 Rc::new(Expr::Str(str)),354 ExprLocation(settings.source.clone(), 0, len as u32),355 )356}357358#[cfg(test)]359pub mod tests {360 use jrsonnet_interner::IStr;361 use BinaryOpType::*;362363 use super::{expr::*, parse};364 use crate::{source::Source, ParserSettings};365366 macro_rules! parse {367 ($s:expr) => {368 parse(369 $s,370 &ParserSettings {371 source: Source::new_virtual("<test>".into(), IStr::empty()),372 },373 )374 .unwrap()375 };376 }377378 macro_rules! el {379 ($expr:expr, $from:expr, $to:expr$(,)?) => {380 LocExpr(381 std::rc::Rc::new($expr),382 ExprLocation(383 Source::new_virtual("<test>".into(), IStr::empty()),384 $from,385 $to,386 ),387 )388 };389 }390391 #[test]392 fn multiline_string() {393 assert_eq!(394 parse!("|||\n Hello world!\n a\n|||"),395 el!(Expr::Str("Hello world!\n a\n".into()), 0, 31),396 );397 assert_eq!(398 parse!("|||\n Hello world!\n a\n|||"),399 el!(Expr::Str("Hello world!\n a\n".into()), 0, 27),400 );401 assert_eq!(402 parse!("|||\n\t\tHello world!\n\t\t\ta\n|||"),403 el!(Expr::Str("Hello world!\n\ta\n".into()), 0, 27),404 );405 assert_eq!(406 parse!("|||\n Hello world!\n a\n |||"),407 el!(Expr::Str("Hello world!\n a\n".into()), 0, 30),408 );409 }410411 #[test]412 fn slice() {413 parse!("a[1:]");414 parse!("a[1::]");415 parse!("a[:1:]");416 parse!("a[::1]");417 parse!("str[:len - 1]");418 }419420 #[test]421 fn string_escaping() {422 assert_eq!(423 parse!(r#""Hello, \"world\"!""#),424 el!(Expr::Str(r#"Hello, "world"!"#.into()), 0, 19),425 );426 assert_eq!(427 parse!(r#"'Hello \'world\'!'"#),428 el!(Expr::Str("Hello 'world'!".into()), 0, 18),429 );430 assert_eq!(parse!(r#"'\\\\'"#), el!(Expr::Str("\\\\".into()), 0, 6));431 }432433 #[test]434 fn string_unescaping() {435 assert_eq!(436 parse!(r#""Hello\nWorld""#),437 el!(Expr::Str("Hello\nWorld".into()), 0, 14),438 );439 }440441 #[test]442 fn string_verbantim() {443 assert_eq!(444 parse!(r#"@"Hello\n""World""""#),445 el!(Expr::Str("Hello\\n\"World\"".into()), 0, 19),446 );447 }448449 #[test]450 fn imports() {451 assert_eq!(452 parse!("import \"hello\""),453 el!(Expr::Import(el!(Expr::Str("hello".into()), 7, 14)), 0, 14),454 );455 assert_eq!(456 parse!("importstr \"garnish.txt\""),457 el!(458 Expr::ImportStr(el!(Expr::Str("garnish.txt".into()), 10, 23)),459 0,460 23461 )462 );463 assert_eq!(464 parse!("importbin \"garnish.bin\""),465 el!(466 Expr::ImportBin(el!(Expr::Str("garnish.bin".into()), 10, 23)),467 0,468 23469 )470 );471 }472473 #[test]474 fn empty_object() {475 assert_eq!(476 parse!("{}"),477 el!(Expr::Obj(ObjBody::MemberList(vec![])), 0, 2)478 );479 }480481 #[test]482 fn basic_math() {483 assert_eq!(484 parse!("2+2*2"),485 el!(486 Expr::BinaryOp(487 el!(Expr::Num(2.0), 0, 1),488 Add,489 el!(490 Expr::BinaryOp(el!(Expr::Num(2.0), 2, 3), Mul, el!(Expr::Num(2.0), 4, 5)),491 2,492 5493 )494 ),495 0,496 5497 )498 );499 }500501 #[test]502 fn basic_math_with_indents() {503 assert_eq!(504 parse!("2 + 2 * 2 "),505 el!(506 Expr::BinaryOp(507 el!(Expr::Num(2.0), 0, 1),508 Add,509 el!(510 Expr::BinaryOp(el!(Expr::Num(2.0), 7, 8), Mul, el!(Expr::Num(2.0), 13, 14),),511 7,512 14513 ),514 ),515 0,516 14517 )518 );519 }520521 #[test]522 fn basic_math_parened() {523 assert_eq!(524 parse!("2+(2+2*2)"),525 el!(526 Expr::BinaryOp(527 el!(Expr::Num(2.0), 0, 1),528 Add,529 el!(530 Expr::Parened(el!(531 Expr::BinaryOp(532 el!(Expr::Num(2.0), 3, 4),533 Add,534 el!(535 Expr::BinaryOp(536 el!(Expr::Num(2.0), 5, 6),537 Mul,538 el!(Expr::Num(2.0), 7, 8),539 ),540 5,541 8542 ),543 ),544 3,545 8546 )),547 2,548 9549 ),550 ),551 0,552 9553 )554 );555 }556557 /// Comments should not affect parsing558 #[test]559 fn comments() {560 assert_eq!(561 parse!("2//comment\n+//comment\n3/*test*/*/*test*/4"),562 el!(563 Expr::BinaryOp(564 el!(Expr::Num(2.0), 0, 1),565 Add,566 el!(567 Expr::BinaryOp(568 el!(Expr::Num(3.0), 22, 23),569 Mul,570 el!(Expr::Num(4.0), 40, 41)571 ),572 22,573 41574 )575 ),576 0,577 41578 )579 );580 }581582 /// Comments should be able to be escaped583 #[test]584 fn comment_escaping() {585 assert_eq!(586 parse!("2/*\\*/+*/ - 22"),587 el!(588 Expr::BinaryOp(el!(Expr::Num(2.0), 0, 1), Sub, el!(Expr::Num(22.0), 12, 14)),589 0,590 14591 )592 );593 }594595 #[test]596 fn suffix() {597 // assert_eq!(parse!("std.test"), el!(Expr::Num(2.2)));598 // assert_eq!(parse!("std(2)"), el!(Expr::Num(2.2)));599 // assert_eq!(parse!("std.test(2)"), el!(Expr::Num(2.2)));600 // assert_eq!(parse!("a[b]"), el!(Expr::Num(2.2)))601 }602603 #[test]604 fn array_comp() {605 use Expr::*;606 /*607 `ArrComp(Apply(Index(Var("std") from "test.jsonnet":1-4, Var("deepJoin") from "test.jsonnet":5-13) from "test.jsonnet":1-13, ArgsDesc { unnamed: [Var("x") from "test.jsonnet":14-15], named: [] }, false) from "test.jsonnet":1-16, [ForSpec(ForSpecData("x", Var("arr") from "test.jsonnet":26-29))]) from "test.jsonnet":0-30`,608 `ArrComp(Apply(Index(Var("std") from "test.jsonnet":1-4, Str("deepJoin") from "test.jsonnet":5-13) from "test.jsonnet":1-13, ArgsDesc { unnamed: [Var("x") from "test.jsonnet":14-15], named: [] }, false) from "test.jsonnet":1-16, [ForSpec(ForSpecData("x", Var("arr") from "test.jsonnet":26-29))]) from "test.jsonnet":0-30`609 */610 assert_eq!(611 parse!("[std.deepJoin(x) for x in arr]"),612 el!(613 ArrComp(614 el!(615 Apply(616 el!(617 Index(618 el!(Var("std".into()), 1, 4),619 el!(Str("deepJoin".into()), 5, 13)620 ),621 1,622 13623 ),624 ArgsDesc::new(vec![el!(Var("x".into()), 14, 15)], vec![]),625 false,626 ),627 1,628 16629 ),630 vec![CompSpec::ForSpec(ForSpecData(631 Destruct::Full("x".into()),632 el!(Var("arr".into()), 26, 29)633 ))]634 ),635 0,636 30637 ),638 )639 }640641 #[test]642 fn reserved() {643 use Expr::*;644 assert_eq!(parse!("null"), el!(Literal(LiteralType::Null), 0, 4));645 assert_eq!(parse!("nulla"), el!(Var("nulla".into()), 0, 5));646 }647648 #[test]649 fn multiple_args_buf() {650 parse!("a(b, null_fields)");651 }652653 #[test]654 fn infix_precedence() {655 use Expr::*;656 assert_eq!(657 parse!("!a && !b"),658 el!(659 BinaryOp(660 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into()), 1, 2)), 0, 2),661 And,662 el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()), 7, 8)), 6, 8)663 ),664 0,665 8666 )667 );668 }669670 #[test]671 fn infix_precedence_division() {672 use Expr::*;673 assert_eq!(674 parse!("!a / !b"),675 el!(676 BinaryOp(677 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into()), 1, 2)), 0, 2),678 Div,679 el!(UnaryOp(UnaryOpType::Not, el!(Var("b".into()), 6, 7)), 5, 7)680 ),681 0,682 7683 )684 );685 }686687 #[test]688 fn double_negation() {689 use Expr::*;690 assert_eq!(691 parse!("!!a"),692 el!(693 UnaryOp(694 UnaryOpType::Not,695 el!(UnaryOp(UnaryOpType::Not, el!(Var("a".into()), 2, 3)), 1, 3)696 ),697 0,698 3699 )700 )701 }702703 #[test]704 fn array_test_error() {705 parse!("[a for a in b if c for e in f]");706 // ^^^^ failed code707 }708709 #[test]710 fn missing_newline_between_comment_and_eof() {711 parse!(712 "{a:1}713714 //+213"715 );716 }717718 #[test]719 fn default_param_before_nondefault() {720 parse!("local x(foo = 'foo', bar) = null; null");721 }722723 #[test]724 fn add_location_info_to_all_sub_expressions() {725 use Expr::*;726727 let file_name = Source::new_virtual("<test>".into(), IStr::empty());728 let expr = parse(729 "{} { local x = 1, x: x } + {}",730 &ParserSettings { source: file_name },731 )732 .unwrap();733 assert_eq!(734 expr,735 el!(736 BinaryOp(737 el!(738 ObjExtend(739 el!(Obj(ObjBody::MemberList(vec![])), 0, 2),740 ObjBody::MemberList(vec![741 Member::BindStmt(BindSpec::Field {742 into: Destruct::Full("x".into()),743 value: el!(Num(1.0), 15, 16)744 }),745 Member::Field(FieldMember {746 name: FieldName::Fixed("x".into()),747 plus: false,748 params: None,749 visibility: Visibility::Normal,750 value: el!(Var("x".into()), 21, 22),751 })752 ])753 ),754 0,755 24756 ),757 BinaryOpType::Add,758 el!(Obj(ObjBody::MemberList(vec![])), 27, 29),759 ),760 0,761 29762 ),763 );764 }765}crates/jrsonnet-stdlib/Cargo.tomldiffbeforeafterboth--- a/crates/jrsonnet-stdlib/Cargo.toml
+++ b/crates/jrsonnet-stdlib/Cargo.toml
@@ -7,7 +7,7 @@
edition = "2021"
[features]
-default = ["codegenerated-stdlib"]
+default = ["codegenerated-stdlib", "exp-more-hashes"]
# Speed-up initialization by generating code for parsed stdlib, instead
# of invoking parser for it
codegenerated-stdlib = ["jrsonnet-parser/structdump"]
@@ -15,6 +15,7 @@
legacy-this-file = []
# Add order preservation flag to some functions
exp-preserve-order = ["jrsonnet-evaluator/exp-preserve-order"]
+exp-more-hashes = ["sha2"]
[dependencies]
jrsonnet-evaluator.workspace = true
@@ -36,6 +37,8 @@
# std.parseYaml, custom library fork is used for C++/golang compatibility
serde_yaml_with_quirks = "0.8.24"
+sha2 = { version = "0.10.6", optional = true }
+
[build-dependencies]
jrsonnet-parser.workspace = true
structdump = { version = "0.2.0", features = ["derive"] }
crates/jrsonnet-stdlib/build.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/build.rs
+++ b/crates/jrsonnet-stdlib/build.rs
@@ -19,7 +19,7 @@
{
let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("stdlib.rs");
- let mut f = File::create(&dest_path).unwrap();
+ let mut f = File::create(dest_path).unwrap();
f.write_all(
("#[allow(clippy::redundant_clone)]".to_owned() + &v.to_string())
.replace(';', ";\n")
crates/jrsonnet-stdlib/src/encoding.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/encoding.rs
+++ b/crates/jrsonnet-stdlib/src/encoding.rs
@@ -1,5 +1,5 @@
use jrsonnet_evaluator::{
- error::{Error::RuntimeError, Result},
+ error::{ErrorKind::RuntimeError, Result},
function::builtin,
typed::{Either, Either2},
IBytes, IStr,
crates/jrsonnet-stdlib/src/hash.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/hash.rs
+++ b/crates/jrsonnet-stdlib/src/hash.rs
@@ -4,3 +4,10 @@
pub fn builtin_md5(str: IStr) -> Result<String> {
Ok(format!("{:x}", md5::compute(str.as_bytes())))
}
+
+#[cfg(feature = "exp-more-hashes")]
+#[builtin]
+pub fn builtin_sha256(str: IStr) -> Result<String> {
+ use sha2::digest::Digest;
+ Ok(format!("{:?}", sha2::Sha256::digest(str.as_bytes())))
+}
crates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/lib.rs
+++ b/crates/jrsonnet-stdlib/src/lib.rs
@@ -5,7 +5,7 @@
};
use jrsonnet_evaluator::{
- error::{Error::*, Result},
+ error::{ErrorKind::*, Result},
function::{builtin::Builtin, CallLocation, FuncVal, TlaArg},
gc::{GcHashMap, TraceBox},
tb,
@@ -101,6 +101,8 @@
("sort", builtin_sort::INST),
// Hash
("md5", builtin_md5::INST),
+ #[cfg(feature = "exp-more-hashes")]
+ ("sha256", builtin_sha256::INST),
// Encoding
("encodeUTF8", builtin_encode_utf8::INST),
("decodeUTF8", builtin_decode_utf8::INST),
crates/jrsonnet-stdlib/src/misc.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/misc.rs
+++ b/crates/jrsonnet-stdlib/src/misc.rs
@@ -1,7 +1,7 @@
use std::{cell::RefCell, rc::Rc};
use jrsonnet_evaluator::{
- error::{Error::*, Result},
+ error::{ErrorKind::*, Result},
function::{builtin, ArgLike, CallLocation, FuncVal},
throw,
typed::{Any, Either2, Either4},
crates/jrsonnet-stdlib/src/parse.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/parse.rs
+++ b/crates/jrsonnet-stdlib/src/parse.rs
@@ -1,5 +1,5 @@
use jrsonnet_evaluator::{
- error::{Error::RuntimeError, Result},
+ error::{ErrorKind::RuntimeError, Result},
function::builtin,
typed::Any,
IStr, Val,
crates/jrsonnet-stdlib/src/strings.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/strings.rs
+++ b/crates/jrsonnet-stdlib/src/strings.rs
@@ -1,5 +1,5 @@
use jrsonnet_evaluator::{
- error::{Error::*, Result},
+ error::{ErrorKind::*, Result},
function::builtin,
typed::{Either2, VecVal, M1},
val::ArrValue,
tests/tests/common.rsdiffbeforeafterboth--- a/tests/tests/common.rs
+++ b/tests/tests/common.rs
@@ -29,7 +29,7 @@
macro_rules! ensure_val_eq {
($a:expr, $b:expr) => {{
if !::jrsonnet_evaluator::val::equals(&$a.clone(), &$b.clone())? {
- use ::jrsonnet_evaluator::stdlib::manifest::JsonFormat;
+ use ::jrsonnet_evaluator::manifest::JsonFormat;
::jrsonnet_evaluator::throw!(
"assertion failed: a != b\na={:#?}\nb={:#?}",
$a.manifest(JsonFormat::default())?,
tests/tests/golden.rsdiffbeforeafterboth--- a/tests/tests/golden.rs
+++ b/tests/tests/golden.rs
@@ -4,7 +4,7 @@
};
use jrsonnet_evaluator::{
- stdlib::manifest::JsonFormat,
+ manifest::JsonFormat,
trace::{CompactFormat, PathResolver, TraceFormat},
FileImportResolver, State,
};