rsjsonnet_lang/
ast.rs

1//! The abstract syntax tree (AST) of Jsonnet code.
2//!
3//! Since Jsonnet is a purely functional language, it is composed mainly of
4//! expressions. See [`Expr`] and [`ExprKind`] as starting point.
5//!
6//! # Lifetimes
7//!
8//! AST structures in this module are intended to be allocated with arena
9//! allocation. Two lifetime are used:
10//!
11//! * `'p`, which represents interned strings.
12//! * `'ast`, which represents most allocations of AST nodes.
13//!
14//! Independent arenas can be used for each lifetime, allowing to free most of
15//! an AST while keeping interned strings.
16
17use crate::interner::InternedStr;
18use crate::span::SpanId;
19use crate::token::Number;
20
21#[derive(Copy, Clone, Debug, PartialEq, Eq)]
22pub struct Ident<'p> {
23    pub value: InternedStr<'p>,
24    pub span: SpanId,
25}
26
27#[derive(Copy, Clone, Debug, PartialEq, Eq)]
28pub struct Expr<'p, 'ast> {
29    pub kind: ExprKind<'p, 'ast>,
30    pub span: SpanId,
31}
32
33#[derive(Copy, Clone, Debug, PartialEq, Eq)]
34pub enum ExprKind<'p, 'ast> {
35    Null,
36    Bool(bool),
37    SelfObj,
38    Dollar,
39    String(&'ast str),
40    TextBlock(&'ast str),
41    Number(Number<'ast>),
42    Paren(&'ast Expr<'p, 'ast>),
43    Object(ObjInside<'p, 'ast>),
44    Array(&'ast [Expr<'p, 'ast>]),
45    ArrayComp(&'ast Expr<'p, 'ast>, &'ast [CompSpecPart<'p, 'ast>]),
46    Field(&'ast Expr<'p, 'ast>, Ident<'p>),
47    Index(&'ast Expr<'p, 'ast>, &'ast Expr<'p, 'ast>),
48    Slice(
49        &'ast Expr<'p, 'ast>,
50        Option<&'ast Expr<'p, 'ast>>,
51        Option<&'ast Expr<'p, 'ast>>,
52        Option<&'ast Expr<'p, 'ast>>,
53    ),
54    SuperField(SpanId, Ident<'p>),
55    SuperIndex(SpanId, &'ast Expr<'p, 'ast>),
56    Call(&'ast Expr<'p, 'ast>, &'ast [Arg<'p, 'ast>], bool),
57    Ident(Ident<'p>),
58    Local(&'ast [Bind<'p, 'ast>], &'ast Expr<'p, 'ast>),
59    If(
60        &'ast Expr<'p, 'ast>,
61        &'ast Expr<'p, 'ast>,
62        Option<&'ast Expr<'p, 'ast>>,
63    ),
64    Binary(&'ast Expr<'p, 'ast>, BinaryOp, &'ast Expr<'p, 'ast>),
65    Unary(UnaryOp, &'ast Expr<'p, 'ast>),
66    ObjExt(&'ast Expr<'p, 'ast>, ObjInside<'p, 'ast>, SpanId),
67    Func(&'ast [Param<'p, 'ast>], &'ast Expr<'p, 'ast>),
68    Assert(&'ast Assert<'p, 'ast>, &'ast Expr<'p, 'ast>),
69    Import(&'ast Expr<'p, 'ast>),
70    ImportStr(&'ast Expr<'p, 'ast>),
71    ImportBin(&'ast Expr<'p, 'ast>),
72    Error(&'ast Expr<'p, 'ast>),
73    InSuper(&'ast Expr<'p, 'ast>, SpanId),
74}
75
76#[derive(Copy, Clone, Debug, PartialEq, Eq)]
77pub enum ObjInside<'p, 'ast> {
78    Members(&'ast [Member<'p, 'ast>]),
79    Comp {
80        locals1: &'ast [ObjLocal<'p, 'ast>],
81        name: &'ast Expr<'p, 'ast>,
82        body: &'ast Expr<'p, 'ast>,
83        locals2: &'ast [ObjLocal<'p, 'ast>],
84        comp_spec: &'ast [CompSpecPart<'p, 'ast>],
85    },
86}
87
88#[derive(Copy, Clone, Debug, PartialEq, Eq)]
89pub enum Member<'p, 'ast> {
90    Local(ObjLocal<'p, 'ast>),
91    Assert(Assert<'p, 'ast>),
92    Field(Field<'p, 'ast>),
93}
94
95#[derive(Copy, Clone, Debug, PartialEq, Eq)]
96pub enum Field<'p, 'ast> {
97    Value(FieldName<'p, 'ast>, bool, Visibility, Expr<'p, 'ast>),
98    Func(
99        FieldName<'p, 'ast>,
100        &'ast [Param<'p, 'ast>],
101        SpanId,
102        Visibility,
103        Expr<'p, 'ast>,
104    ),
105}
106
107impl<'p, 'ast> Field<'p, 'ast> {
108    #[inline]
109    pub fn name(&self) -> &FieldName<'p, 'ast> {
110        match self {
111            Self::Value(name, ..) => name,
112            Self::Func(name, ..) => name,
113        }
114    }
115}
116
117#[derive(Copy, Clone, Debug, PartialEq, Eq)]
118pub enum Visibility {
119    Default,
120    Hidden,
121    ForceVisible,
122}
123
124#[derive(Copy, Clone, Debug, PartialEq, Eq)]
125pub struct ObjLocal<'p, 'ast> {
126    pub bind: Bind<'p, 'ast>,
127}
128
129#[derive(Copy, Clone, Debug, PartialEq, Eq)]
130pub enum CompSpecPart<'p, 'ast> {
131    For(ForSpec<'p, 'ast>),
132    If(IfSpec<'p, 'ast>),
133}
134
135#[derive(Copy, Clone, Debug, PartialEq, Eq)]
136pub struct ForSpec<'p, 'ast> {
137    pub var: Ident<'p>,
138    pub inner: Expr<'p, 'ast>,
139}
140
141#[derive(Copy, Clone, Debug, PartialEq, Eq)]
142pub struct IfSpec<'p, 'ast> {
143    pub cond: Expr<'p, 'ast>,
144}
145
146#[derive(Copy, Clone, Debug, PartialEq, Eq)]
147pub enum FieldName<'p, 'ast> {
148    Ident(Ident<'p>),
149    String(InternedStr<'p>, SpanId),
150    Expr(Expr<'p, 'ast>, SpanId),
151}
152
153#[derive(Copy, Clone, Debug, PartialEq, Eq)]
154pub struct Assert<'p, 'ast> {
155    pub span: SpanId,
156    pub cond: Expr<'p, 'ast>,
157    pub msg: Option<Expr<'p, 'ast>>,
158}
159
160#[derive(Copy, Clone, Debug, PartialEq, Eq)]
161pub struct Bind<'p, 'ast> {
162    pub name: Ident<'p>,
163    pub params: Option<(&'ast [Param<'p, 'ast>], SpanId)>,
164    pub value: Expr<'p, 'ast>,
165}
166
167#[derive(Copy, Clone, Debug, PartialEq, Eq)]
168pub enum Arg<'p, 'ast> {
169    Positional(Expr<'p, 'ast>),
170    Named(Ident<'p>, Expr<'p, 'ast>),
171}
172
173#[derive(Copy, Clone, Debug, PartialEq, Eq)]
174pub struct Param<'p, 'ast> {
175    pub name: Ident<'p>,
176    pub default_value: Option<Expr<'p, 'ast>>,
177}
178
179#[derive(Copy, Clone, Debug, PartialEq, Eq)]
180pub enum BinaryOp {
181    Add,
182    Sub,
183    Mul,
184    Div,
185    Rem,
186    Shl,
187    Shr,
188    Lt,
189    Le,
190    Gt,
191    Ge,
192    Eq,
193    Ne,
194    In,
195    BitwiseAnd,
196    BitwiseOr,
197    BitwiseXor,
198    LogicAnd,
199    LogicOr,
200}
201
202#[derive(Copy, Clone, Debug, PartialEq, Eq)]
203pub enum UnaryOp {
204    Minus,
205    Plus,
206    BitwiseNot,
207    LogicNot,
208}