code: func flattenObjects(node ast.Node) {
  	ast.Walk(node, func(n ast.Node) (ast.Node, bool) {
  		// We only care about lists, because this is what we modify
  		list, ok := n.(*ast.ObjectList)
  		if !ok {
  			return n, true
  		}
  
  		// Rebuild the item list
  		items := make([]*ast.ObjectItem, 0, len(list.Items))
  		frontier := make([]*ast.ObjectItem, len(list.Items))
  		copy(frontier, list.Items)
  		for len(frontier) > 0 {
  			// Pop the current item
  			n := len(frontier)
  			item := frontier[n-1]
  			frontier = frontier[:n-1]
  
  			switch v := item.Val.(type) {
  			case *ast.ObjectType:
  				items, frontier = flattenObjectType(v, item, items, frontier)
  			case *ast.ListType:
  				items, frontier = flattenListType(v, item, items, frontier)
  			default:
  				items = append(items, item)
  			}
  		}
  
  		// Reverse the list since the frontier model runs things backwards
  		for i := len(items)/2 - 1; i >= 0; i-- {
  			opp := len(items) - 1 - i
  			items[i], items[opp] = items[opp], items[i]
  		}
  
  		// Done! Set the original items
  		list.Items = items
  		return n, true
  	})
  }
docs: // flattenObjects takes an AST node, walks it, and flattens