Skip to content

Commit 42a47eb

Browse files
author
Benjamin Feng
committed
Leverage comptime recursion
1 parent 9d8e84c commit 42a47eb

File tree

1 file changed

+15
-41
lines changed

1 file changed

+15
-41
lines changed

lib/std/fmtgen.zig

Lines changed: 15 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,6 @@ pub fn format(
150150
comptime var specifier_end = 0;
151151
comptime var options = FormatOptions{};
152152

153-
// TODO: calculate this
154-
var recur_stack: [0x10000]u8 = undefined;
155-
var recur_allocator = std.heap.FixedBufferAllocator.init(&recur_stack);
156-
157153
inline for (fmt) |c, i| {
158154
switch (state) {
159155
.Start => switch (c) {
@@ -211,7 +207,6 @@ pub fn format(
211207
fmt[0..0],
212208
options,
213209
generator,
214-
&recur_allocator.allocator,
215210
default_max_depth,
216211
);
217212

@@ -243,7 +238,6 @@ pub fn format(
243238
fmt[specifier_start..i],
244239
options,
245240
generator,
246-
&recur_allocator.allocator,
247241
default_max_depth,
248242
);
249243
state = .Start;
@@ -289,7 +283,6 @@ pub fn format(
289283
fmt[specifier_start..specifier_end],
290284
options,
291285
generator,
292-
&recur_allocator.allocator,
293286
default_max_depth,
294287
);
295288
state = .Start;
@@ -316,7 +309,6 @@ pub fn format(
316309
fmt[specifier_start..specifier_end],
317310
options,
318311
generator,
319-
&recur_allocator.allocator,
320312
default_max_depth,
321313
);
322314
state = .Start;
@@ -352,9 +344,14 @@ pub fn formatType(
352344
comptime fmt: []const u8,
353345
options: FormatOptions,
354346
generator: *Generator([]const u8),
355-
allocator: *mem.Allocator,
356-
max_depth: usize,
347+
comptime max_depth: comptime_int,
357348
) void {
349+
if (max_depth < 0) {
350+
// This shouldn't ever be reached as we account for it later in the function.
351+
// But the compiler analysis phase gets confused and generates infinite versions of this function if there's no check.
352+
@compileError("max_depth less than 0");
353+
}
354+
358355
if (comptime std.mem.eql(u8, fmt, "*")) {
359356
return formatPtr(@TypeOf(value).Child, @ptrToInt(value), generator);
360357
}
@@ -372,25 +369,16 @@ pub fn formatType(
372369
},
373370
.Optional => {
374371
if (value) |payload| {
375-
// return @call(.{ .modifier = .always_tail }, formatType, .{ payload, fmt, options, generator, allocator, max_depth });
376-
// TODO: reenable tail call once it is fixed https://github.com/ziglang/zig/issues/4060
377-
var frame = allocator.create(
378-
@TypeOf(async formatType(payload, fmt, options, generator, allocator, max_depth)),
379-
) catch |err| switch (err) {
380-
error.OutOfMemory => return generator.yield(" ??OOM?? "),
381-
};
382-
defer allocator.destroy(frame);
383-
frame.* = async formatType(payload, fmt, options, generator, allocator, max_depth);
384-
await frame.*;
372+
return @call(.{ .modifier = .always_tail }, formatType, .{ payload, fmt, options, generator, max_depth });
385373
} else {
386374
return generator.yield("null");
387375
}
388376
},
389377
.ErrorUnion => {
390378
if (value) |payload| {
391-
return @call(.{ .modifier = .always_tail }, formatType, .{ payload, fmt, options, generator, allocator, max_depth });
379+
return @call(.{ .modifier = .always_tail }, formatType, .{ payload, fmt, options, generator, max_depth });
392380
} else |err| {
393-
return @call(.{ .modifier = .always_tail }, formatType, .{ err, fmt, options, generator, allocator, max_depth });
381+
return @call(.{ .modifier = .always_tail }, formatType, .{ err, fmt, options, generator, max_depth });
394382
}
395383
},
396384
.ErrorSet => {
@@ -403,7 +391,7 @@ pub fn formatType(
403391
// }
404392
generator.yield(@typeName(T));
405393
generator.yield(".");
406-
return @call(.{ .modifier = .always_tail }, formatType, .{ @tagName(value), "", options, generator, allocator, max_depth });
394+
return @call(.{ .modifier = .always_tail }, formatType, .{ @tagName(value), "", options, generator, max_depth });
407395
},
408396
.Union => {
409397
// if (comptime std.meta.trait.hasFn("format")(T)) {
@@ -420,14 +408,7 @@ pub fn formatType(
420408
generator.yield(" = ");
421409
inline for (info.fields) |u_field| {
422410
if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {
423-
var frame = allocator.create(
424-
@TypeOf(async formatType(@field(value, u_field.name), "", options, generator, allocator, max_depth - 1)),
425-
) catch |err| switch (err) {
426-
error.OutOfMemory => return generator.yield(" ??OOM?? "),
427-
};
428-
defer allocator.destroy(frame);
429-
frame.* = async formatType(@field(value, u_field.name), "", options, generator, allocator, max_depth - 1);
430-
await frame.*;
411+
formatType(@field(value, u_field.name), "", options, generator, max_depth - 1);
431412
}
432413
}
433414
generator.yield(" }");
@@ -455,14 +436,7 @@ pub fn formatType(
455436
generator.yield(@memberName(T, field_i));
456437
generator.yield(" = ");
457438

458-
var frame = allocator.create(
459-
@TypeOf(async formatType(@field(value, @memberName(T, field_i)), "", options, generator, allocator, max_depth - 1)),
460-
) catch |err| switch (err) {
461-
error.OutOfMemory => return generator.yield(" ??OOM?? "),
462-
};
463-
defer allocator.destroy(frame);
464-
frame.* = async formatType(@field(value, @memberName(T, field_i)), "", options, generator, allocator, max_depth - 1);
465-
await frame.*;
439+
formatType(@field(value, @memberName(T, field_i)), "", options, generator, max_depth - 1);
466440
}
467441
generator.yield(" }");
468442
},
@@ -475,7 +449,7 @@ pub fn formatType(
475449
return formatPtr(T.Child, @ptrToInt(value), generator);
476450
},
477451
builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => {
478-
return @call(.{ .modifier = .always_tail }, formatType, .{ value.*, fmt, options, generator, allocator, max_depth });
452+
return @call(.{ .modifier = .always_tail }, formatType, .{ value.*, fmt, options, generator, max_depth });
479453
},
480454
else => return formatPtr(T.Child, @ptrToInt(value), generator),
481455
},
@@ -513,7 +487,7 @@ pub fn formatType(
513487
.sentinel = null,
514488
},
515489
});
516-
return @call(.{ .modifier = .always_tail }, formatType, .{ @as(Slice, &value), fmt, options, generator, allocator, max_depth });
490+
return @call(.{ .modifier = .always_tail }, formatType, .{ @as(Slice, &value), fmt, options, generator, max_depth });
517491
},
518492
.Fn => {
519493
return formatPtr(T, @ptrToInt(value), generator);

0 commit comments

Comments
 (0)