we (web engine): Experimental web browser project to understand the limits of Claude
1//! Abstract Syntax Tree node types for ECMAScript 2024.
2
3use crate::lexer::Span;
4
5/// A complete JavaScript program.
6#[derive(Debug, Clone, PartialEq)]
7pub struct Program {
8 pub body: Vec<Stmt>,
9 pub source_type: SourceType,
10 pub span: Span,
11}
12
13/// Whether the program is a script or module.
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum SourceType {
16 Script,
17 Module,
18}
19
20// ── Statements ──────────────────────────────────────────────
21
22/// A statement or declaration.
23#[derive(Debug, Clone, PartialEq)]
24pub struct Stmt {
25 pub kind: StmtKind,
26 pub span: Span,
27}
28
29#[derive(Debug, Clone, PartialEq)]
30pub enum StmtKind {
31 /// Expression followed by semicolon.
32 Expr(Expr),
33 /// `{ ... }`
34 Block(Vec<Stmt>),
35 /// `var`/`let`/`const` declaration.
36 VarDecl {
37 kind: VarKind,
38 declarators: Vec<VarDeclarator>,
39 },
40 /// `function name(...) { ... }`
41 FunctionDecl(FunctionDef),
42 /// `class Name { ... }`
43 ClassDecl(ClassDef),
44 /// `if (test) consequent else alternate`
45 If {
46 test: Expr,
47 consequent: Box<Stmt>,
48 alternate: Option<Box<Stmt>>,
49 },
50 /// `for (init; test; update) body`
51 For {
52 init: Option<ForInit>,
53 test: Option<Expr>,
54 update: Option<Expr>,
55 body: Box<Stmt>,
56 },
57 /// `for (left in right) body`
58 ForIn {
59 left: ForInOfLeft,
60 right: Expr,
61 body: Box<Stmt>,
62 },
63 /// `for (left of right) body`
64 ForOf {
65 left: ForInOfLeft,
66 right: Expr,
67 body: Box<Stmt>,
68 is_await: bool,
69 },
70 /// `while (test) body`
71 While { test: Expr, body: Box<Stmt> },
72 /// `do body while (test)`
73 DoWhile { body: Box<Stmt>, test: Expr },
74 /// `switch (discriminant) { cases }`
75 Switch {
76 discriminant: Expr,
77 cases: Vec<SwitchCase>,
78 },
79 /// `try { block } catch (param) { handler } finally { finalizer }`
80 Try {
81 block: Vec<Stmt>,
82 handler: Option<CatchClause>,
83 finalizer: Option<Vec<Stmt>>,
84 },
85 /// `return expr;`
86 Return(Option<Expr>),
87 /// `throw expr;`
88 Throw(Expr),
89 /// `break label;`
90 Break(Option<String>),
91 /// `continue label;`
92 Continue(Option<String>),
93 /// `label: stmt`
94 Labeled { label: String, body: Box<Stmt> },
95 /// `with (object) body`
96 With { object: Expr, body: Box<Stmt> },
97 /// `debugger;`
98 Debugger,
99 /// `;`
100 Empty,
101 /// `import` declaration.
102 Import {
103 specifiers: Vec<ImportSpecifier>,
104 source: String,
105 },
106 /// `export` declaration.
107 Export(ExportDecl),
108}
109
110// ── Variable declarations ───────────────────────────────────
111
112#[derive(Debug, Clone, Copy, PartialEq, Eq)]
113pub enum VarKind {
114 Var,
115 Let,
116 Const,
117}
118
119#[derive(Debug, Clone, PartialEq)]
120pub struct VarDeclarator {
121 pub pattern: Pattern,
122 pub init: Option<Expr>,
123 pub span: Span,
124}
125
126// ── For-statement helpers ───────────────────────────────────
127
128#[derive(Debug, Clone, PartialEq)]
129pub enum ForInit {
130 VarDecl {
131 kind: VarKind,
132 declarators: Vec<VarDeclarator>,
133 },
134 Expr(Expr),
135}
136
137#[derive(Debug, Clone, PartialEq)]
138pub enum ForInOfLeft {
139 VarDecl { kind: VarKind, pattern: Pattern },
140 Pattern(Pattern),
141}
142
143// ── Switch / Try helpers ────────────────────────────────────
144
145#[derive(Debug, Clone, PartialEq)]
146pub struct SwitchCase {
147 /// `None` for `default:`.
148 pub test: Option<Expr>,
149 pub consequent: Vec<Stmt>,
150 pub span: Span,
151}
152
153#[derive(Debug, Clone, PartialEq)]
154pub struct CatchClause {
155 pub param: Option<Pattern>,
156 pub body: Vec<Stmt>,
157 pub span: Span,
158}
159
160// ── Import / Export ─────────────────────────────────────────
161
162#[derive(Debug, Clone, PartialEq)]
163pub enum ImportSpecifier {
164 /// `import defaultExport from "mod"`
165 Default(String),
166 /// `import { foo } from "mod"` or `import { foo as bar } from "mod"`
167 Named { imported: String, local: String },
168 /// `import * as ns from "mod"`
169 Namespace(String),
170}
171
172#[derive(Debug, Clone, PartialEq)]
173pub enum ExportDecl {
174 /// `export default expr`
175 Default(Expr),
176 /// `export function/class/var ...`
177 Declaration(Box<Stmt>),
178 /// `export { a, b as c }`
179 Named {
180 specifiers: Vec<ExportSpecifier>,
181 source: Option<String>,
182 },
183 /// `export * from "mod"`
184 AllFrom(String),
185}
186
187#[derive(Debug, Clone, PartialEq)]
188pub struct ExportSpecifier {
189 pub local: String,
190 pub exported: String,
191}
192
193// ── Expressions ─────────────────────────────────────────────
194
195#[derive(Debug, Clone, PartialEq)]
196pub struct Expr {
197 pub kind: ExprKind,
198 pub span: Span,
199}
200
201#[derive(Debug, Clone, PartialEq)]
202pub enum ExprKind {
203 /// Numeric literal.
204 Number(f64),
205 /// String literal.
206 String(String),
207 /// `true` / `false`.
208 Bool(bool),
209 /// `null`.
210 Null,
211 /// An identifier reference.
212 Identifier(String),
213 /// `this`.
214 This,
215 /// `[a, b, c]`
216 Array(Vec<Option<ArrayElement>>),
217 /// `{ key: value, ... }`
218 Object(Vec<Property>),
219 /// `function name(...) { ... }` expression.
220 Function(FunctionDef),
221 /// `(...) => body`
222 Arrow {
223 params: Vec<Pattern>,
224 body: ArrowBody,
225 is_async: bool,
226 },
227 /// `class Name { ... }` expression.
228 Class(ClassDef),
229 /// Prefix unary (`!x`, `-x`, `~x`, `typeof x`, `void x`, `delete x`).
230 Unary { op: UnaryOp, argument: Box<Expr> },
231 /// `++x`, `--x`, `x++`, `x--`.
232 Update {
233 op: UpdateOp,
234 argument: Box<Expr>,
235 prefix: bool,
236 },
237 /// `a + b`, `a * b`, etc.
238 Binary {
239 op: BinaryOp,
240 left: Box<Expr>,
241 right: Box<Expr>,
242 },
243 /// `a && b`, `a || b`, `a ?? b`.
244 Logical {
245 op: LogicalOp,
246 left: Box<Expr>,
247 right: Box<Expr>,
248 },
249 /// `a = b`, `a += b`, etc.
250 Assignment {
251 op: AssignOp,
252 left: Box<Expr>,
253 right: Box<Expr>,
254 },
255 /// `test ? consequent : alternate`
256 Conditional {
257 test: Box<Expr>,
258 consequent: Box<Expr>,
259 alternate: Box<Expr>,
260 },
261 /// `callee(arguments)`
262 Call {
263 callee: Box<Expr>,
264 arguments: Vec<Expr>,
265 },
266 /// `new callee(arguments)`
267 New {
268 callee: Box<Expr>,
269 arguments: Vec<Expr>,
270 },
271 /// `object.property` or `object[property]`
272 Member {
273 object: Box<Expr>,
274 property: Box<Expr>,
275 computed: bool,
276 },
277 /// `obj?.prop`, `obj?.[expr]`, `fn?.(args)`
278 OptionalChain { base: Box<Expr> },
279 /// Template literal: `` `hello ${name}` ``
280 TemplateLiteral {
281 quasis: Vec<String>,
282 expressions: Vec<Expr>,
283 },
284 /// Tagged template: `` tag`string` ``
285 TaggedTemplate { tag: Box<Expr>, quasi: Box<Expr> },
286 /// `a, b, c`
287 Sequence(Vec<Expr>),
288 /// `...expr`
289 Spread(Box<Expr>),
290 /// `yield expr` / `yield* expr`
291 Yield {
292 argument: Option<Box<Expr>>,
293 delegate: bool,
294 },
295 /// `await expr`
296 Await(Box<Expr>),
297 /// `/pattern/flags`
298 RegExp { pattern: String, flags: String },
299}
300
301// ── Array element ───────────────────────────────────────────
302
303#[derive(Debug, Clone, PartialEq)]
304pub enum ArrayElement {
305 Expr(Expr),
306 Spread(Expr),
307}
308
309// ── Object literal ──────────────────────────────────────────
310
311#[derive(Debug, Clone, PartialEq)]
312pub struct Property {
313 pub key: PropertyKey,
314 pub value: Option<Expr>,
315 pub kind: PropertyKind,
316 pub computed: bool,
317 pub shorthand: bool,
318 pub method: bool,
319 pub span: Span,
320}
321
322#[derive(Debug, Clone, PartialEq)]
323pub enum PropertyKey {
324 Identifier(String),
325 String(String),
326 Number(f64),
327 Computed(Expr),
328}
329
330#[derive(Debug, Clone, Copy, PartialEq, Eq)]
331pub enum PropertyKind {
332 Init,
333 Get,
334 Set,
335}
336
337// ── Arrow function body ─────────────────────────────────────
338
339#[derive(Debug, Clone, PartialEq)]
340pub enum ArrowBody {
341 Expr(Box<Expr>),
342 Block(Vec<Stmt>),
343}
344
345// ── Function definition ─────────────────────────────────────
346
347#[derive(Debug, Clone, PartialEq)]
348pub struct FunctionDef {
349 pub id: Option<String>,
350 pub params: Vec<Pattern>,
351 pub body: Vec<Stmt>,
352 pub is_async: bool,
353 pub is_generator: bool,
354}
355
356// ── Class definition ────────────────────────────────────────
357
358#[derive(Debug, Clone, PartialEq)]
359pub struct ClassDef {
360 pub id: Option<String>,
361 pub super_class: Option<Box<Expr>>,
362 pub body: Vec<ClassMember>,
363}
364
365#[derive(Debug, Clone, PartialEq)]
366pub struct ClassMember {
367 pub kind: ClassMemberKind,
368 pub span: Span,
369}
370
371#[derive(Debug, Clone, PartialEq)]
372pub enum ClassMemberKind {
373 Method {
374 key: PropertyKey,
375 value: FunctionDef,
376 kind: MethodKind,
377 is_static: bool,
378 computed: bool,
379 },
380 Property {
381 key: PropertyKey,
382 value: Option<Expr>,
383 is_static: bool,
384 computed: bool,
385 },
386}
387
388#[derive(Debug, Clone, Copy, PartialEq, Eq)]
389pub enum MethodKind {
390 Method,
391 Get,
392 Set,
393 Constructor,
394}
395
396// ── Patterns (destructuring) ────────────────────────────────
397
398#[derive(Debug, Clone, PartialEq)]
399pub struct Pattern {
400 pub kind: PatternKind,
401 pub span: Span,
402}
403
404#[derive(Debug, Clone, PartialEq)]
405pub enum PatternKind {
406 /// Simple binding: `x`
407 Identifier(String),
408 /// Array destructuring: `[a, b, ...rest]`
409 Array {
410 elements: Vec<Option<Pattern>>,
411 rest: Option<Box<Pattern>>,
412 },
413 /// Object destructuring: `{ a, b: c, ...rest }`
414 Object {
415 properties: Vec<ObjectPatternProp>,
416 rest: Option<Box<Pattern>>,
417 },
418 /// Default value: `x = defaultValue`
419 Assign {
420 left: Box<Pattern>,
421 right: Box<Expr>,
422 },
423}
424
425#[derive(Debug, Clone, PartialEq)]
426pub struct ObjectPatternProp {
427 pub key: PropertyKey,
428 pub value: Pattern,
429 pub computed: bool,
430 pub shorthand: bool,
431 pub span: Span,
432}
433
434// ── Operators ───────────────────────────────────────────────
435
436#[derive(Debug, Clone, Copy, PartialEq, Eq)]
437pub enum UnaryOp {
438 Minus,
439 Plus,
440 Not,
441 BitwiseNot,
442 Typeof,
443 Void,
444 Delete,
445}
446
447#[derive(Debug, Clone, Copy, PartialEq, Eq)]
448pub enum UpdateOp {
449 Increment,
450 Decrement,
451}
452
453#[derive(Debug, Clone, Copy, PartialEq, Eq)]
454pub enum BinaryOp {
455 Add,
456 Sub,
457 Mul,
458 Div,
459 Rem,
460 Exp,
461 Eq,
462 Ne,
463 StrictEq,
464 StrictNe,
465 Lt,
466 Le,
467 Gt,
468 Ge,
469 Shl,
470 Shr,
471 Ushr,
472 BitAnd,
473 BitOr,
474 BitXor,
475 In,
476 Instanceof,
477}
478
479#[derive(Debug, Clone, Copy, PartialEq, Eq)]
480pub enum LogicalOp {
481 And,
482 Or,
483 Nullish,
484}
485
486#[derive(Debug, Clone, Copy, PartialEq, Eq)]
487pub enum AssignOp {
488 Assign,
489 AddAssign,
490 SubAssign,
491 MulAssign,
492 DivAssign,
493 RemAssign,
494 ExpAssign,
495 ShlAssign,
496 ShrAssign,
497 UshrAssign,
498 BitAndAssign,
499 BitOrAssign,
500 BitXorAssign,
501 AndAssign,
502 OrAssign,
503 NullishAssign,
504}