Commit 5d4c88c741

Loris Cro <kappaloris@gmail.com>
2022-02-15 20:45:07
autodoc: added basic support for unresolved comptime expressions
1 parent ee16edd
Changed files (2)
lib
docs
src
lib/docs/main.js
@@ -80,7 +80,7 @@
     var rootIsStd = detectRootIsStd();
 
     // map of decl index to list of non-generic fn indexes
-    var nodesToFnsMap = indexNodesToFns();
+    // var nodesToFnsMap = indexNodesToFns();
     // map of decl index to list of comptime fn calls
     var nodesToCallsMap = indexNodesToCalls();
 
@@ -160,7 +160,7 @@
         console.assert(false);
     }
 
-    function resolveDeclValueTypeId(decl){
+    function typeOfDecl(decl){
         var i = 0;
         while(i < 1000) {
             i += 1;
@@ -186,7 +186,12 @@
                 return resolveTypeRefToTypeId(decl.value.struct.typeRef);
             }
 
-            console.log("TODO: handle in `resolveDeclValueTypeId` more cases: ", decl);
+            if ("comptimeExpr" in decl.value) {
+                const cte = zigAnalysis.comptimeExprs[decl.value.comptimeExpr];
+                return resolveTypeRefToTypeId(cte.typeRef);
+            }
+
+            console.log("TODO: handle in `typeOfDecl` more cases: ", decl);
             console.assert(false);
         }
         console.assert(false);
@@ -199,7 +204,7 @@
         }
 
         if ("declRef" in ref) {
-            return resolveDeclValueTypeId(ref.declRef);
+            return typeOfDecl(ref.declRef);
         }
 
         if ("type" in ref) {
@@ -265,7 +270,11 @@
 
             var childDeclValue = resolveValue(childDecl.value);
             if ("type" in childDeclValue) {
-                childDecl = zigAnalysis.types[childDeclValue.type];
+
+                const t = zigAnalysis.types[childDeclValue.type];
+                if (t.kind != typeKinds.Fn) {
+                    childDecl = t;
+                }
             }
 
             currentType = childDecl;
@@ -280,21 +289,28 @@
         var lastIsContainerType = isContainerType(last);
 
         if (lastIsContainerType) {
-            renderContainer(last);
+            return renderContainer(last);
         }
+
         if (!lastIsDecl && !lastIsType) {
             return renderUnknownDecl(last);
-        } else if (lastIsDecl && last.kind === 'var') {
+        }
+
+        if (lastIsType) {
+            return renderType(last);
+        }
+
+        if (lastIsDecl && last.kind === 'var') {
             return renderVar(last);
-        } else if (lastIsDecl && last.kind === 'const' && !(declContainsType(last))) {
+        }
+
+        if (lastIsDecl && last.kind === 'const') {
             var typeObj = zigAnalysis.types[resolveValue(last.value).type];
-            if (typeObj.kind === typeKinds.Fn) {
+            if (typeObj && typeObj.kind === typeKinds.Fn) {
                 return renderFn(last);
-            } else {
-                return renderValue(last);
             }
-        } else {
-            renderType(last);
+
+            return renderValue(last);
         }
     }
 
@@ -1102,7 +1118,7 @@
 
     function renderValue(decl) {
 
-        var declTypeId = resolveDeclValueTypeId(decl);
+        var declTypeId = typeOfDecl(decl);
         var declValueText = "";
         switch(Object.keys(decl.value)[0]) {
             case "int":
@@ -1111,6 +1127,9 @@
             case "float":
                 declValueText += decl.value.float.value;
                 break;
+            case "comptimeExpr":
+                declValueText += "[ComptimeExpr]";
+                break;
             default:
                 console.log("TODO: renderValue for ", Object.keys(decl.value)[0]);
                 declValueText += "#TODO#";
@@ -1130,7 +1149,7 @@
     }
 
     function renderVar(decl) {
-        var declTypeId = resolveDeclValueTypeId(decl);
+        var declTypeId = typeOfDecl(decl);
         domFnProtoCode.innerHTML = '<span class="tok-kw">var</span> ' +
             escapeHtml(decl.name) + ': ' + typeIndexName(declTypeId, true, true);
 
@@ -1324,7 +1343,7 @@
                 tdNameA.setAttribute('href', navLinkDecl(decl.name));
                 tdNameA.textContent = decl.name;
 
-                tdType.innerHTML = typeIndexName(resolveDeclValueTypeId(decl), true, true);
+                tdType.innerHTML = typeIndexName(typeOfDecl(decl), true, true);
 
                 var docs = zigAnalysis.astNodes[decl.src].docs;
                 if (docs != null) {
@@ -1351,7 +1370,7 @@
                 tdNameA.setAttribute('href', navLinkDecl(decl.name));
                 tdNameA.textContent = decl.name;
 
-                tdType.innerHTML = typeIndexName(resolveDeclValueTypeId(decl), true, true);
+                tdType.innerHTML = typeIndexName(typeOfDecl(decl), true, true);
 
                 var docs = zigAnalysis.astNodes[decl.src].docs;
                 if (docs != null) {
@@ -2106,19 +2125,7 @@ function renderSearchCursor() {
     }
 }
 
-function indexNodesToFns() {
-    var map = {};
-    for (var i = 0; i < zigAnalysis.fns.length; i += 1) {
-        var fn = zigAnalysis.fns[i];
-        if (typeIsGenericFn(fn.type)) continue;
-        if (map[fn.src] == null) {
-            map[fn.src] = [i];
-        } else {
-            map[fn.src].push(i);
-        }
-    }
-    return map;
-}
+
 
 function indexNodesToCalls() {
     var map = {};
src/Autodoc.zig
@@ -12,6 +12,7 @@ arena: std.mem.Allocator,
 types: std.ArrayListUnmanaged(DocData.Type) = .{},
 decls: std.ArrayListUnmanaged(DocData.Decl) = .{},
 ast_nodes: std.ArrayListUnmanaged(DocData.AstNode) = .{},
+comptimeExprs: std.ArrayListUnmanaged(DocData.ComptimeExpr) = .{},
 
 var arena_allocator: std.heap.ArenaAllocator = undefined;
 pub fn init(m: *Module, doc_location: Compilation.EmitLoc) Autodoc {
@@ -48,9 +49,11 @@ pub fn generateZirData(self: *Autodoc) !void {
 
     // append all the types in Zir.Inst.Ref
     {
-
-        // TODO: we don't want to add .none, but the index math has to check out
-        var i: u32 = 0;
+        try self.types.append(self.arena, .{
+            .ComptimeExpr = .{ .name = "ComptimeExpr" },
+        });
+        // this skipts Ref.none but it's ok becuse we replaced it with ComptimeExpr
+        var i: u32 = 1;
         while (i <= @enumToInt(Ref.anyerror_void_error_union_type)) : (i += 1) {
             var tmpbuf = std.ArrayList(u8).init(self.arena);
             try Ref.typed_value_map[i].val.format("", .{}, tmpbuf.writer());
@@ -128,6 +131,7 @@ pub fn generateZirData(self: *Autodoc) !void {
         .types = self.types.items,
         .decls = self.decls.items,
         .astNodes = self.ast_nodes.items,
+        .comptimeExprs = self.comptimeExprs.items,
     };
 
     data.packages[0].main = main_type_index.type;
@@ -196,7 +200,7 @@ const Scope = struct {
 };
 
 const DocData = struct {
-    typeKinds: []const []const u8 = std.meta.fieldNames(std.builtin.TypeId),
+    typeKinds: []const []const u8 = std.meta.fieldNames(DocTypeKinds),
     rootPkg: u32 = 0,
     params: struct {
         zigId: []const u8 = "arst",
@@ -208,7 +212,6 @@ const DocData = struct {
         },
     } = .{},
     packages: [1]Package = .{.{}},
-    fns: []struct {} = &.{},
     errors: []struct {} = &.{},
     calls: []struct {} = &.{},
 
@@ -217,11 +220,27 @@ const DocData = struct {
     files: []const []const u8,
     types: []Type,
     decls: []Decl,
+    comptimeExprs: []ComptimeExpr,
+
+    const DocTypeKinds = blk: {
+        var info = @typeInfo(std.builtin.TypeId);
+        info.Enum.fields = info.Enum.fields ++ [1]std.builtin.TypeInfo.EnumField{
+            .{
+                .name = "ComptimeExpr",
+                .value = info.Enum.fields.len,
+            },
+        };
+        break :blk @Type(info);
+    };
 
+    const ComptimeExpr = struct {
+        code: []const u8,
+        typeRef: TypeRef,
+    };
     const Package = struct {
         name: []const u8 = "root",
-        file: usize = 0, // index into files
-        main: usize = 0, // index into decls
+        file: usize = 0, // index into `files`
+        main: usize = 0, // index into `decls`
         table: struct { root: usize } = .{
             .root = 0,
         },
@@ -244,7 +263,7 @@ const DocData = struct {
         fields: ?[]usize = null, // index into astNodes
     };
 
-    const Type = union(std.builtin.TypeId) {
+    const Type = union(DocTypeKinds) {
         Type: struct { name: []const u8 },
         Void: struct { name: []const u8 },
         Bool: struct { name: []const u8 },
@@ -260,6 +279,7 @@ const DocData = struct {
             pubDecls: ?[]usize = null, // index into decls
             fields: ?[]TypeRef = null, // (use src->fields to find names)
         },
+        ComptimeExpr: struct { name: []const u8 },
         ComptimeFloat: struct { name: []const u8 },
         ComptimeInt: struct { name: []const u8 },
         Undefined: struct { name: []const u8 },
@@ -309,6 +329,7 @@ const DocData = struct {
                 .Array => |v| try printTypeBody(v, options, w),
                 .Bool => |v| try printTypeBody(v, options, w),
                 .Void => |v| try printTypeBody(v, options, w),
+                .ComptimeExpr => |v| try printTypeBody(v, options, w),
                 .ComptimeInt => |v| try printTypeBody(v, options, w),
                 .ComptimeFloat => |v| try printTypeBody(v, options, w),
                 .Null => |v| try printTypeBody(v, options, w),
@@ -355,6 +376,7 @@ const DocData = struct {
         unspecified,
         declRef: usize, // index in `decls`
         type: usize, // index in `types`
+        comptimeExpr: usize, // index in `comptimeExprs`
 
         pub fn fromWalkResult(wr: WalkResult) TypeRef {
             return switch (wr) {
@@ -376,7 +398,7 @@ const DocData = struct {
                     , .{});
                 },
 
-                .declRef, .type => |v| {
+                .declRef, .type, .comptimeExpr => |v| {
                     try w.print(
                         \\{{ "{s}":{} }}
                     , .{ @tagName(self), v });
@@ -386,6 +408,7 @@ const DocData = struct {
     };
 
     const WalkResult = union(enum) {
+        comptimeExpr: usize, // index in `comptimeExprs`
         void,
         @"unreachable",
         @"null": TypeRef,
@@ -421,7 +444,7 @@ const DocData = struct {
                         \\{{ "{s}":{{}} }}
                     , .{@tagName(self)});
                 },
-                .type, .declRef => |v| {
+                .type, .declRef, .comptimeExpr => |v| {
                     try w.print(
                         \\{{ "{s}":{} }}
                     , .{ @tagName(self), v });
@@ -493,6 +516,14 @@ fn walkInstruction(
             var new_scope = Scope{ .parent = null };
             return self.walkInstruction(new_file.file, &new_scope, Zir.main_struct_inst);
         },
+        .block => {
+            const res = DocData.WalkResult{ .comptimeExpr = self.comptimeExprs.items.len };
+            try self.comptimeExprs.append(self.arena, .{
+                .code = "if(banana) 1 else 0",
+                .typeRef = .{ .type = 0 },
+            });
+            return res;
+        },
         .int => {
             const int = data[inst_index].int;
             return DocData.WalkResult{
@@ -545,7 +576,9 @@ fn walkInstruction(
                 // and we don't want to toss away the
                 // decl_val information (eg by replacing it with
                 // a WalkResult.type).
-
+                .comptimeExpr => {
+                    self.comptimeExprs.items[operand.comptimeExpr].typeRef = dest_type_ref;
+                },
                 .int => operand.int.typeRef = dest_type_ref,
                 .@"struct" => operand.@"struct".typeRef = dest_type_ref,
                 .@"undefined" => operand.@"undefined" = dest_type_ref,