difftreelog
feat parse new object iteration syntax
in: master
10 files changed
cmds/jrsonnet/Cargo.tomldiffbeforeafterboth--- a/cmds/jrsonnet/Cargo.toml
+++ b/cmds/jrsonnet/Cargo.toml
@@ -31,7 +31,7 @@
]
# Destructuring of locals
exp-destruct = ["jrsonnet-evaluator/exp-destruct"]
-# Iteration over objects yields [key, value] elements
+# Iteration over objects using [key]: value syntax
exp-object-iteration = ["jrsonnet-evaluator/exp-object-iteration"]
# Bigint type
exp-bigint = ["jrsonnet-evaluator/exp-bigint", "jrsonnet-cli/exp-bigint"]
crates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth1[package]2name = "jrsonnet-evaluator"3description = "Rust implementation of the jsonnet language interpreter"4keywords = ["jsonnet", "interpreter", "config"]5categories = ["compilers", "template-engine", "config"]6readme = "README.adoc"7authors.workspace = true8edition.workspace = true9license.workspace = true10repository.workspace = true11version.workspace = true1213build = "build.rs"1415[lints]16workspace = true1718[features]19default = ["explaining-traces", "ir-parser", "wasm-bindgen"]20# Rustc-like trace visualization21explaining-traces = ["hi-doc"]22# Allows library authors to throw custom errors23anyhow-error = ["anyhow"]24# Use hand-written recursive descent parser25ir-parser = ["dep:jrsonnet-ir-parser"]26# Use PEG parser27peg-parser = ["dep:jrsonnet-peg-parser"]2829experimental = [30 "exp-preserve-order",31 "exp-destruct",32 "exp-object-iteration",33 "exp-bigint",34 "exp-null-coaelse",35]36# Allows to preserve field order in objects37exp-preserve-order = []38# Implements field destructuring39exp-destruct = [40 "jrsonnet-peg-parser?/exp-destruct",41 "jrsonnet-ir-parser?/exp-destruct",42]43# Iteration over objects yields [key, value] elements44exp-object-iteration = []45# Bigint type46exp-bigint = ["num-bigint", "jrsonnet-types/exp-bigint"]47# obj?.field, obj?.['field']48exp-null-coaelse = [49 "jrsonnet-peg-parser?/exp-null-coaelse",50 "jrsonnet-ir-parser?/exp-null-coaelse",51]52wasm-bindgen = ["dep:wasm-bindgen"]5354[dependencies]55jrsonnet-interner.workspace = true56jrsonnet-ir.workspace = true57jrsonnet-peg-parser = { workspace = true, optional = true }58jrsonnet-ir-parser = { workspace = true, optional = true }59jrsonnet-types.workspace = true60jrsonnet-macros.workspace = true61jrsonnet-gcmodule.workspace = true6263pathdiff.workspace = true64static_assertions.workspace = true6566rustc-hash.workspace = true6768thiserror.workspace = true69# Friendly errors70strsim.workspace = true7172serde.workspace = true7374anyhow = { workspace = true, optional = true }75# Better explaining traces76hi-doc = { workspace = true, optional = true }77# Bigint78num-bigint = { workspace = true, features = ["serde"], optional = true }7980stacker.workspace = true81educe = { workspace = true, features = [82 "Clone",83 "Debug",84 "Eq",85 "Hash",86 "PartialEq",87] }88smallvec.workspace = true89drop_bomb.workspace = true90wasm-bindgen = { workspace = true, optional = true }9192[build-dependencies]93rustversion.workspace = true9495[dev-dependencies]96insta.workspace = true97strip-ansi-escapes.workspace = truecrates/jrsonnet-evaluator/src/analyze.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/analyze.rs
+++ b/crates/jrsonnet-evaluator/src/analyze.rs
@@ -1862,6 +1862,8 @@
);
(r, rest)
}
+ #[cfg(feature = "exp-object-iteration")]
+ CompSpec::ForObjSpec(_) => todo!(),
}
}
let outer_depth = stack.depth;
crates/jrsonnet-ir-parser/Cargo.tomldiffbeforeafterboth--- a/crates/jrsonnet-ir-parser/Cargo.toml
+++ b/crates/jrsonnet-ir-parser/Cargo.toml
@@ -11,9 +11,10 @@
[features]
default = []
-experimental = ["exp-null-coaelse", "exp-destruct"]
+experimental = ["exp-null-coaelse", "exp-destruct", "exp-object-iteration"]
exp-null-coaelse = ["jrsonnet-ir/exp-null-coaelse"]
exp-destruct = ["jrsonnet-ir/exp-destruct"]
+exp-object-iteration = ["jrsonnet-ir/exp-object-iteration"]
[dependencies]
insta.workspace = true
crates/jrsonnet-ir-parser/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-ir-parser/src/lib.rs
+++ b/crates/jrsonnet-ir-parser/src/lib.rs
@@ -66,6 +66,13 @@
!self.at_eof() && self.peek() == kind
}
+ #[allow(dead_code)]
+ fn nth(&self, n: usize) -> SyntaxKind {
+ self.lexemes
+ .get(self.offset + n)
+ .map_or(SyntaxKind::EOF, |l| l.kind)
+ }
+
fn eat_any(&mut self) {
self.offset += 1;
}
@@ -561,20 +568,36 @@
}
}
-fn for_spec(p: &mut Parser<'_>) -> Result<ForSpecData> {
+fn for_spec(p: &mut Parser<'_>) -> Result<CompSpec> {
p.eat(T![for])?;
+ #[cfg(feature = "exp-object-iteration")]
+ if p.at(T!['[']) && p.nth(1) == SyntaxKind::IDENT && p.nth(2) == T![']'] && p.nth(3) == T![:] {
+ p.eat(T!['['])?;
+ let key = ident(p)?;
+ p.eat(T![']'])?;
+ let visibility = visibility(p)?;
+ let value = destruct(p)?;
+ p.eat(T![in])?;
+ let over = expr(p)?;
+ return Ok(CompSpec::ForObjSpec(jrsonnet_ir::ForObjSpecData {
+ key,
+ visibility,
+ value,
+ over,
+ }));
+ }
let d = destruct(p)?;
p.eat(T![in])?;
let over = expr(p)?;
- Ok(ForSpecData { destruct: d, over })
+ Ok(CompSpec::ForSpec(ForSpecData { destruct: d, over }))
}
fn compspecs(p: &mut Parser<'_>) -> Result<Vec<CompSpec>> {
let mut specs = Vec::new();
- specs.push(CompSpec::ForSpec(for_spec(p)?));
+ specs.push(for_spec(p)?);
loop {
if p.at(T![for]) {
- specs.push(CompSpec::ForSpec(for_spec(p)?));
+ specs.push(for_spec(p)?);
} else if p.at(T![if]) {
let isd = if_spec_data(p)?;
specs.push(CompSpec::IfSpec(isd));
crates/jrsonnet-ir/Cargo.tomldiffbeforeafterboth--- a/crates/jrsonnet-ir/Cargo.toml
+++ b/crates/jrsonnet-ir/Cargo.toml
@@ -12,9 +12,10 @@
[features]
default = []
-experimental = ["exp-destruct", "exp-null-coaelse"]
+experimental = ["exp-destruct", "exp-null-coaelse", "exp-object-iteration"]
exp-destruct = []
exp-null-coaelse = []
+exp-object-iteration = []
[dependencies]
jrsonnet-interner.workspace = true
crates/jrsonnet-ir/src/expr.rsdiffbeforeafterboth--- a/crates/jrsonnet-ir/src/expr.rs
+++ b/crates/jrsonnet-ir/src/expr.rs
@@ -314,10 +314,21 @@
pub over: Expr,
}
+#[cfg(feature = "exp-object-iteration")]
#[derive(Debug, PartialEq, Acyclic)]
+pub struct ForObjSpecData {
+ pub key: IStr,
+ pub visibility: Visibility,
+ pub value: Destruct,
+ pub over: Expr,
+}
+
+#[derive(Debug, PartialEq, Acyclic)]
pub enum CompSpec {
IfSpec(IfSpecData),
ForSpec(ForSpecData),
+ #[cfg(feature = "exp-object-iteration")]
+ ForObjSpec(ForObjSpecData),
}
#[derive(Debug, PartialEq, Acyclic)]
crates/jrsonnet-ir/src/visit.rsdiffbeforeafterboth--- a/crates/jrsonnet-ir/src/visit.rs
+++ b/crates/jrsonnet-ir/src/visit.rs
@@ -1,5 +1,7 @@
use jrsonnet_interner::IStr;
+#[cfg(feature = "exp-object-iteration")]
+use crate::ForObjSpecData;
use crate::{
ArgsDesc, AssertExpr, AssertStmt, BinaryOp, BindSpec, CompSpec, Destruct, Expr, ExprParam,
ExprParams, FieldMember, FieldName, ForSpecData, IfElse, IfSpecData, ImportKind, IndexPart,
@@ -69,6 +71,17 @@
visit_destruct(v, destruct);
v.visit_expr(over);
}
+ #[cfg(feature = "exp-object-iteration")]
+ CompSpec::ForObjSpec(for_obj_spec_data) => {
+ let ForObjSpecData {
+ key: _,
+ visibility: _,
+ value,
+ over,
+ } = for_obj_spec_data;
+ visit_destruct(v, value);
+ v.visit_expr(over);
+ }
}
}
pub fn visit_params<V: Visitor>(v: &mut V, par: &ExprParams) {
crates/jrsonnet-peg-parser/Cargo.tomldiffbeforeafterboth--- a/crates/jrsonnet-peg-parser/Cargo.toml
+++ b/crates/jrsonnet-peg-parser/Cargo.toml
@@ -22,6 +22,7 @@
[features]
default = []
-experimental = ["exp-destruct", "exp-null-coaelse"]
+experimental = ["exp-destruct", "exp-null-coaelse", "exp-object-iteration"]
exp-destruct = ["jrsonnet-ir/exp-destruct"]
exp-null-coaelse = ["jrsonnet-ir/exp-null-coaelse"]
+exp-object-iteration = ["jrsonnet-ir/exp-object-iteration"]
crates/jrsonnet-peg-parser/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-peg-parser/src/lib.rs
+++ b/crates/jrsonnet-peg-parser/src/lib.rs
@@ -241,11 +241,21 @@
= i:spanned(<keyword("if")>, s) _ cond:expr(s) {IfSpecData { span: i.span, cond }}
pub rule forspec(s: &ParserSettings) -> ForSpecData
= keyword("for") _ destruct:destruct(s) _ keyword("in") _ over:expr(s) { ForSpecData { destruct, over } }
+ rule ensure_object_iteration()
+ = "" {?
+ #[cfg(not(feature = "exp-object-iteration"))] return Err("!!!experimental object iteration was not enabled");
+ #[cfg(feature = "exp-object-iteration")] Ok(())
+ }
+ pub rule forobjspec(s: &ParserSettings) -> CompSpec
+ = ensure_object_iteration() keyword("for") _ "[" _ key:id() _ "]" _ vis:visibility() _ value:destruct(s) _ keyword("in") _ over:expr(s) {
+ #[cfg(feature = "exp-object-iteration")] return CompSpec::ForObjSpec(jrsonnet_ir::ForObjSpecData { key, visibility: vis, value, over });
+ #[cfg(not(feature = "exp-object-iteration"))] unreachable!("ensure_object_iteration will fail if feature is not enabled")
+ }
rule compspec(s: &ParserSettings) -> CompSpec
- = i:ifspec(s) { CompSpec::IfSpec(i) } / f:forspec(s) {CompSpec::ForSpec(f)}
+ = i:ifspec(s) { CompSpec::IfSpec(i) } / f:forobjspec(s) { f } / f:forspec(s) {CompSpec::ForSpec(f)}
pub rule compspecs(s: &ParserSettings) -> Vec<CompSpec>
= specs:compspec(s) ++ _ {?
- if !matches!(specs[0], CompSpec::ForSpec(_)) {
+ if matches!(specs[0], CompSpec::IfSpec(_)) {
return Err("<first compspec should be for>")
}
Ok(specs)