@@ -150,6 +150,10 @@ 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+
153157 inline for (fmt ) | c , i | {
154158 switch (state ) {
155159 .Start = > switch (c ) {
@@ -207,6 +211,7 @@ pub fn format(
207211 fmt [0.. 0],
208212 options ,
209213 generator ,
214+ & recur_allocator .allocator ,
210215 default_max_depth ,
211216 );
212217
@@ -238,6 +243,7 @@ pub fn format(
238243 fmt [specifier_start .. i ],
239244 options ,
240245 generator ,
246+ & recur_allocator .allocator ,
241247 default_max_depth ,
242248 );
243249 state = .Start ;
@@ -283,6 +289,7 @@ pub fn format(
283289 fmt [specifier_start .. specifier_end ],
284290 options ,
285291 generator ,
292+ & recur_allocator .allocator ,
286293 default_max_depth ,
287294 );
288295 state = .Start ;
@@ -309,6 +316,7 @@ pub fn format(
309316 fmt [specifier_start .. specifier_end ],
310317 options ,
311318 generator ,
319+ & recur_allocator .allocator ,
312320 default_max_depth ,
313321 );
314322 state = .Start ;
@@ -344,6 +352,7 @@ pub fn formatType(
344352 comptime fmt : []const u8 ,
345353 options : FormatOptions ,
346354 generator : * Generator ([]const u8 ),
355+ allocator : * mem.Allocator ,
347356 max_depth : usize ,
348357) void {
349358 if (comptime std .mem .eql (u8 , fmt , "*" )) {
@@ -363,16 +372,24 @@ pub fn formatType(
363372 },
364373 .Optional = > {
365374 if (value ) | payload | {
366- return @call (.{ .modifier = .always_tail }, formatType , .{ payload , fmt , options , generator , max_depth });
375+ // return @call(.{ .modifier = .always_tail }, formatType, .{ payload, fmt, options, generator, allocator, max_depth });
376+ var frame = allocator .create (
377+ @TypeOf (async formatType (payload , fmt , options , generator , allocator , max_depth )),
378+ ) catch | err | switch (err ) {
379+ error .OutOfMemory = > return generator .yield (" ??OOM?? " ),
380+ };
381+ defer allocator .destroy (frame );
382+ frame .* = async formatType (payload , fmt , options , generator , allocator , max_depth );
383+ await frame .* ;
367384 } else {
368385 return generator .yield ("null" );
369386 }
370387 },
371388 .ErrorUnion = > {
372389 if (value ) | payload | {
373- return @call (.{ .modifier = .always_tail }, formatType , .{ payload , fmt , options , generator , max_depth });
390+ return @call (.{ .modifier = .always_tail }, formatType , .{ payload , fmt , options , generator , allocator , max_depth });
374391 } else | err | {
375- return @call (.{ .modifier = .always_tail }, formatType , .{ err , fmt , options , generator , max_depth });
392+ return @call (.{ .modifier = .always_tail }, formatType , .{ err , fmt , options , generator , allocator , max_depth });
376393 }
377394 },
378395 .ErrorSet = > {
@@ -385,7 +402,7 @@ pub fn formatType(
385402 // }
386403 generator .yield (@typeName (T ));
387404 generator .yield ("." );
388- return @call (.{ .modifier = .always_tail }, formatType , .{ @tagName (value ), "" , options , generator , max_depth });
405+ return @call (.{ .modifier = .always_tail }, formatType , .{ @tagName (value ), "" , options , generator , allocator , max_depth });
389406 },
390407 .Union = > {
391408 // if (comptime std.meta.trait.hasFn("format")(T)) {
@@ -402,8 +419,14 @@ pub fn formatType(
402419 generator .yield (" = " );
403420 inline for (info .fields ) | u_field | {
404421 if (@enumToInt (@as (UnionTagType , value )) == u_field .enum_field .? .value ) {
405- // TODO: investigate why recursion just works
406- formatType (@field (value , u_field .name ), "" , options , generator , max_depth - 1 );
422+ var frame = allocator .create (
423+ @TypeOf (async formatType (@field (value , u_field .name ), "" , options , generator , allocator , max_depth - 1 )),
424+ ) catch | err | switch (err ) {
425+ error .OutOfMemory = > return generator .yield (" ??OOM?? " ),
426+ };
427+ defer allocator .destroy (frame );
428+ frame .* = async formatType (@field (value , u_field .name ), "" , options , generator , allocator , max_depth - 1 );
429+ await frame .* ;
407430 }
408431 }
409432 generator .yield (" }" );
@@ -430,7 +453,15 @@ pub fn formatType(
430453 }
431454 generator .yield (@memberName (T , field_i ));
432455 generator .yield (" = " );
433- formatType (@field (value , @memberName (T , field_i )), "" , options , generator , max_depth - 1 );
456+
457+ var frame = allocator .create (
458+ @TypeOf (async formatType (@field (value , @memberName (T , field_i )), "" , options , generator , allocator , max_depth - 1 )),
459+ ) catch | err | switch (err ) {
460+ error .OutOfMemory = > return generator .yield (" ??OOM?? " ),
461+ };
462+ defer allocator .destroy (frame );
463+ frame .* = async formatType (@field (value , @memberName (T , field_i )), "" , options , generator , allocator , max_depth - 1 );
464+ await frame .* ;
434465 }
435466 generator .yield (" }" );
436467 },
@@ -443,7 +474,7 @@ pub fn formatType(
443474 return formatPtr (T .Child , @ptrToInt (value ), generator );
444475 },
445476 builtin .TypeId .Enum , builtin .TypeId .Union , builtin .TypeId .Struct = > {
446- return @call (.{ .modifier = .always_tail }, formatType , .{ value .* , fmt , options , generator , max_depth });
477+ return @call (.{ .modifier = .always_tail }, formatType , .{ value .* , fmt , options , generator , allocator , max_depth });
447478 },
448479 else = > return formatPtr (T .Child , @ptrToInt (value ), generator ),
449480 },
@@ -481,7 +512,7 @@ pub fn formatType(
481512 .sentinel = null ,
482513 },
483514 });
484- return @call (.{ .modifier = .always_tail }, formatType , .{ @as (Slice , & value ), fmt , options , generator , max_depth });
515+ return @call (.{ .modifier = .always_tail }, formatType , .{ @as (Slice , & value ), fmt , options , generator , allocator , max_depth });
485516 },
486517 .Fn = > {
487518 return formatPtr (T , @ptrToInt (value ), generator );
@@ -1510,34 +1541,34 @@ test "enum" {
15101541 try testFmt ("E.Two" , "{}" , .{inst });
15111542}
15121543
1513- // test "struct.self-referential" {
1514- // const S = struct {
1515- // const SelfType = @This();
1516- // a: ?*SelfType,
1517- // };
1544+ test "struct.self-referential" {
1545+ const S = struct {
1546+ const SelfType = @This ();
1547+ a : ? * SelfType ,
1548+ };
15181549
1519- // var inst = S{
1520- // .a = null,
1521- // };
1522- // inst.a = &inst;
1550+ var inst = S {
1551+ .a = null ,
1552+ };
1553+ inst .a = & inst ;
15231554
1524- // try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst});
1525- // }
1555+ try testFmt ("S{ .a = S{ .a = S{ .a = S{ ... } } } }" , "{}" , .{inst });
1556+ }
15261557
1527- // test "struct.zero-size" {
1528- // const A = struct {
1529- // fn foo() void {}
1530- // };
1531- // const B = struct {
1532- // a: A,
1533- // c: i32,
1534- // };
1558+ test "struct.zero-size" {
1559+ const A = struct {
1560+ fn foo () void {}
1561+ };
1562+ const B = struct {
1563+ a : A ,
1564+ c : i32 ,
1565+ };
15351566
1536- // const a = A{};
1537- // const b = B{ .a = a, .c = 0 };
1567+ const a = A {};
1568+ const b = B { .a = a , .c = 0 };
15381569
1539- // try testFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b});
1540- // }
1570+ try testFmt ("B{ .a = A{ }, .c = 0 }" , "{}" , .{b });
1571+ }
15411572
15421573test "bytes.hex" {
15431574 const some_bytes = "\xCA\xFE\xBA\xBE " ;
0 commit comments