Commit 413cfd4066

Loris Cro <kappaloris@gmail.com>
2022-05-30 21:48:46
autodoc: init generic function support
1 parent 51647c3
Changed files (2)
lib
docs
src
lib/docs/main.js
@@ -724,7 +724,7 @@ var zigAnalysis;
         if (typeObj.kind !== typeKinds.Fn) {
             return false;
         }
-        return  /** @type {Fn} */(typeObj).generic;
+        return  /** @type {Fn} */(typeObj).generic_ret != null;
     }
 
     /** @param {Decl} fnDecl */
@@ -772,7 +772,26 @@ var zigAnalysis;
 
         let protoSrcIndex = fnDecl.src;
         if (typeIsGenericFn(value.expr.type)) {
-            throw "TODO";
+            // does the generic_ret contain a container?
+            var resolvedGenericRet = resolveValue({expr: typeObj.generic_ret});
+            // TODO: see if unwrapping the `as` here is a good idea or not.
+            if ("as" in resolvedGenericRet.expr) {
+                resolvedGenericRet = {
+                    expr: zigAnalysis.exprs[resolvedGenericRet.expr.as.exprArg]
+                };
+            }
+
+            if (!("type" in resolvedGenericRet.expr)) return;
+            const genericType = zigAnalysis.types[resolvedGenericRet.expr.type];
+            if (isContainerType(genericType)) {
+                renderContainer(genericType)
+            }
+
+
+
+
+
+            // old code
             // let instantiations = nodesToFnsMap[protoSrcIndex];
             // let calls = nodesToCallsMap[protoSrcIndex];
             // if (instantiations == null && calls == null) {
@@ -1530,7 +1549,7 @@ var zigAnalysis;
                         return html;
                       }
                   }
-                  
+
                   case typeKinds.ErrorUnion:
                   {
                     let errUnionObj = /** @type {ErrUnionType} */(typeObj);
@@ -1614,7 +1633,7 @@ var zigAnalysis;
 
                                   if (isVarArgs && i === fnObj.params.length - 1) {
                                       payloadHtml += '...';
-                                  } 
+                                  }
                                   else if ("typeOf" in value) {
                                     if (opts.wantHtml) {
                                       payloadHtml += '<a href="">';
@@ -1626,7 +1645,7 @@ var zigAnalysis;
                                       payloadHtml += exprName(value, opts);
                                     }
 
-                                  } 
+                                  }
                                   else if ("typeOf_peer" in value) {
                                     if (opts.wantHtml) {
                                       payloadHtml += '<a href="">';
@@ -1638,7 +1657,7 @@ var zigAnalysis;
                                       payloadHtml += exprName(value, opts);
                                     }
 
-                                  } 
+                                  }
                                   else if ("declRef" in value) {
                                     if (opts.wantHtml) {
                                       payloadHtml += '<a href="">';
@@ -1650,7 +1669,7 @@ var zigAnalysis;
                                       payloadHtml += exprName(value, opts);
                                     }
 
-                                  } 
+                                  }
                                   else if ("call" in value) {
                                     if (opts.wantHtml) {
                                       payloadHtml += '<a href="">';
@@ -1661,7 +1680,7 @@ var zigAnalysis;
                                     } else {
                                       payloadHtml += exprName(value, opts);
                                     }
-                                  } 
+                                  }
                                   else if ("refPath" in value) {
                                     if (opts.wantHtml) {
                                       payloadHtml += '<a href="">';
src/Autodoc.zig
@@ -476,8 +476,9 @@ const DocData = struct {
         },
         Fn: struct {
             name: []const u8,
-            src: ?usize = null, // index into astNodes
+            src: ?usize = null, // index into `astNodes`
             ret: Expr,
+            generic_ret: ?Expr = null,
             params: ?[]Expr = null, // (use src->fields to find names)
             lib_name: []const u8 = "",
             is_var_args: bool = false,
@@ -522,7 +523,6 @@ const DocData = struct {
                 .ComptimeFloat => |v| try printTypeBody(v, options, w),
                 .Null => |v| try printTypeBody(v, options, w),
                 .Optional => |v| try printTypeBody(v, options, w),
-
                 .Struct => |v| try printTypeBody(v, options, w),
                 .Fn => |v| try printTypeBody(v, options, w),
                 .Union => |v| try printTypeBody(v, options, w),
@@ -886,6 +886,10 @@ fn walkInstruction(
             );
             return self.cteTodo(@tagName(tags[inst_index]));
         },
+        .ret_node => {
+            const un_node = data[inst_index].un_node;
+            return self.walkRef(file, parent_scope, un_node.operand, false);
+        },
         .closure_get => {
             const inst_node = data[inst_index].inst_node;
             return try self.walkInstruction(file, parent_scope, inst_node.inst, need_type);
@@ -3882,7 +3886,20 @@ fn analyzeFunctionExtended(
     }
 
     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, .is_extern = extra.data.bits.is_extern, .has_cc = extra.data.bits.has_cc, .has_align = extra.data.bits.has_align, .has_lib_name = extra.data.bits.has_lib_name, .lib_name = lib_name, .is_inferred_error = extra.data.bits.is_inferred_error, .cc = cc_index, .@"align" = align_index },
+        .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,
+            .has_align = extra.data.bits.has_align,
+            .has_lib_name = extra.data.bits.has_lib_name,
+            .lib_name = lib_name,
+            .is_inferred_error = extra.data.bits.is_inferred_error,
+            .cc = cc_index,
+            .@"align" = align_index,
+        },
     };
 
     return DocData.WalkResult{
@@ -3974,6 +3991,21 @@ fn analyzeFunction(
         break :blk wr;
     };
 
+    // TODO: a complete version of this will probably need a scope
+    //       in order to evaluate correctly closures around funcion
+    //       parameters etc.
+    const generic_ret: ?DocData.Expr = switch (ret_type_ref.expr) {
+        .type => |t| if (t == @enumToInt(Ref.type_type))
+            try self.getGenericReturnType(
+                file,
+                scope,
+                fn_info.body[fn_info.body.len - 1],
+            )
+        else
+            null,
+        else => null,
+    };
+
     self.ast_nodes.items[self_ast_node_index].fields = param_ast_indexes.items;
     self.types.items[type_slot_index] = .{
         .Fn = .{
@@ -3981,6 +4013,7 @@ fn analyzeFunction(
             .src = self_ast_node_index,
             .params = param_type_refs.items,
             .ret = ret_type_ref.expr,
+            .generic_ret = generic_ret,
         },
     };
 
@@ -3990,6 +4023,16 @@ fn analyzeFunction(
     };
 }
 
+fn getGenericReturnType(
+    self: *Autodoc,
+    file: *File,
+    scope: *Scope,
+    body_end: usize,
+) !DocData.Expr {
+    const wr = try self.walkInstruction(file, scope, body_end, false);
+    return wr.expr;
+}
+
 fn collectUnionFieldInfo(
     self: *Autodoc,
     file: *File,