mirror of
https://github.com/hsjobeki/noogle.git
synced 2024-12-28 08:26:53 +03:00
pasta - nixpkgs evaluation analysis: init
This commit is contained in:
parent
2f1aead693
commit
eac456913d
109
flake.lock
109
flake.lock
@ -16,6 +16,22 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat_2": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1673956053,
|
||||
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
@ -95,19 +111,58 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"lowdown-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1700390070,
|
||||
"narHash": "sha256-de9KYi8rSJpqvBfNwscWdalIJXPo8NjdIZcEJum1mH0=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "e4ad989506ec7d71f7302cc3067abd82730a4beb",
|
||||
"lastModified": 1633514407,
|
||||
"narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
|
||||
"owner": "kristapsdz",
|
||||
"repo": "lowdown",
|
||||
"rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-unstable",
|
||||
"type": "indirect"
|
||||
"owner": "kristapsdz",
|
||||
"repo": "lowdown",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"lowdown-src": "lowdown-src",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs-regression": "nixpkgs-regression"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1700475714,
|
||||
"narHash": "sha256-8OXrkNaIpdtErfLN4u1Ew1IThTbk6n8POYRQfNatkSA=",
|
||||
"owner": "hsjobeki",
|
||||
"repo": "nix",
|
||||
"rev": "9bf2153e696d88c6beb8e34709bb743af5cdd940",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hsjobeki",
|
||||
"ref": "feat/positions",
|
||||
"repo": "nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1695283060,
|
||||
"narHash": "sha256-CJz71xhCLlRkdFUSQEL0pIAAfcnWFXMzd9vXhPrnrEg=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "31ed632c692e6a36cfc18083b88ece892f863ed4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-23.05-small",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-master": {
|
||||
@ -125,6 +180,22 @@
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"nixpkgs-regression": {
|
||||
"locked": {
|
||||
"lastModified": 1643052045,
|
||||
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1685801374,
|
||||
@ -141,9 +212,24 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1700390070,
|
||||
"narHash": "sha256-de9KYi8rSJpqvBfNwscWdalIJXPo8NjdIZcEJum1mH0=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "e4ad989506ec7d71f7302cc3067abd82730a4beb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-unstable",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"pre-commit-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-compat": "flake-compat_2",
|
||||
"flake-utils": "flake-utils",
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
@ -169,7 +255,8 @@
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts",
|
||||
"floco": "floco",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nix": "nix",
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"nixpkgs-master": "nixpkgs-master",
|
||||
"pre-commit-hooks": "pre-commit-hooks",
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
|
10
flake.nix
10
flake.nix
@ -4,6 +4,9 @@
|
||||
nixpkgs.url = "nixpkgs/nixos-unstable";
|
||||
nixpkgs-master.url = "nixpkgs/master";
|
||||
|
||||
# A custom nix verison, to introspect lambda values.
|
||||
nix.url = "github:hsjobeki/nix/?ref=feat/positions";
|
||||
|
||||
pre-commit-hooks = {
|
||||
url = "github:cachix/pre-commit-hooks.nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
@ -21,6 +24,11 @@
|
||||
outputs = inputs@{ flake-parts, ... }:
|
||||
flake-parts.lib.mkFlake { inherit inputs; } ({ ... }: {
|
||||
systems = [ "x86_64-linux" ];
|
||||
imports = [ ./devShell.nix ./preCommit.nix ./website/flake-module.nix ];
|
||||
imports = [
|
||||
./devShell.nix
|
||||
./preCommit.nix
|
||||
./website/flake-module.nix
|
||||
./pasta/flake-module.nix
|
||||
];
|
||||
});
|
||||
}
|
||||
|
25
pasta/README.md
Normal file
25
pasta/README.md
Normal file
@ -0,0 +1,25 @@
|
||||
# Dough -> Pasta
|
||||
|
||||
We have to make our pasta from the Nixpkgs raw dough.
|
||||
|
||||
Analyse arbitrary nix expressions.
|
||||
|
||||
Contains tools, such as nix functions, that allow us to introspect the nix language.
|
||||
|
||||
Evaluating expressions and their metadata allows for precise documentation building
|
||||
|
||||
Evaluation requires a custom nix version available via devShell '.#pastaMaker'
|
||||
|
||||
Analyses a given path in the expression tree.
|
||||
|
||||
- Recursive tool, that works well with e.g., `pkgs.lib` or other sets that don't have hard evaluation errors inside them. Note: All kinds of recursions are reliably avoided.
|
||||
- Flat tool, that works on attribute sets, without recursing it. Since both tools are not lazy they require at least the analyzed value to have no hard errors.
|
||||
|
||||
## Features
|
||||
|
||||
- Finding lambdas recursively
|
||||
- Adding metadata about lambdas
|
||||
- Attribute Source Position
|
||||
- Lambda Source position
|
||||
- Count Partially Applied
|
||||
- ...
|
11
pasta/default.nix
Normal file
11
pasta/default.nix
Normal file
@ -0,0 +1,11 @@
|
||||
{ pkgs, nixpkgs, nix, ... }:
|
||||
pkgs.stdenv.mkDerivation {
|
||||
name = "pasta";
|
||||
src = ./src;
|
||||
nativeBuildInputs = [ nix ];
|
||||
buildPhase = ''
|
||||
nix-instantiate --eval --strict --json --store $PWD \
|
||||
eval.nix --arg 'pkgs' 'import ${nixpkgs} {}' -A docs.lib \
|
||||
> $out
|
||||
'';
|
||||
}
|
12
pasta/flake-module.nix
Normal file
12
pasta/flake-module.nix
Normal file
@ -0,0 +1,12 @@
|
||||
{ inputs, ... }: {
|
||||
perSystem = { self', inputs', pkgs, ... }:
|
||||
let
|
||||
nix = inputs'.nix.packages.nix-clangStdenv;
|
||||
nixpkgs = inputs.nixpkgs-master;
|
||||
in {
|
||||
packages = {
|
||||
pasta = pkgs.callPackage ./default.nix { inherit nixpkgs nix pkgs; };
|
||||
};
|
||||
devShells.pastaMaker = pkgs.callPackage ./shell.nix { inherit pkgs nix; };
|
||||
};
|
||||
}
|
7
pasta/shell.nix
Normal file
7
pasta/shell.nix
Normal file
@ -0,0 +1,7 @@
|
||||
{ pkgs, nix, ... }:
|
||||
pkgs.mkShell {
|
||||
buildInputs = [ nix ];
|
||||
shellHook = ''
|
||||
echo "using a custom nix build: ${nix}"
|
||||
'';
|
||||
}
|
37
pasta/src/eval.nix
Normal file
37
pasta/src/eval.nix
Normal file
@ -0,0 +1,37 @@
|
||||
{ pkgs ?
|
||||
# import (builtins.fetchTree {
|
||||
# repo = "nixpkgs";
|
||||
# ref = "migrate-doc-comments";
|
||||
# owner = "hsjobeki";
|
||||
# type = "github";
|
||||
# }) {},
|
||||
import (builtins.fetchTree {
|
||||
repo = "nixpkgs";
|
||||
ref = "master";
|
||||
owner = "nixos";
|
||||
type = "github";
|
||||
}) { }, }:
|
||||
let
|
||||
inherit pkgs;
|
||||
inherit (pkgs) lib;
|
||||
tools = import ./tools.nix { inherit lib; };
|
||||
inherit (tools) getDocsFromSet collectFns toFile;
|
||||
|
||||
# Contains seperate sets of metadata.
|
||||
# which then allows running seperate evaluations. Once at a time for better error tracing and memory management.
|
||||
docs = {
|
||||
############# Recusive analysis sets
|
||||
lib = collectFns lib { initialPath = [ "lib" ]; };
|
||||
rustTools = collectFns pkgs.pkgs.rustPackages {
|
||||
initialPath = [ "pkgs" "rustPackages" ];
|
||||
};
|
||||
stdenvTools = getDocsFromSet pkgs.stdenv [ "pkgs" "stdenv" ];
|
||||
|
||||
############# Non-recursive analysis sets
|
||||
pkgs = getDocsFromSet pkgs [ "pkgs" ];
|
||||
dockerTools = getDocsFromSet pkgs.pkgs.dockerTools [ "pkgs" "dockerTools" ];
|
||||
pythonTools =
|
||||
getDocsFromSet pkgs.pkgs.pythonPackages [ "pkgs" "pythonPackages" ];
|
||||
};
|
||||
|
||||
in { inherit tools pkgs docs toFile; }
|
97
pasta/src/tools.nix
Normal file
97
pasta/src/tools.nix
Normal file
@ -0,0 +1,97 @@
|
||||
{ lib }:
|
||||
let
|
||||
force = v: (builtins.tryEval v).value;
|
||||
|
||||
dropBack = l: lib.reverseList (lib.drop 1 (lib.reverseList l));
|
||||
|
||||
getDocs = parent: name:
|
||||
let
|
||||
lambda = builtins.lambdaMeta parent.${name};
|
||||
attr = { position = builtins.unsafeGetAttrPos name parent; };
|
||||
in { inherit lambda attr; };
|
||||
|
||||
/* *
|
||||
Recursively collect documentation for all values
|
||||
*/
|
||||
collectFns = set:
|
||||
{ initialPath ? [ ], limit ? null, }:
|
||||
let
|
||||
filterFns = builtins.filter (item: item.type == "lambda");
|
||||
getFnDocs = map (fn: {
|
||||
path = initialPath ++ fn.path;
|
||||
inherit (fn) docs;
|
||||
});
|
||||
in getFnDocs (filterFns (builtins.genericClosure {
|
||||
startSet = [{
|
||||
__initial = true;
|
||||
key = [ ];
|
||||
value = set;
|
||||
|
||||
path = [ ];
|
||||
name = "?";
|
||||
|
||||
depth = 0;
|
||||
type = "?";
|
||||
parent = null;
|
||||
docs = null;
|
||||
}];
|
||||
operator = item:
|
||||
let
|
||||
currVal = force item.value;
|
||||
# Dont traverse into: "derivations", "option types"
|
||||
in if lib.isDerivation currVal || lib.isOptionType currVal || currVal
|
||||
== null then
|
||||
[ ]
|
||||
# Doc support for named key value pairs (sets)
|
||||
else if builtins.typeOf currVal == "set" then
|
||||
map (name:
|
||||
# NEXT ITEM
|
||||
let
|
||||
nextVal = force item.value.${name};
|
||||
# calling lib.unique prevents infinite recursion
|
||||
path = lib.unique (item.key ++ [ name ]);
|
||||
in if lib.isDerivation nextVal || name == "__functor"
|
||||
|| (limit != null && item.depth >= limit) then
|
||||
# skipping some values by
|
||||
# returning the previous item
|
||||
item
|
||||
else {
|
||||
key = path;
|
||||
value = item.value.${name};
|
||||
# Propagate some values.
|
||||
type = if lib.isFunction nextVal then
|
||||
"lambda"
|
||||
else
|
||||
builtins.typeOf nextVal;
|
||||
docs = getDocs (lib.attrByPath (dropBack path) null set) name;
|
||||
inherit name path;
|
||||
parent = currVal;
|
||||
depth = item.depth + 1;
|
||||
}) (builtins.attrNames item.value)
|
||||
else
|
||||
[ ];
|
||||
}));
|
||||
|
||||
# Convinient wrapper for debugging.
|
||||
toFile = thing: builtins.toFile "data.json" (builtins.toJSON thing);
|
||||
|
||||
# Non-rcusively collect docs of all functions present in a set
|
||||
getDocsFromSet = s: path:
|
||||
let
|
||||
docs = lib.pipe s [
|
||||
# Filter out all attributes that are not a function or __functor
|
||||
(lib.filterAttrs (v: v: lib.isFunction (force v)))
|
||||
# Call getDocs for each name value pair
|
||||
(lib.mapAttrs (n: v: getDocs s n))
|
||||
];
|
||||
in lib.pipe docs [
|
||||
# Transform into list
|
||||
builtins.attrNames
|
||||
# Collect all values
|
||||
(builtins.foldl' (res: name:
|
||||
res ++ [{
|
||||
path = path ++ [ name ];
|
||||
docs = docs.${name};
|
||||
}]) [ ])
|
||||
];
|
||||
in { inherit toFile collectFns getDocsFromSet; }
|
Loading…
Reference in New Issue
Block a user