diff options
Diffstat (limited to 'src/syntax.zig')
| -rw-r--r-- | src/syntax.zig | 69 |
1 files changed, 5 insertions, 64 deletions
diff --git a/src/syntax.zig b/src/syntax.zig index e637bf67..5c8b9c0f 100644 --- a/src/syntax.zig +++ b/src/syntax.zig @@ -3,6 +3,7 @@ const config = @import("pardes_config"); const tracy = @import("tracy.zig"); const grammar_manifest = @import("grammar_manifest.zig"); const look = @import("look.zig"); +const c_heap = @import("c_heap"); pub const enabled = config.syntax_highlighting; const zig_grammar = config.syntax_zig_grammar; @@ -139,8 +140,10 @@ fn initSpecs() [specCount()]Spec { var specs = initSpecs(); -const allocation_header_size = 16; +/// What the tree-sitter runtime allocates from: `start`'s allocator, through +/// the shared C heap. var syntax_allocator: std.mem.Allocator = undefined; +const syntax_heap = c_heap.Heap(&syntax_allocator); var syntax_started = false; extern fn ts_set_allocator( @@ -150,56 +153,13 @@ extern fn ts_set_allocator( new_free: ?*const fn (ptr: ?*anyopaque) callconv(.c) void, ) void; -fn syntaxAlloc(size_arg: usize) callconv(.c) ?*anyopaque { - const size = @max(size_arg, 1); - const total = std.math.add(usize, allocation_header_size, size) catch return null; - const bytes = syntax_allocator.alignedAlloc(u8, .@"16", total) catch return null; - const header: *align(16) usize = @ptrCast(bytes.ptr); - header.* = total; - return @ptrCast(bytes.ptr + allocation_header_size); -} - -fn syntaxCalloc(count: usize, size: usize) callconv(.c) ?*anyopaque { - const len = std.math.mul(usize, count, size) catch return null; - const pointer = syntaxAlloc(len) orelse return null; - const bytes: [*]u8 = @ptrCast(pointer); - @memset(bytes[0..len], 0); - return pointer; -} - -fn syntaxRealloc(ptr: ?*anyopaque, new_size: usize) callconv(.c) ?*anyopaque { - const pointer = ptr orelse return syntaxAlloc(new_size); - if (new_size == 0) { - syntaxFree(pointer); - return null; - } - const user: [*]u8 = @ptrCast(pointer); - const header: *align(16) usize = @ptrCast(@alignCast(user - allocation_header_size)); - const old_total = header.*; - const old_bytes: []align(16) u8 = @as([*]align(16) u8, @ptrCast(header))[0..old_total]; - const new_total = std.math.add(usize, allocation_header_size, new_size) catch return null; - const new_bytes = syntax_allocator.realloc(old_bytes, new_total) catch return null; - const new_header: *align(16) usize = @ptrCast(new_bytes.ptr); - new_header.* = new_total; - return @ptrCast(new_bytes.ptr + allocation_header_size); -} - -fn syntaxFree(ptr: ?*anyopaque) callconv(.c) void { - const pointer = ptr orelse return; - const user: [*]u8 = @ptrCast(pointer); - const header: *align(16) usize = @ptrCast(@alignCast(user - allocation_header_size)); - const total = header.*; - const bytes: []align(16) u8 = @as([*]align(16) u8, @ptrCast(header))[0..total]; - syntax_allocator.free(bytes); -} - pub fn start(gpa: std.mem.Allocator) void { if (comptime enabled) { std.debug.assert(!syntax_started); stop(); syntax_allocator = gpa; syntax_started = true; - ts_set_allocator(syntaxAlloc, syntaxCalloc, syntaxRealloc, syntaxFree); + ts_set_allocator(syntax_heap.malloc, syntax_heap.calloc, syntax_heap.realloc, syntax_heap.free); } } @@ -935,25 +895,6 @@ test "syntax codeAfterLocation takes whole-token locations and nothing else" { try std.testing.expect(codeAfterLocation(" leading space") == null); } -test "syntax tree-sitter allocator callbacks preserve and free exact allocations" { - syntax_allocator = std.testing.allocator; - defer syntax_allocator = undefined; - - var live: ?*anyopaque = syntaxCalloc(4, 1) orelse return error.OutOfMemory; - defer if (live) |pointer| syntaxFree(pointer); - const original: [*]u8 = @ptrCast(live.?); - try std.testing.expectEqualSlices(u8, &.{ 0, 0, 0, 0 }, original[0..4]); - @memcpy(original[0..4], "data"); - - live = syntaxRealloc(live, 32) orelse return error.OutOfMemory; - const grown: [*]u8 = @ptrCast(live.?); - try std.testing.expectEqualSlices(u8, "data", grown[0..4]); - - try std.testing.expect(syntaxCalloc(std.math.maxInt(usize), 2) == null); - try std.testing.expect(syntaxRealloc(live, 0) == null); - live = null; -} - test "syntax default full grammar set highlights Typst source" { if (!enabled or !full_grammars) return; start(std.testing.allocator); |
