aboutsummaryrefslogtreecommitdiff
path: root/src/js_ast.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/js_ast.zig')
-rw-r--r--src/js_ast.zig679
1 files changed, 414 insertions, 265 deletions
diff --git a/src/js_ast.zig b/src/js_ast.zig
index 701abd474..5b3f1a7c1 100644
--- a/src/js_ast.zig
+++ b/src/js_ast.zig
@@ -12,132 +12,6 @@ const _hash_map = @import("hash_map.zig");
const StringHashMap = _hash_map.StringHashMap;
const AutoHashMap = _hash_map.AutoHashMap;
-pub fn NewBaseStore(comptime Union: anytype, count: usize) type {
- var max_size: usize = 0;
- var max_align: usize = 1;
- for (Union) |kind| {
- max_size = std.math.max(@sizeOf(kind), max_size);
- max_align = if (@sizeOf(kind) == 0) max_align else std.math.max(@alignOf(kind), max_align);
- }
-
- max_size = std.mem.alignForward(max_size, max_align);
- const element_size = max_size;
- const total_byte_count = count * max_size;
-
- return struct {
- const Self = @This();
- const OverflowList = std.ArrayListUnmanaged(u8);
- pub threadlocal var byte_buffer: [total_byte_count]u8 align(max_align) = undefined;
- pub threadlocal var bytes_used: usize = undefined;
- pub threadlocal var bytes_element_count: usize = undefined;
- pub threadlocal var instance: Self = undefined;
- pub threadlocal var self: *Self = undefined;
- pub threadlocal var has_loaded: bool = false;
- allocator: *std.mem.Allocator,
- overflow_list: []u8,
- overflow_list_ptr: [*]u8 = undefined,
- overflow_list_ptr_len: usize = 0,
- overflow_element_count: usize = 0,
-
- pub fn init(allocator: *std.mem.Allocator) *Self {
- if (has_loaded) {
- return self;
- }
-
- instance = Self{
- .allocator = allocator,
- .overflow_list = &([_]u8{}),
- };
- bytes_used = 0;
- bytes_element_count = 0;
- self = &instance;
- has_loaded = true;
- return self;
- }
-
- pub fn reset() void {
- std.debug.assert(has_loaded);
- self.overflow_list = &([_]u8{});
- self.overflow_element_count = 0;
- bytes_used = 0;
- bytes_element_count = 0;
- }
-
- pub fn growOverflowListIfNeeded(store: *Self, to: usize) void {
- if (store.overflow_list_ptr_len >= to) {
- return;
- }
-
- const is_new = store.overflow_list_ptr_len == 0;
- store.overflow_list_ptr_len = to + (max_size * 100);
-
- if (!is_new) {
- _ = store.allocator.resize(store.overflow_list_ptr[0..store.overflow_list_ptr_len], store.overflow_list_ptr_len) catch unreachable;
- } else {
- store.overflow_list_ptr = (store.allocator.alloc(u8, store.overflow_list_ptr_len) catch unreachable).ptr;
- }
- }
-
- pub fn append(comptime ValueType: type, value: ValueType) ListIndex {
- std.debug.assert(has_loaded);
-
- if (bytes_used < max_size - 1) {
- const index = bytes_element_count;
- const offset = bytes_used;
- bytes_element_count += 1;
- bytes_used += max_size;
- std.mem.copy(u8, byte_buffer[offset..bytes_used], std.mem.asBytes(&value));
- return ListIndex{ .is_overflowing = false, .index = @intCast(u31, index) };
- } else {
- const index = self.overflow_element_count;
- const offset = self.overflow_list.len;
- self.overflow_element_count += 1;
- const end_length = offset + max_size;
- self.growOverflowListIfNeeded(end_length);
- std.mem.copy(u8, self.overflow_list_ptr[offset..end_length], std.mem.asBytes(&value));
- self.overflow_list = self.overflow_list_ptr[0..end_length];
- return ListIndex{ .is_overflowing = true, .index = @intCast(u31, index) };
- }
- }
-
- pub fn at(index: ListIndex, comptime ValueType: type) *ValueType {
- std.debug.assert(index.index != allocators.NotFound.index and index.index != allocators.Unassigned.index);
- @setRuntimeSafety(false);
-
- const slice_begin = index.index * element_size;
- const slice_end = slice_begin + element_size;
-
- var slice: []u8 = undefined;
- if (index.is_overflowing) {
- slice = self.overflow_list_ptr[slice_begin..slice_end];
- @setRuntimeSafety(false);
- } else {
- slice = byte_buffer[slice_begin..];
- @setRuntimeSafety(false);
- }
-
- var aligned_slice = @alignCast(@alignOf(ValueType), slice.ptr);
-
- return @ptrCast(
- *ValueType,
- aligned_slice,
- );
- }
- };
-}
-
-pub fn NewStore(comptime BaseStore: type, comptime ValueType: type) type {
- return struct {
- pub fn at(index: ListIndex) *ValueType {
- return BaseStore.at(index, ValueType);
- }
-
- pub fn append(value: ValueType) ListIndex {
- return BaseStore.append(ValueType, value);
- }
- };
-}
-
pub const ListIndex = packed struct {
index: u31,
is_overflowing: bool = false,
@@ -323,9 +197,7 @@ pub const Binding = struct {
b_missing,
};
- pub var binding_count: usize = 0;
pub fn init(t: anytype, loc: logger.Loc) Binding {
- binding_count += 1;
switch (@TypeOf(t)) {
*B.Identifier => {
return Binding{ .loc = loc, .data = B{ .b_identifier = t } };
@@ -349,7 +221,6 @@ pub const Binding = struct {
}
pub fn alloc(allocator: *std.mem.Allocator, t: anytype, loc: logger.Loc) Binding {
- binding_count += 1;
switch (@TypeOf(t)) {
B.Identifier => {
var data = allocator.create(B.Identifier) catch unreachable;
@@ -819,7 +690,7 @@ pub const E = struct {
op: Op.Code,
};
- pub const Boolean = struct { value: bool };
+ pub const Boolean = packed struct { value: bool };
pub const Super = struct {};
pub const Null = struct {};
pub const This = struct {};
@@ -906,7 +777,7 @@ pub const E = struct {
pub const Function = struct { func: G.Fn };
- pub const Identifier = struct {
+ pub const Identifier = packed struct {
ref: Ref = Ref.None,
// If we're inside a "with" statement, this identifier may be a property
@@ -1588,8 +1459,10 @@ pub const Stmt = struct {
s_class: ListIndex,
s_comment: ListIndex,
s_continue: ListIndex,
+ s_debugger: S.Debugger,
s_directive: ListIndex,
s_do_while: ListIndex,
+ s_empty: S.Empty, // special case, its a zero value type
s_enum: ListIndex,
s_export_clause: ListIndex,
s_export_default: ListIndex,
@@ -1611,85 +1484,113 @@ pub const Stmt = struct {
s_switch: ListIndex,
s_throw: ListIndex,
s_try: ListIndex,
+ s_type_script: S.TypeScript,
s_while: ListIndex,
s_with: ListIndex,
- s_type_script: S.TypeScript,
- s_empty: S.Empty, // special case, its a zero value type
- s_debugger: S.Debugger,
-
pub const Store = struct {
- const Union = [_]type{
- S.Block,
- S.Break,
- S.Class,
- S.Comment,
- S.Continue,
- S.Directive,
- S.DoWhile,
- S.Enum,
- S.ExportClause,
- S.ExportDefault,
- S.ExportEquals,
- S.ExportFrom,
- S.ExportStar,
- S.SExpr,
- S.ForIn,
- S.ForOf,
- S.For,
- S.Function,
- S.If,
- S.Import,
- S.Label,
- S.LazyExport,
- S.Local,
- S.Namespace,
- S.Return,
- S.Switch,
- S.Throw,
- S.Try,
- S.While,
- S.With,
- };
- pub const BaseStore = NewBaseStore(&Union, 512);
- pub const Block = NewStore(BaseStore, S.Block);
- pub const Break = NewStore(BaseStore, S.Break);
- pub const Class = NewStore(BaseStore, S.Class);
- pub const Comment = NewStore(BaseStore, S.Comment);
- pub const Continue = NewStore(BaseStore, S.Continue);
- pub const Directive = NewStore(BaseStore, S.Directive);
- pub const DoWhile = NewStore(BaseStore, S.DoWhile);
- pub const Enum = NewStore(BaseStore, S.Enum);
- pub const ExportClause = NewStore(BaseStore, S.ExportClause);
- pub const ExportDefault = NewStore(BaseStore, S.ExportDefault);
- pub const ExportEquals = NewStore(BaseStore, S.ExportEquals);
- pub const ExportFrom = NewStore(BaseStore, S.ExportFrom);
- pub const ExportStar = NewStore(BaseStore, S.ExportStar);
- pub const SExpr = NewStore(BaseStore, S.SExpr);
- pub const ForIn = NewStore(BaseStore, S.ForIn);
- pub const ForOf = NewStore(BaseStore, S.ForOf);
- pub const For = NewStore(BaseStore, S.For);
- pub const Function = NewStore(BaseStore, S.Function);
- pub const If = NewStore(BaseStore, S.If);
- pub const Import = NewStore(BaseStore, S.Import);
- pub const Label = NewStore(BaseStore, S.Label);
- pub const LazyExport = NewStore(BaseStore, S.LazyExport);
- pub const Local = NewStore(BaseStore, S.Local);
- pub const Namespace = NewStore(BaseStore, S.Namespace);
- pub const Return = NewStore(BaseStore, S.Return);
- pub const Switch = NewStore(BaseStore, S.Switch);
- pub const Throw = NewStore(BaseStore, S.Throw);
- pub const Try = NewStore(BaseStore, S.Try);
- pub const While = NewStore(BaseStore, S.While);
- pub const With = NewStore(BaseStore, S.With);
+ pub const Block = NewStore(S.Block);
+ pub const Break = NewStore(S.Break);
+ pub const Class = NewStore(S.Class);
+ pub const Comment = NewStore(S.Comment);
+ pub const Continue = NewStore(S.Continue);
+ pub const Directive = NewStore(S.Directive);
+ pub const DoWhile = NewStore(S.DoWhile);
+ pub const Enum = NewStore(S.Enum);
+ pub const ExportClause = NewStore(S.ExportClause);
+ pub const ExportDefault = NewStore(S.ExportDefault);
+ pub const ExportEquals = NewStore(S.ExportEquals);
+ pub const ExportFrom = NewStore(S.ExportFrom);
+ pub const ExportStar = NewStore(S.ExportStar);
+ pub const SExpr = NewStore(S.SExpr);
+ pub const ForIn = NewStore(S.ForIn);
+ pub const ForOf = NewStore(S.ForOf);
+ pub const For = NewStore(S.For);
+ pub const Function = NewStore(S.Function);
+ pub const If = NewStore(S.If);
+ pub const Import = NewStore(S.Import);
+ pub const Label = NewStore(S.Label);
+ pub const LazyExport = NewStore(S.LazyExport);
+ pub const Local = NewStore(S.Local);
+ pub const Namespace = NewStore(S.Namespace);
+ pub const Return = NewStore(S.Return);
+ pub const Switch = NewStore(S.Switch);
+ pub const Throw = NewStore(S.Throw);
+ pub const Try = NewStore(S.Try);
+ pub const TypeScript = NewStore(S.TypeScript);
+ pub const While = NewStore(S.While);
+ pub const With = NewStore(S.With);
threadlocal var has_inited = false;
pub fn create(allocator: *std.mem.Allocator) void {
- _ = BaseStore.init(allocator);
+ if (has_inited) {
+ return;
+ }
+
+ has_inited = true;
+ _ = Block.init(allocator);
+ _ = Break.init(allocator);
+ _ = Class.init(allocator);
+ _ = Comment.init(allocator);
+ _ = Continue.init(allocator);
+ _ = Directive.init(allocator);
+ _ = DoWhile.init(allocator);
+ _ = Enum.init(allocator);
+ _ = ExportClause.init(allocator);
+ _ = ExportDefault.init(allocator);
+ _ = ExportEquals.init(allocator);
+ _ = ExportFrom.init(allocator);
+ _ = ExportStar.init(allocator);
+ _ = SExpr.init(allocator);
+ _ = ForIn.init(allocator);
+ _ = ForOf.init(allocator);
+ _ = For.init(allocator);
+ _ = Function.init(allocator);
+ _ = If.init(allocator);
+ _ = Import.init(allocator);
+ _ = Label.init(allocator);
+ _ = LazyExport.init(allocator);
+ _ = Local.init(allocator);
+ _ = Namespace.init(allocator);
+ _ = Return.init(allocator);
+ _ = Switch.init(allocator);
+ _ = Throw.init(allocator);
+ _ = Try.init(allocator);
+ _ = While.init(allocator);
+ _ = With.init(allocator);
}
pub fn reset() void {
- BaseStore.reset();
+ Block.reset();
+ Break.reset();
+ Class.reset();
+ Comment.reset();
+ Continue.reset();
+ Directive.reset();
+ DoWhile.reset();
+ Enum.reset();
+ ExportClause.reset();
+ ExportDefault.reset();
+ ExportEquals.reset();
+ ExportFrom.reset();
+ ExportStar.reset();
+ SExpr.reset();
+ ForIn.reset();
+ ForOf.reset();
+ For.reset();
+ Function.reset();
+ If.reset();
+ Import.reset();
+ Label.reset();
+ LazyExport.reset();
+ Local.reset();
+ Namespace.reset();
+ Return.reset();
+ Switch.reset();
+ Throw.reset();
+ Try.reset();
+ While.reset();
+ With.reset();
}
pub fn append(comptime ValueType: type, value: anytype) ListIndex {
@@ -1794,6 +1695,76 @@ pub const Stmt = struct {
},
}
}
+
+ pub fn NewStore(comptime ValueType: type) type {
+ const count = 8096;
+ const max_index = count - 1;
+ const list_count = count;
+ return struct {
+ pub threadlocal var backing_buf: [count]ValueType = undefined;
+ pub threadlocal var backing_buf_used: u16 = 0;
+ const Allocator = std.mem.Allocator;
+ const Self = @This();
+ const NotFound = allocators.NotFound;
+ const Unassigned = allocators.Unassigned;
+
+ overflow_list: std.ArrayListUnmanaged(ValueType),
+ allocator: *Allocator,
+
+ pub threadlocal var instance: Self = undefined;
+ pub threadlocal var self: *Self = undefined;
+
+ pub fn reset() void {
+ backing_buf_used = 0;
+ self.overflow_list.items.len = 0;
+ }
+
+ pub fn init(allocator: *std.mem.Allocator) *Self {
+ instance = Self{
+ .allocator = allocator,
+ .overflow_list = std.ArrayListUnmanaged(ValueType){},
+ };
+
+ self = &instance;
+ return self;
+ }
+
+ pub fn isOverflowing() bool {
+ return backing_buf_used >= @as(u16, count);
+ }
+
+ pub fn at(index: ListIndex) *ValueType {
+ std.debug.assert(index.index != NotFound.index and index.index != Unassigned.index);
+
+ if (index.is_overflowing) {
+ return &self.overflow_list.items[index.index];
+ } else {
+ return &backing_buf[index.index];
+ }
+ }
+
+ pub fn exists(value: ValueType) bool {
+ return isSliceInBuffer(value, backing_buf);
+ }
+
+ pub fn append(value: ValueType) ListIndex {
+ var result = ListIndex{ .index = std.math.maxInt(u31), .is_overflowing = backing_buf_used > max_index };
+ if (result.is_overflowing) {
+ result.index = @intCast(u31, self.overflow_list.items.len);
+ self.overflow_list.append(self.allocator, value) catch unreachable;
+ } else {
+ result.index = backing_buf_used;
+ backing_buf[result.index] = value;
+ backing_buf_used += 1;
+ if (backing_buf_used >= max_index and self.overflow_list.capacity == 0) {
+ self.overflow_list = @TypeOf(self.overflow_list).initCapacity(self.allocator, 1) catch unreachable;
+ }
+ }
+
+ return result;
+ }
+ };
+ }
};
pub inline fn set(data: *Data, value: anytype) void {
@@ -3292,12 +3263,11 @@ pub const Expr = struct {
e_null: E.Null,
e_undefined: E.Undefined,
e_new_target: E.NewTarget,
- e_import_meta: E.ImportMeta,
e_new: ListIndex,
e_function: ListIndex,
-
+ e_import_meta: E.ImportMeta,
e_call: ListIndex,
e_dot: ListIndex,
e_index: ListIndex,
@@ -3323,67 +3293,41 @@ pub const Expr = struct {
e_import: ListIndex,
pub const Store = struct {
- const Union = [_]type{
- E.Array,
- E.Unary,
- E.Binary,
- E.Class,
- E.Boolean,
- E.New,
- E.Function,
- E.Call,
- E.Dot,
- E.Index,
- E.Arrow,
- E.Identifier,
- E.ImportIdentifier,
- E.PrivateIdentifier,
- E.JSXElement,
- E.Number,
- E.BigInt,
- E.Object,
- E.Spread,
- E.String,
- E.TemplatePart,
- E.Template,
- E.RegExp,
- E.Await,
- E.Yield,
- E.If,
- E.Require,
- E.RequireOrRequireResolve,
- E.Import,
- };
- pub const BaseStore = NewBaseStore(&Union, 2048);
- pub const Array = NewStore(BaseStore, E.Array);
- pub const Unary = NewStore(BaseStore, E.Unary);
- pub const Binary = NewStore(BaseStore, E.Binary);
- pub const Class = NewStore(BaseStore, E.Class);
- pub const Boolean = NewStore(BaseStore, E.Boolean);
- pub const New = NewStore(BaseStore, E.New);
- pub const Function = NewStore(BaseStore, E.Function);
- pub const Call = NewStore(BaseStore, E.Call);
- pub const Dot = NewStore(BaseStore, E.Dot);
- pub const Index = NewStore(BaseStore, E.Index);
- pub const Arrow = NewStore(BaseStore, E.Arrow);
- pub const Identifier = NewStore(BaseStore, E.Identifier);
- pub const ImportIdentifier = NewStore(BaseStore, E.ImportIdentifier);
- pub const PrivateIdentifier = NewStore(BaseStore, E.PrivateIdentifier);
- pub const JSXElement = NewStore(BaseStore, E.JSXElement);
- pub const Number = NewStore(BaseStore, E.Number);
- pub const BigInt = NewStore(BaseStore, E.BigInt);
- pub const Object = NewStore(BaseStore, E.Object);
- pub const Spread = NewStore(BaseStore, E.Spread);
- pub const String = NewStore(BaseStore, E.String);
- pub const TemplatePart = NewStore(BaseStore, E.TemplatePart);
- pub const Template = NewStore(BaseStore, E.Template);
- pub const RegExp = NewStore(BaseStore, E.RegExp);
- pub const Await = NewStore(BaseStore, E.Await);
- pub const Yield = NewStore(BaseStore, E.Yield);
- pub const If = NewStore(BaseStore, E.If);
- pub const Require = NewStore(BaseStore, E.Require);
- pub const RequireOrRequireResolve = NewStore(BaseStore, E.RequireOrRequireResolve);
- pub const Import = NewStore(BaseStore, E.Import);
+ pub const Array = NewStore(E.Array);
+ pub const Unary = NewStore(E.Unary);
+ pub const Binary = NewStore(E.Binary);
+ pub const This = NewStore(E.This);
+ pub const Class = NewStore(E.Class);
+ pub const Boolean = NewStore(E.Boolean);
+ pub const Super = NewStore(E.Super);
+ pub const Null = NewStore(E.Null);
+ pub const Undefined = NewStore(E.Undefined);
+ pub const New = NewStore(E.New);
+ pub const Function = NewStore(E.Function);
+ pub const ImportMeta = NewStore(E.ImportMeta);
+ pub const Call = NewStore(E.Call);
+ pub const Dot = NewStore(E.Dot);
+ pub const Index = NewStore(E.Index);
+ pub const Arrow = NewStore(E.Arrow);
+ pub const Identifier = NewStore(E.Identifier);
+ pub const ImportIdentifier = NewStore(E.ImportIdentifier);
+ pub const PrivateIdentifier = NewStore(E.PrivateIdentifier);
+ pub const JSXElement = NewStore(E.JSXElement);
+ pub const Missing = NewStore(E.Missing);
+ pub const Number = NewStore(E.Number);
+ pub const BigInt = NewStore(E.BigInt);
+ pub const Object = NewStore(E.Object);
+ pub const Spread = NewStore(E.Spread);
+ pub const String = NewStore(E.String);
+ pub const TemplatePart = NewStore(E.TemplatePart);
+ pub const Template = NewStore(E.Template);
+ pub const RegExp = NewStore(E.RegExp);
+ pub const Await = NewStore(E.Await);
+ pub const Yield = NewStore(E.Yield);
+ pub const If = NewStore(E.If);
+ pub const Require = NewStore(E.Require);
+ pub const RequireOrRequireResolve = NewStore(E.RequireOrRequireResolve);
+ pub const Import = NewStore(E.Import);
threadlocal var has_inited = false;
pub fn create(allocator: *std.mem.Allocator) void {
@@ -3392,11 +3336,73 @@ pub const Expr = struct {
}
has_inited = true;
- _ = BaseStore.init(allocator);
+ _ = Array.init(allocator);
+ _ = Unary.init(allocator);
+ _ = Binary.init(allocator);
+ _ = This.init(allocator);
+ _ = Class.init(allocator);
+ _ = Boolean.init(allocator);
+ _ = New.init(allocator);
+ _ = Function.init(allocator);
+ _ = ImportMeta.init(allocator);
+ _ = Call.init(allocator);
+ _ = Dot.init(allocator);
+ _ = Index.init(allocator);
+ _ = Arrow.init(allocator);
+ _ = Identifier.init(allocator);
+ _ = ImportIdentifier.init(allocator);
+ _ = PrivateIdentifier.init(allocator);
+ _ = JSXElement.init(allocator);
+ _ = Missing.init(allocator);
+ _ = Number.init(allocator);
+ _ = BigInt.init(allocator);
+ _ = Object.init(allocator);
+ _ = Spread.init(allocator);
+ _ = String.init(allocator);
+ _ = TemplatePart.init(allocator);
+ _ = Template.init(allocator);
+ _ = RegExp.init(allocator);
+ _ = Await.init(allocator);
+ _ = Yield.init(allocator);
+ _ = If.init(allocator);
+ _ = Require.init(allocator);
+ _ = RequireOrRequireResolve.init(allocator);
+ _ = Import.init(allocator);
}
pub fn reset() void {
- BaseStore.reset();
+ Array.reset();
+ Unary.reset();
+ Binary.reset();
+ This.reset();
+ Class.reset();
+ Boolean.reset();
+ New.reset();
+ Function.reset();
+ ImportMeta.reset();
+ Call.reset();
+ Dot.reset();
+ Index.reset();
+ Arrow.reset();
+ Identifier.reset();
+ ImportIdentifier.reset();
+ PrivateIdentifier.reset();
+ JSXElement.reset();
+ Missing.reset();
+ Number.reset();
+ BigInt.reset();
+ Object.reset();
+ Spread.reset();
+ String.reset();
+ TemplatePart.reset();
+ Template.reset();
+ RegExp.reset();
+ Await.reset();
+ Yield.reset();
+ If.reset();
+ Require.reset();
+ RequireOrRequireResolve.reset();
+ Import.reset();
}
pub fn append(comptime ValueType: type, value: anytype) ListIndex {
@@ -3514,6 +3520,77 @@ pub const Expr = struct {
},
}
}
+
+ pub fn NewStore(comptime ValueType: type) type {
+ const count = 8096;
+ const max_index = count - 1;
+ const list_count = count;
+ return struct {
+ pub threadlocal var backing_buf: [count]ValueType = undefined;
+ pub threadlocal var backing_buf_used: u16 = 0;
+ const Allocator = std.mem.Allocator;
+ const Self = @This();
+ const NotFound = allocators.NotFound;
+ const Unassigned = allocators.Unassigned;
+
+ overflow_list: std.ArrayListUnmanaged(ValueType),
+ allocator: *Allocator,
+
+ pub threadlocal var instance: Self = undefined;
+ pub threadlocal var self: *Self = undefined;
+
+ pub fn reset() void {
+ backing_buf_used = 0;
+ self.overflow_list.shrinkRetainingCapacity(0);
+ }
+
+ pub fn init(allocator: *std.mem.Allocator) *Self {
+ instance = Self{
+ .allocator = allocator,
+ .overflow_list = std.ArrayListUnmanaged(ValueType){},
+ };
+
+ self = &instance;
+ return self;
+ }
+
+ pub fn isOverflowing() bool {
+ return backing_buf_used >= @as(u16, count);
+ }
+
+ pub fn at(index: ListIndex) *ValueType {
+ std.debug.assert(index.index != NotFound.index and index.index != Unassigned.index);
+
+ if (index.is_overflowing) {
+ return &self.overflow_list.items[index.index];
+ } else {
+ return &backing_buf[index.index];
+ }
+ }
+
+ pub fn exists(value: ValueType) bool {
+ return isSliceInBuffer(value, backing_buf);
+ }
+
+ pub fn append(value: ValueType) ListIndex {
+ var result = ListIndex{ .index = std.math.maxInt(u31), .is_overflowing = backing_buf_used > max_index };
+ if (result.is_overflowing) {
+ result.index = @intCast(u31, self.overflow_list.items.len);
+ self.overflow_list.append(self.allocator, value) catch unreachable;
+ } else {
+ result.index = backing_buf_used;
+ backing_buf[result.index] = value;
+ backing_buf_used += 1;
+
+ if (backing_buf_used >= max_index and self.overflow_list.capacity == 0) {
+ self.overflow_list = @TypeOf(self.overflow_list).initCapacity(self.allocator, 1) catch unreachable;
+ }
+ }
+
+ return result;
+ }
+ };
+ }
};
pub fn isBooleanValue(self: *Expr) bool {
@@ -4071,6 +4148,78 @@ pub const Dependency = packed struct {
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 &t;
+ // 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