difftreelog
feat destructure in comprehensions
in: master
3 files changed
crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs
@@ -8,6 +8,7 @@
};
use jrsonnet_types::ValType;
+use self::destructure::destruct;
use crate::{
destructure::evaluate_dest,
error::Error::*,
@@ -63,12 +64,16 @@
}
Some(CompSpec::ForSpec(ForSpecData(var, expr))) => match evaluate(ctx.clone(), expr)? {
Val::Arr(list) => {
- for item in list.iter() {
- evaluate_comp(
- ctx.clone().with_var(var.clone(), item?.clone()),
- &specs[1..],
- callback,
- )?;
+ for item in list.iter_lazy() {
+ let fctx = Pending::new();
+ let mut new_bindings = GcHashMap::new();
+ destruct(var, item, fctx.clone(), &mut new_bindings)?;
+ let ctx = ctx
+ .clone()
+ .extend(new_bindings, None, None, None)
+ .into_future(fctx);
+
+ evaluate_comp(ctx, &specs[1..], callback)?;
}
}
_ => throw!(InComprehensionCanOnlyIterateOverArray),
@@ -78,6 +83,7 @@
}
trait CloneableUnbound<T>: Unbound<Bound = T> + Clone {}
+impl<V, T> CloneableUnbound<T> for V where V: Unbound<Bound = T> + Clone {}
fn evaluate_object_locals(
fctx: Pending<Context>,
@@ -88,7 +94,6 @@
fctx: Pending<Context>,
locals: Rc<Vec<BindSpec>>,
}
- impl CloneableUnbound<Context> for UnboundLocals {}
impl Unbound for UnboundLocals {
type Bound = Context;
@@ -117,15 +122,20 @@
builder: &mut ObjValueBuilder,
ctx: Context,
uctx: B,
- member: &FieldMember,
+ field: &FieldMember,
) -> Result<()> {
- match member {
+ let name = evaluate_field_name(ctx.clone(), &field.name)?;
+ let Some(name) = name else {
+ return Ok(());
+ };
+
+ match field {
FieldMember {
- name,
plus,
params: None,
visibility,
value,
+ ..
} => {
#[derive(Trace)]
struct UnboundValue<B: Trace> {
@@ -143,11 +153,6 @@
)?)
}
}
-
- let name = evaluate_field_name(ctx.clone(), name)?;
- let Some(name) = name else {
- return Ok(());
- };
builder
.member(name.clone())
@@ -161,7 +166,6 @@
}))?;
}
FieldMember {
- name,
params: Some(params),
value,
..
@@ -184,10 +188,6 @@
))
}
}
-
- let Some(name) = evaluate_field_name(ctx.clone(), name)? else {
- return Ok(());
- };
builder
.member(name.clone())
@@ -227,9 +227,6 @@
Member::Field(field) => {
evaluate_field_member(&mut builder, ctx.clone(), uctx.clone(), &field)?
}
- Member::BindStmt(_) => {
- // Already handled
- }
Member::AssertStmt(stmt) => {
#[derive(Trace)]
struct ObjectAssert<B: Trace> {
@@ -247,6 +244,9 @@
assert: stmt.clone(),
}));
}
+ Member::BindStmt(_) => {
+ // Already handled
+ }
}
}
let this = builder.build();
crates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth1use std::{2 fmt::{self, Debug, Display},3 ops::Deref,4 rc::Rc,5};67use jrsonnet_gcmodule::Trace;8use jrsonnet_interner::IStr;9#[cfg(feature = "serde")]10use serde::{Deserialize, Serialize};11#[cfg(feature = "structdump")]12use structdump::Codegen;1314use crate::source::Source;1516#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]17#[cfg_attr(feature = "structdump", derive(Codegen))]18#[derive(Debug, PartialEq, Trace)]19pub enum FieldName {20 /// {fixed: 2}21 Fixed(IStr),22 /// {["dyn"+"amic"]: 3}23 Dyn(LocExpr),24}2526#[cfg_attr(feature = "structdump", derive(Codegen))]27#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]28#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]29pub enum Visibility {30 /// :31 Normal,32 /// ::33 Hidden,34 /// :::35 Unhide,36}3738impl Visibility {39 pub fn is_visible(&self) -> bool {40 matches!(self, Self::Normal | Self::Unhide)41 }42}4344#[cfg_attr(feature = "structdump", derive(Codegen))]45#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]46#[derive(Clone, Debug, PartialEq, Trace)]47pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);4849#[cfg_attr(feature = "structdump", derive(Codegen))]50#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]51#[derive(Debug, PartialEq, Trace)]52pub struct FieldMember {53 pub name: FieldName,54 pub plus: bool,55 pub params: Option<ParamsDesc>,56 pub visibility: Visibility,57 pub value: LocExpr,58}5960#[cfg_attr(feature = "structdump", derive(Codegen))]61#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]62#[derive(Debug, PartialEq, Trace)]63pub enum Member {64 Field(FieldMember),65 BindStmt(BindSpec),66 AssertStmt(AssertStmt),67}6869#[cfg_attr(feature = "structdump", derive(Codegen))]70#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]71#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]72pub enum UnaryOpType {73 Plus,74 Minus,75 BitNot,76 Not,77}7879impl Display for UnaryOpType {80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {81 use UnaryOpType::*;82 write!(83 f,84 "{}",85 match self {86 Plus => "+",87 Minus => "-",88 BitNot => "~",89 Not => "!",90 }91 )92 }93}9495#[cfg_attr(feature = "structdump", derive(Codegen))]96#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]97#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]98pub enum BinaryOpType {99 Mul,100 Div,101102 /// Implemented as intrinsic, put here for completeness103 Mod,104105 Add,106 Sub,107108 Lhs,109 Rhs,110111 Lt,112 Gt,113 Lte,114 Gte,115116 BitAnd,117 BitOr,118 BitXor,119120 Eq,121 Neq,122123 And,124 Or,125126 // Equialent to std.objectHasEx(a, b, true)127 In,128}129130impl Display for BinaryOpType {131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {132 use BinaryOpType::*;133 write!(134 f,135 "{}",136 match self {137 Mul => "*",138 Div => "/",139 Mod => "%",140 Add => "+",141 Sub => "-",142 Lhs => "<<",143 Rhs => ">>",144 Lt => "<",145 Gt => ">",146 Lte => "<=",147 Gte => ">=",148 BitAnd => "&",149 BitOr => "|",150 BitXor => "^",151 Eq => "==",152 Neq => "!=",153 And => "&&",154 Or => "||",155 In => "in",156 }157 )158 }159}160161/// name, default value162#[cfg_attr(feature = "structdump", derive(Codegen))]163#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]164#[derive(Debug, PartialEq, Trace)]165pub struct Param(pub Destruct, pub Option<LocExpr>);166167/// Defined function parameters168#[cfg_attr(feature = "structdump", derive(Codegen))]169#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]170#[derive(Debug, Clone, PartialEq, Trace)]171pub struct ParamsDesc(pub Rc<Vec<Param>>);172173impl Deref for ParamsDesc {174 type Target = Vec<Param>;175 fn deref(&self) -> &Self::Target {176 &self.0177 }178}179180#[cfg_attr(feature = "structdump", derive(Codegen))]181#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]182#[derive(Debug, PartialEq, Trace)]183pub struct ArgsDesc {184 pub unnamed: Vec<LocExpr>,185 pub named: Vec<(IStr, LocExpr)>,186}187impl ArgsDesc {188 pub fn new(unnamed: Vec<LocExpr>, named: Vec<(IStr, LocExpr)>) -> Self {189 Self { unnamed, named }190 }191}192193#[cfg_attr(feature = "structdump", derive(Codegen))]194#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]195#[derive(Debug, Clone, PartialEq, Eq, Trace)]196pub enum DestructRest {197 /// ...rest198 Keep(IStr),199 /// ...200 Drop,201}202203#[cfg_attr(feature = "structdump", derive(Codegen))]204#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]205#[derive(Debug, Clone, PartialEq, Trace)]206pub enum Destruct {207 Full(IStr),208 #[cfg(feature = "exp-destruct")]209 Skip,210 #[cfg(feature = "exp-destruct")]211 Array {212 start: Vec<Destruct>,213 rest: Option<DestructRest>,214 end: Vec<Destruct>,215 },216 #[cfg(feature = "exp-destruct")]217 Object {218 fields: Vec<(IStr, Option<Destruct>, Option<LocExpr>)>,219 rest: Option<DestructRest>,220 },221}222impl Destruct {223 /// Name of destructure, used for function parameter names224 pub fn name(&self) -> Option<IStr> {225 match self {226 Self::Full(name) => Some(name.clone()),227 #[cfg(feature = "exp-destruct")]228 _ => None,229 }230 }231}232233#[cfg_attr(feature = "structdump", derive(Codegen))]234#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]235#[derive(Debug, Clone, PartialEq, Trace)]236pub enum BindSpec {237 Field {238 into: Destruct,239 value: LocExpr,240 },241 Function {242 name: IStr,243 params: ParamsDesc,244 value: LocExpr,245 },246}247248#[cfg_attr(feature = "structdump", derive(Codegen))]249#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]250#[derive(Debug, PartialEq, Trace)]251pub struct IfSpecData(pub LocExpr);252253#[cfg_attr(feature = "structdump", derive(Codegen))]254#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]255#[derive(Debug, PartialEq, Trace)]256pub struct ForSpecData(pub IStr, pub LocExpr);257258#[cfg_attr(feature = "structdump", derive(Codegen))]259#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]260#[derive(Debug, PartialEq, Trace)]261pub enum CompSpec {262 IfSpec(IfSpecData),263 ForSpec(ForSpecData),264}265266#[cfg_attr(feature = "structdump", derive(Codegen))]267#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]268#[derive(Debug, PartialEq, Trace)]269pub struct ObjComp {270 pub pre_locals: Vec<BindSpec>,271 pub field: FieldMember,272 pub post_locals: Vec<BindSpec>,273 pub compspecs: Vec<CompSpec>,274}275276#[cfg_attr(feature = "structdump", derive(Codegen))]277#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]278#[derive(Debug, PartialEq, Trace)]279pub enum ObjBody {280 MemberList(Vec<Member>),281 ObjComp(ObjComp),282}283284#[cfg_attr(feature = "structdump", derive(Codegen))]285#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]286#[derive(Debug, PartialEq, Eq, Clone, Copy, Trace)]287pub enum LiteralType {288 This,289 Super,290 Dollar,291 Null,292 True,293 False,294}295296#[cfg_attr(feature = "structdump", derive(Codegen))]297#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]298#[derive(Debug, PartialEq, Trace)]299pub struct SliceDesc {300 pub start: Option<LocExpr>,301 pub end: Option<LocExpr>,302 pub step: Option<LocExpr>,303}304305/// Syntax base306#[cfg_attr(feature = "structdump", derive(Codegen))]307#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]308#[derive(Debug, PartialEq, Trace)]309pub enum Expr {310 Literal(LiteralType),311312 /// String value: "hello"313 Str(IStr),314 /// Number: 1, 2.0, 2e+20315 Num(f64),316 /// Variable name: test317 Var(IStr),318319 /// Array of expressions: [1, 2, "Hello"]320 Arr(Vec<LocExpr>),321 /// Array comprehension:322 /// ```jsonnet323 /// ingredients: [324 /// { kind: kind, qty: 4 / 3 }325 /// for kind in [326 /// 'Honey Syrup',327 /// 'Lemon Juice',328 /// 'Farmers Gin',329 /// ]330 /// ],331 /// ```332 ArrComp(LocExpr, Vec<CompSpec>),333334 /// Object: {a: 2}335 Obj(ObjBody),336 /// Object extension: var1 {b: 2}337 ObjExtend(LocExpr, ObjBody),338339 /// (obj)340 Parened(LocExpr),341342 /// -2343 UnaryOp(UnaryOpType, LocExpr),344 /// 2 - 2345 BinaryOp(LocExpr, BinaryOpType, LocExpr),346 /// assert 2 == 2 : "Math is broken"347 AssertExpr(AssertStmt, LocExpr),348 /// local a = 2; { b: a }349 LocalExpr(Vec<BindSpec>, LocExpr),350351 /// import "hello"352 Import(IStr),353 /// importStr "file.txt"354 ImportStr(IStr),355 /// importBin "file.txt"356 ImportBin(IStr),357 /// error "I'm broken"358 ErrorStmt(LocExpr),359 /// a(b, c)360 Apply(LocExpr, ArgsDesc, bool),361 /// a[b]362 Index(LocExpr, LocExpr),363 /// function(x) x364 Function(ParamsDesc, LocExpr),365 /// if true == false then 1 else 2366 IfElse {367 cond: IfSpecData,368 cond_then: LocExpr,369 cond_else: Option<LocExpr>,370 },371 Slice(LocExpr, SliceDesc),372}373374/// file, begin offset, end offset375#[cfg_attr(feature = "structdump", derive(Codegen))]376#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]377#[derive(Clone, PartialEq, Eq, Trace)]378#[trace(skip)]379#[repr(C)]380pub struct ExprLocation(pub Source, pub u32, pub u32);381impl ExprLocation {382 pub fn belongs_to(&self, other: &ExprLocation) -> bool {383 other.0 == self.0 && other.1 <= self.1 && other.2 >= self.2384 }385}386387#[cfg(target_pointer_width = "64")]388static_assertions::assert_eq_size!(ExprLocation, [u8; 16]);389390impl Debug for ExprLocation {391 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {392 write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)393 }394}395396/// Holds AST expression and its location in source file397#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]398#[cfg_attr(feature = "structdump", derive(Codegen))]399#[derive(Clone, PartialEq, Trace)]400pub struct LocExpr(pub Rc<Expr>, pub ExprLocation);401402#[cfg(target_pointer_width = "64")]403static_assertions::assert_eq_size!(LocExpr, [u8; 24]);404405impl Debug for LocExpr {406 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {407 if f.alternate() {408 write!(f, "{:#?}", self.0)?;409 } else {410 write!(f, "{:?}", self.0)?;411 }412 write!(f, " from {:?}", self.1)?;413 Ok(())414 }415}1use std::{2 fmt::{self, Debug, Display},3 ops::Deref,4 rc::Rc,5};67use jrsonnet_gcmodule::Trace;8use jrsonnet_interner::IStr;9#[cfg(feature = "serde")]10use serde::{Deserialize, Serialize};11#[cfg(feature = "structdump")]12use structdump::Codegen;1314use crate::source::Source;1516#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]17#[cfg_attr(feature = "structdump", derive(Codegen))]18#[derive(Debug, PartialEq, Trace)]19pub enum FieldName {20 /// {fixed: 2}21 Fixed(IStr),22 /// {["dyn"+"amic"]: 3}23 Dyn(LocExpr),24}2526#[cfg_attr(feature = "structdump", derive(Codegen))]27#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]28#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]29pub enum Visibility {30 /// :31 Normal,32 /// ::33 Hidden,34 /// :::35 Unhide,36}3738impl Visibility {39 pub fn is_visible(&self) -> bool {40 matches!(self, Self::Normal | Self::Unhide)41 }42}4344#[cfg_attr(feature = "structdump", derive(Codegen))]45#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]46#[derive(Clone, Debug, PartialEq, Trace)]47pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);4849#[cfg_attr(feature = "structdump", derive(Codegen))]50#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]51#[derive(Debug, PartialEq, Trace)]52pub struct FieldMember {53 pub name: FieldName,54 pub plus: bool,55 pub params: Option<ParamsDesc>,56 pub visibility: Visibility,57 pub value: LocExpr,58}5960#[cfg_attr(feature = "structdump", derive(Codegen))]61#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]62#[derive(Debug, PartialEq, Trace)]63pub enum Member {64 Field(FieldMember),65 BindStmt(BindSpec),66 AssertStmt(AssertStmt),67}6869#[cfg_attr(feature = "structdump", derive(Codegen))]70#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]71#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]72pub enum UnaryOpType {73 Plus,74 Minus,75 BitNot,76 Not,77}7879impl Display for UnaryOpType {80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {81 use UnaryOpType::*;82 write!(83 f,84 "{}",85 match self {86 Plus => "+",87 Minus => "-",88 BitNot => "~",89 Not => "!",90 }91 )92 }93}9495#[cfg_attr(feature = "structdump", derive(Codegen))]96#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]97#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]98pub enum BinaryOpType {99 Mul,100 Div,101102 /// Implemented as intrinsic, put here for completeness103 Mod,104105 Add,106 Sub,107108 Lhs,109 Rhs,110111 Lt,112 Gt,113 Lte,114 Gte,115116 BitAnd,117 BitOr,118 BitXor,119120 Eq,121 Neq,122123 And,124 Or,125126 // Equialent to std.objectHasEx(a, b, true)127 In,128}129130impl Display for BinaryOpType {131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {132 use BinaryOpType::*;133 write!(134 f,135 "{}",136 match self {137 Mul => "*",138 Div => "/",139 Mod => "%",140 Add => "+",141 Sub => "-",142 Lhs => "<<",143 Rhs => ">>",144 Lt => "<",145 Gt => ">",146 Lte => "<=",147 Gte => ">=",148 BitAnd => "&",149 BitOr => "|",150 BitXor => "^",151 Eq => "==",152 Neq => "!=",153 And => "&&",154 Or => "||",155 In => "in",156 }157 )158 }159}160161/// name, default value162#[cfg_attr(feature = "structdump", derive(Codegen))]163#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]164#[derive(Debug, PartialEq, Trace)]165pub struct Param(pub Destruct, pub Option<LocExpr>);166167/// Defined function parameters168#[cfg_attr(feature = "structdump", derive(Codegen))]169#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]170#[derive(Debug, Clone, PartialEq, Trace)]171pub struct ParamsDesc(pub Rc<Vec<Param>>);172173impl Deref for ParamsDesc {174 type Target = Vec<Param>;175 fn deref(&self) -> &Self::Target {176 &self.0177 }178}179180#[cfg_attr(feature = "structdump", derive(Codegen))]181#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]182#[derive(Debug, PartialEq, Trace)]183pub struct ArgsDesc {184 pub unnamed: Vec<LocExpr>,185 pub named: Vec<(IStr, LocExpr)>,186}187impl ArgsDesc {188 pub fn new(unnamed: Vec<LocExpr>, named: Vec<(IStr, LocExpr)>) -> Self {189 Self { unnamed, named }190 }191}192193#[cfg_attr(feature = "structdump", derive(Codegen))]194#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]195#[derive(Debug, Clone, PartialEq, Eq, Trace)]196pub enum DestructRest {197 /// ...rest198 Keep(IStr),199 /// ...200 Drop,201}202203#[cfg_attr(feature = "structdump", derive(Codegen))]204#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]205#[derive(Debug, Clone, PartialEq, Trace)]206pub enum Destruct {207 Full(IStr),208 #[cfg(feature = "exp-destruct")]209 Skip,210 #[cfg(feature = "exp-destruct")]211 Array {212 start: Vec<Destruct>,213 rest: Option<DestructRest>,214 end: Vec<Destruct>,215 },216 #[cfg(feature = "exp-destruct")]217 Object {218 fields: Vec<(IStr, Option<Destruct>, Option<LocExpr>)>,219 rest: Option<DestructRest>,220 },221}222impl Destruct {223 /// Name of destructure, used for function parameter names224 pub fn name(&self) -> Option<IStr> {225 match self {226 Self::Full(name) => Some(name.clone()),227 #[cfg(feature = "exp-destruct")]228 _ => None,229 }230 }231}232233#[cfg_attr(feature = "structdump", derive(Codegen))]234#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]235#[derive(Debug, Clone, PartialEq, Trace)]236pub enum BindSpec {237 Field {238 into: Destruct,239 value: LocExpr,240 },241 Function {242 name: IStr,243 params: ParamsDesc,244 value: LocExpr,245 },246}247248#[cfg_attr(feature = "structdump", derive(Codegen))]249#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]250#[derive(Debug, PartialEq, Trace)]251pub struct IfSpecData(pub LocExpr);252253#[cfg_attr(feature = "structdump", derive(Codegen))]254#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]255#[derive(Debug, PartialEq, Trace)]256pub struct ForSpecData(pub Destruct, pub LocExpr);257258#[cfg_attr(feature = "structdump", derive(Codegen))]259#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]260#[derive(Debug, PartialEq, Trace)]261pub enum CompSpec {262 IfSpec(IfSpecData),263 ForSpec(ForSpecData),264}265266#[cfg_attr(feature = "structdump", derive(Codegen))]267#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]268#[derive(Debug, PartialEq, Trace)]269pub struct ObjComp {270 pub pre_locals: Vec<BindSpec>,271 pub field: FieldMember,272 pub post_locals: Vec<BindSpec>,273 pub compspecs: Vec<CompSpec>,274}275276#[cfg_attr(feature = "structdump", derive(Codegen))]277#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]278#[derive(Debug, PartialEq, Trace)]279pub enum ObjBody {280 MemberList(Vec<Member>),281 ObjComp(ObjComp),282}283284#[cfg_attr(feature = "structdump", derive(Codegen))]285#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]286#[derive(Debug, PartialEq, Eq, Clone, Copy, Trace)]287pub enum LiteralType {288 This,289 Super,290 Dollar,291 Null,292 True,293 False,294}295296#[cfg_attr(feature = "structdump", derive(Codegen))]297#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]298#[derive(Debug, PartialEq, Trace)]299pub struct SliceDesc {300 pub start: Option<LocExpr>,301 pub end: Option<LocExpr>,302 pub step: Option<LocExpr>,303}304305/// Syntax base306#[cfg_attr(feature = "structdump", derive(Codegen))]307#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]308#[derive(Debug, PartialEq, Trace)]309pub enum Expr {310 Literal(LiteralType),311312 /// String value: "hello"313 Str(IStr),314 /// Number: 1, 2.0, 2e+20315 Num(f64),316 /// Variable name: test317 Var(IStr),318319 /// Array of expressions: [1, 2, "Hello"]320 Arr(Vec<LocExpr>),321 /// Array comprehension:322 /// ```jsonnet323 /// ingredients: [324 /// { kind: kind, qty: 4 / 3 }325 /// for kind in [326 /// 'Honey Syrup',327 /// 'Lemon Juice',328 /// 'Farmers Gin',329 /// ]330 /// ],331 /// ```332 ArrComp(LocExpr, Vec<CompSpec>),333334 /// Object: {a: 2}335 Obj(ObjBody),336 /// Object extension: var1 {b: 2}337 ObjExtend(LocExpr, ObjBody),338339 /// (obj)340 Parened(LocExpr),341342 /// -2343 UnaryOp(UnaryOpType, LocExpr),344 /// 2 - 2345 BinaryOp(LocExpr, BinaryOpType, LocExpr),346 /// assert 2 == 2 : "Math is broken"347 AssertExpr(AssertStmt, LocExpr),348 /// local a = 2; { b: a }349 LocalExpr(Vec<BindSpec>, LocExpr),350351 /// import "hello"352 Import(IStr),353 /// importStr "file.txt"354 ImportStr(IStr),355 /// importBin "file.txt"356 ImportBin(IStr),357 /// error "I'm broken"358 ErrorStmt(LocExpr),359 /// a(b, c)360 Apply(LocExpr, ArgsDesc, bool),361 /// a[b]362 Index(LocExpr, LocExpr),363 /// function(x) x364 Function(ParamsDesc, LocExpr),365 /// if true == false then 1 else 2366 IfElse {367 cond: IfSpecData,368 cond_then: LocExpr,369 cond_else: Option<LocExpr>,370 },371 Slice(LocExpr, SliceDesc),372}373374/// file, begin offset, end offset375#[cfg_attr(feature = "structdump", derive(Codegen))]376#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]377#[derive(Clone, PartialEq, Eq, Trace)]378#[trace(skip)]379#[repr(C)]380pub struct ExprLocation(pub Source, pub u32, pub u32);381impl ExprLocation {382 pub fn belongs_to(&self, other: &ExprLocation) -> bool {383 other.0 == self.0 && other.1 <= self.1 && other.2 >= self.2384 }385}386387#[cfg(target_pointer_width = "64")]388static_assertions::assert_eq_size!(ExprLocation, [u8; 16]);389390impl Debug for ExprLocation {391 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {392 write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)393 }394}395396/// Holds AST expression and its location in source file397#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]398#[cfg_attr(feature = "structdump", derive(Codegen))]399#[derive(Clone, PartialEq, Trace)]400pub struct LocExpr(pub Rc<Expr>, pub ExprLocation);401402#[cfg(target_pointer_width = "64")]403static_assertions::assert_eq_size!(LocExpr, [u8; 24]);404405impl Debug for LocExpr {406 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {407 if f.alternate() {408 write!(f, "{:#?}", self.0)?;409 } else {410 write!(f, "{:?}", self.0)?;411 }412 write!(f, " from {:?}", self.1)?;413 Ok(())414 }415}crates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-parser/src/lib.rs
+++ b/crates/jrsonnet-parser/src/lib.rs
@@ -208,7 +208,7 @@
pub rule ifspec(s: &ParserSettings) -> IfSpecData
= keyword("if") _ expr:expr(s) {IfSpecData(expr)}
pub rule forspec(s: &ParserSettings) -> ForSpecData
- = keyword("for") _ id:id() _ keyword("in") _ cond:expr(s) {ForSpecData(id, cond)}
+ = keyword("for") _ id:destruct(s) _ keyword("in") _ cond:expr(s) {ForSpecData(id, cond)}
pub rule compspec(s: &ParserSettings) -> Vec<expr::CompSpec>
= s:(i:ifspec(s) { expr::CompSpec::IfSpec(i) } / f:forspec(s) {expr::CompSpec::ForSpec(f)} ) ** _ {s}
pub rule local_expr(s: &ParserSettings) -> Expr
@@ -620,7 +620,7 @@
16
),
vec![CompSpec::ForSpec(ForSpecData(
- "x".into(),
+ Destruct::Full("x".into()),
el!(Var("arr".into()), 26, 29)
))]
),