From 2a3fb341aa4e4603774289627c8eb397fdc854d1 Mon Sep 17 00:00:00 2001 From: Vallahor Date: Tue, 24 May 2022 22:14:05 -0300 Subject: [PATCH] fix: handling more types of sentinels. now can be structs too --- lib/docs/main.js | 28 +++++++++++++- src/Autodoc.zig | 98 +++++++++++++++++++++++++++++------------------- 2 files changed, 86 insertions(+), 40 deletions(-) diff --git a/lib/docs/main.js b/lib/docs/main.js index f33bdfad5..346681b20 100644 --- a/lib/docs/main.js +++ b/lib/docs/main.js @@ -1062,6 +1062,30 @@ var zigAnalysis; function exprName(expr, opts) { switch (Object.keys(expr)[0]) { default: throw "oh no"; + case "struct": { + const struct_name = zigAnalysis.decls[expr.struct[0].val.typeRef.refPath[0].declRef].name; + let struct_body = ""; + struct_body += struct_name + "{ "; + for (let i = 0; i < expr.struct.length; i++) { + const val = expr.struct[i].name + const exprArg = zigAnalysis.exprs[expr.struct[i].val.expr.as.exprArg]; + let value_field = exprArg[Object.keys(exprArg)[0]]; + if (value_field instanceof Object) { + value_field = zigAnalysis.decls[value_field[0].val.typeRef.refPath[0].declRef].name; + }; + struct_body += "." + val + " = " + value_field; + if (i !== expr.struct.length - 1) { + struct_body += ", "; + } else { + struct_body += " "; + } + } + struct_body += "}"; + return struct_body; + } + case "null": { + return "null"; + } case "array": { let payloadHtml = ".{"; for (let i = 0; i < expr.array.length; i++) { @@ -1141,7 +1165,7 @@ var zigAnalysis; let arrayObj = /** @type {ArrayType} */ (typeObj); let name = "["; let lenName = exprName(arrayObj.len, opts); - let sentinel = arrayObj.sentinel ? ":0" : ""; + let sentinel = arrayObj.sentinel ? ":"+exprName(arrayObj.sentinel, opts) : ""; let is_mutable = arrayObj.is_multable ? "const " : ""; if (opts.wantHtml) { @@ -1160,7 +1184,7 @@ var zigAnalysis; case typeKinds.Pointer: { let ptrObj = /** @type {PointerType} */(typeObj); - let sentinel = ptrObj.sentinel ? ":0" : ""; + let sentinel = ptrObj.sentinel ? ":"+exprName(ptrObj.sentinel, opts) : ""; let is_mutable = !ptrObj.is_mutable ? "const " : ""; let name = ""; switch (ptrObj.size) { diff --git a/src/Autodoc.zig b/src/Autodoc.zig index d16b481a6..e5f95bfad 100644 --- a/src/Autodoc.zig +++ b/src/Autodoc.zig @@ -383,13 +383,13 @@ const DocData = struct { Pointer: struct { size: std.builtin.TypeInfo.Pointer.Size, child: Expr, - sentinel: bool = false, + sentinel: ?Expr = null, is_mutable: bool = true, }, Array: struct { len: Expr, child: Expr, - sentinel: bool = false, + sentinel: ?Expr = null, }, Struct: struct { name: []const u8, @@ -482,11 +482,14 @@ const DocData = struct { \\ , .{@enumToInt(v.size)}); if (options.whitespace) |ws| try ws.outputIndent(w); - try w.print( - \\"sentinel": {}, - \\ - , .{v.sentinel}); - if (options.whitespace) |ws| try ws.outputIndent(w); + if (v.sentinel) |sentinel| { + try w.print( + \\"sentinel": + , .{}); + if (options.whitespace) |*ws| ws.indent_level += 1; + try sentinel.jsonStringify(options, w); + try w.print(",", .{}); + } try w.print( \\"is_mutable": {}, \\ @@ -766,7 +769,10 @@ fn walkInstruction( .Array = .{ .len = .{ .int = .{ .value = str.len } }, .child = .{ .type = @enumToInt(Ref.u8_type) }, - .sentinel = true, + .sentinel = .{ .int = .{ + .value = 0, + .negated = false, + } }, }, }); // const sentinel: ?usize = if (ptr.flags.has_sentinel) 0 else null; @@ -775,7 +781,10 @@ fn walkInstruction( .Pointer = .{ .size = .One, .child = .{ .type = arrTypeId }, - .sentinel = true, + .sentinel = .{ .int = .{ + .value = 0, + .negated = false, + } }, .is_mutable = false, }, }); @@ -842,10 +851,7 @@ fn walkInstruction( false, ); - return DocData.WalkResult{ - .typeRef = .{ .type = operand.typeRef.?.type }, - .expr = .{ .type = operand.expr.type }, - }; + return operand; }, .ptr_type_simple => { const ptr = data[inst_index].ptr_type_simple; @@ -868,8 +874,6 @@ fn walkInstruction( const ptr = data[inst_index].ptr_type; const extra = file.zir.extraData(Zir.Inst.PtrType, ptr.payload_index); - const sentinel: bool = if (ptr.flags.has_sentinel) true else false; - const type_slot_index = self.types.items.len; const elem_type_ref = try self.walkRef( file, @@ -877,8 +881,9 @@ fn walkInstruction( extra.data.elem_type, false, ); + try self.types.append(self.arena, .{ - .Pointer = .{ .size = ptr.size, .child = elem_type_ref.expr, .sentinel = sentinel, .is_mutable = ptr.flags.is_mutable }, + .Pointer = .{ .size = ptr.size, .child = elem_type_ref.expr, .sentinel = .{ .int = .{ .value = 0, .negated = false } }, .is_mutable = ptr.flags.is_mutable }, }); return DocData.WalkResult{ .typeRef = .{ .type = @enumToInt(Ref.type_type) }, @@ -907,7 +912,7 @@ fn walkInstruction( const pl_node = data[inst_index].pl_node; const extra = file.zir.extraData(Zir.Inst.ArrayTypeSentinel, pl_node.payload_index); const len = try self.walkRef(file, parent_scope, extra.data.len, false); - // const sentinel = try self.walkRef(file, parent_scope, extra.data.sentinel, false); + const sentinel = try self.walkRef(file, parent_scope, extra.data.sentinel, false); const elem_type = try self.walkRef(file, parent_scope, extra.data.elem_type, false); const type_slot_index = self.types.items.len; @@ -915,7 +920,7 @@ fn walkInstruction( .Array = .{ .len = len.expr, .child = elem_type.expr, - .sentinel = true, + .sentinel = sentinel.expr, }, }); return DocData.WalkResult{ @@ -966,12 +971,12 @@ fn walkInstruction( .array_init_sent => { const pl_node = data[inst_index].pl_node; const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index); - const operands = file.zir.refSlice(extra.end, extra.data.operands_len - 1); - const array_data = try self.arena.alloc(usize, operands.len); + const operands = file.zir.refSlice(extra.end, extra.data.operands_len); + const array_data = try self.arena.alloc(usize, operands.len - 1); // TODO: make sure that you want the array to be fully normalized for real // then update this code to conform to your choice. - + var sentinel: ?DocData.Expr = null; var array_type: ?DocData.Expr = null; for (operands) |op, idx| { // we only ask to figure out type info for the first element @@ -981,20 +986,21 @@ fn walkInstruction( array_type = wr.typeRef; } - // We know that Zir wraps every operand in an @as expression - // so we want to peel it away and only save the target type - // once, since we need it later to define the array type. - array_data[idx] = wr.expr.as.exprArg; + if (idx == extra.data.operands_len - 1) { + sentinel = self.exprs.items[wr.expr.as.exprArg]; + } else { + array_data[idx] = wr.expr.as.exprArg; + } } const type_slot_index = self.types.items.len; try self.types.append(self.arena, .{ .Array = .{ .len = .{ .int = .{ - .value = operands.len, + .value = operands.len - 1, .negated = false, }, - }, .child = array_type.?, .sentinel = true }, + }, .child = array_type.?, .sentinel = sentinel }, }); return DocData.WalkResult{ @@ -1084,28 +1090,36 @@ fn walkInstruction( .array_init_sent_ref => { const pl_node = data[inst_index].pl_node; const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index); - // the sentinel terminator are calculated at compile time - // (extra.data.operands_len - 1) is to not account for that - const operands = file.zir.refSlice(extra.end, extra.data.operands_len - 1); - const array_data = try self.arena.alloc(usize, operands.len); + const operands = file.zir.refSlice(extra.end, extra.data.operands_len); + const array_data = try self.arena.alloc(usize, operands.len - 1); + // TODO: This should output: + // const array: *[value:sentinel]type = &.{}; + // but right now it's printing: + // const array: [value:sentinel]u8 = .{}; + + var sentinel: ?DocData.Expr = null; var array_type: ?DocData.Expr = null; for (operands) |op, idx| { const wr = try self.walkRef(file, parent_scope, op, idx == 0); if (idx == 0) { array_type = wr.typeRef; } - array_data[idx] = wr.expr.as.exprArg; + if (idx == extra.data.operands_len - 1) { + sentinel = self.exprs.items[wr.expr.as.exprArg]; + } else { + array_data[idx] = wr.expr.as.exprArg; + } } const type_slot_index = self.types.items.len; try self.types.append(self.arena, .{ .Array = .{ .len = .{ .int = .{ - .value = operands.len, + .value = operands.len - 1, .negated = false, }, - }, .child = array_type.?, .sentinel = true }, + }, .child = array_type.?, .sentinel = sentinel }, }); return DocData.WalkResult{ @@ -1117,7 +1131,9 @@ fn walkInstruction( const pl_node = data[inst_index].pl_node; const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index); const operands = file.zir.refSlice(extra.end, extra.data.operands_len); - const array_data = try self.arena.alloc(usize, operands.len); + const array_data = try self.arena.alloc(usize, operands.len - 1); + + var sentinel: ?DocData.Expr = null; var array_type: ?DocData.Expr = null; for (operands) |op, idx| { @@ -1125,17 +1141,23 @@ fn walkInstruction( if (idx == 0) { array_type = wr.typeRef; } - array_data[idx] = wr.expr.int.value; + + if (idx == extra.data.operands_len - 1) { + sentinel = wr.expr; + const expr_index = self.exprs.items.len; + try self.exprs.append(self.arena, wr.expr); + array_data[idx] = expr_index; + } } const type_slot_index = self.types.items.len; try self.types.append(self.arena, .{ .Array = .{ .len = .{ .int = .{ - .value = operands.len, + .value = operands.len - 1, .negated = false, }, - }, .child = array_type.? }, + }, .child = array_type.?, .sentinel = sentinel }, }); return DocData.WalkResult{