add: extern, callconv and return errors

This commit is contained in:
Vallahor
2022-05-28 00:34:35 -03:00
committed by Andrew Kelley
parent 76e934dba8
commit f04f23a3aa
2 changed files with 105 additions and 41 deletions

View File

@@ -1062,6 +1062,13 @@ var zigAnalysis;
function exprName(expr, opts) {
switch (Object.keys(expr)[0]) {
default: throw "oh no";
case "errorUnion": {
const errUnionObj = zigAnalysis.types[expr.errorUnion];
let lhs = exprName(errUnionObj.lhs, opts);
let rhs = exprName(errUnionObj.rhs, opts);
return lhs + "!" + rhs;
}
case "struct": {
const struct_name = zigAnalysis.decls[expr.struct[0].val.typeRef.refPath[0].declRef].name;
let struct_body = "";
@@ -1084,7 +1091,6 @@ var zigAnalysis;
return struct_body;
}
case "typeOf_peer": {
console.log(expr)
let payloadHtml = "@TypeOf("
for (let i = 0; i < expr.typeOf_peer.length; i++) {
let elem = zigAnalysis.exprs[expr.typeOf_peer[i]];
@@ -1094,7 +1100,6 @@ var zigAnalysis;
}
}
payloadHtml += ")";
console.log(payloadHtml)
return payloadHtml;
}
@@ -1111,7 +1116,7 @@ var zigAnalysis;
for (let i = 0; i < expr.array.length; i++) {
if (i != 0) payloadHtml += ", ";
let elem = zigAnalysis.exprs[expr.array[i]];
payloadHtml += exprName(elem);
payloadHtml += exprName(elem, opts);
}
return payloadHtml + "}";
}
@@ -1127,7 +1132,7 @@ var zigAnalysis;
default: throw "TODO";
case "declRef":
case "refPath": {
payloadHtml += exprName(call.func);
payloadHtml += exprName(call.func, opts);
break;
}
}
@@ -1135,7 +1140,7 @@ var zigAnalysis;
for (let i = 0; i < call.args.length; i++) {
if (i != 0) payloadHtml += ", ";
payloadHtml += exprName(call.args[i]);
payloadHtml += exprName(call.args[i], opts);
}
payloadHtml += ")";
@@ -1173,7 +1178,6 @@ var zigAnalysis;
let typeObj = expr.type;
if (typeof typeObj === 'number') typeObj = zigAnalysis.types[typeObj];
switch (typeObj.kind) {
default: throw "TODO";
case typeKinds.ComptimeExpr:
@@ -1210,7 +1214,6 @@ var zigAnalysis;
let sentinel = ptrObj.sentinel ? ":"+exprName(ptrObj.sentinel, opts) : "";
let is_mutable = !ptrObj.is_mutable ? "const " : "";
let name = "";
console.log(ptrObj);
switch (ptrObj.size) {
default:
console.log("TODO: implement unhandled pointer size case");
@@ -1352,40 +1355,29 @@ var zigAnalysis;
{
let errSetObj = /** @type {ErrSetType} */(typeObj);
if (errSetObj.fields == null) {
if (wantHtml) {
return '<span class="tok-type">anyerror</span>';
} else {
return "anyerror";
}
} else {
throw "TODO";
// if (wantHtml) {
// return escapeHtml(typeObj.name);
// } else {
// return typeObj.name;
// }
// throw "TODO";
let html = "error{" + errSetObj.fields[0].name + "}";
return html;
}
}
case typeKinds.ErrorUnion:
{
throw "TODO";
// TODO: implement error union printing assuming that both
// payload and error union are walk results!
// let errUnionObj = /** @type {ErrUnionType} */(typeObj);
// let errSetTypeObj = /** @type {ErrSetType} */ (zigAnalysis.types[errUnionObj.err]);
// let payloadHtml = typeValueName(errUnionObj.payload, wantHtml, wantSubLink, null);
// if (fnDecl != null && errSetTypeObj.fn === fnDecl.value.type) {
// // function index parameter supplied and this is the inferred error set of it
// return "!" + payloadHtml;
// } else {
// return typeValueName(errUnionObj.err, wantHtml, wantSubLink, null) + "!" + payloadHtml;
// }
let errUnionObj = /** @type {ErrUnionType} */(typeObj);
let lhs = exprName(errUnionObj.lhs, opts);
let rhs = exprName(errUnionObj.rhs, opts);
return lhs + "!" + rhs;
}
case typeKinds.Fn:
{
let fnObj = /** @type {Fn} */(typeObj);
let payloadHtml = "";
if (opts.wantHtml) {
if (fnObj.is_extern) {
payloadHtml += "pub \"extern\" ";
}
payloadHtml += '<span class="tok-kw">fn</span>';
if (opts.fnDecl) {
payloadHtml += ' <span class="tok-fn">';
@@ -1533,6 +1525,14 @@ var zigAnalysis;
}
payloadHtml += ') ';
if (fnObj.has_cc) {
let cc = zigAnalysis.types[fnObj.cc]
payloadHtml += "callconv(." + cc.name + ") ";
}
if (fnObj.is_inferred_error) {
payloadHtml += "!";
}
if (fnObj.ret != null) {
payloadHtml += exprName(fnObj.ret, opts);
} else if (opts.wantHtml) {

View File

@@ -153,6 +153,9 @@ pub fn generateZirData(self: *Autodoc) !void {
.type_type => .{
.Type = .{ .name = tmpbuf.toOwnedSlice() },
},
.anyerror_type => .{
.ErrorSet = .{ .name = tmpbuf.toOwnedSlice() },
},
},
);
}
@@ -429,10 +432,11 @@ const DocData = struct {
name: []const u8,
child: Expr,
},
ErrorUnion: struct { name: []const u8 },
ErrorUnion: struct { lhs: Expr, rhs: Expr },
// ErrorUnion: struct { name: []const u8 },
ErrorSet: struct {
name: []const u8,
fields: []const Field,
fields: ?[]const Field = null,
// TODO: fn field for inferred error sets?
},
Enum: struct {
@@ -454,6 +458,14 @@ const DocData = struct {
src: ?usize = null, // index into astNodes
ret: Expr,
params: ?[]Expr = null, // (use src->fields to find names)
is_var_args: bool = false,
is_inferred_error: bool = false,
has_lib_name: bool = false,
has_cc: bool = false,
cc: ?usize = null,
has_align: bool = false,
is_test: bool = false,
is_extern: bool = false,
},
BoundFn: struct { name: []const u8 },
Opaque: struct { name: []const u8 },
@@ -492,6 +504,7 @@ const DocData = struct {
.Fn => |v| try printTypeBody(v, options, w),
.Union => |v| try printTypeBody(v, options, w),
.ErrorSet => |v| try printTypeBody(v, options, w),
.ErrorUnion => |v| try printTypeBody(v, options, w),
.Enum => |v| try printTypeBody(v, options, w),
.Int => |v| try printTypeBody(v, options, w),
.Float => |v| try printTypeBody(v, options, w),
@@ -588,6 +601,7 @@ const DocData = struct {
enumLiteral: []const u8, // direct value
typeOf: usize, // index in `exprs`
typeOf_peer: []usize,
errorUnion: usize, // index in `exprs`
as: As,
sizeOf: usize, // index in `exprs`
compileError: []const u8,
@@ -617,7 +631,7 @@ const DocData = struct {
\\{{ "{s}":{{}} }}
, .{@tagName(self)});
},
.type, .comptimeExpr, .call, .this, .declRef, .typeOf => |v| {
.type, .comptimeExpr, .call, .this, .declRef, .typeOf, .errorUnion => |v| {
try w.print(
\\{{ "{s}":{} }}
, .{ @tagName(self), v });
@@ -853,7 +867,7 @@ fn walkInstruction(
const literal = file.zir.nullTerminatedString(str_tok.start);
const type_index = self.types.items.len;
try self.types.append(self.arena, .{
.EnumLiteral = .{ .name = "todo enum literal" },
.EnumLiteral = .{ .name = literal },
});
return DocData.WalkResult{
@@ -872,8 +886,29 @@ fn walkInstruction(
const pl_node = data[inst_index].pl_node;
const extra = file.zir.extraData(Zir.Inst.Bin, pl_node.payload_index);
// TODO: return the actual error union instread of cheating
return self.walkRef(file, parent_scope, extra.data.rhs, need_type);
var lhs: DocData.WalkResult = try self.walkRef(
file,
parent_scope,
extra.data.lhs,
false,
);
var rhs: DocData.WalkResult = try self.walkRef(
file,
parent_scope,
extra.data.rhs,
false,
);
const type_slot_index = self.types.items.len;
try self.types.append(self.arena, .{ .ErrorUnion = .{
.lhs = lhs.expr,
.rhs = rhs.expr,
} });
return DocData.WalkResult{
.typeRef = .{ .type = @enumToInt(Ref.type_type) },
.expr = .{ .errorUnion = type_slot_index },
};
},
.elem_type => {
const un_node = data[inst_index].un_node;
@@ -2744,14 +2779,43 @@ fn analyzeFunction(
};
self.ast_nodes.items[self_ast_node_index].fields = param_ast_indexes.items;
self.types.items[type_slot_index] = .{
.Fn = .{
.name = "todo_name func",
.src = self_ast_node_index,
.params = param_type_refs.items,
.ret = ret_type_ref.expr,
self.types.items[type_slot_index] = switch (tags[inst_index]) {
.func, .func_inferred => blk: {
break :blk .{
.Fn = .{
.name = "todo_name func",
.src = self_ast_node_index,
.params = param_type_refs.items,
.ret = ret_type_ref.expr,
},
};
},
.func_extended => blk: {
const inst_data = data[inst_index].pl_node;
const extra = file.zir.extraData(Zir.Inst.ExtendedFunc, inst_data.payload_index);
var cc_index: ?usize = null;
if (extra.data.bits.has_cc) {
const cc_ref = @intToEnum(Zir.Inst.Ref, file.zir.extra[extra.end]);
_ = try self.walkRef(file, scope, cc_ref, false);
cc_index = self.types.items.len - 1;
}
break :blk .{
.Fn = .{
.name = "todo_name func",
.src = self_ast_node_index,
.params = param_type_refs.items,
.ret = ret_type_ref.expr,
.is_extern = extra.data.bits.is_extern,
.has_cc = extra.data.bits.has_cc,
.is_inferred_error = extra.data.bits.is_inferred_error,
.cc = cc_index,
},
};
},
else => unreachable,
};
return DocData.WalkResult{
.typeRef = .{ .type = @enumToInt(Ref.type_type) },
.expr = .{ .type = type_slot_index },