Skip to main content

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        plus: bool,
83        body: &'ast Expr<'p, 'ast>,
84        locals2: &'ast [ObjLocal<'p, 'ast>],
85        comp_spec: &'ast [CompSpecPart<'p, 'ast>],
86    },
87}
88
89#[derive(Copy, Clone, Debug, PartialEq, Eq)]
90pub enum Member<'p, 'ast> {
91    Local(ObjLocal<'p, 'ast>),
92    Assert(Assert<'p, 'ast>),
93    Field(Field<'p, 'ast>),
94}
95
96#[derive(Copy, Clone, Debug, PartialEq, Eq)]
97pub enum Field<'p, 'ast> {
98    Value(FieldName<'p, 'ast>, bool, Visibility, Expr<'p, 'ast>),
99    Func(
100        FieldName<'p, 'ast>,
101        &'ast [Param<'p, 'ast>],
102        SpanId,
103        Visibility,
104        Expr<'p, 'ast>,
105    ),
106}
107
108impl<'p, 'ast> Field<'p, 'ast> {
109    #[inline]
110    pub fn name(&self) -> &FieldName<'p, 'ast> {
111        match self {
112            Self::Value(name, ..) => name,
113            Self::Func(name, ..) => name,
114        }
115    }
116}
117
118#[derive(Copy, Clone, Debug, PartialEq, Eq)]
119pub enum Visibility {
120    Default,
121    Hidden,
122    ForceVisible,
123}
124
125#[derive(Copy, Clone, Debug, PartialEq, Eq)]
126pub struct ObjLocal<'p, 'ast> {
127    pub bind: Bind<'p, 'ast>,
128}
129
130#[derive(Copy, Clone, Debug, PartialEq, Eq)]
131pub enum CompSpecPart<'p, 'ast> {
132    For(ForSpec<'p, 'ast>),
133    If(IfSpec<'p, 'ast>),
134}
135
136#[derive(Copy, Clone, Debug, PartialEq, Eq)]
137pub struct ForSpec<'p, 'ast> {
138    pub var: Ident<'p>,
139    pub inner: Expr<'p, 'ast>,
140}
141
142#[derive(Copy, Clone, Debug, PartialEq, Eq)]
143pub struct IfSpec<'p, 'ast> {
144    pub cond: Expr<'p, 'ast>,
145}
146
147#[derive(Copy, Clone, Debug, PartialEq, Eq)]
148pub enum FieldName<'p, 'ast> {
149    Ident(Ident<'p>),
150    String(InternedStr<'p>, SpanId),
151    Expr(Expr<'p, 'ast>, SpanId),
152}
153
154#[derive(Copy, Clone, Debug, PartialEq, Eq)]
155pub struct Assert<'p, 'ast> {
156    pub span: SpanId,
157    pub cond: Expr<'p, 'ast>,
158    pub msg: Option<Expr<'p, 'ast>>,
159}
160
161#[derive(Copy, Clone, Debug, PartialEq, Eq)]
162pub struct Bind<'p, 'ast> {
163    pub name: Ident<'p>,
164    pub params: Option<(&'ast [Param<'p, 'ast>], SpanId)>,
165    pub value: Expr<'p, 'ast>,
166}
167
168#[derive(Copy, Clone, Debug, PartialEq, Eq)]
169pub enum Arg<'p, 'ast> {
170    Positional(Expr<'p, 'ast>),
171    Named(Ident<'p>, Expr<'p, 'ast>),
172}
173
174#[derive(Copy, Clone, Debug, PartialEq, Eq)]
175pub struct Param<'p, 'ast> {
176    pub name: Ident<'p>,
177    pub default_value: Option<Expr<'p, 'ast>>,
178}
179
180#[derive(Copy, Clone, Debug, PartialEq, Eq)]
181pub enum BinaryOp {
182    Add,
183    Sub,
184    Mul,
185    Div,
186    Rem,
187    Shl,
188    Shr,
189    Lt,
190    Le,
191    Gt,
192    Ge,
193    Eq,
194    Ne,
195    In,
196    BitwiseAnd,
197    BitwiseOr,
198    BitwiseXor,
199    LogicAnd,
200    LogicOr,
201}
202
203#[derive(Copy, Clone, Debug, PartialEq, Eq)]
204pub enum UnaryOp {
205    Minus,
206    Plus,
207    BitwiseNot,
208    LogicNot,
209}