git.delta.rocks / jrsonnet / refs/commits / ee32be682119

difftreelog

docs(ir) deny(missing_docs)

ulolskzwYaroslav Bolyukin2026-05-15parent: #21844b4.patch.diff
in: master

8 files changed

modifiedcrates/jrsonnet-ir-parser/src/lib.rsdiffbeforeafterboth
2use jrsonnet_ir::{2use jrsonnet_ir::{
3 ArgsDesc, AssertExpr, AssertStmt, BinaryOp, BinaryOpType, BindSpec, CompSpec, Destruct, Expr,3 ArgsDesc, AssertExpr, AssertStmt, BinaryOp, BinaryOpType, BindSpec, CompSpec, Destruct, Expr,
4 ExprParam, ExprParams, FieldMember, FieldName, ForSpecData, IStr, IdentityKind, IfElse,4 ExprParam, ExprParams, FieldMember, FieldName, ForSpecData, IStr, IdentityKind, IfElse,
5 IfSpecData, ImportKind, IndexPart, Member, NumValue, ObjBody, ObjComp, ObjMembers, Slice,5 IfSpecData, ImportKind, IndexPart, NumValue, ObjBody, ObjComp, ObjMembers, Slice, SliceDesc,
6 SliceDesc, Source, Span, Spanned, TrivialVal, UnaryOpType, Visibility,6 Source, Span, Spanned, TrivialVal, UnaryOpType, Visibility,
7};7};
8use jrsonnet_lexer::{8use jrsonnet_lexer::{
9 Lexeme, Lexer, Span as LexSpan, SyntaxKind, T, collect_lexed_str_block, unescape,9 Lexeme, Lexer, Span as LexSpan, SyntaxKind, T, collect_lexed_str_block, unescape,
558 }558 }
559}559}
560560
561enum Member {
562 BindStmt(BindSpec),
563 AssertStmt(AssertStmt),
564 Field(FieldMember),
565}
561fn member(p: &mut Parser<'_>) -> Result<Member> {566fn member(p: &mut Parser<'_>) -> Result<Member> {
562 if p.at(T![local]) {567 if p.at(T![local]) {
563 p.eat(T![local])?;568 p.eat(T![local])?;
modifiedcrates/jrsonnet-ir/src/expr.rsdiffbeforeafterboth
1//! Jrsonnet AST expression types.
2
1use std::{3use std::{
2 fmt::{self, Debug, Display},4 fmt::{self, Debug, Display},
12 source::Source,14 source::Source,
13};15};
1416
17/// Field name in object/obj-comp definition.
15#[derive(Debug, PartialEq, Acyclic)]18#[derive(Debug, PartialEq, Acyclic)]
16pub enum FieldName {19pub enum FieldName {
17 /// {fixed: 2}20 /// `{fixed: 2}`
18 Fixed(IStr),21 Fixed(IStr),
19 /// {["dyn"+"amic"]: 3}22 /// `{["dyn"+"amic"]: 3}` - may only reference locals defined outside of the object.
20 Dyn(Expr),23 Dyn(Expr),
21}24}
2225
26/// Field visibility in object/obj-comp/exp-object-iteration definition.
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]27#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]
24#[repr(u8)]28#[repr(u8)]
25pub enum Visibility {29pub enum Visibility {
26 /// :30 /// `:` - normal visibility, visible by default, but inherits field visibility from `super`.
27 Normal,31 Normal,
28 /// ::32 /// `::` - hidden visibility, field should not be visible by default manifest functions and iteration.
29 Hidden,33 Hidden,
30 /// :::34 /// `:::` - unhide visibility, visible by default, ignores `super` visibility,
35 /// can be overriden by [`Visibility::Hidden`]
31 Unhide,36 Unhide,
32}37}
3338
39/// Trivial values are passed from the AST to the evaluator as-is and have trivial conversions from and to
40/// jsonnet runtime values.
34#[derive(Debug, Clone, PartialEq, Acyclic)]41#[derive(Debug, Clone, PartialEq, Acyclic)]
35pub enum TrivialVal {42pub enum TrivialVal {
43 /// Jsonnet `null`.
36 Null,44 Null,
45 /// Jsonnet `true` or `false`.
37 Bool(bool),46 Bool(bool),
47 /// Jsonnet number, finite, non-nan, see [`NumValue`].
38 Num(NumValue),48 Num(NumValue),
49 /// Jsonnet interned flat string, see [`IStr`].
39 Str(IStr),50 Str(IStr),
40}51}
4152
42impl Visibility {53impl Visibility {
54 /// Is this visibility defines/matches (in exp-object-iteration) a visible field?
55 ///
56 /// Note: [`Self::Unhide`] also matches hidden fields.
43 pub fn is_visible(&self) -> bool {57 pub fn is_visible(&self) -> bool {
44 matches!(self, Self::Normal | Self::Unhide)58 matches!(self, Self::Normal | Self::Unhide)
45 }59 }
46}60}
4761
62/// Assert statement, used in `assert` expressions and for object assertions.
63///
64/// ```jsonnet
65/// assert a == 1: "message"
66/// ```
48#[derive(Debug, PartialEq, Acyclic)]67#[derive(Debug, PartialEq, Acyclic)]
49pub struct AssertStmt {68pub struct AssertStmt {
69 /// Assertion condition, `a == 1`.
50 pub assertion: Spanned<Expr>,70 pub assertion: Spanned<Expr>,
71 /// Message to be shown on assertion failure, `"message"`.
51 pub message: Option<Expr>,72 pub message: Option<Expr>,
52}73}
5374
75/// Object/obj-comp full field definition.
76///
77/// ```jsonnet
78/// [name]+:: value,
79/// ```
54#[derive(Debug, PartialEq, Acyclic)]80#[derive(Debug, PartialEq, Acyclic)]
55pub struct FieldMember {81pub struct FieldMember {
82 /// Field name, possibly dynamic, see [`FieldName`].
56 pub name: Spanned<FieldName>,83 pub name: Spanned<FieldName>,
84 /// Is this a `+:` field? (extends super field with the same name using `+`).
57 pub plus: bool,85 pub plus: bool,
86 /// Method definition syntax: `a(b): c` is equivalent to `a: function(b) c`.
58 pub params: Option<ExprParams>,87 pub params: Option<ExprParams>,
88 /// Field visibility, see [`Visibility`].
59 pub visibility: Visibility,89 pub visibility: Visibility,
90 /// Field value.
60 pub value: Expr,91 pub value: Expr,
61}92}
6293
63#[derive(Debug, PartialEq, Acyclic)]94/// Unary operator.
64pub enum Member {
65 Field(FieldMember),
66 BindStmt(BindSpec),
67 AssertStmt(AssertStmt),
68}
69
70#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]95#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]
71pub enum UnaryOpType {96pub enum UnaryOpType {
97 /// `+v`
72 Plus,98 Plus,
99 /// `-v`
73 Minus,100 Minus,
101 /// `~v`
74 BitNot,102 BitNot,
103 /// `!v`
75 Not,104 Not,
76}105}
77106
91 }120 }
92}121}
93122
123/// Jsonnet binary expression.
124///
125/// ```jsonnet
126/// a + b
127/// ```
94#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]128#[derive(Debug, Clone, Copy, PartialEq, Eq, Acyclic)]
95pub enum BinaryOpType {129pub enum BinaryOpType {
130 /// `*`
96 Mul,131 Mul,
132 /// `/`
97 Div,133 Div,
98134
99 /// Implemented as intrinsic, put here for completeness135 /// `%` - modulo for numbers, formatting for strings, equivalent to `std.mod(a, b)`.
100 Mod,136 Mod,
101137
138 /// `+`
102 Add,139 Add,
140 /// `-`
103 Sub,141 Sub,
104142
143 /// `<<`
105 Lhs,144 Lhs,
145 /// `>>`
106 Rhs,146 Rhs,
107147
148 /// `<`
108 Lt,149 Lt,
150 /// `>`
109 Gt,151 Gt,
152 /// `<=`
110 Lte,153 Lte,
154 /// `>=`
111 Gte,155 Gte,
112156
157 /// `&`
113 BitAnd,158 BitAnd,
159 /// `|`
114 BitOr,160 BitOr,
161 /// `^`
115 BitXor,162 BitXor,
116163
164 /// `==`
117 Eq,165 Eq,
166 /// `!=`
118 Neq,167 Neq,
119168
169 /// `&&`
120 And,170 And,
171 /// `||`
121 Or,172 Or,
173 /// `??`
122 #[cfg(feature = "exp-null-coaelse")]174 #[cfg(feature = "exp-null-coaelse")]
123 NullCoaelse,175 NullCoaelse,
124176
125 // Equialent to std.objectHasEx(a, b, true)177 /// `in` - equialent to `std.objectHasEx(a, b, true)`.
126 In,178 In,
127}179}
128180
159 }211 }
160}212}
161213
214/// Parameter definition in function expression/method object member.
215///
216/// ```jsonnet
162/// name, default value217/// name = default
218/// ```
163#[derive(Debug, PartialEq, Acyclic)]219#[derive(Debug, PartialEq, Acyclic)]
164pub struct ExprParam {220pub struct ExprParam {
221 /// Destruct for the field value, if not [`Destruct::Full`] - can only be used with positional argument.
165 pub destruct: Destruct,222 pub destruct: Destruct,
223 /// Default value.
166 pub default: Option<Expr>,224 pub default: Option<Expr>,
167}225}
168226
169/// Defined function parameters227/// Defined function parameters.
170#[derive(Debug, PartialEq, Acyclic)]228#[derive(Debug, PartialEq, Acyclic)]
171pub struct ExprParams {229pub struct ExprParams {
230 /// Defined function parameters.
172 pub exprs: Vec<ExprParam>,231 pub exprs: Vec<ExprParam>,
232 /// Cached function signature. TODO: Should be calculated by static analyzer.
173 pub signature: FunctionSignature,233 pub signature: FunctionSignature,
174 pub(crate) binds_len: usize,234 pub(crate) binds_len: usize,
175}235}
176impl ExprParams {236impl ExprParams {
237 /// Number of all parameters, including those with set defaults.
177 pub fn len(&self) -> usize {238 pub fn len(&self) -> usize {
178 self.exprs.len()239 self.exprs.len()
179 }240 }
241 /// Is this function has no parameters?
180 pub fn is_empty(&self) -> bool {242 pub fn is_empty(&self) -> bool {
181 self.exprs.is_empty()243 self.exprs.is_empty()
182 }244 }
183245
246 /// Amount of bound locals, equal to number of parameters without `exp-destruct`.
184 pub fn binds_len(&self) -> usize {247 pub fn binds_len(&self) -> usize {
185 self.binds_len248 self.binds_len
186 }249 }
250 /// Create an [`ExprParams`].
187 pub fn new(exprs: Vec<ExprParam>) -> Self {251 pub fn new(exprs: Vec<ExprParam>) -> Self {
188 Self {252 Self {
189 signature: FunctionSignature::new(253 signature: FunctionSignature::new(
203 }267 }
204}268}
205269
270/// Function call arguments.
271///
272/// ```jsonnet
273/// call(unnamed1, unnamed2, named1 = value, named2 = value)
274/// ```
275///
276/// TODO: should `tailstrict` be moved here?
206#[derive(Debug, PartialEq, Acyclic)]277#[derive(Debug, PartialEq, Acyclic)]
207pub struct ArgsDesc {278pub struct ArgsDesc {
279 /// Positional argument values.
208 pub unnamed: Vec<Expr>,280 pub unnamed: Vec<Expr>,
281 /// Named argument names.
209 pub names: Vec<IStr>,282 pub names: Vec<IStr>,
283 /// Named argument values.
210 pub values: Vec<Expr>,284 pub values: Vec<Expr>,
211}285}
212impl ArgsDesc {286impl ArgsDesc {
287 /// Construct an [`ArgsDesc`].
213 pub fn new(unnamed: Vec<Expr>, names: Vec<IStr>, values: Vec<Expr>) -> Self {288 pub fn new(unnamed: Vec<Expr>, names: Vec<IStr>, values: Vec<Expr>) -> Self {
214 Self {289 Self {
215 unnamed,290 unnamed,
219 }294 }
220}295}
221296
297/// In [`Destruct`], unmatched array elements/object fields should either not exist,
298/// or be explicitly dropped [`DestructRest::Drop`] or collected into another local [`DestructRest::Keep`].
222#[derive(Debug, PartialEq, Eq, Acyclic)]299#[derive(Debug, PartialEq, Eq, Acyclic)]
223pub enum DestructRest {300pub enum DestructRest {
224 /// ...rest301 /// `...rest`
225 Keep(IStr),302 Keep(IStr),
226 /// ...303 /// `...`
227 Drop,304 Drop,
228}305}
229306
307/// Local definition/destructuring (with `exp-destruct`).
308///
309/// `name` in `local name = value`.
230#[derive(Debug, PartialEq, Acyclic)]310#[derive(Debug, PartialEq, Acyclic)]
231pub enum Destruct {311pub enum Destruct {
312 /// `name` - normal local definition, value is assigned to the specified name.
232 Full(Spanned<IStr>),313 Full(Spanned<IStr>),
314 /// `?` - value is ignored, mostly useful for nested destructuring of arrays/objects.
233 #[cfg(feature = "exp-destruct")]315 #[cfg(feature = "exp-destruct")]
234 Skip,316 Skip,
317 /// `[a, b, ...rest, c]` - destructure the value as array.
318 ///
319 /// If the value length is not matched by `start` and there is no `rest` - throws.
235 #[cfg(feature = "exp-destruct")]320 #[cfg(feature = "exp-destruct")]
236 Array {321 Array {
322 /// How to collect first elements.
237 start: Vec<Destruct>,323 start: Vec<Destruct>,
324 /// How the elements in between the `start` and `end` should be handled.
238 rest: Option<DestructRest>,325 rest: Option<DestructRest>,
326 /// How to collect last elements. Might only be non-empty in presence of `rest`.
239 end: Vec<Destruct>,327 end: Vec<Destruct>,
240 },328 },
329 /// `{a, b = default, c: rename, ...rest}` - destructure the value as object.
241 #[cfg(feature = "exp-destruct")]330 #[cfg(feature = "exp-destruct")]
242 Object {331 Object {
332 /// Destructuring of the individual fields.
333 ///
334 /// Source field name, target destructure (defaults to `Destruct::Full` with the source name),
335 /// default value (defaults to throw on the match time due to match failure).
243 #[allow(clippy::type_complexity)]336 #[allow(clippy::type_complexity)]
244 fields: Vec<(IStr, Option<Destruct>, Option<Spanned<Expr>>)>,337 fields: Vec<(IStr, Option<Destruct>, Option<Spanned<Expr>>)>,
338 /// How the remaining fields should be handled, the result is similar to how `std.objectRemoveField` behaves.
245 rest: Option<DestructRest>,339 rest: Option<DestructRest>,
246 },340 },
247}341}
248impl Destruct {342impl Destruct {
249 /// Name of destructure, used for function parameter names343 /// Name of destructure, used for function named parameter names.
250 pub fn name(&self) -> ParamName {344 pub fn name(&self) -> ParamName {
251 match self {345 match self {
252 Self::Full(name) => ParamName::Named(name.value.clone()),346 Self::Full(name) => ParamName::Named(name.value.clone()),
253 #[cfg(feature = "exp-destruct")]347 #[cfg(feature = "exp-destruct")]
254 _ => ParamName::Unnamed,348 _ => ParamName::Unnamed,
255 }349 }
256 }350 }
351 /// How many local names this [`Destruct`] will create, always `1` when `exp-destruct` feature is not enabled.
257 pub fn binds_len(&self) -> usize {352 pub fn binds_len(&self) -> usize {
258 #[cfg(feature = "exp-destruct")]353 #[cfg(feature = "exp-destruct")]
259 fn cap_rest(rest: &Option<DestructRest>) -> usize {354 fn cap_rest(rest: &Option<DestructRest>) -> usize {
289 }384 }
290}385}
291386
387/// Single element of `local` expression/value of the `local` object/obj-comp member.
388///
389/// ```jsonnet
390/// local a = b;
391/// ```
292#[derive(Debug, PartialEq, Acyclic)]392#[derive(Debug, PartialEq, Acyclic)]
293pub enum BindSpec {393pub enum BindSpec {
394 /// Normal local definition/destructure: `local a = b;`.
294 Field {395 Field {
396 /// Local name/destructure.
295 into: Destruct,397 into: Destruct,
398 /// Value.
296 value: Expr,399 value: Expr,
297 },400 },
401 /// Method-like local: `local a(b) = c;`, equivalent to `local a = function(b) c;`.
298 Function {402 Function {
403 /// Local name, can't be destructure since functions can't be destructured.
299 name: Spanned<IStr>,404 name: Spanned<IStr>,
405 /// Function parameters.
300 params: ExprParams,406 params: ExprParams,
407 /// Function body.
301 value: Expr,408 value: Expr,
302 },409 },
303}410}
304impl BindSpec {411impl BindSpec {
412 /// How many locals will this local definition define.
305 pub fn binds_len(&self) -> usize {413 pub fn binds_len(&self) -> usize {
306 match self {414 match self {
307 BindSpec::Field { into, .. } => into.binds_len(),415 BindSpec::Field { into, .. } => into.binds_len(),
310 }418 }
311}419}
312420
421/// `if` expression/`if` compspec condition.
422///
423/// ```jsonnet
424/// if a == b
425/// ```
313#[derive(Debug, PartialEq, Acyclic)]426#[derive(Debug, PartialEq, Acyclic)]
314pub struct IfSpecData {427pub struct IfSpecData {
428 /// Span for the `if` token.
315 pub span: Span,429 pub span: Span,
430 /// Condition expression.
316 pub cond: Expr,431 pub cond: Expr,
317}432}
318433
434/// `for` compspec definition.
435///
436/// ```jsonnet
437/// for a in b
438/// ```
319#[derive(Debug, PartialEq, Acyclic)]439#[derive(Debug, PartialEq, Acyclic)]
320pub struct ForSpecData {440pub struct ForSpecData {
441 /// New local definition, will be set per `over` iteration.
321 pub destruct: Destruct,442 pub destruct: Destruct,
443 /// Expression which should evaluate to array to be iterated over.
322 pub over: Expr,444 pub over: Expr,
323}445}
324446
325#[cfg(feature = "exp-object-iteration")]447/// `for` compspec object iteration definition.
448///
449/// ```jsonnet
450/// for [key]: value in obj
451/// ```
452///
453/// TODO: `exp-preserve-order` integration.
326#[derive(Debug, PartialEq, Acyclic)]454#[derive(Debug, PartialEq, Acyclic)]
327pub struct ForObjSpecData {455pub struct ForObjSpecData {
456 /// Object field name, will be set per `over` field iteration.
328 pub key: IStr,457 pub key: IStr,
458 /// Filter for the iterated object fields,
459 /// - `:` will iterate over visible fields.
460 /// - `::` will iterate over only invisible fields.
461 /// - `:::` will iterate over all defined fields.
329 pub visibility: Visibility,462 pub visibility: Visibility,
463 /// Object value destructure, will be set per `over` field iteration.
330 pub value: Destruct,464 pub value: Destruct,
465 /// Expression which should evaluate to object to be iterated over.
331 pub over: Expr,466 pub over: Expr,
332}467}
333468
469/// One element of array/obj-comp iteration definition.
470///
471/// `for a in b if c` in [1 for a in b if c].
334#[derive(Debug, PartialEq, Acyclic)]472#[derive(Debug, PartialEq, Acyclic)]
335pub enum CompSpec {473pub enum CompSpec {
474 /// `if` filter, see [`IfSpecData`].
336 IfSpec(IfSpecData),475 IfSpec(IfSpecData),
476 /// `for` array iterator, see [`ForSpecData`].
337 ForSpec(ForSpecData),477 ForSpec(ForSpecData),
478 /// `for` object iterator, see [`ForObjSpecData`].
338 #[cfg(feature = "exp-object-iteration")]479 #[cfg(feature = "exp-object-iteration")]
339 ForObjSpec(ForObjSpecData),480 ForObjSpec(ForObjSpecData),
340}481}
341482
483/// Object constructed from dynamically constructed field list using iteration.
484///
485/// ```jsonnet
486/// {
487/// ["field_" + id]: value
488/// for id in [1, 2, 3]
489/// }
490/// ```
342#[derive(Debug, PartialEq, Acyclic)]491#[derive(Debug, PartialEq, Acyclic)]
343pub struct ObjComp {492pub struct ObjComp {
493 /// Locals to be defined to be used by object field values, may reference object identity.
344 pub locals: Vec<BindSpec>,494 pub locals: Vec<BindSpec>,
495 /// Field definition template, will be evaluated for every compspec iteration, normally uses [`FieldName::Dyn`].
345 pub field: Box<FieldMember>,496 pub field: Box<FieldMember>,
497 /// Compspec.
346 pub compspecs: Vec<CompSpec>,498 pub compspecs: Vec<CompSpec>,
347}499}
348500
501/// Object constructed from explicitly defined elements.
502///
503/// ```jsonnet
504/// {
505/// a: 1,
506/// b: 2,
507/// }
508/// ```
349#[derive(Debug, PartialEq, Acyclic)]509#[derive(Debug, PartialEq, Acyclic)]
350pub struct ObjMembers {510pub struct ObjMembers {
511 /// Locals to be defined to be used by object field values, may reference object identity.
351 pub locals: Vec<BindSpec>,512 pub locals: Vec<BindSpec>,
513 /// Associated object assertions, checked on first time object field value is computed.
352 pub asserts: Vec<AssertStmt>,514 pub asserts: Vec<AssertStmt>,
515 /// Static list of field definitions.
353 pub fields: Vec<FieldMember>,516 pub fields: Vec<FieldMember>,
354}517}
355518
519/// Object constructed by any means.
356#[derive(Debug, PartialEq, Acyclic)]520#[derive(Debug, PartialEq, Acyclic)]
357pub enum ObjBody {521pub enum ObjBody {
522 /// Static field list, see [`ObjMembers`].
358 MemberList(ObjMembers),523 MemberList(ObjMembers),
524 /// Field list is created by iteration, see [`ObjComp`].
359 ObjComp(ObjComp),525 ObjComp(ObjComp),
360}526}
361527
362/// Object identity reference: `self`, `super`, or `$`.#[derive(Debug, PartialEq, Eq, Clone, Copy, Acyclic)]528/// Object identity reference: `self`, `super`, or `$`.#[derive(Debug, PartialEq, Eq, Clone, Copy, Acyclic)]
363#[derive(Debug, PartialEq, Acyclic)]529#[derive(Debug, PartialEq, Acyclic)]
364pub enum IdentityKind {530pub enum IdentityKind {
531 /// `self` - renamed to `this` for easier usage in the code.
365 This,532 This,
533 /// `super`.
366 Super,534 Super,
535 /// `$`.
367 Dollar,536 Dollar,
368}537}
369538
539/// Slice expression range/step.
540///
541/// `[start:end:step]` in `array[start:end:step]`.
370#[derive(Debug, PartialEq, Acyclic)]542#[derive(Debug, PartialEq, Acyclic)]
371pub struct SliceDesc {543pub struct SliceDesc {
544 /// Slice start (inclusive) - elements before are not included. Counts from the end when negative.
545 ///
546 /// `0` when `None`.
372 pub start: Option<Spanned<Expr>>,547 pub start: Option<Spanned<Expr>>,
548 /// Slice end (exclusive) - elements after/at are not included. Counts from the end when negative.
549 ///
550 /// `std.length(array)` when `None`.
373 pub end: Option<Spanned<Expr>>,551 pub end: Option<Spanned<Expr>>,
552 /// Slice step - every `step`'th element is included in the resulting array. `step >= 1`.
553 ///
554 /// `1` when `None`.
374 pub step: Option<Spanned<Expr>>,555 pub step: Option<Spanned<Expr>>,
375}556}
376557
558/// Assert expression.
559///
560/// ```jsonnet
561/// assert value; rest
562/// ```
563///
564/// Asserts `value`, continues with the evaluation of `rest`.
377#[derive(Debug, PartialEq, Acyclic)]565#[derive(Debug, PartialEq, Acyclic)]
378pub struct AssertExpr {566pub struct AssertExpr {
567 /// Value to assert, see [`AssertStmt`].
379 pub assert: AssertStmt,568 pub assert: AssertStmt,
569 /// What value to return when the assertion is succeeded.
380 pub rest: Expr,570 pub rest: Expr,
381}571}
382572
573/// Binary expression.
574///
575/// ```jsonnet
576/// a + b
577/// ```
383#[derive(Debug, PartialEq, Acyclic)]578#[derive(Debug, PartialEq, Acyclic)]
384pub struct BinaryOp {579pub struct BinaryOp {
580 /// Value to the left of binary operator.
385 pub lhs: Expr,581 pub lhs: Expr,
582 /// Operator to apply.
386 pub op: BinaryOpType,583 pub op: BinaryOpType,
584 /// Value to the right of binary operator.
387 pub rhs: Expr,585 pub rhs: Expr,
388}586}
389587
588/// Import expression kind.
589///
590/// `str` in `importstr "path"`.
390#[derive(Debug, PartialEq, Acyclic, Clone, Copy)]591#[derive(Debug, PartialEq, Acyclic, Clone, Copy)]
391pub enum ImportKind {592pub enum ImportKind {
593 /// `import`
392 Normal,594 Normal,
595 /// `importstr`
393 Str,596 Str,
597 /// `importbin`
394 Bin,598 Bin,
395}599}
396600
601/// If else expression.
602///
603/// ```jsonnet
604/// if a then b else c
605/// ```
397#[derive(Debug, PartialEq, Acyclic)]606#[derive(Debug, PartialEq, Acyclic)]
398pub struct IfElse {607pub struct IfElse {
608 /// Condition to evaluate, see [`IfSpecData`].
399 pub cond: IfSpecData,609 pub cond: IfSpecData,
610 /// Value to return if the condition is `true`.
400 pub cond_then: Expr,611 pub cond_then: Expr,
612 /// Value to return if the condition is `false`, `null` when `None`.
401 pub cond_else: Option<Expr>,613 pub cond_else: Option<Expr>,
402}614}
403615
616/// Slice expression.
617///
618/// ```jsonnet
619/// value[start:end:slice]
620/// ```
404#[derive(Debug, PartialEq, Acyclic)]621#[derive(Debug, PartialEq, Acyclic)]
405pub struct Slice {622pub struct Slice {
623 /// Value to slice, should evaluate to iterable.
406 pub value: Expr,624 pub value: Expr,
625 /// Slice definition, see [`SliceDesc`].
407 pub slice: SliceDesc,626 pub slice: SliceDesc,
408}627}
409628
413 /// Object-identity reference: `self`, `super`, `$`.632 /// Object-identity reference: `self`, `super`, `$`.
414 Identity(Span, IdentityKind),633 Identity(Span, IdentityKind),
415634
416 /// Trivial value literal635 /// Trivial value literal, see [`TrivialVal`].
417 Trivial(TrivialVal),636 Trivial(TrivialVal),
418637
419 /// Variable name: test638 /// Local reference.
420 Var(Spanned<IStr>),639 Var(Spanned<IStr>),
421640
422 /// Array of expressions: [1, 2, "Hello"]641 /// Array of expressions.
642 ///
643 /// ```jsonnet
644 /// [1, 2, "Hello"]
645 /// ```
423 Arr(Vec<Expr>),646 Arr(Vec<Expr>),
424 /// Array comprehension:647 /// Array comprehension.
648 ///
425 /// ```jsonnet649 /// ```jsonnet
426 /// ingredients: [650 /// ingredients: [
427 /// { kind: kind, qty: 4 / 3 }651 /// { kind: kind, qty: 4 / 3 }
434 /// ```658 /// ```
435 ArrComp(Box<Expr>, Vec<CompSpec>),659 ArrComp(Box<Expr>, Vec<CompSpec>),
436660
661 /// Object creation, see [`ObjBody`].
662 ///
663 /// ```jsonnet
437 /// Object: {a: 2}664 /// {a: 2}
665 /// ```
438 Obj(ObjBody),666 Obj(ObjBody),
439 /// Object extension: var1 {b: 2}667 /// Object extension.
668 ///
669 /// ```jsonnet
670 /// var1 {b: 2}
671 /// ```
672 ///
673 /// Equivalent to `var {b: 2}`.
440 ObjExtend(Box<Expr>, ObjBody),674 ObjExtend(Box<Expr>, ObjBody),
441675
676 /// Unary operator expression, see [`UnaryOpType`].
677 ///
678 /// ```jsonnet
442 /// -2679 /// -2
680 /// ```
443 UnaryOp(UnaryOpType, Box<Expr>),681 UnaryOp(UnaryOpType, Box<Expr>),
682 /// Binary operator expression, see [`BinaryOp`].
683 ///
684 /// ```jsonnet
444 /// 2 - 2685 /// 2 - 2
686 /// ```
445 BinaryOp(Box<BinaryOp>),687 BinaryOp(Box<BinaryOp>),
688 /// Assertion expression, see [`AssertExpr`].
689 ///
690 /// ```jsonnet
446 /// assert 2 == 2 : "Math is broken"691 /// assert 2 == 2 : "Math is broken"
692 /// ```
447 AssertExpr(Box<AssertExpr>),693 AssertExpr(Box<AssertExpr>),
694 /// Local expression.
695 ///
696 /// Defines locals using [`BindSpec`], then evaluates expression in the resulting context scope.
697 ///
698 /// ```jsonnet
448 /// local a = 2; { b: a }699 /// local a = 2; { b: a }
700 /// ```
449 LocalExpr(Vec<BindSpec>, Box<Expr>),701 LocalExpr(Vec<BindSpec>, Box<Expr>),
450702
703 /// Import expression
704 ///
705 /// ```jsonnet
451 /// import* "hello"706 /// import "hello"
707 /// ```
452 Import(Spanned<ImportKind>, Box<Expr>),708 Import(Spanned<ImportKind>, Box<Expr>),
709 /// Error expression, immideately throws the error on evaluation.
710 ///
711 /// ```jsonnet
453 /// error "I'm broken"712 /// error "I'm broken"
713 /// ```
454 ErrorStmt(Span, Box<Expr>),714 ErrorStmt(Span, Box<Expr>),
455 /// a(b, c)715 /// Function call.
716 ///
717 /// See [`ArgsDesc`].
456 Apply(Box<Expr>, Spanned<ArgsDesc>, bool),718 Apply(Box<Expr>, Spanned<ArgsDesc>, bool),
719 /// Indexing chain.
720 ///
457 /// a[b], a.b, a?.b721 /// `a[b]`, `a.b`, `a?.b`
458 Index {722 Index {
723 /// Value to index into.
459 indexable: Box<Expr>,724 indexable: Box<Expr>,
725 /// Indexing operators to apply in sequence, see [`IndexPart`].
460 parts: Vec<IndexPart>,726 parts: Vec<IndexPart>,
461 },727 },
728 /// Function definition.
729 ///
730 /// ```jsonnet
462 /// function(x) x731 /// function(x) x
732 /// ```
463 Function(Span, ExprParams, Box<Expr>),733 Function(Span, ExprParams, Box<Expr>),
464 /// if true == false then 1 else 2734 /// IfElse expression, see [`IfElse`]
465 IfElse(Box<IfElse>),735 IfElse(Box<IfElse>),
736 /// Slice expression, see [`Slice`]
466 Slice(Box<Slice>),737 Slice(Box<Slice>),
467}738}
468739
740/// Single index chain expression.
741///
742/// `.value` in `indexed.value`.
469#[derive(Debug, PartialEq, Acyclic)]743#[derive(Debug, PartialEq, Acyclic)]
470pub struct IndexPart {744pub struct IndexPart {
745 /// Span encompassing the current index element definition.
471 pub span: Span,746 pub span: Span,
747 /// Field/element to get from the indexable value.
472 pub value: Expr,748 pub value: Expr,
749 /// Null-coaelsing - interrupt the chain earlier returning `null` when the field is missing in the indexed value.
473 #[cfg(feature = "exp-null-coaelse")]750 #[cfg(feature = "exp-null-coaelse")]
474 pub null_coaelse: bool,751 pub null_coaelse: bool,
475}752}
476753
477/// file, begin offset, end offset754/// A slice of source code, plus path and code itself. Contains begin byte offset, end byte offset.
478#[derive(Clone, PartialEq, Eq, Acyclic)]755#[derive(Clone, PartialEq, Eq, Acyclic)]
479#[repr(C)]756#[repr(C)]
480pub struct Span(pub Source, pub u32, pub u32);757pub struct Span(pub Source, pub u32, pub u32);
481impl Span {758impl Span {
759 /// Is this span a substring of the other span?
482 pub fn belongs_to(&self, other: &Span) -> bool {760 pub fn belongs_to(&self, other: &Span) -> bool {
483 other.0 == self.0 && other.1 <= self.1 && other.2 >= self.2761 other.0 == self.0 && other.1 <= self.1 && other.2 >= self.2
484 }762 }
763 /// Span standard inclusive range value.
485 pub fn range(&self) -> RangeInclusive<usize> {764 pub fn range(&self) -> RangeInclusive<usize> {
486 let start = self.1;765 let start = self.1;
487 let mut end = self.2;766 let mut end = self.2;
502 }781 }
503}782}
504783
784/// Spanned expression.
505#[derive(Clone, PartialEq, Acyclic)]785#[derive(Clone, PartialEq, Acyclic)]
506pub struct Spanned<T: Acyclic> {786pub struct Spanned<T: Acyclic> {
787 /// Spanned expression.
507 pub value: T,788 pub value: T,
789 /// Span.
508 pub span: Span,790 pub span: Span,
509}791}
510impl<T: Acyclic> Deref for Spanned<T> {792impl<T: Acyclic> Deref for Spanned<T> {
514 }796 }
515}797}
516impl<T: Acyclic> Spanned<T> {798impl<T: Acyclic> Spanned<T> {
799 /// Construct the spanned expression.
517 #[inline]800 #[inline]
518 pub fn new(value: T, span: Span) -> Self {801 pub fn new(value: T, span: Span) -> Self {
519 Self { value, span }802 Self { value, span }
520 }803 }
804 /// Map the spanned expression, leaving span as is.
521 pub fn map<U: Acyclic>(self, v: impl FnOnce(T) -> U) -> Spanned<U> {805 pub fn map<U: Acyclic>(self, v: impl FnOnce(T) -> U) -> Spanned<U> {
522 Spanned {806 Spanned {
523 span: self.span,807 span: self.span,
524 value: v(self.value),808 value: v(self.value),
525 }809 }
526 }810 }
811 /// Create [`Spanned`] with the reference to the expression.
527 pub fn as_ref<'a>(&'a self) -> Spanned<&'a T>812 pub fn as_ref<'a>(&'a self) -> Spanned<&'a T>
528 where813 where
529 &'a T: Acyclic,814 &'a T: Acyclic,
modifiedcrates/jrsonnet-ir/src/function.rsdiffbeforeafterboth
1//! Function signature definition.
2//!
3//! TODO: To be moved to analyzer.
4//! TODO: Unify the anonymous/unnamed/positional naming.
5
1use std::{fmt, ops::Deref, rc::Rc};6use std::{fmt, ops::Deref, rc::Rc};
27
3use jrsonnet_gcmodule::Acyclic;8use jrsonnet_gcmodule::Acyclic;
4use jrsonnet_interner::IStr;9use jrsonnet_interner::IStr;
510
11/// Function parameter name.
6#[derive(Clone, Acyclic, Debug, PartialEq, Eq)]12#[derive(Clone, Acyclic, Debug, PartialEq, Eq)]
7pub enum ParamName {13pub enum ParamName {
14 /// Unnamed (only possible with `exp-destruct`).
8 Unnamed,15 Unnamed,
16 /// Named.
9 Named(IStr),17 Named(IStr),
10}18}
11impl ParamName {19impl ParamName {
20 /// Get the named parameter name as string.
12 pub fn as_str(&self) -> Option<&str> {21 pub fn as_str(&self) -> Option<&str> {
13 match self {22 match self {
14 ParamName::Unnamed => None,23 ParamName::Unnamed => None,
15 ParamName::Named(istr) => Some(istr),24 ParamName::Named(istr) => Some(istr),
16 }25 }
17 }26 }
27 /// Is the parameter positional.
18 pub fn is_anonymous(&self) -> bool {28 pub fn is_anonymous(&self) -> bool {
19 matches!(self, Self::Unnamed)29 matches!(self, Self::Unnamed)
20 }30 }
31 /// Is the parameter named.
21 pub fn is_named(&self) -> bool {32 pub fn is_named(&self) -> bool {
22 matches!(self, Self::Named(_))33 matches!(self, Self::Named(_))
23 }34 }
40 }51 }
41}52}
4253
54/// Parameter default value description.
43#[derive(Clone, Copy, Debug, Acyclic, PartialEq, Eq)]55#[derive(Clone, Copy, Debug, Acyclic, PartialEq, Eq)]
44pub enum ParamDefault {56pub enum ParamDefault {
57 /// No default exists.
45 None,58 None,
59 /// Default exists, but omitted from the error details (e.g handled in native code).
46 Exists,60 Exists,
61 /// Default exists, stringified.
47 Literal(&'static str),62 Literal(&'static str),
48}63}
49impl ParamDefault {64impl ParamDefault {
65 /// Createn optional [`ParamDefault`] without the stringified value for the error messages.
50 pub const fn exists(is_exists: bool) -> Self {66 pub const fn exists(is_exists: bool) -> Self {
51 if is_exists { Self::Exists } else { Self::None }67 if is_exists { Self::Exists } else { Self::None }
52 }68 }
61 }77 }
62}78}
6379
80/// Function parameter for argument matching purposes.
64#[derive(Clone, Acyclic, Debug, PartialEq, Eq)]81#[derive(Clone, Acyclic, Debug, PartialEq, Eq)]
65pub struct ParamParse {82pub struct ParamParse {
66 name: ParamName,83 name: ParamName,
67 default: ParamDefault,84 default: ParamDefault,
68}85}
69impl ParamParse {86impl ParamParse {
87 /// Construct the function parameter definition.
70 pub fn new(name: ParamName, default: ParamDefault) -> Self {88 pub fn new(name: ParamName, default: ParamDefault) -> Self {
71 Self { name, default }89 Self { name, default }
72 }90 }
73 /// Parameter name for named call parsing91 /// Parameter name for named call parsing.
74 pub fn name(&self) -> &ParamName {92 pub fn name(&self) -> &ParamName {
75 &self.name93 &self.name
76 }94 }
95 /// Default value for error reporting.
77 pub fn default(&self) -> ParamDefault {96 pub fn default(&self) -> ParamDefault {
78 self.default97 self.default
79 }98 }
99 /// Can this parameter be derived implicitly?
80 pub fn has_default(&self) -> bool {100 pub fn has_default(&self) -> bool {
81 !matches!(self.default, ParamDefault::None)101 !matches!(self.default, ParamDefault::None)
82 }102 }
87 }107 }
88}108}
89109
110/// Function definition signature internals.
90#[derive(Debug, Clone, Acyclic, PartialEq, Eq)]111#[derive(Debug, Clone, Acyclic, PartialEq, Eq)]
91pub struct FunctionSignature(Rc<[ParamParse]>);112pub struct FunctionSignature(Rc<[ParamParse]>);
92impl Deref for FunctionSignature {113impl Deref for FunctionSignature {
102}123}
103124
104impl FunctionSignature {125impl FunctionSignature {
126 /// Construct a function signature.
105 pub fn new(v: Rc<[ParamParse]>) -> Self {127 pub fn new(v: Rc<[ParamParse]>) -> Self {
106 Self(v)128 Self(v)
107 }129 }
130 /// Function signature of a degenerate function `function() value`.
108 pub fn empty() -> Self {131 pub fn empty() -> Self {
109 EMPTY_SIGNATURE.with(|p| p.clone())132 EMPTY_SIGNATURE.with(|p| p.clone())
110 }133 }
modifiedcrates/jrsonnet-ir/src/lib.rsdiffbeforeafterboth
1#![allow(clippy::redundant_closure_call, clippy::derive_partial_eq_without_eq)]1#![allow(clippy::redundant_closure_call, clippy::derive_partial_eq_without_eq)]
2#![deny(missing_docs)]
2//! Jrsonnet AST definitions3//! Jrsonnet AST definitions
34
4mod expr;5mod expr;
modifiedcrates/jrsonnet-ir/src/location.rsdiffbeforeafterboth
1/// Parsed source code location info.
1#[allow(clippy::module_name_repetitions)]2#[allow(clippy::module_name_repetitions)]
2#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]3#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
3pub struct CodeLocation {4pub struct CodeLocation {
5 /// Source code byte offset.
4 pub offset: usize,6 pub offset: usize,
57
8 /// 1-based line number.
6 pub line: usize,9 pub line: usize,
10 /// 1-based column number.
7 pub column: usize,11 pub column: usize,
812
13 /// Source code byte offset for the current line start.
9 pub line_start_offset: usize,14 pub line_start_offset: usize,
15 /// Source code byte offset for the current line end.
10 pub line_end_offset: usize,16 pub line_end_offset: usize,
11}17}
1218
modifiedcrates/jrsonnet-ir/src/source.rsdiffbeforeafterboth
1414
15macro_rules! any_ext_methods {15macro_rules! any_ext_methods {
16 ($T:ident) => {16 ($T:ident) => {
17 fn as_any(&self) -> &dyn Any;17 /// Object-safe Hash implementation, usually provided by [`any_ext_impl`] macro.
18 fn dyn_hash(&self, hasher: &mut dyn Hasher);18 fn dyn_hash(&self, hasher: &mut dyn Hasher);
19 /// Object-safe PartialEq/Eq implementation, usually provided by [`any_ext_impl`] macro.
19 fn dyn_eq(&self, other: &dyn $T) -> bool;20 fn dyn_eq(&self, other: &dyn $T) -> bool;
20 fn dyn_debug(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result;
21 };21 };
22}22}
23macro_rules! any_ext_impl {23macro_rules! any_ext_impl {
24 ($T:ident) => {24 ($T:ident) => {
25 fn as_any(&self) -> &dyn Any {
26 self
27 }
28 fn dyn_hash(&self, mut hasher: &mut dyn Hasher) {25 fn dyn_hash(&self, mut hasher: &mut dyn Hasher) {
29 self.hash(&mut hasher)26 self.hash(&mut hasher)
30 }27 }
31 fn dyn_eq(&self, other: &dyn $T) -> bool {28 fn dyn_eq(&self, other: &dyn $T) -> bool {
29 let other: &dyn Any = &*other;
32 let Some(other) = other.as_any().downcast_ref::<Self>() else {30 let Some(other) = other.downcast_ref::<Self>() else {
33 return false;31 return false;
34 };32 };
35 let this = <Self as $T>::as_any(self)33 let this: &dyn Any = &*self;
36 .downcast_ref::<Self>()34 let this = this.downcast_ref::<Self>().expect("restricted by impl");
37 .expect("restricted by impl");
38 this == other35 this == other
39 }36 }
40 fn dyn_debug(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 <Self as std::fmt::Debug>::fmt(self, fmt)
42 }
43 };37 };
44}38}
45macro_rules! any_ext {39macro_rules! any_ext {
57 impl Eq for dyn $T {}51 impl Eq for dyn $T {}
58 };52 };
59}53}
54/// Represents trait methods used by [`SourcePath`] implementation.
60pub trait SourcePathT: Acyclic + Debug + Display {55pub trait SourcePathT: Acyclic + Debug + Display + Any {
61 /// This method should be checked by resolver before panicking with bad SourcePath input56 /// This method should be checked by resolver before panicking with bad SourcePath input
62 /// if `true` - then resolver may threat this path as default, and default is usally a CWD57 /// if `true` - then resolver may threat this path as default, and default is usally a CWD.
63 fn is_default(&self) -> bool;58 fn is_default(&self) -> bool;
59 /// If this source path is backed by Os [`Path`] - it can be obtained from here.
64 fn path(&self) -> Option<&Path>;60 fn path(&self) -> Option<&Path>;
65 any_ext_methods!(SourcePathT);61 any_ext_methods!(SourcePathT);
66}62}
67any_ext!(SourcePathT);63any_ext!(SourcePathT);
6864
69/// Represents location of a file65/// Represents location of a file.
70///66///
71/// Standard CLI only operates using67/// Standard CLI only operates using
72/// - [`SourceFile`] - for any file68/// - [`SourceFile`] - for any file.
73/// - [`SourceDirectory`] - for resolution from CWD69/// - [`SourceDirectory`] - for resolution from CWD.
74/// - [`SourceVirtual`] - for stdlib/ext-str70/// - [`SourceVirtual`] - for stdlib/ext-str.
75/// - [`SourceFifo`] - for /dev/fd/X (This path may appear with `jrsonnet <(command_that_produces_jsonnet)`)71/// - [`SourceFifo`] - for /dev/fd/X (This path may appear with `jrsonnet <(command_that_produces_jsonnet)`).
76///72///
77/// From all of those, only [`SourceVirtual`] may be constructed manually, any other path kind should be only obtained73/// From all of those, only [`SourceVirtual`] may be constructed manually, any other path kind should be only obtained
78/// from assigned `ImportResolver`74/// from assigned `ImportResolver`.
79/// However, you should always check `is_default` method return, as it will return true for any paths, where default75/// However, you should always check `is_default` method return, as it will return true for any paths, where default
80/// search location is applicable76/// search location is applicable.
81///77///
82/// Resolver may also return custom implementations of this trait, for example it may return http url in case of remotely loaded files78/// Resolver may also return custom implementations of this trait, for example it may return http url in case of
79/// remotely loaded files.
83#[derive(Eq, Clone, Acyclic)]80#[derive(Eq, Clone, Acyclic)]
84pub struct SourcePath(Rc<dyn SourcePathT>);81pub struct SourcePath(Rc<dyn SourcePathT>);
85impl SourcePath {82impl SourcePath {
83 /// Create [`SourcePath`] structure from a unboxed [`SourcePathT`]
86 pub fn new(inner: impl SourcePathT) -> Self {84 pub fn new(inner: impl SourcePathT) -> Self {
87 Self(Rc::new(inner))85 Self(Rc::new(inner))
88 }86 }
87 /// Try to downcast the inner boxed [`SourcePathT`] to the specific type.
89 pub fn downcast_ref<T: SourcePathT>(&self) -> Option<&T> {88 pub fn downcast_ref<T: SourcePathT>(&self) -> Option<&T> {
90 self.0.as_any().downcast_ref()89 let this: &dyn Any = &*self.0;
90 this.downcast_ref()
91 }91 }
92 /// This method should be checked by resolver before panicking with bad SourcePath input
93 /// if `true` - then resolver may threat this path as default, and default is usally a CWD.
92 pub fn is_default(&self) -> bool {94 pub fn is_default(&self) -> bool {
93 self.0.is_default()95 self.0.is_default()
94 }96 }
97 /// If this source path is backed by Os [`Path`] - it can be obtained from here.
95 pub fn path(&self) -> Option<&Path> {98 pub fn path(&self) -> Option<&Path> {
96 self.0.path()99 self.0.path()
97 }100 }
123 }126 }
124}127}
125128
129/// Used as a search base, represents default search path, including JPATH.
130/// Used for import resolution for `--ext-str` and other methods without definitive import source.
126#[derive(Acyclic, Hash, PartialEq, Eq, Debug)]131#[derive(Acyclic, Hash, PartialEq, Eq, Debug)]
127struct SourceDefault;132pub struct SourceDefault;
128impl Display for SourceDefault {133impl Display for SourceDefault {
129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 write!(f, "<default>")135 write!(f, "<default>")
140 any_ext_impl!(SourcePathT);145 any_ext_impl!(SourcePathT);
141}146}
142147
148/// Used as a search base, represents default search path, excluding JPATH.
149/// Used by default by jrsonnet cli.
143#[derive(Acyclic, Hash, PartialEq, Eq, Debug)]150#[derive(Acyclic, Hash, PartialEq, Eq, Debug)]
144pub struct SourceDefaultIgnoreJpath;151pub struct SourceDefaultIgnoreJpath;
145impl Display for SourceDefaultIgnoreJpath {152impl Display for SourceDefaultIgnoreJpath {
157 any_ext_impl!(SourcePathT);164 any_ext_impl!(SourcePathT);
158}165}
159166
160/// Represents path to the file on the disk167/// Represents path to the file on the disk.
168///
161/// Directories shouldn't be put here, as resolution for files differs from resolution for directories:169/// Directories shouldn't be put here, as resolution for files differs from resolution for directories:
162///170///
163/// When `file` is being resolved from `SourceFile(a/b/c)`, it should be resolved to `SourceFile(a/b/file)`,171/// When `file` is being resolved from `SourceFile(a/b/c)`, it should be resolved to `SourceFile(a/b/file)`,
164/// however if it is being resolved from `SourceDirectory(a/b/c)`, then it should be resolved to `SourceDirectory(a/b/c/file)`172/// however if it is being resolved from `SourceDirectory(a/b/c)`, then it should be resolved to `SourceDirectory(a/b/c/file)`
165#[derive(Acyclic, Hash, PartialEq, Eq, Debug)]173#[derive(Acyclic, Hash, PartialEq, Eq, Debug)]
166pub struct SourceFile(PathBuf);174pub struct SourceFile(PathBuf);
167impl SourceFile {175impl SourceFile {
176 /// Wrap a path buf for [`SourceFile`]
168 pub fn new(path: PathBuf) -> Self {177 pub fn new(path: PathBuf) -> Self {
169 Self(path)178 Self(path)
170 }179 }
180 /// Retrieve a wrapped [`Path`]
171 pub fn path(&self) -> &Path {181 pub fn path(&self) -> &Path {
172 &self.0182 &self.0
173 }183 }
187 any_ext_impl!(SourcePathT);197 any_ext_impl!(SourcePathT);
188}198}
189199
200/// Represents path to the file by URL, used for WASM builds, and UNUSABLE by the default import resolvers.
201///
202/// Note that it might contain file: urls, but they are not returned in .path() getter (TODO: should it be?..),
203/// since we have no defined OsStr encoding for wasm.
190#[derive(Acyclic, Hash, PartialEq, Eq, Debug)]204#[derive(Acyclic, Hash, PartialEq, Eq, Debug)]
191pub struct SourceUrl(Url);205pub struct SourceUrl(Url);
192impl SourceUrl {206impl SourceUrl {
207 /// Wrap a url for [`SourceUrl`]
193 pub fn new(url: Url) -> Self {208 pub fn new(url: Url) -> Self {
194 Self(url)209 Self(url)
195 }210 }
204 false219 false
205 }220 }
206 fn path(&self) -> Option<&Path> {221 fn path(&self) -> Option<&Path> {
222 // TODO: Parse file:?
207 None223 None
208 }224 }
209 any_ext_impl!(SourcePathT);225 any_ext_impl!(SourcePathT);
210}226}
211227
212/// Represents path to the directory on the disk228/// Represents path to the directory on the disk.
213///229///
214/// See also [`SourceFile`]230/// See also [`SourceFile`].
215#[derive(Acyclic, Hash, PartialEq, Eq, Debug)]231#[derive(Acyclic, Hash, PartialEq, Eq, Debug)]
216pub struct SourceDirectory(PathBuf);232pub struct SourceDirectory(PathBuf);
217impl SourceDirectory {233impl SourceDirectory {
234 /// Wrap a path buf pointing to directory for [`SourceDirectory`]
218 pub fn new(path: PathBuf) -> Self {235 pub fn new(path: PathBuf) -> Self {
219 Self(path)236 Self(path)
220 }237 }
238 /// Retrieve a wrapped [`Path`]
221 pub fn path(&self) -> &Path {239 pub fn path(&self) -> &Path {
222 &self.0240 &self.0
223 }241 }
300pub struct Source(pub Rc<(SourcePath, IStr)>);318pub struct Source(pub Rc<(SourcePath, IStr)>);
301319
302impl Source {320impl Source {
321 /// Wrap a source path and source code.
303 pub fn new(path: SourcePath, code: IStr) -> Self {322 pub fn new(path: SourcePath, code: IStr) -> Self {
304 Self(Rc::new((path, code)))323 Self(Rc::new((path, code)))
305 }324 }
306325
326 /// Create a virtual source for the given name and source code.
307 pub fn new_virtual(name: IStr, code: IStr) -> Self {327 pub fn new_virtual(name: IStr, code: IStr) -> Self {
308 Self::new(SourcePath::new(SourceVirtual(name)), code)328 Self::new(SourcePath::new(SourceVirtual(name)), code)
309 }329 }
310330
331 /// Retrieve the stored source code.
311 pub fn code(&self) -> &str {332 pub fn code(&self) -> &str {
312 &self.0.1333 &self.0.1
313 }334 }
314335
336 /// Retrieve the stored file path.
315 pub fn source_path(&self) -> &SourcePath {337 pub fn source_path(&self) -> &SourcePath {
316 &self.0.0338 &self.0.0
317 }339 }
318340
341 /// Convert span locations into line number+column+extra information for diagnostics/lsp.
342 ///
343 /// See [`CodeLocation`].
319 pub fn map_source_locations<const S: usize>(&self, locs: &[u32; S]) -> [CodeLocation; S] {344 pub fn map_source_locations<const S: usize>(&self, locs: &[u32; S]) -> [CodeLocation; S] {
320 offset_to_location(&self.0.1, locs)345 offset_to_location(&self.0.1, locs)
321 }346 }
347 /// Unconvert the line number+column from the representaion used by [`CodeLocation`] to the span offset.
322 pub fn map_from_source_location(&self, line: usize, column: usize) -> Option<usize> {348 pub fn map_from_source_location(&self, line: usize, column: usize) -> Option<usize> {
323 location_to_offset(&self.0.1, line, column)349 location_to_offset(&self.0.1, line, column)
324 }350 }
modifiedcrates/jrsonnet-ir/src/visit.rsdiffbeforeafterboth
1//! Visitor for jrsonnet AST
2//!
3//! Only useful for import analysis for now, if you want to use it for something else -
4//! feel free to submit your PRs for the necessary features.
5
1use jrsonnet_interner::IStr;6use jrsonnet_interner::IStr;
27
modifiedcrates/jrsonnet-peg-parser/src/lib.rsdiffbeforeafterboth
2use jrsonnet_ir::{2use jrsonnet_ir::{
3 ArgsDesc, AssertExpr, AssertStmt, BinaryOp, BindSpec, CompSpec, Destruct, DestructRest, Expr,3 ArgsDesc, AssertExpr, AssertStmt, BinaryOp, BindSpec, CompSpec, Destruct, DestructRest, Expr,
4 ExprParam, ExprParams, FieldMember, FieldName, ForSpecData, IStr, IdentityKind, IfElse,4 ExprParam, ExprParams, FieldMember, FieldName, ForSpecData, IStr, IdentityKind, IfElse,
5 IfSpecData, ImportKind, IndexPart, Member, NumValue, ObjBody, ObjComp, ObjMembers, Slice,5 IfSpecData, ImportKind, IndexPart, NumValue, ObjBody, ObjComp, ObjMembers, Slice, SliceDesc,
6 SliceDesc, Source, Span, Spanned, TrivialVal, Visibility,6 Source, Span, Spanned, TrivialVal, Visibility,
7};7};
8use jrsonnet_lexer::unescape;8use jrsonnet_lexer::unescape;
27 };27 };
28}28}
2929
30enum Member {
31 BindStmt(BindSpec),
32 AssertStmt(AssertStmt),
33 Field(FieldMember),
34}
30parser! {35parser! {
31 pub grammar jsonnet_parser() for str {36 pub grammar jsonnet_parser() for str {
32 use peg::ParseLiteral;37 use peg::ParseLiteral;