aboutsummaryrefslogtreecommitdiffstats
#!/bin/bash

cloc --by-file ./theories --include-ext=v --json | jq -r '
	def categories: {
		"./theories/lambda/operational.v": {
			component: "(2) LambdaLang",
			category1: "(1) Operational semantics",
			category2: "General",
		},
		"./theories/lambda/operational_props.v": {
			component: "(2) LambdaLang",
			category1: "(1) Operational semantics",
			category2: "Properties",
		},
		"./theories/lambda/interp.v": {
			component: "(2) LambdaLang",
			category1: "(2) Interpreter",
			category2: "General",
		},
		"./theories/lambda/interp_proofs.v": {
			component: "(2) LambdaLang",
			category1: "(2) Interpreter",
			category2: "Theorem + proofs",
		},
		"./theories/dynlang/operational.v": {
			component: "(3) DynLang",
			category1: "(1) Operational semantics",
			category2: "General",
		},
		"./theories/dynlang/operational_props.v": {
			component: "(3) DynLang",
			category1: "(1) Operational semantics",
			category2: "Properties",
		},
		"./theories/dynlang/interp.v": {
			component: "(3) DynLang",
			category1: "(2) Interpreter",
			category2: "General",
		},
		"./theories/dynlang/interp_proofs.v": {
			component: "(3) DynLang",
			category1: "(2) Interpreter",
			category2: "Theorem + proofs",
		},
		"./theories/dynlang/equiv.v": {
			component: "(3) DynLang",
			category1: "(4) Extra",
			category2: "Equivalence with LambdaLang",
		},
		"./theories/evallang/operational.v": {
			component: "(4) EvalLang",
			category1: "(1) Operational semantics",
			category2: "General",
		},
		"./theories/evallang/operational_props.v": {
			component: "(4) EvalLang",
			category1: "(1) Operational semantics",
			category2: "Properties",
		},
		"./theories/evallang/interp.v": {
			component: "(4) EvalLang",
			category1: "(2) Interpreter",
			category2: "General",
		},
		"./theories/evallang/interp_proofs.v": {
			component: "(4) EvalLang",
			category1: "(2) Interpreter",
			category2: "Theorem + proofs",
		},
		"./theories/evallang/tests.v": {
			component: "(4) EvalLang",
			category1: "(3) Tests",
			category2: "General",
		},
		"./theories/nix/floats.v": {
			component: "(5) NixLang",
			category1: "(4) Extra",
			category2: "General",
		},
		"./theories/nix/operational.v": {
			component: "(5) NixLang",
			category1: "(1) Operational semantics",
			category2: "General",
		},
		"./theories/nix/operational_props.v": {
			component: "(5) NixLang",
			category1: "(1) Operational semantics",
			category2: "Properties",
		},
		"./theories/nix/notations.v": {
			component: "(5) NixLang",
			category1: "(4) Extra",
			category2: "General",
		},
		"./theories/nix/interp.v": {
			component: "(5) NixLang",
			category1: "(2) Interpreter",
			category2: "General",
		},
		"./theories/nix/interp_proofs.v": {
			component: "(5) NixLang",
			category1: "(2) Interpreter",
			category2: "Theorem + proofs",
		},
		"./theories/nix/tests.v": {
			component: "(5) NixLang",
			category1: "(3) Tests",
			category2: "General",
		},
		"./theories/nix/wp.v": {
			component: "(5) NixLang",
			category1: "(4) Extra",
			category2: "General",
		},
		"./theories/nix/wp_examples.v": {
			component: "(5) NixLang",
			category1: "(4) Extra",
			category2: "General",
		},
		"./theories/utils.v": {
			component: "(1) Shared",
			category1: "General",
			category2: "General",
		},
		"./theories/res.v": {
			component: "(1) Shared",
			category1: "General",
			category2: "General",
		},
	};
	def add_cat_data:
		{ key, value: ({loc: .value.code} + categories[.key]) };
	def categorize_by(key):
		group_by(.value[key]) | map({ key: .[0].value[key], value: . }) | from_entries;
	def spaces: if . == 0 then "" else " " + (. - 1 | spaces) end;
	def pretty(ind):
		if (. | type) == "number" then
			. | tostring
		else
			to_entries | reduce .[] as $item (""; . + "\n" + (ind | spaces) + $item.key + ": " + ($item.value | pretty(ind + 2)))
		end;
	.SUM.code as $sum | del(.header, .SUM) | with_entries(add_cat_data) | to_entries
	| categorize_by("component") | map_values(categorize_by("category1"))
	| map_values(map_values(categorize_by("category2") | map_values(map(.value.loc) | add)))
	| map_values(map_values(. + { TOTAL: to_entries | map(.value) | add }))
	| map_values(. + { TOTAL: to_entries | map(.value.TOTAL) | add })
	| . + { TOTAL: to_entries | map(.value.TOTAL) | add }
	| if .TOTAL == $sum then . else error("internal error: calculated total \(.TOTAL) does not match provided sum \($sum)") end
	| "Lines of code for the different parts of the Rocq development:" + pretty(0)
'