diff options
Diffstat (limited to 'src/js_ast.zig')
-rw-r--r-- | src/js_ast.zig | 153 |
1 files changed, 117 insertions, 36 deletions
diff --git a/src/js_ast.zig b/src/js_ast.zig index a5894e6fa..0601b3dd8 100644 --- a/src/js_ast.zig +++ b/src/js_ast.zig @@ -6,6 +6,10 @@ usingnamespace @import("ast/base.zig"); const ImportRecord = @import("import_record.zig").ImportRecord; +pub const BindingNodeIndex = NodeIndex; +pub const StmtNodeIndex = NodeIndex; +pub const ExprNodeIndex = NodeIndex; + // TODO: figure out if we actually need this // -- original comment -- // Files are parsed in parallel for speed. We want to allow each parser to @@ -38,27 +42,6 @@ pub const ImportItemStatus = enum(u8) { pub const LocRef = struct { loc: logger.Loc, ref: ?Ref }; -pub const FnBody = struct { - loc: logger.Loc, - stmts: []StmtNodeIndex, -}; - -pub const Fn = struct { - name: ?LocRef, - open_parens_loc: logger.Loc, - args: []Arg, - body: FnBody, - arguments_ref: ?Ref, - - is_async: bool = false, - is_generator: bool = false, - has_rest_arg: bool = false, - has_if_scope: bool = false, - - // This is true if the function is a method - is_unique_formal_parameters: bool = false, -}; - pub const Binding = struct { data: B, }; @@ -106,15 +89,6 @@ pub const B = union(enum) { pub const Missing = struct {}; }; -pub const Arg = struct { - ts_decorators: ?[]Expr = null, - binding: Binding, - default: ?Expr = null, - - // "constructor(public x: boolean) {}" - is_typescript_ctor_field: bool = false, -}; - pub const ClauseItem = struct { alias: string, alias_loc: logger.Loc, @@ -159,7 +133,7 @@ pub const G = struct { key: ExprNodeIndex, // This is omitted for class fields - value: ?Expr, + value: ?ExprNodeIndex = null, // This is used when parsing a pattern that uses default values: // @@ -177,6 +151,36 @@ pub const G = struct { is_static: bool = false, was_shorthand: bool = false, }; + + pub const FnBody = struct { + loc: logger.Loc, + stmts: []StmtNodeIndex, + }; + + pub const Fn = struct { + name: ?LocRef, + open_parens_loc: logger.Loc, + args: ?[]Arg = null, + body: ?FnBody = null, + arguments_ref: ?Ref, + + is_async: bool = false, + is_generator: bool = false, + has_rest_arg: bool = false, + has_if_scope: bool = false, + + // This is true if the function is a method + is_unique_formal_parameters: bool = false, + }; + + pub const Arg = struct { + ts_decorators: ?[]ExprNodeIndex = null, + binding: BindingNodeIndex, + default: ?ExprNodeIndex = null, + + // "constructor(public x: boolean) {}" + is_typescript_ctor_field: bool = false, + }; }; pub const Symbol = struct { @@ -533,8 +537,8 @@ pub const E = struct { }; pub const Arrow = struct { - args: []Arg, - body: FnBody, + args: []G.Arg, + body: G.FnBody, is_async: bool = false, has_rest_arg: bool = false, @@ -1023,7 +1027,7 @@ pub const S = struct { }; pub const Function = struct { - func: Fn, + func: G.Fn, is_export: bool, }; @@ -1395,6 +1399,81 @@ pub const Dependency = struct { part_index: u32 = 0, }; +pub const ExprList = std.ArrayList(Expr); +pub const StmtList = std.ArrayList(Stmt); +pub const BindingList = std.ArrayList(Binding); +pub const AstData = struct { + expr_list: ExprList, + stmt_list: StmtList, + binding_list: BindingList, + + pub fn init(allocator: *std.mem.Allocator) AstData { + return AstData{ + .expr_list = ExprList.init(allocator), + .stmt_list = StmtList.init(allocator), + .binding_list = BindingList.init(allocator), + }; + } + + pub fn deinit(self: *AstData) void { + self.expr_list.deinit(); + self.stmt_list.deinit(); + self.binding_list.deinit(); + } + + pub fn expr(self: *AstData, index: ExprNodeIndex) Expr { + return self.expr_list.items[index]; + } + + pub fn stmt(self: *AstData, index: StmtNodeIndex) Stmt { + return self.stmt_list.items[index]; + } + + pub fn binding(self: *AstData, index: BindingNodeIndex) Binding { + return self.binding_list.items[index]; + } + + pub fn add_(self: *AstData, t: anytype) !void { + return switch (@TypeOf(t)) { + Stmt => { + try self.stmt_list.append(t); + }, + Expr => { + try self.expr_list.append(t); + }, + Binding => { + try self.binding_list.append(t); + }, + else => { + @compileError("Invalid type passed to AstData.add. Expected Stmt, Expr, or Binding."); + }, + }; + } + + pub fn add(self: *AstData, t: anytype) !NodeIndex { + return switch (@TypeOf(t)) { + Stmt => { + var len = self.stmt_list.items.len; + try self.stmt_list.append(t); + return @intCast(StmtNodeIndex, len); + }, + Expr => { + var len = self.expr_list.items.len; + try self.expr_list.append(t); + return @intCast(ExprNodeIndex, len); + }, + Binding => { + var len = self.binding_list.items.len; + try self.binding_list.append(t); + return @intCast(BindingNodeIndex, len); + }, + else => { + @compileError("Invalid type passed to AstData.add. Expected Stmt, Expr, or Binding."); + }, + }; + } +}; + // Each file is made up of multiple parts, and each part consists of one or // more top-level statements. Parts are used for tree shaking and code // splitting analysis. Individual parts of a file can be discarded by tree @@ -1403,6 +1482,7 @@ pub const Dependency = struct { pub const Part = struct { stmts: []Stmt, expr: []Expr, + bindings: []Binding, scopes: []*Scope, // Each is an index into the file-level import record list @@ -1502,7 +1582,7 @@ pub const StrictModeKind = enum { pub const Scope = struct { kind: Kind = Kind.block, parent: ?*Scope, - children: []*Scope, + children: std.ArrayList(*Scope), members: std.StringHashMap(Member), generated: ?[]Ref = null, @@ -1537,7 +1617,7 @@ pub const Scope = struct { pub fn recursiveSetStrictMode(s: *Scope, kind: StrictModeKind) void { if (s.strict_mode == .sloppy_mode) { s.strict_mode = kind; - for (s.children) |child| { + for (s.children.items) |child| { child.recursiveSetStrictMode(kind); } } @@ -1557,3 +1637,4 @@ pub const Scope = struct { // test "ast" { // const ast = Ast{}; // } + |